Skip to content

Commit f30522e

Browse files
authored
Unrolled build for rust-lang#127568
Rollup merge of rust-lang#127568 - lcnr:undo-leakcheck, r=oli-obk instantiate higher ranked goals in candidate selection again This reverts rust-lang#119820 as that PR has a significant impact and breaks code which *feels like it should work*. The impact ended up being larger than we expected during the FCP and we've ended up with some ideas for how we can work around this issue in the next solver. This has been discussed in the previous high bandwidth t-types meeting: https://rust-lang.zulipchat.com/#narrow/stream/326132-t-types.2Fmeetings/topic/2024-07-09.20high.20bandwidth.20meeting. We'll therefore keep this inconsistency between the two solvers for now and will have to deal with it before stabilizating the use of the new solver outside of coherence: rust-lang/trait-system-refactor-initiative#120. fixes rust-lang#125194 after a beta-backport. The pattern which is more widely used than expected and feels like it should work, especially without deep knowledge of the type system is ```rust trait Trait<'a> {} impl<'a, T> Trait<'a> for T {} fn trait_bound<T: for<'a> Trait<'a>>() {} // A function with a where-bound which is more restrictive than the impl. fn function1<T: Trait<'static>>() { // stable: ok // with rust-lang#119820: error as we prefer the where-bound over the impl // with this PR: back to ok trait_bound::<T>(); } ``` r? `@rust-lang/types`
2 parents b215beb + f77394f commit f30522e

21 files changed

+121
-299
lines changed

Diff for: compiler/rustc_trait_selection/src/traits/select/mod.rs

+12-54
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,6 @@ mod _match;
6464
mod candidate_assembly;
6565
mod confirmation;
6666

67-
/// Whether to consider the binder of higher ranked goals for the `leak_check` when
68-
/// evaluating higher-ranked goals. See #119820 for more info.
69-
///
70-
/// While this is a bit hacky, it is necessary to match the behavior of the new solver:
71-
/// We eagerly instantiate binders in the new solver, outside of candidate selection, so
72-
/// the leak check inside of candidates does not consider any bound vars from the higher
73-
/// ranked goal. However, we do exit the binder once we're completely finished with a goal,
74-
/// so the leak-check can be used in evaluate by causing nested higher-ranked goals to fail.
75-
#[derive(Debug, Copy, Clone)]
76-
enum LeakCheckHigherRankedGoal {
77-
No,
78-
Yes,
79-
}
80-
8167
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
8268
pub enum IntercrateAmbiguityCause<'tcx> {
8369
DownstreamCrate { trait_ref: ty::TraitRef<'tcx>, self_ty: Option<Ty<'tcx>> },
@@ -402,10 +388,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
402388
let mut no_candidates_apply = true;
403389

