Overflow evaluating the requirement


#1

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.


#2

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.


#3

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.


#4

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?


#5

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.


#6

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


#7

Thanks for issue link, subscribed to it.