11use rustc_infer:: infer:: TyCtxtInferExt ;
2+ use rustc_infer:: traits:: ScrubbedTraitError ;
3+ use rustc_middle:: bug;
24use rustc_middle:: query:: Providers ;
35use rustc_middle:: traits:: query:: NoSolution ;
4- use rustc_middle:: ty:: { self , PseudoCanonicalInput , TyCtxt , TypeFoldable , TypeVisitableExt } ;
5- use rustc_trait_selection:: traits:: query:: normalize:: QueryNormalizeExt ;
6- use rustc_trait_selection:: traits:: { Normalized , ObligationCause } ;
6+ use rustc_middle:: ty:: {
7+ self , PseudoCanonicalInput , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable ,
8+ TypeVisitableExt , TypingMode ,
9+ } ;
10+ use rustc_span:: DUMMY_SP ;
11+ use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ;
12+ use rustc_trait_selection:: error_reporting:: traits:: OverflowCause ;
13+ use rustc_trait_selection:: traits:: { self , ObligationCause , ObligationCtxt } ;
714use tracing:: debug;
815
916pub ( crate ) fn provide ( p : & mut Providers ) {
@@ -17,54 +24,83 @@ pub(crate) fn provide(p: &mut Providers) {
1724 } ;
1825}
1926
27+ // FIXME(-Znext-solver): This can be simplified further to just a `deeply_normalize` call.
2028fn try_normalize_after_erasing_regions < ' tcx , T : TypeFoldable < TyCtxt < ' tcx > > + PartialEq + Copy > (
2129 tcx : TyCtxt < ' tcx > ,
2230 goal : PseudoCanonicalInput < ' tcx , T > ,
2331) -> Result < T , NoSolution > {
2432 let PseudoCanonicalInput { typing_env, value } = goal;
2533 let ( infcx, param_env) = tcx. infer_ctxt ( ) . build_with_typing_env ( typing_env) ;
26- let cause = ObligationCause :: dummy ( ) ;
27- match infcx. at ( & cause, param_env) . query_normalize ( value) {
28- Ok ( Normalized { value : normalized_value, obligations : normalized_obligations } ) => {
29- // We don't care about the `obligations`; they are
30- // always only region relations, and we are about to
31- // erase those anyway:
32- // This has been seen to fail in RL, so making it a non-debug assertion to better catch
33- // those cases.
34- assert_eq ! (
35- normalized_obligations. iter( ) . find( |p| not_outlives_predicate( p. predicate) ) ,
36- None ,
37- ) ;
34+ let ocx = ObligationCtxt :: new ( & infcx) ;
35+ let mut normalized =
36+ ocx. deeply_normalize ( & ObligationCause :: dummy ( ) , param_env, value) . map_err ( |errors| {
37+ match infcx. typing_mode ( ) {
38+ TypingMode :: PostAnalysis => {
39+ for error in errors {
40+ match error {
41+ ScrubbedTraitError :: Cycle ( pred) => {
42+ infcx. err_ctxt ( ) . report_overflow_error (
43+ OverflowCause :: TraitSolver ( pred. first ( ) . unwrap ( ) . predicate ) ,
44+ DUMMY_SP ,
45+ false ,
46+ |_| { } ,
47+ ) ;
48+ }
49+ _ => { }
50+ }
51+ }
52+ }
53+ _ => { }
54+ }
3855
39- let resolved_value = infcx. resolve_vars_if_possible ( normalized_value) ;
40- // It's unclear when `resolve_vars` would have an effect in a
41- // fresh `InferCtxt`. If this assert does trigger, it will give
42- // us a test case.
43- debug_assert_eq ! ( normalized_value, resolved_value) ;
44- let erased = infcx. tcx . erase_regions ( resolved_value) ;
45- debug_assert ! ( !erased. has_infer( ) , "{erased:?}" ) ;
46- Ok ( erased)
47- }
48- Err ( NoSolution ) => Err ( NoSolution ) ,
56+ // Otherwise, bail with `NoSolution`
57+ NoSolution
58+ } ) ?;
59+
60+ if tcx. features ( ) . generic_const_exprs ( ) {
61+ normalized =
62+ normalized. fold_with ( & mut FoldConsts { ocx : & ocx, param_env, universes : vec ! [ ] } ) ;
63+ }
64+
65+ let resolved = infcx. resolve_vars_if_possible ( normalized) ;
66+ let erased = tcx. erase_regions ( resolved) ;
67+
68+ if erased. has_non_region_infer ( ) {
69+ bug ! ( "encountered infer when normalizing {value:?} to {erased:?}" ) ;
4970 }
71+
72+ Ok ( erased)
5073}
5174
52- fn not_outlives_predicate ( p : ty:: Predicate < ' _ > ) -> bool {
53- match p. kind ( ) . skip_binder ( ) {
54- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives ( ..) )
55- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives ( ..) ) => false ,
56- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( ..) )
57- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( ..) )
58- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: HostEffect ( ..) )
59- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: ConstArgHasType ( ..) )
60- | ty:: PredicateKind :: NormalizesTo ( ..)
61- | ty:: PredicateKind :: AliasRelate ( ..)
62- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( ..) )
63- | ty:: PredicateKind :: DynCompatible ( ..)
64- | ty:: PredicateKind :: Subtype ( ..)
65- | ty:: PredicateKind :: Coerce ( ..)
66- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: ConstEvaluatable ( ..) )
67- | ty:: PredicateKind :: ConstEquate ( ..)
68- | ty:: PredicateKind :: Ambiguous => true ,
75+ struct FoldConsts < ' a , ' tcx > {
76+ ocx : & ' a ObligationCtxt < ' a , ' tcx > ,
77+ param_env : ty:: ParamEnv < ' tcx > ,
78+ universes : Vec < Option < ty:: UniverseIndex > > ,
79+ }
80+
81+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for FoldConsts < ' _ , ' tcx > {
82+ fn cx ( & self ) -> TyCtxt < ' tcx > {
83+ self . ocx . infcx . tcx
84+ }
85+
86+ fn fold_binder < T > ( & mut self , binder : ty:: Binder < ' tcx , T > ) -> ty:: Binder < ' tcx , T >
87+ where
88+ T : TypeFoldable < TyCtxt < ' tcx > > ,
89+ {
90+ self . universes . push ( None ) ;
91+ let binder = binder. super_fold_with ( self ) ;
92+ self . universes . pop ( ) ;
93+ binder
94+ }
95+
96+ fn fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
97+ let ct = traits:: with_replaced_escaping_bound_vars (
98+ self . ocx . infcx ,
99+ & mut self . universes ,
100+ ct,
101+ |constant| traits:: evaluate_const ( self . ocx . infcx , constant, self . param_env ) ,
102+ ) ;
103+ debug ! ( ?ct, ?self . param_env) ;
104+ ct. super_fold_with ( self )
69105 }
70106}
0 commit comments