@@ -16,11 +16,15 @@ use rustc_index::IndexVec;
1616use rustc_infer:: infer:: canonical:: query_response:: make_query_region_constraints;
1717use rustc_infer:: infer:: canonical:: CanonicalVarValues ;
1818use rustc_infer:: infer:: canonical:: { CanonicalExt , QueryRegionConstraints } ;
19+ use rustc_infer:: infer:: InferCtxt ;
1920use rustc_middle:: traits:: query:: NoSolution ;
2021use rustc_middle:: traits:: solve:: {
21- ExternalConstraints , ExternalConstraintsData , MaybeCause , PredefinedOpaquesData , QueryInput ,
22+ ExternalConstraintsData , MaybeCause , PredefinedOpaquesData , QueryInput ,
23+ } ;
24+ use rustc_middle:: ty:: {
25+ self , BoundVar , GenericArgKind , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable ,
26+ TypeVisitableExt ,
2227} ;
23- use rustc_middle:: ty:: { self , BoundVar , GenericArgKind , Ty , TyCtxt , TypeFoldable } ;
2428use rustc_span:: DUMMY_SP ;
2529use std:: iter;
2630use std:: ops:: Deref ;
@@ -32,6 +36,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
3236 & self ,
3337 goal : Goal < ' tcx , T > ,
3438 ) -> ( Vec < ty:: GenericArg < ' tcx > > , CanonicalInput < ' tcx , T > ) {
39+ let opaque_types = self . infcx . clone_opaque_types_for_query_response ( ) ;
40+ let ( goal, opaque_types) =
41+ ( goal, opaque_types) . fold_with ( & mut EagerResolver { infcx : self . infcx } ) ;
42+
3543 let mut orig_values = Default :: default ( ) ;
3644 let canonical_goal = Canonicalizer :: canonicalize (
3745 self . infcx ,
@@ -40,11 +48,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
4048 QueryInput {
4149 goal,
4250 anchor : self . infcx . defining_use_anchor ,
43- predefined_opaques_in_body : self . tcx ( ) . mk_predefined_opaques_in_body (
44- PredefinedOpaquesData {
45- opaque_types : self . infcx . clone_opaque_types_for_query_response ( ) ,
46- } ,
47- ) ,
51+ predefined_opaques_in_body : self
52+ . tcx ( )
53+ . mk_predefined_opaques_in_body ( PredefinedOpaquesData { opaque_types } ) ,
4854 } ,
4955 ) ;
5056 ( orig_values, canonical_goal)
@@ -70,34 +76,43 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
7076 ) ;
7177
7278 let certainty = certainty. unify_with ( goals_certainty) ;
79+ if let Certainty :: OVERFLOW = certainty {
80+ // If we have overflow, it's probable that we're substituting a type
81+ // into itself infinitely and any partial substitutions in the query
82+ // response are probably not useful anyways, so just return an empty
83+ // query response.
84+ //
85+ // This may prevent us from potentially useful inference, e.g.
86+ // 2 candidates, one ambiguous and one overflow, which both
87+ // have the same inference constraints.
88+ //
89+ // Changing this to retain some constraints in the future
90+ // won't be a breaking change, so this is good enough for now.
91+ return Ok ( self . make_ambiguous_response_no_constraints ( MaybeCause :: Overflow ) ) ;
92+ }
7393
74- let response = match certainty {
75- Certainty :: Yes | Certainty :: Maybe ( MaybeCause :: Ambiguity ) => {
76- let external_constraints = self . compute_external_query_constraints ( ) ?;
77- Response { var_values : self . var_values , external_constraints, certainty }
78- }
79- Certainty :: Maybe ( MaybeCause :: Overflow ) => {
80- // If we have overflow, it's probable that we're substituting a type
81- // into itself infinitely and any partial substitutions in the query
82- // response are probably not useful anyways, so just return an empty
83- // query response.
84- //
85- // This may prevent us from potentially useful inference, e.g.
86- // 2 candidates, one ambiguous and one overflow, which both
87- // have the same inference constraints.
88- //
89- // Changing this to retain some constraints in the future
90- // won't be a breaking change, so this is good enough for now.
91- return Ok ( self . make_ambiguous_response_no_constraints ( MaybeCause :: Overflow ) ) ;
92- }
93- } ;
94+ let var_values = self . var_values ;
95+ let external_constraints = self . compute_external_query_constraints ( ) ?;
96+
97+ let ( var_values, mut external_constraints) =
98+ ( var_values, external_constraints) . fold_with ( & mut EagerResolver { infcx : self . infcx } ) ;
99+ // Remove any trivial region constraints once we've resolved regions
100+ external_constraints
101+ . region_constraints
102+ . outlives
103+ . retain ( |( outlives, _) | outlives. 0 . as_region ( ) . map_or ( true , |re| re != outlives. 1 ) ) ;
94104
95105 let canonical = Canonicalizer :: canonicalize (
96106 self . infcx ,
97107 CanonicalizeMode :: Response { max_input_universe : self . max_input_universe } ,
98108 & mut Default :: default ( ) ,
99- response,
109+ Response {
110+ var_values,
111+ certainty,
112+ external_constraints : self . tcx ( ) . mk_external_constraints ( external_constraints) ,
113+ } ,
100114 ) ;
115+
101116 Ok ( canonical)
102117 }
103118
@@ -143,7 +158,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
143158 /// further constrained by inference, that will be passed back in the var
144159 /// values.
145160 #[ instrument( level = "debug" , skip( self ) , ret) ]
146- fn compute_external_query_constraints ( & self ) -> Result < ExternalConstraints < ' tcx > , NoSolution > {
161+ fn compute_external_query_constraints (
162+ & self ,
163+ ) -> Result < ExternalConstraintsData < ' tcx > , NoSolution > {
147164 // We only check for leaks from universes which were entered inside
148165 // of the query.
149166 self . infcx . leak_check ( self . max_input_universe , None ) . map_err ( |e| {
@@ -173,9 +190,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
173190 self . predefined_opaques_in_body . opaque_types . iter ( ) . all ( |( pa, _) | pa != a)
174191 } ) ;
175192
176- Ok ( self
177- . tcx ( )
178- . mk_external_constraints ( ExternalConstraintsData { region_constraints, opaque_types } ) )
193+ Ok ( ExternalConstraintsData { region_constraints, opaque_types } )
179194 }
180195
181196 /// After calling a canonical query, we apply the constraints returned
@@ -333,3 +348,65 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
333348 Ok ( ( ) )
334349 }
335350}
351+
352+ /// Resolves ty, region, and const vars to their inferred values or their root vars.
353+ struct EagerResolver < ' a , ' tcx > {
354+ infcx : & ' a InferCtxt < ' tcx > ,
355+ }
356+
357+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for EagerResolver < ' _ , ' tcx > {
358+ fn interner ( & self ) -> TyCtxt < ' tcx > {
359+ self . infcx . tcx
360+ }
361+
362+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
363+ match * t. kind ( ) {
364+ ty:: Infer ( ty:: TyVar ( vid) ) => match self . infcx . probe_ty_var ( vid) {
365+ Ok ( t) => t. fold_with ( self ) ,
366+ Err ( _) => Ty :: new_var ( self . infcx . tcx , self . infcx . root_var ( vid) ) ,
367+ } ,
368+ ty:: Infer ( ty:: IntVar ( vid) ) => self . infcx . opportunistic_resolve_int_var ( vid) ,
369+ ty:: Infer ( ty:: FloatVar ( vid) ) => self . infcx . opportunistic_resolve_float_var ( vid) ,
370+ _ => {
371+ if t. has_infer ( ) {
372+ t. super_fold_with ( self )
373+ } else {
374+ t
375+ }
376+ }
377+ }
378+ }
379+
380+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
381+ match * r {
382+ ty:: ReVar ( vid) => self
383+ . infcx
384+ . inner
385+ . borrow_mut ( )
386+ . unwrap_region_constraints ( )
387+ . opportunistic_resolve_var ( self . infcx . tcx , vid) ,
388+ _ => r,
389+ }
390+ }
391+
392+ fn fold_const ( & mut self , c : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
393+ match c. kind ( ) {
394+ ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( vid) ) => {
395+ // FIXME: we need to fold the ty too, I think.
396+ match self . infcx . probe_const_var ( vid) {
397+ Ok ( c) => c. fold_with ( self ) ,
398+ Err ( _) => {
399+ ty:: Const :: new_var ( self . infcx . tcx , self . infcx . root_const_var ( vid) , c. ty ( ) )
400+ }
401+ }
402+ }
403+ _ => {
404+ if c. has_infer ( ) {
405+ c. super_fold_with ( self )
406+ } else {
407+ c
408+ }
409+ }
410+ }
411+ }
412+ }
0 commit comments