@@ -42,7 +42,7 @@ pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'
4242
4343pub  type  ProjectionTyObligation < ' tcx >  = Obligation < ' tcx ,  ty:: ProjectionTy < ' tcx > > ; 
4444
45- pub ( super )  struct  InProgress ; 
45+ pub  struct  InProgress ; 
4646
4747/// When attempting to resolve `<T as TraitRef>::Name` ... 
4848#[ derive( Debug ) ]  
@@ -188,7 +188,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
188188/// If successful, this may result in additional obligations. 
189189/// 
190190/// See [poly_project_and_unify_type] for an explanation of the return value. 
191- fn  project_and_unify_type < ' cx ,  ' tcx > ( 
191+ pub   fn  project_and_unify_type < ' cx ,  ' tcx > ( 
192192    selcx :  & mut  SelectionContext < ' cx ,  ' tcx > , 
193193    obligation :  & ProjectionObligation < ' tcx > , 
194194)  -> Result < 
@@ -484,7 +484,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
484484                // there won't be bound vars there. 
485485
486486                let  data = data. super_fold_with ( self ) ; 
487-                 let  normalized_ty = if  self . eager_inference_replacement  { 
487+                 let  normalized_ty = if  self . selcx . normalization_mode . eager_inference_replacement  { 
488488                    normalize_projection_type ( 
489489                        self . selcx , 
490490                        self . param_env , 
@@ -914,7 +914,8 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
914914    // Don't use the projection cache in intercrate mode - 
915915    // the `infcx` may be re-used between intercrate in non-intercrate 
916916    // mode, which could lead to using incorrect cache results. 
917-     let  use_cache = !selcx. is_intercrate ( ) ; 
917+     let  use_cache =
918+         !selcx. is_intercrate ( )  && selcx. normalization_mode . allow_infer_constraint_during_projection ; 
918919
919920    let  projection_ty = infcx. resolve_vars_if_possible ( projection_ty) ; 
920921    let  cache_key = ProjectionCacheKey :: new ( projection_ty) ; 
@@ -1168,7 +1169,7 @@ fn project<'cx, 'tcx>(
11681169
11691170    match  candidates { 
11701171        ProjectionCandidateSet :: Single ( candidate)  => { 
1171-             Ok ( Projected :: Progress ( confirm_candidate ( selcx,  obligation,  candidate) ) ) 
1172+             Ok ( confirm_candidate ( selcx,  obligation,  candidate) ) 
11721173        } 
11731174        ProjectionCandidateSet :: None  => Ok ( Projected :: NoProgress ( 
11741175            // FIXME(associated_const_generics): this may need to change in the future? 
@@ -1583,7 +1584,7 @@ fn confirm_candidate<'cx, 'tcx>(
15831584    selcx :  & mut  SelectionContext < ' cx ,  ' tcx > , 
15841585    obligation :  & ProjectionTyObligation < ' tcx > , 
15851586    candidate :  ProjectionCandidate < ' tcx > , 
1586- )  -> Progress < ' tcx >  { 
1587+ )  -> Projected < ' tcx >  { 
15871588    debug ! ( ?obligation,  ?candidate,  "confirm_candidate" ) ; 
15881589    let  mut  progress = match  candidate { 
15891590        ProjectionCandidate :: ParamEnv ( poly_projection) 
@@ -1596,7 +1597,7 @@ fn confirm_candidate<'cx, 'tcx>(
15961597        } 
15971598
15981599        ProjectionCandidate :: Select ( impl_source)  => { 
1599-             confirm_select_candidate ( selcx,  obligation,  impl_source) 
1600+             Projected :: Progress ( confirm_select_candidate ( selcx,  obligation,  impl_source) ) 
16001601        } 
16011602    } ; 
16021603
@@ -1605,9 +1606,11 @@ fn confirm_candidate<'cx, 'tcx>(
16051606    // with new region variables, we need to resolve them to existing variables 
16061607    // when possible for this to work. See `auto-trait-projection-recursion.rs` 
16071608    // for a case where this matters. 
1608-     if  progress. term . has_infer_regions ( )  { 
1609-         progress. term  =
1610-             progress. term . fold_with ( & mut  OpportunisticRegionResolver :: new ( selcx. infcx ( ) ) ) ; 
1609+     if  let  Projected :: Progress ( progress)  = & mut  progress { 
1610+         if  progress. term . has_infer_regions ( )  { 
1611+             progress. term  =
1612+                 progress. term . fold_with ( & mut  OpportunisticRegionResolver :: new ( selcx. infcx ( ) ) ) ; 
1613+         } 
16111614    } 
16121615    progress
16131616} 
@@ -1688,9 +1691,12 @@ fn confirm_generator_candidate<'cx, 'tcx>(
16881691        } 
16891692    } ) ; 
16901693
1691-     confirm_param_env_candidate ( selcx,  obligation,  predicate,  false ) 
1692-         . with_addl_obligations ( impl_source. nested ) 
1693-         . with_addl_obligations ( obligations) 
1694+     let  progress = confirm_param_env_candidate ( selcx,  obligation,  predicate,  false ) ; 
1695+     let  progress = match  progress { 
1696+         Projected :: Progress ( progress)  => progress, 
1697+         Projected :: NoProgress ( _)  => bug ! ( ) , 
1698+     } ; 
1699+     progress. with_addl_obligations ( impl_source. nested ) . with_addl_obligations ( obligations) 
16941700} 
16951701
16961702fn  confirm_discriminant_kind_candidate < ' cx ,  ' tcx > ( 
@@ -1715,7 +1721,12 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
17151721
17161722    // We get here from `poly_project_and_unify_type` which replaces bound vars 
17171723    // with placeholders, so dummy is okay here. 
1718-     confirm_param_env_candidate ( selcx,  obligation,  ty:: Binder :: dummy ( predicate) ,  false ) 
1724+     let  progress =
1725+         confirm_param_env_candidate ( selcx,  obligation,  ty:: Binder :: dummy ( predicate) ,  false ) ; 
1726+     match  progress { 
1727+         Projected :: Progress ( progress)  => progress, 
1728+         Projected :: NoProgress ( _)  => bug ! ( ) , 
1729+     } 
17191730} 
17201731
17211732fn  confirm_pointee_candidate < ' cx ,  ' tcx > ( 
@@ -1746,8 +1757,12 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
17461757        term :  metadata_ty. into ( ) , 
17471758    } ; 
17481759
1749-     confirm_param_env_candidate ( selcx,  obligation,  ty:: Binder :: dummy ( predicate) ,  false ) 
1750-         . with_addl_obligations ( obligations) 
1760+     let  progress =
1761+         confirm_param_env_candidate ( selcx,  obligation,  ty:: Binder :: dummy ( predicate) ,  false ) ; 
1762+     match  progress { 
1763+         Projected :: Progress ( progress)  => progress. with_addl_obligations ( obligations) , 
1764+         Projected :: NoProgress ( _)  => bug ! ( ) , 
1765+     } 
17511766} 
17521767
17531768fn  confirm_fn_pointer_candidate < ' cx ,  ' tcx > ( 
@@ -1819,15 +1834,19 @@ fn confirm_callable_candidate<'cx, 'tcx>(
18191834        term :  ret_type. into ( ) , 
18201835    } ) ; 
18211836
1822-     confirm_param_env_candidate ( selcx,  obligation,  predicate,  true ) 
1837+     let  progress = confirm_param_env_candidate ( selcx,  obligation,  predicate,  true ) ; 
1838+     match  progress { 
1839+         Projected :: Progress ( progress)  => progress, 
1840+         Projected :: NoProgress ( _)  => bug ! ( ) , 
1841+     } 
18231842} 
18241843
18251844fn  confirm_param_env_candidate < ' cx ,  ' tcx > ( 
18261845    selcx :  & mut  SelectionContext < ' cx ,  ' tcx > , 
18271846    obligation :  & ProjectionTyObligation < ' tcx > , 
18281847    poly_cache_entry :  ty:: PolyProjectionPredicate < ' tcx > , 
18291848    potentially_unnormalized_candidate :  bool , 
1830- )  -> Progress < ' tcx >  { 
1849+ )  -> Projected < ' tcx >  { 
18311850    let  infcx = selcx. infcx ( ) ; 
18321851    let  cause = & obligation. cause ; 
18331852    let  param_env = obligation. param_env ; 
@@ -1868,23 +1887,42 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
18681887
18691888    debug ! ( ?cache_projection,  ?obligation_projection) ; 
18701889
1871-     match  infcx. at ( cause,  param_env) . eq ( cache_projection,  obligation_projection)  { 
1872-         Ok ( InferOk  {  value :  _,  obligations } )  => { 
1873-             nested_obligations. extend ( obligations) ; 
1874-             assoc_ty_own_obligations ( selcx,  obligation,  & mut  nested_obligations) ; 
1875-             // FIXME(associated_const_equality): Handle consts here as well? Maybe this progress type should just take 
1876-             // a term instead. 
1877-             Progress  {  term :  cache_entry. term ,  obligations :  nested_obligations } 
1878-         } 
1879-         Err ( e)  => { 
1880-             let  msg = format ! ( 
1881-                 "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}" , 
1882-                 obligation,  poly_cache_entry,  e, 
1883-             ) ; 
1884-             debug ! ( "confirm_param_env_candidate: {}" ,  msg) ; 
1885-             let  err = infcx. tcx . ty_error_with_message ( obligation. cause . span ,  & msg) ; 
1886-             Progress  {  term :  err. into ( ) ,  obligations :  vec ! [ ]  } 
1890+     match  infcx. commit_if_ok ( |snapshot| { 
1891+         let  progress = match  infcx. at ( cause,  param_env) . eq ( cache_projection,  obligation_projection) 
1892+         { 
1893+             Ok ( InferOk  {  value :  _,  obligations } )  => { 
1894+                 nested_obligations. extend ( obligations) ; 
1895+                 assoc_ty_own_obligations ( selcx,  obligation,  & mut  nested_obligations) ; 
1896+                 // FIXME(associated_const_equality): Handle consts here as well? Maybe this progress type should just take 
1897+                 // a term instead. 
1898+                 Progress  {  term :  cache_entry. term ,  obligations :  nested_obligations } 
1899+             } 
1900+             Err ( e)  => { 
1901+                 let  msg = format ! ( 
1902+                     "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}" , 
1903+                     obligation,  poly_cache_entry,  e, 
1904+                 ) ; 
1905+                 debug ! ( "confirm_param_env_candidate: {}" ,  msg) ; 
1906+                 let  err = infcx. tcx . ty_error_with_message ( obligation. cause . span ,  & msg) ; 
1907+                 Progress  {  term :  err. into ( ) ,  obligations :  vec ! [ ]  } 
1908+             } 
1909+         } ; 
1910+ 
1911+         let  any_instantiations = infcx. any_instantiations ( & snapshot) ; 
1912+ 
1913+         if  any_instantiations && !selcx. normalization_mode . allow_infer_constraint_during_projection 
1914+         { 
1915+             Err ( ty:: Term :: Ty ( 
1916+                 infcx
1917+                     . tcx 
1918+                     . mk_projection ( obligation_projection. item_def_id ,  obligation_projection. substs ) , 
1919+             ) ) 
1920+         }  else  { 
1921+             Ok ( progress) 
18871922        } 
1923+     } )  { 
1924+         Ok ( p)  => Projected :: Progress ( p) , 
1925+         Err ( p)  => Projected :: NoProgress ( p) , 
18881926    } 
18891927} 
18901928
0 commit comments