Overflow evaluating the requirement

I tries to use syntax::ast::ItemKind inside lazy_static! in my compiler plugin:

lazy_static! {
    static ref ITEMS: Vec<ItemKind> = Vec::<ItemKind>::new();
}

but get following error:

error[E0275]: overflow evaluating the requirement `std::ptr::Unique<syntax::ast::InlineAsmOutput>: std::marker::Sync`
  --> src/lib.in.rs:37:1
   |
37 | / lazy_static! {
38 | |     static ref ITEMS: Vec<ItemKind> = Vec::<ItemKind>::new();
39 | | }
   | |_^
   |
   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
   = note: required because it appears within the type `alloc::raw_vec::RawVec<syntax::ast::InlineAsmOutput>`
   = note: required because it appears within the type `std::vec::Vec<syntax::ast::InlineAsmOutput>`
   = note: required because it appears within the type `syntax::ast::InlineAsm`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `syntax::ast::ExprKind`
   = note: required because it appears within the type `syntax::ast::Expr`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::Expr>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ast::ExprKind`
   = note: required because it appears within the type `syntax::ast::Expr`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::Expr>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ast::InlineAsmOutput`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::InlineAsmOutput>`
   = note: required because it appears within the type `alloc::raw_vec::RawVec<syntax::ast::InlineAsmOutput>`
   = note: required because it appears within the type `std::vec::Vec<syntax::ast::InlineAsmOutput>`
   = note: required because it appears within the type `syntax::ast::InlineAsm`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `syntax::ast::ExprKind`
   = note: required because it appears within the type `syntax::ast::Expr`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::Expr>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ast::InlineAsmOutput`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::InlineAsmOutput>`
   = note: required because it appears within the type `alloc::raw_vec::RawVec<syntax::ast::InlineAsmOutput>`
   = note: required because it appears within the type `std::vec::Vec<syntax::ast::InlineAsmOutput>`
   = note: required because it appears within the type `syntax::ast::InlineAsm`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::InlineAsm>`
   = note: required because it appears within the type `syntax::ast::ExprKind`
   = note: required because it appears within the type `syntax::ast::Expr`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::Expr>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ast::TyKind`
   = note: required because it appears within the type `syntax::ast::Ty`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::Ty>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::Ty>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::Ty>`
   = note: required because it appears within the type `std::option::Option<syntax::ptr::P<syntax::ast::Ty>>`
   = note: required because it appears within the type `syntax::ast::ParenthesizedParameterData`
   = note: required because it appears within the type `syntax::ast::PathParameters`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::PathParameters>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::PathParameters>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::PathParameters>`
   = note: required because it appears within the type `std::option::Option<syntax::ptr::P<syntax::ast::PathParameters>>`
   = note: required because it appears within the type `syntax::ast::PathSegment`
   = note: required because it appears within the type `syntax::ast::ExprKind`
   = note: required because it appears within the type `syntax::ast::Expr`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::Expr>`
   = note: required because it appears within the type `std::boxed::Box<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ptr::P<syntax::ast::Expr>`
   = note: required because it appears within the type `syntax::ast::ItemKind`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntax::ast::ItemKind>`
   = note: required because it appears within the type `alloc::raw_vec::RawVec<syntax::ast::ItemKind>`
   = note: required because it appears within the type `std::vec::Vec<syntax::ast::ItemKind>`
   = note: required by `lazy_static::lazy::Lazy`
   = note: this error originates in a macro outside of the current crate

error: aborting due to previous error

Is this a bug? Is there any workaround? Increasing recursion limit doesn't help.

1 Like

What happens when you bump the recursion limit up to something stupidly large, like 1024? It's pretty rare for a type to be so nested that it'll overflow while checking if something satisfies a trait, so you may have encountered a compiler bug.

A workaround would be to avoid using lazy_static and pass the thing around normally, although this probably isn't going to be possible for your use case. Otherwise you could use a static mut and a sprinkling of unsafe, which I'd usually wrap in a function to ensure safety.

I made a quick proof-of-concept "lazy static" on the playground. I had to wrap it in a mutex so things are thread safe, but I'm pretty sure what I've done is sound.

EDIT: I just realised you can work around the issue by wrapping your Vec<ItemKind> in something which implements Sync directly instead of having to recursively check each thing in an ItemKind to see if they are Sync. So ITEMS: Mutex<Vec<ItemKind>> should fix your problem.

1 Like

I tried as much as 20000 — it didn't help. If you look closely to error, you'll see there is loop in it (with period like 20 items). Seems like it can't handle self-recursive structures?

And using Mutex doesn't help, error message is exactly the same.

1 Like

If that's the case, you should file a bug report. That way someone who knows more about trait resolution will be able to give you a workaround.

Does my unsafe lazy static work if you drop the Mutex completely?

If you google this error you’ll see several reported instances. Here’s a very simple one.

Is the Mutex error exactly the same or is it now trying to determine if the types are Send (rather than Sync)? A Mutex<T> is Sync if T:Send so I’d expect it to start trying to determine if the types are Send.

You are right! It is now trying to evaluate Send instead of Sync.

Thanks for issue link, subscribed to it.