@@ -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