-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rustdoc recursion limit issue #62059
Comments
Just to make sure you are adding the recursion limit attribute to the |
We do not directly use the synstructure crate directly ourselves. It is listed as a dependency of Therefore we do not directly add it to the |
Minimal [package]
name = "a"
version = "0.1.0"
[dependencies]
synstructure = "0.10"
syn = { version = "0.15", features = ["full"] } Adding fn assert_unpin<T: std::marker::Unpin>() {}
pub fn foo() {
assert_unpin::<Vec<syn::GenericParam>>();
} which only needs the attribute in the crate which actually contains this code (i.e. it does not necessarily infect the dependent crates). This is, sadly a deeper issue and the change in #60293 only happens to expose it. Any ideas what we could do here to remove/propagate/etc this limit when documenting cc @rust-lang/compiler? cc @dtolnay you may want to be aware about |
Thanks @nagisa. Is there anything I can do about this on my end? The trace in the error looks correct to me; this is a consequence of almost all Rust syntax being allowed inside of almost all other Rust syntax.
|
@dtolnay Other than reducing the depth of types somehow, there’s very little that can be done on your side. You could manually implement all the marker types for certain types, but the same issue will resurface for new/external auto-traits. |
Does this warrant increasing the default recursion limit? I would expect the default to be selected such that it is higher than what you would need in any "reasonable" real world code. If the data structures in Syn are "reasonable" i.e. neither contrived nor somehow unsolvable regardless of recursion limit, then this suggests that the current limit is too aggressive. What are the implications of changing it? |
This also affected fuzzy-pickles but there were some fixes that seemed to help there. Wonder why the difference. |
@nagisa, are you saying that the expected fix is to go through the ecosystem and add |
cc #61960, which tracks the instances where #60444 has hit an overflow during recursive trait constraint resolution. (Also, I am assuming that this issue (#62059) is not resolved by PR #61754, but it would be good to double-check that assumption.) @SimonSapin asked
my hope is that many of the cases affected by PR #60444 will be addressed by PR #61754, which we recently approved for beta backport so that it lands in time for the release. |
@SimonSapin I will probably just revert the patch to rustdoc if there is no other option than annotating crates with an attribute. rustdoc’s case is special in that it infects dependent crates much more easily and having such an attribute in a large number of crates is not a tenable solution. Ideally rustc/rustdoc would work for arbitrarily deep types, but I can see raising the default limit as a good stop-gap as well. |
@pnkfelix at this point I doubt either of #60444 or #61754 are very related as the type-stack here seems to be very linear. Nominating for a short section of time in the meeting to discuss the best way to proceed here. The non-involved solutions I know at the moment are:
Will see if raising the limit is something that we could or should do and perhaps whether there are other options that I have missed. |
pre-triage: P-high. Leaving nominated in hopes we discuss it today. Leaving unassigned to reflect reality that I don't think I can take this on myself. (But maybe @nagisa can take point on ensuring this gets resolved in short order...?) |
discussed at compiler team meeting. @eddyb raised the idea that In any case, based on assumption that this is indeed a stable-to-nightly regression, I think we have a little bit of breathing room to figure out how we want to address this long term. Assigning to @nagisa to take point on resolving this, potentially via delegation. (@nagisa , let me know if that does not work for you.) |
This is blocking the upgrade of rustc in Servo. (And I get nagged about it every day by the corresponding CI job failing.) @rust-lang/compiler Is anyone working on a revert or other fix, or should I go add recursion_limit to synstructure and other crates as needed? |
I’m looking into this and investigating the feasibility of implementing @eddyb’s idea or some other fix. Alas, I only have sufficiently long uninterrupted chunks of time on the weekends, so the progress is slow and is very plausible that this won’t be fixed within a few days. |
triage: assigning to @nagisa and myself for follow-up. |
@SimonSapin do you have any estimate of how many crates would require the recursion_limit addition? |
There is one that we know of in Servo’s dependency graph ( |
For the purposes of rustdoc, you’ll need to add attribute not only for the |
By running |
See rust-lang/rust#62132 and rust-lang/rust#62059 The fix in rustdoc is at the “investigating the feasibility” stage, and this is preventing Servo from upgrading its Rust toolchain.
See rust-lang/rust#62132 and rust-lang/rust#62059 The fix in rustdoc is at the “investigating the feasibility” stage, and this is preventing Servo from upgrading its Rust toolchain.
In current Nightly, `cargo doc` fails with the error message below. The fix in rustdoc is at the “investigating the feasibility” stage. See rust-lang/rust#62132 and rust-lang/rust#62059 ``` error[E0275]: overflow evaluating the requirement `proc_macro2::Group: std::marker::Unpin` | = help: consider adding a `#![recursion_limit="128"]` attribute to your crate = note: required because it appears within the type `proc_macro2::TokenTree` = note: required because it appears within the type `*const proc_macro2::TokenTree` = note: required because it appears within the type `std::ptr::Unique<proc_macro2::TokenTree>` = note: required because it appears within the type `alloc::raw_vec::RawVec<proc_macro2::TokenTree>` = note: required because it appears within the type `std::vec::Vec<proc_macro2::TokenTree>` = note: required because it appears within the type `proc_macro2::fallback::TokenStream` = note: required because it appears within the type `proc_macro2::imp::TokenStream` = note: required because it appears within the type `proc_macro2::TokenStream` = note: required because it appears within the type `syn::Macro` = note: required because it appears within the type `syn::PatMacro` = note: required because it appears within the type `syn::Pat` = note: required because it appears within the type `(syn::Pat, syn::token::Or)` = note: required because it appears within the type `*const (syn::Pat, syn::token::Or)` = note: required because it appears within the type `std::ptr::Unique<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `std::vec::Vec<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::Pat, syn::token::Or>` = note: required because it appears within the type `syn::ExprLet` = note: required because it appears within the type `syn::Expr` = note: required because it appears within the type `syn::TypeArray` = note: required because it appears within the type `syn::Type` = note: required because it appears within the type `syn::GenericArgument` = note: required because it appears within the type `(syn::GenericArgument, syn::token::Comma)` = note: required because it appears within the type `*const (syn::GenericArgument, syn::token::Comma)` = note: required because it appears within the type `std::ptr::Unique<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `std::vec::Vec<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::GenericArgument, syn::token::Comma>` = note: required because it appears within the type `syn::AngleBracketedGenericArguments` = note: required because it appears within the type `syn::PathArguments` = note: required because it appears within the type `syn::PathSegment` = note: required because it appears within the type `(syn::PathSegment, syn::token::Colon2)` = note: required because it appears within the type `*const (syn::PathSegment, syn::token::Colon2)` = note: required because it appears within the type `std::ptr::Unique<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `std::vec::Vec<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::PathSegment, syn::token::Colon2>` = note: required because it appears within the type `syn::Path` = note: required because it appears within the type `syn::Attribute` = note: required because it appears within the type `*const syn::Attribute` = note: required because it appears within the type `std::ptr::Unique<syn::Attribute>` = note: required because it appears within the type `alloc::raw_vec::RawVec<syn::Attribute>` = note: required because it appears within the type `std::vec::Vec<syn::Attribute>` = note: required because it appears within the type `syn::LifetimeDef` = note: required because it appears within the type `(syn::LifetimeDef, syn::token::Comma)` = note: required because it appears within the type `*const (syn::LifetimeDef, syn::token::Comma)` = note: required because it appears within the type `std::ptr::Unique<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `std::vec::Vec<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::LifetimeDef, syn::token::Comma>` = note: required because it appears within the type `syn::BoundLifetimes` = note: required because it appears within the type `std::option::Option<syn::BoundLifetimes>` = note: required because it appears within the type `syn::PredicateType` = note: required because it appears within the type `syn::WherePredicate` = note: required because it appears within the type `*const syn::WherePredicate` = note: required because it appears within the type `std::ptr::Unique<syn::WherePredicate>` = note: required because it appears within the type `alloc::raw_vec::RawVec<syn::WherePredicate>` = note: required because it appears within the type `std::vec::Vec<syn::WherePredicate>` = note: required because it appears within the type `std::option::Option<std::vec::Vec<syn::WherePredicate>>` = note: required because it appears within the type `attr::InputClone` = note: required because it appears within the type `std::option::Option<attr::InputClone>` = note: required because it appears within the type `attr::Input` = note: required because it appears within the type `ast::Input<'a>` error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. error: Could not document `derivative`. ```
In current Nightly, `cargo doc` fails with the error message below. The fix in rustdoc is at the “investigating the feasibility” stage. See rust-lang/rust#62132 and rust-lang/rust#62059 ```rust error[E0275]: overflow evaluating the requirement `proc_macro2::Group: std::marker::Unpin` | = help: consider adding a `#![recursion_limit="128"]` attribute to your crate = note: required because it appears within the type `proc_macro2::TokenTree` = note: required because it appears within the type `*const proc_macro2::TokenTree` = note: required because it appears within the type `std::ptr::Unique<proc_macro2::TokenTree>` = note: required because it appears within the type `alloc::raw_vec::RawVec<proc_macro2::TokenTree>` = note: required because it appears within the type `std::vec::Vec<proc_macro2::TokenTree>` = note: required because it appears within the type `proc_macro2::fallback::TokenStream` = note: required because it appears within the type `proc_macro2::imp::TokenStream` = note: required because it appears within the type `proc_macro2::TokenStream` = note: required because it appears within the type `syn::Macro` = note: required because it appears within the type `syn::PatMacro` = note: required because it appears within the type `syn::Pat` = note: required because it appears within the type `(syn::Pat, syn::token::Or)` = note: required because it appears within the type `*const (syn::Pat, syn::token::Or)` = note: required because it appears within the type `std::ptr::Unique<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `std::vec::Vec<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::Pat, syn::token::Or>` = note: required because it appears within the type `syn::ExprLet` = note: required because it appears within the type `syn::Expr` = note: required because it appears within the type `syn::TypeArray` = note: required because it appears within the type `syn::Type` = note: required because it appears within the type `syn::GenericArgument` = note: required because it appears within the type `(syn::GenericArgument, syn::token::Comma)` = note: required because it appears within the type `*const (syn::GenericArgument, syn::token::Comma)` = note: required because it appears within the type `std::ptr::Unique<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `std::vec::Vec<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::GenericArgument, syn::token::Comma>` = note: required because it appears within the type `syn::AngleBracketedGenericArguments` = note: required because it appears within the type `syn::PathArguments` = note: required because it appears within the type `syn::PathSegment` = note: required because it appears within the type `(syn::PathSegment, syn::token::Colon2)` = note: required because it appears within the type `*const (syn::PathSegment, syn::token::Colon2)` = note: required because it appears within the type `std::ptr::Unique<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `std::vec::Vec<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::PathSegment, syn::token::Colon2>` = note: required because it appears within the type `syn::Path` = note: required because it appears within the type `syn::Attribute` = note: required because it appears within the type `*const syn::Attribute` = note: required because it appears within the type `std::ptr::Unique<syn::Attribute>` = note: required because it appears within the type `alloc::raw_vec::RawVec<syn::Attribute>` = note: required because it appears within the type `std::vec::Vec<syn::Attribute>` = note: required because it appears within the type `syn::LifetimeDef` = note: required because it appears within the type `(syn::LifetimeDef, syn::token::Comma)` = note: required because it appears within the type `*const (syn::LifetimeDef, syn::token::Comma)` = note: required because it appears within the type `std::ptr::Unique<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `std::vec::Vec<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::LifetimeDef, syn::token::Comma>` = note: required because it appears within the type `syn::BoundLifetimes` = note: required because it appears within the type `std::option::Option<syn::BoundLifetimes>` = note: required because it appears within the type `syn::PredicateType` = note: required because it appears within the type `syn::WherePredicate` = note: required because it appears within the type `*const syn::WherePredicate` = note: required because it appears within the type `std::ptr::Unique<syn::WherePredicate>` = note: required because it appears within the type `alloc::raw_vec::RawVec<syn::WherePredicate>` = note: required because it appears within the type `std::vec::Vec<syn::WherePredicate>` = note: required because it appears within the type `std::option::Option<std::vec::Vec<syn::WherePredicate>>` = note: required because it appears within the type `attr::InputClone` = note: required because it appears within the type `std::option::Option<attr::InputClone>` = note: required because it appears within the type `attr::Input` = note: required because it appears within the type `ast::Input<'a>` error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. error: Could not document `derivative`. ```
In current Nightly, `cargo doc` fails with the error message below. The fix in rustdoc is at the “investigating the feasibility” stage. See rust-lang/rust#62132 and rust-lang/rust#62059 ```rust error[E0275]: overflow evaluating the requirement `proc_macro2::Group: std::marker::Unpin` | = help: consider adding a `#![recursion_limit="128"]` attribute to your crate = note: required because it appears within the type `proc_macro2::TokenTree` = note: required because it appears within the type `*const proc_macro2::TokenTree` = note: required because it appears within the type `std::ptr::Unique<proc_macro2::TokenTree>` = note: required because it appears within the type `alloc::raw_vec::RawVec<proc_macro2::TokenTree>` = note: required because it appears within the type `std::vec::Vec<proc_macro2::TokenTree>` = note: required because it appears within the type `proc_macro2::fallback::TokenStream` = note: required because it appears within the type `proc_macro2::imp::TokenStream` = note: required because it appears within the type `proc_macro2::TokenStream` = note: required because it appears within the type `syn::Macro` = note: required because it appears within the type `syn::PatMacro` = note: required because it appears within the type `syn::Pat` = note: required because it appears within the type `(syn::Pat, syn::token::Or)` = note: required because it appears within the type `*const (syn::Pat, syn::token::Or)` = note: required because it appears within the type `std::ptr::Unique<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `std::vec::Vec<(syn::Pat, syn::token::Or)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::Pat, syn::token::Or>` = note: required because it appears within the type `syn::ExprLet` = note: required because it appears within the type `syn::Expr` = note: required because it appears within the type `syn::TypeArray` = note: required because it appears within the type `syn::Type` = note: required because it appears within the type `syn::GenericArgument` = note: required because it appears within the type `(syn::GenericArgument, syn::token::Comma)` = note: required because it appears within the type `*const (syn::GenericArgument, syn::token::Comma)` = note: required because it appears within the type `std::ptr::Unique<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `std::vec::Vec<(syn::GenericArgument, syn::token::Comma)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::GenericArgument, syn::token::Comma>` = note: required because it appears within the type `syn::AngleBracketedGenericArguments` = note: required because it appears within the type `syn::PathArguments` = note: required because it appears within the type `syn::PathSegment` = note: required because it appears within the type `(syn::PathSegment, syn::token::Colon2)` = note: required because it appears within the type `*const (syn::PathSegment, syn::token::Colon2)` = note: required because it appears within the type `std::ptr::Unique<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `std::vec::Vec<(syn::PathSegment, syn::token::Colon2)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::PathSegment, syn::token::Colon2>` = note: required because it appears within the type `syn::Path` = note: required because it appears within the type `syn::Attribute` = note: required because it appears within the type `*const syn::Attribute` = note: required because it appears within the type `std::ptr::Unique<syn::Attribute>` = note: required because it appears within the type `alloc::raw_vec::RawVec<syn::Attribute>` = note: required because it appears within the type `std::vec::Vec<syn::Attribute>` = note: required because it appears within the type `syn::LifetimeDef` = note: required because it appears within the type `(syn::LifetimeDef, syn::token::Comma)` = note: required because it appears within the type `*const (syn::LifetimeDef, syn::token::Comma)` = note: required because it appears within the type `std::ptr::Unique<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `alloc::raw_vec::RawVec<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `std::vec::Vec<(syn::LifetimeDef, syn::token::Comma)>` = note: required because it appears within the type `syn::punctuated::Punctuated<syn::LifetimeDef, syn::token::Comma>` = note: required because it appears within the type `syn::BoundLifetimes` = note: required because it appears within the type `std::option::Option<syn::BoundLifetimes>` = note: required because it appears within the type `syn::PredicateType` = note: required because it appears within the type `syn::WherePredicate` = note: required because it appears within the type `*const syn::WherePredicate` = note: required because it appears within the type `std::ptr::Unique<syn::WherePredicate>` = note: required because it appears within the type `alloc::raw_vec::RawVec<syn::WherePredicate>` = note: required because it appears within the type `std::vec::Vec<syn::WherePredicate>` = note: required because it appears within the type `std::option::Option<std::vec::Vec<syn::WherePredicate>>` = note: required because it appears within the type `attr::InputClone` = note: required because it appears within the type `std::option::Option<attr::InputClone>` = note: required because it appears within the type `attr::Input` = note: required because it appears within the type `ast::Input<'a>` error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. error: Could not document `derivative`. ```
I've just bumped into this issue when trying to build glutin's docs.
Hoping this gets raised. |
Raise the default recursion limit to 128 The previous limit of 64 is being (just) barely hit by genuine code out there, which is causing issues like rust-lang#62059 to rear their end. Ideally, we wouldn’t have such arbitrary limits at all, but while we do, it makes a lot of sense to just raise this limit whenever genuine use-cases end up hitting it. r? @pnkfelix Fixes rust-lang#62059
Raise the default recursion limit to 128 The previous limit of 64 is being (just) barely hit by genuine code out there, which is causing issues like rust-lang#62059 to rear their end. Ideally, we wouldn’t have such arbitrary limits at all, but while we do, it makes a lot of sense to just raise this limit whenever genuine use-cases end up hitting it. r? @pnkfelix Fixes rust-lang#62059
Today we ran into a weird issue while generating the rustdoc page for our project. As you can see here we run into a recursion limit issue. However increasing the recursion limit (
#![recursion_limit = "4096"]
) does not resolve it.It worked on version
1.37.0-nightly-2019-06-21
but breaks on1.37.0-nightly-2019-06-22
Any help would be appreciated.
Edit:
For reference as to how we got this error, here is our repo.
The text was updated successfully, but these errors were encountered: