Fix marker trait winnowing depending on impl order#153847
Open
traviscross wants to merge 1 commit intorust-lang:mainfrom
Open
Fix marker trait winnowing depending on impl order#153847traviscross wants to merge 1 commit intorust-lang:mainfrom
traviscross wants to merge 1 commit intorust-lang:mainfrom
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
411054e to
85b6665
Compare
oli-obk
reviewed
Mar 14, 2026
Contributor
There was a problem hiding this comment.
Since this mentions the old solver, is there an equivalent next solver test that this one was derived from?
Either way, should probably run on both solvers
Contributor
Author
There was a problem hiding this comment.
None that I could find. I added the directives to test with both solvers.
The `TypeOutlives` handler in `evaluate_predicate_recursively` checks whether a type in a `T: 'a` predicate has free regions, bound regions, or inference variables -- and if so, returns `EvaluatedToOkModuloRegions` rather than `EvaluatedToOk`. The comment says "no free lifetimes or generic parameters", but the code checked `has_non_region_infer` twice instead of checking `has_non_region_param()`. This meant that `TypeOutlives(T, 'static)` where `T` is a type parameter returned `EvaluatedToOk` -- claiming the result holds unconditionally -- when the correct answer is `EvaluatedToOkModuloRegions`. The distinction matters during marker trait winnowing in `prefer_lhs_over_victim`, which uses `must_apply_considering_regions()` (true only for `EvaluatedToOk`) to decide whether one overlapping impl beats another. With the bug, a `T: 'static`-bounded impl appeared equally as strong as an unrestricted impl, making the winner depend on source order. This caused spurious E0310 errors when the more-constrained impl happened to appear after the less-constrained one. Fixes Rust issue 109481. This same symptom was originally filed as issue 84917 and fixed in PR 88139. Then PR 102472 rewrote the `TypeOutlives` handler, introducing the duplicate `has_non_region_infer()` and losing the param check, regressing this. Shortly after, issue 109481 was filed. It noted the connection to PR 102472 -- that it was only relevant after it -- but the duplicate condition was not noticed.
85b6665 to
516f56b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Story: I was looking through this code for an unrelated reason and happened to notice the duplicate condition. That seemed obviously wrong, especially in light of the comment, so I worked backward to what it affected, wrote a test that failed, and then found that the test matched an existing
known-bugtest, which pointed me to #109481.The
TypeOutliveshandler inevaluate_predicate_recursivelychecks whether a type in aT: 'apredicate has free regions, bound regions, or inference variables -- and if so, returnsEvaluatedToOkModuloRegionsrather thanEvaluatedToOk. The comment says "no free lifetimes or generic parameters", but the code checkedhas_non_region_infer()twice instead of checkinghas_non_region_param().This meant that
TypeOutlives(T, 'static)whereTis a type parameter returnedEvaluatedToOk-- claiming the result holds unconditionally -- when the correct answer isEvaluatedToOkModuloRegions.The distinction matters during marker trait winnowing in
prefer_lhs_over_victim, which usesmust_apply_considering_regions()(true only forEvaluatedToOk) to decide whether one overlapping impl beats another. With the bug, aT: 'static-bounded impl appeared equally as strong as an unrestricted impl, making the winner depend on source order. This caused spurious E0310 errors when the more-constrained impl happened to appear after the less-constrained one.Fixes #109481.
This same symptom was originally filed as #84917 and fixed in PR #88139. Then PR #102472 rewrote the
TypeOutliveshandler, introducing the duplicatehas_non_region_infer()and losing the param check, regressing this. Shortly after, #109481 was filed. It noted the connection to #102472 -- that it was only relevant after it -- but the duplicate condition was not noticed.r? @lcnr
cc @oli-obk @nikomatsakis