-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Check for unbounded recursion during dropck #22777
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
// except according to those terms. | ||
|
||
// Issue 22443: Reject code using non-regular types that would | ||
// otherwise cause dropck to loop infinitely. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the difference between this and the first test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the comment below says why. (The bug report observed different behaviors, both bad, depending on the order of Digit versus Box)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, I think it'd be helpful to write in the comment something like "In contrast to Digit after Box, which is the other test."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, will do
r+ modulo nit |
2369945
to
ed18e6b
Compare
(Note for rollup builders: I marked this as rollup, but do note that it adds a new error code, which increases its chances for collision with another PR that also adds the same error code, especially since the same error code might be added in a different file.) |
Check for unbounded recursion during dropck. Such recursion can be introduced by the erroneous use of non-regular types (aka types employing polymorphic recursion), which Rust does not support. Fix rust-lang#22443
This caused a slew of dropck overflows in the rollup. a sample:
|
Looks like they were caused during |
weird! Okay, I'll look into that. |
@bors r- |
@Manishearth wow, I totally failed to |
Hah. I don't think anyone expects rustc-stage2 from anything but large PRs. So, this PR needs rustc-stage2 to be tested properly? I don't envy your next few days 😬 (I had to do the same for |
@Manishearth no, now that I know about it, I can make a test applicable for the stage1 compiler (and put it into |
That sounds less painful 😃 |
Reduced test case: #![allow(non_camel_case_types)]
pub fn noop_fold_impl_item() -> SmallVector<ImplItem> {
loop { }
}
pub struct SmallVector<T>(P<T>);
pub struct ImplItem(P<S01_Method>);
struct P<T>(Box<T>);
struct S01_Method(P<S02_Generics>);
struct S02_Generics(P<S03_TyParam>);
struct S03_TyParam(P<S04_TyParamBound>);
struct S04_TyParamBound(S05_PolyTraitRef);
struct S05_PolyTraitRef(S06_TraitRef);
struct S06_TraitRef(S07_Path);
struct S07_Path(Vec<S08_PathSegment>);
struct S08_PathSegment(S09_PathParameters);
struct S09_PathParameters(P<S10_ParenthesizedParameterData>);
struct S10_ParenthesizedParameterData(Option<P<S11_Ty>>);
struct S11_Ty(P<S12_Expr>);
struct S12_Expr(P<S13_Block>);
struct S13_Block(Vec<P<S14_Stmt>>);
struct S14_Stmt(P<S15_Decl>);
struct S15_Decl(P<S16_Local>);
struct S16_Local(P<S17_Pat>);
struct S17_Pat(P<S18_Mac>);
struct S18_Mac(Vec<P<S19_TokenTree>>);
struct S19_TokenTree(P<S20_Token>);
struct S20_Token(P<S21_Nonterminal>);
struct S21_Nonterminal(P<S22_Item>);
struct S22_Item(P<S23_EnumDef>);
struct S23_EnumDef(Vec<P<S24_Variant>>);
struct S24_Variant(P<S25_VariantKind>);
struct S25_VariantKind(P<S26_StructDef>);
struct S26_StructDef(Vec<P<S27_StructField>>);
struct S27_StructField(P<S28_StructFieldKind>);
struct S28_StructFieldKind;
pub fn main() {} |
☔ The latest upstream changes (presumably #22895) made this pull request unmergeable. Please resolve the merge conflicts. |
So, after walking through the debug log, I see that a likely problem here is that I am incrementing the recursion counter even for the recursion that descends from BUT that kind of recursive descent is just standard traversal over the inductive structure of the type; i.e., it cannot lead to infinite loops. The only kind of traversal that can lead to infinite loops are those that go through references, i.e. cases like SO: For the short term, my plan is to keep a separate counter that is incremented only when the recursion traverses through an owning reference, as outlined above. For the long term, however, I am a little worried that such an approach does not scale up properly. I.e. one is still going to be able to make programs (probably real programs) that will exceed the threshold, and I am not convinced the solution of "just tell such crates to increase the value of the recursion counter" will be satisfying in practice. Instead of just using a fixed recursion limit, we may want to instead make the recursion threshold a function of the number of nodes in the AST, or some similar value that can be easily derived from the static text. E.g. we instead made the threshold where we signal an error be equal to Anyway, that's just a stray thought. For this PR, I'm certainly going to take the short-cut of just not increasing this counter so fast. |
hmm, my simplistic attempt to apply the strategy from the previous comment does not seem to actually catch the test from #22443 Update: ah, I somehow forgot that we still treat |
Count recursion across phantom data separately from all recursion, and treat `Box<T>` just as if it were carrying `PhantomData<T>`. (Regression tests are in followup commit.) The practical effect of this is just to increment the `xref_depth` counter, the same way that `Vec` and other types carrying `PhantomData` do.
@bors r=nikomatsakis |
(Note again for rollup builders: I marked this as rollup, but do note that it adds a new error code, which increases its chances for collision with another PR that also adds the same error code, especially since the same error code might be added in a different file. On the bright side, I did run |
Check for unbounded recursion during dropck. Such recursion can be introduced by the erroneous use of non-regular types (aka types employing polymorphic recursion), which Rust does not support. Fix rust-lang#22443
Check for unbounded recursion during dropck.
Such recursion can be introduced by the erroneous use of non-regular types (aka types employing polymorphic recursion), which Rust does not support.
Fix #22443