matklad / once_cell

Rust library for single assignment cells and lazy statics without macros

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`Lazy` returning different results

kpark-hrp opened this issue · comments

For unit testing, I have a const String that is randomly generated and shared.

const CLIENT_ID: Lazy<String> =
        Lazy::new(|| Alphanumeric.sample_string(&mut rand::thread_rng(), 16));

But it appears that Lazy is being evaluated multiple times and returns different String each call. I have a very basic equality check unit test to show this.

#[tokio::test]
async fn test_client_id() {
    assert_eq!(CLIENT_ID.clone(), CLIENT_ID.clone());
}
thread 'tests::test_client_id' panicked at 'assertion failed: `(left == right)`
  left: `"1ScRLmtGM8LcSHNJ"`,
 right: `"DezhUcYvnBbIOtyA"`', oauth/src/bin/authorizer.rs:201:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

It appears that replacing const with static fixes the issue.

static CLIENT_ID: Lazy<String> = Lazy::new(|| Alphanumeric.sample_string(&mut rand::thread_rng(), 16));

But, shouldn't const still behave the same way where the closure in Lazy is only evaluated once and shared?

It appears that this behavior is documented.

Note that the variable that holds Lazy is declared as static, not const. This is important: using const instead compiles, but works wrong.

But to me, this feels like an unintended behavior which should not compile

Yeah, it’s a known language level issue without good solutions, see rust-lang/rust#40543

const is not named right, that more like macro in C, basically it's copy the expression and put it where you use it. That just a leçon that rust developer learn at some point, nothing is perfect.