@@ -16,11 +16,15 @@ use rustc_index::IndexVec;
16
16
use rustc_infer:: infer:: canonical:: query_response:: make_query_region_constraints;
17
17
use rustc_infer:: infer:: canonical:: CanonicalVarValues ;
18
18
use rustc_infer:: infer:: canonical:: { CanonicalExt , QueryRegionConstraints } ;
19
+ use rustc_infer:: infer:: InferCtxt ;
19
20
use rustc_middle:: traits:: query:: NoSolution ;
20
21
use 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 ,
22
27
} ;
23
- use rustc_middle:: ty:: { self , BoundVar , GenericArgKind , Ty , TyCtxt , TypeFoldable } ;
24
28
use rustc_span:: DUMMY_SP ;
25
29
use std:: iter;
26
30
use std:: ops:: Deref ;
@@ -32,6 +36,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
32
36
& self ,
33
37
goal : Goal < ' tcx , T > ,
34
38
) -> ( 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
+
35
43
let mut orig_values = Default :: default ( ) ;
36
44
let canonical_goal = Canonicalizer :: canonicalize (
37
45
self . infcx ,
@@ -40,11 +48,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
40
48
QueryInput {
41
49
goal,
42
50
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 } ) ,
48
54
} ,
49
55
) ;
50
56
( orig_values, canonical_goal)
@@ -70,34 +76,43 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
70
76
) ;
71
77
72
78
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
+ }
73
93
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 ) ) ;
94
104
95
105
let canonical = Canonicalizer :: canonicalize (
96
106
self . infcx ,
97
107
CanonicalizeMode :: Response { max_input_universe : self . max_input_universe } ,
98
108
& mut Default :: default ( ) ,
99
- response,
109
+ Response {
110
+ var_values,
111
+ certainty,
112
+ external_constraints : self . tcx ( ) . mk_external_constraints ( external_constraints) ,
113
+ } ,
100
114
) ;
115
+
101
116
Ok ( canonical)
102
117
}
103
118
@@ -143,7 +158,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
143
158
/// further constrained by inference, that will be passed back in the var
144
159
/// values.
145
160
#[ 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 > {
147
164
// We only check for leaks from universes which were entered inside
148
165
// of the query.
149
166
self . infcx . leak_check ( self . max_input_universe , None ) . map_err ( |e| {
@@ -173,9 +190,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
173
190
self . predefined_opaques_in_body . opaque_types . iter ( ) . all ( |( pa, _) | pa != a)
174
191
} ) ;
175
192
176
- Ok ( self
177
- . tcx ( )
178
- . mk_external_constraints ( ExternalConstraintsData { region_constraints, opaque_types } ) )
193
+ Ok ( ExternalConstraintsData { region_constraints, opaque_types } )
179
194
}
180
195
181
196
/// After calling a canonical query, we apply the constraints returned
@@ -333,3 +348,65 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
333
348
Ok ( ( ) )
334
349
}
335
350
}
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