someguynamedjosh / ouroboros

Easy self-referential struct generation for Rust.
Apache License 2.0
524 stars 33 forks source link

Ouroboros incompatible with custom Rc-like type? (hybrid_rc crate) #113

Open vlovich opened 4 months ago

vlovich commented 4 months ago

The error is pretty inscrutable, so I'm not sure how to solve it, but it looks like ouroboros is incompatible with hybrid_rc?

error[E0599]: no function or associated item named `is_std_rc_type` found for struct `ouroboros::macro_help::CheckIfTypeIsStd<hybrid_rc::HybridRc<Inner, hybrid_rc::state::Local>>` in the current scope
  --> file.rs:48:1
   |
48 | #[self_referencing]
   | ^^^^^^^^^^^^^^^^^^^ function or associated item not found in `CheckIfTypeIsStd<HybridRc<Inner, Local>>`
   |
   = note: the function or associated item was found for
           - `ouroboros::macro_help::CheckIfTypeIsStd<std::rc::Rc<T>>`
   = note: this error originates in the attribute macro `self_referencing` (in Nightly builds, run with -Z macro-backtrace for more info)
someguynamedjosh commented 4 months ago

This probably happened if you aliased Rc to be something other than std::rc::Rc. You can manually put a #[covariant] or #[not_covariant] annotation above the field to specify the missing information. If that doesn't work, you may need to add a type alias or use the original type name for the field so that ouroboros doesn't assume it's std::rc::Rc. (I forget exactly what triggers the special logic for Rcs)

Unfortunately since this error happens when the code is type checked and is not detectable when the macro is run, I cannot put in a better error message.

vlovich commented 4 months ago

Nope, Rc isn't aliased to anything. I already have covariance specified on another field so the macro fails with TODO: Nice error, covariance specified twice if I also add either annotation you mentioned to this one. I have the type fully specified as hybrid_rc::Rc<Inner> within the wrapped struct.

The type alias trick worked: type HideFromOuroboros<T> = hybrid_rc::Rc<T> but I suspect it's a legit bug in the macro incorrectly ignoring the namespace part & just looking at Rc.

someguynamedjosh commented 4 months ago

That error only shows up if you specify covariance on the same field twice - I'm guessing it's erroneously thinking that hybrid_rc::Rc is std's Rc type (it likely ignores the path and just looks at the type name. Unfortunately macros have no access to semantic information like which exact type a path refers to; instead it works entirely on raw syntax) and concludes that it's covariant. It then sees your annotation and thinks the covariance has been specified twice. The solution to this would be to make a type alias like type HybridRc<T> = hybrid_rc::Rc<T>; and use that so the type name doesn't overlap with the type in std.