@@ -581,7 +581,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
581
581
obligation : & PredicateObligation < ' tcx > ,
582
582
) -> Result < EvaluationResult , OverflowError > {
583
583
debug_assert ! ( !self . infcx. next_trait_solver( ) ) ;
584
- self . evaluation_probe ( |this| {
584
+ self . evaluation_probe ( |this, _outer_universe | {
585
585
let goal =
586
586
this. infcx . resolve_vars_if_possible ( ( obligation. predicate , obligation. param_env ) ) ;
587
587
let mut result = this. evaluate_predicate_recursively (
@@ -597,13 +597,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
597
597
} )
598
598
}
599
599
600
+ /// Computes the evaluation result of `op`, discarding any constraints.
601
+ ///
602
+ /// This also runs for leak check to allow higher ranked region errors to impact
603
+ /// selection. By default it checks for leaks from all universes created inside of
604
+ /// `op`, but this can be overwritten if necessary.
600
605
fn evaluation_probe (
601
606
& mut self ,
602
- op : impl FnOnce ( & mut Self ) -> Result < EvaluationResult , OverflowError > ,
607
+ op : impl FnOnce ( & mut Self , & mut ty :: UniverseIndex ) -> Result < EvaluationResult , OverflowError > ,
603
608
) -> Result < EvaluationResult , OverflowError > {
604
609
self . infcx . probe ( |snapshot| -> Result < EvaluationResult , OverflowError > {
605
- let outer_universe = self . infcx . universe ( ) ;
606
- let result = op ( self ) ?;
610
+ let mut outer_universe = self . infcx . universe ( ) ;
611
+ let result = op ( self , & mut outer_universe ) ?;
607
612
608
613
match self . infcx . leak_check ( outer_universe, Some ( snapshot) ) {
609
614
Ok ( ( ) ) => { }
@@ -1267,9 +1272,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1267
1272
stack : & TraitObligationStack < ' o , ' tcx > ,
1268
1273
candidate : & SelectionCandidate < ' tcx > ,
1269
1274
) -> Result < EvaluationResult , OverflowError > {
1270
- let mut result = self . evaluation_probe ( |this| {
1271
- let candidate = ( * candidate) . clone ( ) ;
1272
- match this. confirm_candidate ( stack. obligation , candidate) {
1275
+ let mut result = self . evaluation_probe ( |this, outer_universe| {
1276
+ // We eagerly instantiate higher ranked goals to prevent universe errors
1277
+ // from impacting candidate selection. This matches the behavior of the new
1278
+ // solver. This slightly weakens type inference.
1279
+ //
1280
+ // In case there are no unresolved type or const variables this
1281
+ // should still not be necessary to select a unique impl as any overlap
1282
+ // relying on a universe error from higher ranked goals should have resulted
1283
+ // in an overlap error in coherence.
1284
+ let p = self . infcx . instantiate_binder_with_placeholders ( stack. obligation . predicate ) ;
1285
+ let obligation = stack. obligation . with ( this. tcx ( ) , ty:: Binder :: dummy ( p) ) ;
1286
+ * outer_universe = self . infcx . universe ( ) ;
1287
+ match this. confirm_candidate ( & obligation, candidate. clone ( ) ) {
1273
1288
Ok ( selection) => {
1274
1289
debug ! ( ?selection) ;
1275
1290
this. evaluate_predicates_recursively (
@@ -1706,8 +1721,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1706
1721
stack : & TraitObligationStack < ' o , ' tcx > ,
1707
1722
where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > ,
1708
1723
) -> Result < EvaluationResult , OverflowError > {
1709
- self . evaluation_probe ( |this| {
1710
- match this. match_where_clause_trait_ref ( stack. obligation , where_clause_trait_ref) {
1724
+ self . evaluation_probe ( |this, outer_universe| {
1725
+ // Eagerly instantiate higher ranked goals.
1726
+ //
1727
+ // See the comment in `evaluate_candidate` to see why.
1728
+ let p = self . infcx . instantiate_binder_with_placeholders ( stack. obligation . predicate ) ;
1729
+ let obligation = stack. obligation . with ( this. tcx ( ) , ty:: Binder :: dummy ( p) ) ;
1730
+ * outer_universe = self . infcx . universe ( ) ;
1731
+ match this. match_where_clause_trait_ref ( & obligation, where_clause_trait_ref) {
1711
1732
Ok ( obligations) => this. evaluate_predicates_recursively ( stack. list ( ) , obligations) ,
1712
1733
Err ( ( ) ) => Ok ( EvaluatedToErr ) ,
1713
1734
}
0 commit comments