@@ -42,7 +42,7 @@ pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'
42
42
43
43
pub type ProjectionTyObligation < ' tcx > = Obligation < ' tcx , ty:: ProjectionTy < ' tcx > > ;
44
44
45
- pub ( super ) struct InProgress ;
45
+ pub struct InProgress ;
46
46
47
47
/// When attempting to resolve `<T as TraitRef>::Name` ...
48
48
#[ derive( Debug ) ]
@@ -188,7 +188,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
188
188
/// If successful, this may result in additional obligations.
189
189
///
190
190
/// 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 > (
192
192
selcx : & mut SelectionContext < ' cx , ' tcx > ,
193
193
obligation : & ProjectionObligation < ' tcx > ,
194
194
) -> Result <
@@ -484,7 +484,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
484
484
// there won't be bound vars there.
485
485
486
486
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 {
488
488
normalize_projection_type (
489
489
self . selcx ,
490
490
self . param_env ,
@@ -914,7 +914,8 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
914
914
// Don't use the projection cache in intercrate mode -
915
915
// the `infcx` may be re-used between intercrate in non-intercrate
916
916
// 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 ;
918
919
919
920
let projection_ty = infcx. resolve_vars_if_possible ( projection_ty) ;
920
921
let cache_key = ProjectionCacheKey :: new ( projection_ty) ;
@@ -1168,7 +1169,7 @@ fn project<'cx, 'tcx>(
1168
1169
1169
1170
match candidates {
1170
1171
ProjectionCandidateSet :: Single ( candidate) => {
1171
- Ok ( Projected :: Progress ( confirm_candidate ( selcx, obligation, candidate) ) )
1172
+ Ok ( confirm_candidate ( selcx, obligation, candidate) )
1172
1173
}
1173
1174
ProjectionCandidateSet :: None => Ok ( Projected :: NoProgress (
1174
1175
// FIXME(associated_const_generics): this may need to change in the future?
@@ -1583,7 +1584,7 @@ fn confirm_candidate<'cx, 'tcx>(
1583
1584
selcx : & mut SelectionContext < ' cx , ' tcx > ,
1584
1585
obligation : & ProjectionTyObligation < ' tcx > ,
1585
1586
candidate : ProjectionCandidate < ' tcx > ,
1586
- ) -> Progress < ' tcx > {
1587
+ ) -> Projected < ' tcx > {
1587
1588
debug ! ( ?obligation, ?candidate, "confirm_candidate" ) ;
1588
1589
let mut progress = match candidate {
1589
1590
ProjectionCandidate :: ParamEnv ( poly_projection)
@@ -1596,7 +1597,7 @@ fn confirm_candidate<'cx, 'tcx>(
1596
1597
}
1597
1598
1598
1599
ProjectionCandidate :: Select ( impl_source) => {
1599
- confirm_select_candidate ( selcx, obligation, impl_source)
1600
+ Projected :: Progress ( confirm_select_candidate ( selcx, obligation, impl_source) )
1600
1601
}
1601
1602
} ;
1602
1603
@@ -1605,9 +1606,11 @@ fn confirm_candidate<'cx, 'tcx>(
1605
1606
// with new region variables, we need to resolve them to existing variables
1606
1607
// when possible for this to work. See `auto-trait-projection-recursion.rs`
1607
1608
// 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
+ }
1611
1614
}
1612
1615
progress
1613
1616
}
@@ -1688,9 +1691,12 @@ fn confirm_generator_candidate<'cx, 'tcx>(
1688
1691
}
1689
1692
} ) ;
1690
1693
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)
1694
1700
}
1695
1701
1696
1702
fn confirm_discriminant_kind_candidate < ' cx , ' tcx > (
@@ -1715,7 +1721,12 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
1715
1721
1716
1722
// We get here from `poly_project_and_unify_type` which replaces bound vars
1717
1723
// 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
+ }
1719
1730
}
1720
1731
1721
1732
fn confirm_pointee_candidate < ' cx , ' tcx > (
@@ -1746,8 +1757,12 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
1746
1757
term : metadata_ty. into ( ) ,
1747
1758
} ;
1748
1759
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
+ }
1751
1766
}
1752
1767
1753
1768
fn confirm_fn_pointer_candidate < ' cx , ' tcx > (
@@ -1819,15 +1834,19 @@ fn confirm_callable_candidate<'cx, 'tcx>(
1819
1834
term : ret_type. into ( ) ,
1820
1835
} ) ;
1821
1836
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
+ }
1823
1842
}
1824
1843
1825
1844
fn confirm_param_env_candidate < ' cx , ' tcx > (
1826
1845
selcx : & mut SelectionContext < ' cx , ' tcx > ,
1827
1846
obligation : & ProjectionTyObligation < ' tcx > ,
1828
1847
poly_cache_entry : ty:: PolyProjectionPredicate < ' tcx > ,
1829
1848
potentially_unnormalized_candidate : bool ,
1830
- ) -> Progress < ' tcx > {
1849
+ ) -> Projected < ' tcx > {
1831
1850
let infcx = selcx. infcx ( ) ;
1832
1851
let cause = & obligation. cause ;
1833
1852
let param_env = obligation. param_env ;
@@ -1868,23 +1887,42 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
1868
1887
1869
1888
debug ! ( ?cache_projection, ?obligation_projection) ;
1870
1889
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)
1887
1922
}
1923
+ } ) {
1924
+ Ok ( p) => Projected :: Progress ( p) ,
1925
+ Err ( p) => Projected :: NoProgress ( p) ,
1888
1926
}
1889
1927
}
1890
1928
0 commit comments