404390
for c in candidate_set.vec.iter() {
405-
if self
406-
.evaluate_candidate(stack, c, LeakCheckHigherRankedGoal::No)?
407-
.may_apply()
408-
{
391+
if self.evaluate_candidate(stack, c)?.may_apply() {
409392
no_candidates_apply = false;
410393
break;
411394
}
@@ -476,7 +459,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
476459
// is needed for specialization. Propagate overflow if it occurs.
477460
let mut candidates = candidates
478461
.into_iter()
479-
.map(|c| match self.evaluate_candidate(stack, &c, LeakCheckHigherRankedGoal::No) {
462+
.map(|c| match self.evaluate_candidate(stack, &c) {
480463
Ok(eval) if eval.may_apply() => {
481464
Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
482465
}
@@ -566,7 +549,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
566549
obligation: &PredicateObligation<'tcx>,
567550
) -> Result<EvaluationResult, OverflowError> {
568551
debug_assert!(!self.infcx.next_trait_solver());
569-
self.evaluation_probe(|this, _outer_universe| {
552+
self.evaluation_probe(|this| {
570553
let goal =
571554
this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
572555
let mut result = this.evaluate_predicate_recursively(
@@ -589,11 +572,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
589572
/// `op`, but this can be overwritten if necessary.
590573
fn evaluation_probe(
591574
&mut self,
592-
op: impl FnOnce(&mut Self, &mut ty::UniverseIndex) -> Result<EvaluationResult, OverflowError>,
575+
op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>,
593576
) -> Result<EvaluationResult, OverflowError> {
594577
self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
595-
let mut outer_universe = self.infcx.universe();
596-
let result = op(self, &mut outer_universe)?;
578+
let outer_universe = self.infcx.universe();
579+
let result = op(self)?;
597580

598581
match self.infcx.leak_check(outer_universe, Some(snapshot)) {
599582
Ok(()) => {}
@@ -1254,7 +1237,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12541237
}
12551238

12561239
match self.candidate_from_obligation(stack) {
1257-
Ok(Some(c)) => self.evaluate_candidate(stack, &c, LeakCheckHigherRankedGoal::Yes),
1240+
Ok(Some(c)) => self.evaluate_candidate(stack, &c),
12581241
Ok(None) => Ok(EvaluatedToAmbig),
12591242
Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
12601243
Err(..) => Ok(EvaluatedToErr),
@@ -1279,10 +1262,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12791262
/// Further evaluates `candidate` to decide whether all type parameters match and whether nested
12801263
/// obligations are met. Returns whether `candidate` remains viable after this further
12811264
/// scrutiny.
1282-
///
1283-
/// Depending on the value of [LeakCheckHigherRankedGoal], we may ignore the binder of the goal
1284-
/// when eagerly detecting higher ranked region errors via the `leak_check`. See that enum for
1285-
/// more info.
12861265
#[instrument(
12871266
level = "debug",
12881267
skip(self, stack),
@@ -1293,25 +1272,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12931272
&mut self,
12941273
stack: &TraitObligationStack<'o, 'tcx>,
12951274
candidate: &SelectionCandidate<'tcx>,
1296-
leak_check_higher_ranked_goal: LeakCheckHigherRankedGoal,
12971275
) -> Result<EvaluationResult, OverflowError> {
1298-
let mut result = self.evaluation_probe(|this, outer_universe| {
1299-
// We eagerly instantiate higher ranked goals to prevent universe errors
1300-
// from impacting candidate selection. This matches the behavior of the new
1301-
// solver. This slightly weakens type inference.
1302-
//
1303-
// In case there are no unresolved type or const variables this
1304-
// should still not be necessary to select a unique impl as any overlap
1305-
// relying on a universe error from higher ranked goals should have resulted
1306-
// in an overlap error in coherence.
1307-
let p = self.infcx.enter_forall_and_leak_universe(stack.obligation.predicate);
1308-
let obligation = stack.obligation.with(this.tcx(), ty::Binder::dummy(p));
1309-
match leak_check_higher_ranked_goal {
1310-
LeakCheckHigherRankedGoal::No => *outer_universe = self.infcx.universe(),
1311-
LeakCheckHigherRankedGoal::Yes => {}
1312-
}
1313-
1314-
match this.confirm_candidate(&obligation, candidate.clone()) {
1276+
let mut result = self.evaluation_probe(|this| {
1277+
match this.confirm_candidate(stack.obligation, candidate.clone()) {
13151278
Ok(selection) => {
13161279
debug!(?selection);
13171280
this.evaluate_predicates_recursively(
@@ -1731,19 +1694,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17311694
})
17321695
.map_err(|_| ())
17331696
}
1697+
17341698
fn where_clause_may_apply<'o>(
17351699
&mut self,
17361700
stack: &TraitObligationStack<'o, 'tcx>,
17371701
where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
17381702
) -> Result<EvaluationResult, OverflowError> {
1739-
self.evaluation_probe(|this, outer_universe| {
1740-
// Eagerly instantiate higher ranked goals.
1741-
//
1742-
// See the comment in `evaluate_candidate` to see why.
1743-
let p = self.infcx.enter_forall_and_leak_universe(stack.obligation.predicate);
1744-
let obligation = stack.obligation.with(this.tcx(), ty::Binder::dummy(p));
1745-
*outer_universe = self.infcx.universe();
1746-
match this.match_where_clause_trait_ref(&obligation, where_clause_trait_ref) {
1703+
self.evaluation_probe(|this| {
1704+
match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
17471705
Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations),
17481706
Err(()) => Ok(EvaluatedToErr),
17491707
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0277]: the trait bound `for<'a> &'a &T: Trait` is not satisfied
2+
--> $DIR/candidate-from-env-universe-err-1.rs:27:16
3+
|
4+
LL | hr_bound::<&T>();
5+
| ^^ the trait `for<'a> Trait` is not implemented for `&'a &T`
6+
|
7+
note: required by a bound in `hr_bound`
8+
--> $DIR/candidate-from-env-universe-err-1.rs:14:20
9+
|
10+
LL | fn hr_bound<T>()
11+
| -------- required by a bound in this function
12+
LL | where
13+
LL | for<'a> &'a T: Trait,
14+
| ^^^^^ required by this bound in `hr_bound`
15+
help: consider removing the leading `&`-reference
16+
|
17+
LL - hr_bound::<&T>();
18+
LL + hr_bound::<T>();
19+
|
20+
21+
error: aborting due to 1 previous error
22+
23+
For more information about this error, try `rustc --explain E0277`.

Diff for: tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
//@ revisions: old next
2+
//@[next] compile-flags: -Znext-solver
3+
//@[old] check-pass
4+
15
// cc #119820
26

37
trait Trait {}
@@ -21,8 +25,7 @@ where
2125
// the leak check both candidates may apply and we prefer the
2226
// `param_env` candidate in winnowing.
2327
hr_bound::<&T>();
24-
//~^ ERROR the parameter type `T` may not live long enough
25-
//~| ERROR implementation of `Trait` is not general enough
28+
//[next]~^ ERROR the trait bound `for<'a> &'a &T: Trait` is not satisfied
2629
}
2730

2831
fn main() {}

Diff for: tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.stderr

-26
This file was deleted.

Diff for: tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.current.stderr

-25
This file was deleted.

Diff for: tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0277]: the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied
2-
--> $DIR/candidate-from-env-universe-err-2.rs:14:5
2+
--> $DIR/candidate-from-env-universe-err-2.rs:15:5
33
|
44
LL | impl_hr::<T>();
55
| ^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a, '_>` is not implemented for `T`
66
|
77
note: required by a bound in `impl_hr`
8-
--> $DIR/candidate-from-env-universe-err-2.rs:11:19
8+
--> $DIR/candidate-from-env-universe-err-2.rs:12:19
99
|
1010
LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
1111
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impl_hr`

Diff for: tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.old.stderr

-26
This file was deleted.

Diff for: tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//@ revisions: current next
22
//@[next] compile-flags: -Znext-solver
3+
//@[current] check-pass
34

45
// cc #119820
56

@@ -13,8 +14,6 @@ fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
1314
fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() {
1415
impl_hr::<T>();
1516
//[next]~^ ERROR the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied
16-
//[current]~^^ERROR lifetime may not live long enough
17-
//[current]~| ERROR implementation of `Trait` is not general enough
1817
}
1918

2019
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,5 @@
1-
error: implementation of `Trait` is not general enough
2-
--> $DIR/candidate-from-env-universe-err-project.rs:28:5
3-
|
4-
LL | trait_bound::<T>();
5-
| ^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
6-
|
7-
= note: `T` must implement `Trait<'0>`, for any lifetime `'0`...
8-
= note: ...but it actually implements `Trait<'static>`
9-
10-
error: implementation of `Trait` is not general enough
11-
--> $DIR/candidate-from-env-universe-err-project.rs:39:5
12-
|
13-
LL | projection_bound::<T>();
14-
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
15-
|
16-
= note: `T` must implement `Trait<'0>`, for any lifetime `'0`...
17-
= note: ...but it actually implements `Trait<'static>`
18-
191
error[E0308]: mismatched types
20-
--> $DIR/candidate-from-env-universe-err-project.rs:39:5
2+
--> $DIR/candidate-from-env-universe-err-project.rs:38:5
213
|
224
LL | projection_bound::<T>();
235
| ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
@@ -31,7 +13,7 @@ LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
3113
| ^^^^^^^^^^^^^
3214

3315
error[E0308]: mismatched types
34-
--> $DIR/candidate-from-env-universe-err-project.rs:55:30
16+
--> $DIR/candidate-from-env-universe-err-project.rs:53:30
3517
|
3618
LL | let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
3719
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
@@ -40,7 +22,7 @@ LL | let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
4022
found associated type `<T as Trait<'a>>::Assoc`
4123

4224
error[E0308]: mismatched types
43-
--> $DIR/candidate-from-env-universe-err-project.rs:55:30
25+
--> $DIR/candidate-from-env-universe-err-project.rs:53:30
4426
|
4527
LL | let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
4628
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
@@ -49,6 +31,6 @@ LL | let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
4931
found associated type `<T as Trait<'a>>::Assoc`
5032
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
5133

52-
error: aborting due to 5 previous errors
34+
error: aborting due to 3 previous errors
5335

5436
For more information about this error, try `rustc --explain E0308`.

Diff for: tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | fn function1<T: Trait<'static> + for<'a> Trait<'a>>() {
1515
| +++++++++++++++++++
1616

1717
error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied
18-
--> $DIR/candidate-from-env-universe-err-project.rs:39:24
18+
--> $DIR/candidate-from-env-universe-err-project.rs:38:24
1919
|
2020
LL | projection_bound::<T>();
2121
| ^ the trait `for<'a> Trait<'a>` is not implemented for `T`
@@ -31,7 +31,7 @@ LL | fn function2<T: Trait<'static, Assoc = usize> + for<'a> Trait<'a>>() {
3131
| +++++++++++++++++++
3232

3333
error[E0271]: type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
34-
--> $DIR/candidate-from-env-universe-err-project.rs:39:24
34+
--> $DIR/candidate-from-env-universe-err-project.rs:38:24
3535
|
3636
LL | projection_bound::<T>();
3737
| ^ type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
@@ -48,13 +48,13 @@ LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
4848
| ^^^^^^^^^^^^^ required by this bound in `projection_bound`
4949

5050
error: higher-ranked subtype error
51-
--> $DIR/candidate-from-env-universe-err-project.rs:55:30
51+
--> $DIR/candidate-from-env-universe-err-project.rs:53:30
5252
|
5353
LL | let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
5454
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5555

5656
error: higher-ranked subtype error
57-
--> $DIR/candidate-from-env-universe-err-project.rs:55:30
57+
--> $DIR/candidate-from-env-universe-err-project.rs:53:30
5858
|
5959
LL | let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
6060
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)