Skip to content

Commit f77394f

Browse files
committed
instantiate higher ranked goals in candidate selection
reverts #119820
1 parent 0fdfb61 commit f77394f

21 files changed

+121
-299
lines changed

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`.

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() {}

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

-26
This file was deleted.

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

-25
This file was deleted.

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`

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

-26
This file was deleted.

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`.

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)