@@ -419,7 +419,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
419
419
let mut no_candidates_apply = true ;
420
420
421
421
for c in candidate_set. vec . iter ( ) {
422
- if self . evaluate_candidate ( stack, c) ?. may_apply ( ) {
422
+ if self . evaluate_candidate ( stack, c, false ) ?. may_apply ( ) {
423
423
no_candidates_apply = false ;
424
424
break ;
425
425
}
@@ -490,7 +490,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
490
490
// is needed for specialization. Propagate overflow if it occurs.
491
491
let mut candidates = candidates
492
492
. into_iter ( )
493
- . map ( |c| match self . evaluate_candidate ( stack, & c) {
493
+ . map ( |c| match self . evaluate_candidate ( stack, & c, false ) {
494
494
Ok ( eval) if eval. may_apply ( ) => {
495
495
Ok ( Some ( EvaluatedCandidate { candidate : c, evaluation : eval } ) )
496
496
}
@@ -580,7 +580,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
580
580
obligation : & PredicateObligation < ' tcx > ,
581
581
) -> Result < EvaluationResult , OverflowError > {
582
582
debug_assert ! ( !self . infcx. next_trait_solver( ) ) ;
583
- self . evaluation_probe ( |this| {
583
+ self . evaluation_probe ( |this, _outer_universe | {
584
584
let goal =
585
585
this. infcx . resolve_vars_if_possible ( ( obligation. predicate , obligation. param_env ) ) ;
586
586
let mut result = this. evaluate_predicate_recursively (
@@ -596,13 +596,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
596
596
} )
597
597
}
598
598
599
+ /// Computes the evaluation result of `op`, discarding any constraints.
600
+ ///
601
+ /// This also runs for leak check to allow higher ranked region errors to impact
602
+ /// selection. By default it checks for leaks from all universes created inside of
603
+ /// `op`, but this can be overwritten if necessary.
599
604
fn evaluation_probe (
600
605
& mut self ,
601
- op : impl FnOnce ( & mut Self ) -> Result < EvaluationResult , OverflowError > ,
606
+ op : impl FnOnce ( & mut Self , & mut ty :: UniverseIndex ) -> Result < EvaluationResult , OverflowError > ,
602
607
) -> Result < EvaluationResult , OverflowError > {
603
608
self . infcx . probe ( |snapshot| -> Result < EvaluationResult , OverflowError > {
604
- let outer_universe = self . infcx . universe ( ) ;
605
- let result = op ( self ) ?;
609
+ let mut outer_universe = self . infcx . universe ( ) ;
610
+ let result = op ( self , & mut outer_universe ) ?;
606
611
607
612
match self . infcx . leak_check ( outer_universe, Some ( snapshot) ) {
608
613
Ok ( ( ) ) => { }
@@ -1229,7 +1234,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1229
1234
}
1230
1235
1231
1236
match self . candidate_from_obligation ( stack) {
1232
- Ok ( Some ( c) ) => self . evaluate_candidate ( stack, & c) ,
1237
+ Ok ( Some ( c) ) => self . evaluate_candidate ( stack, & c, true ) ,
1233
1238
Ok ( None ) => Ok ( EvaluatedToAmbig ) ,
1234
1239
Err ( Overflow ( OverflowError :: Canonical ) ) => Err ( OverflowError :: Canonical ) ,
1235
1240
Err ( ..) => Ok ( EvaluatedToErr ) ,
@@ -1264,10 +1269,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1264
1269
& mut self ,
1265
1270
stack : & TraitObligationStack < ' o , ' tcx > ,
1266
1271
candidate : & SelectionCandidate < ' tcx > ,
1272
+ leak_check_higher_ranked_goal : bool ,
1267
1273
) -> Result < EvaluationResult , OverflowError > {
1268
- let mut result = self . evaluation_probe ( |this| {
1269
- let candidate = ( * candidate) . clone ( ) ;
1270
- match this. confirm_candidate ( stack. obligation , candidate) {
1274
+ let mut result = self . evaluation_probe ( |this, outer_universe| {
1275
+ // We eagerly instantiate higher ranked goals to prevent universe errors
1276
+ // from impacting candidate selection. This matches the behavior of the new
1277
+ // solver. This slightly weakens type inference.
1278
+ //
1279
+ // In case there are no unresolved type or const variables this
1280
+ // should still not be necessary to select a unique impl as any overlap
1281
+ // relying on a universe error from higher ranked goals should have resulted
1282
+ // in an overlap error in coherence.
1283
+ let p = self . infcx . instantiate_binder_with_placeholders ( stack. obligation . predicate ) ;
1284
+ let obligation = stack. obligation . with ( this. tcx ( ) , ty:: Binder :: dummy ( p) ) ;
1285
+ if !leak_check_higher_ranked_goal {
1286
+ * outer_universe = self . infcx . universe ( ) ;
1287
+ }
1288
+ match this. confirm_candidate ( & obligation, candidate. clone ( ) ) {
1271
1289
Ok ( selection) => {
1272
1290
debug ! ( ?selection) ;
1273
1291
this. evaluate_predicates_recursively (
@@ -1704,8 +1722,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1704
1722
stack : & TraitObligationStack < ' o , ' tcx > ,
1705
1723
where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > ,
1706
1724
) -> Result < EvaluationResult , OverflowError > {
1707
- self . evaluation_probe ( |this| {
1708
- match this. match_where_clause_trait_ref ( stack. obligation , where_clause_trait_ref) {
1725
+ self . evaluation_probe ( |this, outer_universe| {
1726
+ // Eagerly instantiate higher ranked goals.
1727
+ //
1728
+ // See the comment in `evaluate_candidate` to see why.
1729
+ let p = self . infcx . instantiate_binder_with_placeholders ( stack. obligation . predicate ) ;
1730
+ let obligation = stack. obligation . with ( this. tcx ( ) , ty:: Binder :: dummy ( p) ) ;
1731
+ * outer_universe = self . infcx . universe ( ) ;
1732
+ match this. match_where_clause_trait_ref ( & obligation, where_clause_trait_ref) {
1709
1733
Ok ( obligations) => this. evaluate_predicates_recursively ( stack. list ( ) , obligations) ,
1710
1734
Err ( ( ) ) => Ok ( EvaluatedToErr ) ,
1711
1735
}
0 commit comments