Skip to content
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

mir: adjust conditional in recursion limit check #72540

Merged

Conversation

davidtwco
Copy link
Member

@davidtwco davidtwco commented May 24, 2020

Fixes #67552.

This PR adjusts the condition used in the recursion limit check of
the monomorphization collector, from > to >=.

In #67552, the test case had infinite indirect recursion, repeating a
handful of functions (from the perspective of the monomorphization
collector): rec -> identity -> Iterator::count -> Iterator::fold
-> Iterator::next -> rec.

During this process, resolve_associated_item was invoked for
Iterator::fold (during the construction of an Instance), and
ICE'd due to substitutions needing inference. However, previous
iterations of this recursion would have called this function for
Iterator::fold - and did! - and succeeded in doing so (trivially
checkable from debug logging, () is present where _ is in the substs
of the failing execution).

The expected outcome of this test case would be a recursion limit error
(which is present when the identity fn indirection is removed), and
the recursion depth of rec is increasing (other functions finish
collecting their neighbours and thus have their recursion depths reset).

When the ICE occurs, the recursion depth of rec is 256 (which matches
the recursion limit), which suggests perhaps that a different part of
the compiler is using a >= comparison and returning a different result
on this recursion rather than what it returned in every previous
recursion, thus stopping the monomorphization collector from reporting
an error on the next recursion, where recursion_depth_of_rec > 256
would have been true.

With grep and some educated guesses, we can determine that
the recursion limit check at line 818 in
src/librustc_trait_selection/traits/project.rs is the other check that
is using a different comparison. Modifying either comparison to be > or
>= respectively will fix the error, but changing the monomorphization
collector produces the nicer error.

@rust-highfive
Copy link
Collaborator

r? @varkor

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 24, 2020
@davidtwco davidtwco force-pushed the issue-67552-mono-collector-comparison branch from 6a06e4c to 70b944b Compare May 24, 2020 15:40
@varkor
Copy link
Member

varkor commented May 24, 2020

It seems this inconsistency is found in more places throughout the compiler, e.g. in these two locations
https://github.com/rust-lang/rust/blob/a59264b01247836c70e24217e0d346b868387525/src/librustc_ty/needs_drop.rs#L70-L72
https://github.com/rust-lang/rust/blob/a59264b01247836c70e24217e0d346b868387525/src/librustc_mir/interpret/eval_context.rs#L635-L637
These should probably be fixed at the same time. Also, this behaviour should be documented, e.g. in https://doc.rust-lang.org/reference/attributes/limits.html (though for now, we could just open an issue). It would be good to make sure the other limit attributes behave similarly.

Do you think you could audit these limits and add a comment somewhere appropriate mentioning this?

@Mark-Simulacrum
Copy link
Member

It seems reasonable to add a struct somewhere with check and increment methods that would store recursion limits and be used throughout the compiler, to hopefully prevent this from happening again.

@davidtwco
Copy link
Member Author

davidtwco commented May 26, 2020

I've added a commit with a Limit type, based on @Mark-Simulacrum's suggestion. I chose to make the comparison value <= limit, as while this did result in a larger diff, it behaved more like I would expect - in the macro expansion recursion limit tests, a limit of four would show four "in expansion of" lines - which matched my expectations. I'll submit an issue to the reference shortly. I've submitted rust-lang/reference#820.

@rust-highfive

This comment has been minimized.

@davidtwco davidtwco force-pushed the issue-67552-mono-collector-comparison branch from 126e7b9 to cac732b Compare May 26, 2020 21:13
Copy link
Member

@varkor varkor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. r=me with the name change, or similar.

This commit adjusts the condition used in the recursion limit check of
the monomorphization collector, from `>` to `>=`.

In rust-lang#67552, the test case had infinite indirect recursion, repeating a
handful of functions (from the perspective of the monomorphization
collector): `rec` -> `identity` -> `Iterator::count` -> `Iterator::fold`
-> `Iterator::next` -> `rec`.

During this process, `resolve_associated_item` was invoked for
`Iterator::fold` (during the construction of an `Instance`), and
ICE'd due to substitutions needing inference. However, previous
iterations of this recursion would have called this function for
`Iterator::fold` - and did! - and succeeded in doing so (trivially
checkable from debug logging, `()` is present where `_` is in the substs
of the failing execution).

The expected outcome of this test case would be a recursion limit error
(which is present when the `identity` fn indirection is removed), and
the recursion depth of `rec` is increasing (other functions finish
collecting their neighbours and thus have their recursion depths reset).

When the ICE occurs, the recursion depth of `rec` is 256 (which matches
the recursion limit), which suggests perhaps that a different part of
the compiler is using a `>=` comparison and returning a different result
on this recursion rather than what it returned in every previous
recursion, thus stopping the monomorphization collector from reporting
an error on the next recursion, where `recursion_depth_of_rec > 256`
would have been true.

With grep and some educated guesses, we can determine that
the recursion limit check at line 818 in
`src/librustc_trait_selection/traits/project.rs` is the other check that
is using a different comparison. Modifying either comparison to be `>` or
`>=` respectively will fix the error, but changing the monomorphization
collector produces the nicer error.

Signed-off-by: David Wood <david@davidtw.co>
This commit introduces a `Limit` type which is used to ensure that all
comparisons against limits within the compiler are consistent (which can
result in ICEs if they aren't).

Signed-off-by: David Wood <david@davidtw.co>
@davidtwco davidtwco force-pushed the issue-67552-mono-collector-comparison branch from cac732b to a54ed87 Compare May 28, 2020 09:50
@davidtwco
Copy link
Member Author

@bors r=varkor

@bors
Copy link
Contributor

bors commented May 28, 2020

📌 Commit a54ed87 has been approved by varkor

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 28, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request May 30, 2020
Rollup of 9 pull requests

Successful merges:

 - rust-lang#72299 (more `LocalDefId`s)
 - rust-lang#72368 (Resolve overflow behavior for RangeFrom)
 - rust-lang#72441 (Fix ICE with explicit late-bound lifetimes)
 - rust-lang#72499 (Override Box::<[T]>::clone_from)
 - rust-lang#72521 (Properly handle InlineAsmOperand::SymFn when collecting monomorphized items)
 - rust-lang#72540 (mir: adjust conditional in recursion limit check)
 - rust-lang#72563 (multiple Return terminators are possible)
 - rust-lang#72585 (Only capture tokens for items with outer attributes)
 - rust-lang#72607 (Eagerly lower asm sub-expressions to HIR even if there is an error)

Failed merges:

r? @ghost
@bors bors merged commit f96e3e2 into rust-lang:master May 30, 2020
@davidtwco davidtwco deleted the issue-67552-mono-collector-comparison branch June 25, 2020 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ICE] with recursive impl trait and Iterator.by_ref()
5 participants