Skip to content

Commit 516f56b

Browse files
committed
Fix marker trait winnowing depending on impl order
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.
1 parent a0e206b commit 516f56b

File tree

3 files changed

+9
-25
lines changed

3 files changed

+9
-25
lines changed

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
750750
if pred.0.has_free_regions()
751751
|| pred.0.has_bound_regions()
752752
|| pred.0.has_non_region_infer()
753-
|| pred.0.has_non_region_infer()
753+
|| pred.0.has_non_region_param()
754754
{
755755
Ok(EvaluatedToOkModuloRegions)
756756
} else {

tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
//@ known-bug: #109481
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
25
//
3-
// While the `T: Copy` is always applicable when checking
4-
// that the impl `impl<T: Copy> F for T {}` is well formed,
5-
// the old trait solver can only approximate this by checking
6-
// that there are no inference variables in the obligation and
7-
// no region constraints in the evaluation result.
6+
// Regression test for #109481 and #84917.
87
//
9-
// Because of this we end up with ambiguity here.
8+
// Overlapping marker trait impls where one has a `T: 'static` bound
9+
// should be accepted. A bug previously made marker trait winnowing
10+
// order-dependent, producing a spurious E0310 here.
1011
#![feature(marker_trait_attr)]
1112

1213
#[marker]

tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)