Lazy<CancellationToken>::is_cancelled() does not work

I'm using once_cell::sync::Lazy and tokio_util::sync::CancellationToken in the following code and don't understand why CANCEL.is_cancelled() returns false.

use once_cell::sync::Lazy;
use tokio_util::sync::{CancellationToken, DropGuard};

const CANCEL: Lazy<CancellationToken> = Lazy::new(CancellationToken::new);

fn main() {
    let cancel: &CancellationToken = &*CANCEL;
    let cancel2: CancellationToken = cancel.clone();
    let cancel3: CancellationToken = cancel2.clone();
    let cancel4: CancellationToken = cancel3.clone();
    let cancel_guard: DropGuard = cancel4.drop_guard();
    drop(cancel_guard);
    println!("CANCEL: {}", CANCEL.is_cancelled()); // why does this report `false`?
    println!("cancel: {}", cancel.is_cancelled());
    println!("cancel2: {}", cancel2.is_cancelled());
    println!("cancel3: {}", cancel2.is_cancelled());
}

(Playground)

Output:

CANCEL: false
cancel: true
cancel2: true
cancel3: true

A CancellationToken created with new() will return false by default. The behaviour of const is to copy the definition of the defined constant to every place it is used, so you are getting a new CancellationToken for CANCEL.is_cancelled(). It is more likely that you intended to use static instead of const.

(updated playground with static)

3 Likes

:man_facepalming:

Of course! I knew the difference between static and const but just wasn't paying attention. A really subtle problem. I could have spent hours on debugging that. Many thanks for pointing me to my mistake!!


I made this mistake because I added the Lazy next to several const items, so I used const instead of static accidentally (and I didn't get any warning, obviously).

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.