@@ -4,7 +4,9 @@ use crate::infer::canonical::{
4
4
use crate :: infer:: { InferCtxt , InferOk } ;
5
5
use crate :: traits:: query:: Fallible ;
6
6
use crate :: traits:: ObligationCause ;
7
- use rustc_infer:: infer:: canonical:: Canonical ;
7
+ use rustc_infer:: infer:: canonical:: { Canonical , Certainty } ;
8
+ use rustc_infer:: traits:: query:: NoSolution ;
9
+ use rustc_infer:: traits:: PredicateObligations ;
8
10
use rustc_middle:: ty:: fold:: TypeFoldable ;
9
11
use rustc_middle:: ty:: { ParamEnvAnd , TyCtxt } ;
10
12
use std:: fmt;
@@ -17,7 +19,6 @@ pub mod implied_outlives_bounds;
17
19
pub mod normalize;
18
20
pub mod outlives;
19
21
pub mod prove_predicate;
20
- use self :: prove_predicate:: ProvePredicate ;
21
22
pub mod subtype;
22
23
23
24
pub use rustc_middle:: traits:: query:: type_op:: * ;
@@ -80,9 +81,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
80
81
query_key : ParamEnvAnd < ' tcx , Self > ,
81
82
infcx : & InferCtxt < ' _ , ' tcx > ,
82
83
output_query_region_constraints : & mut QueryRegionConstraints < ' tcx > ,
83
- ) -> Fallible < ( Self :: QueryResponse , Option < Canonical < ' tcx , ParamEnvAnd < ' tcx , Self > > > ) > {
84
+ ) -> Fallible < (
85
+ Self :: QueryResponse ,
86
+ Option < Canonical < ' tcx , ParamEnvAnd < ' tcx , Self > > > ,
87
+ PredicateObligations < ' tcx > ,
88
+ Certainty ,
89
+ ) > {
84
90
if let Some ( result) = QueryTypeOp :: try_fast_path ( infcx. tcx , & query_key) {
85
- return Ok ( ( result, None ) ) ;
91
+ return Ok ( ( result, None , vec ! [ ] , Certainty :: Proven ) ) ;
86
92
}
87
93
88
94
// FIXME(#33684) -- We need to use
@@ -104,20 +110,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
104
110
output_query_region_constraints,
105
111
) ?;
106
112
107
- // Typically, instantiating NLL query results does not
108
- // create obligations. However, in some cases there
109
- // are unresolved type variables, and unify them *can*
110
- // create obligations. In that case, we have to go
111
- // fulfill them. We do this via a (recursive) query.
112
- for obligation in obligations {
113
- let ( ( ) , _) = ProvePredicate :: fully_perform_into (
114
- obligation. param_env . and ( ProvePredicate :: new ( obligation. predicate ) ) ,
115
- infcx,
116
- output_query_region_constraints,
117
- ) ?;
118
- }
119
-
120
- Ok ( ( value, Some ( canonical_self) ) )
113
+ Ok ( ( value, Some ( canonical_self) , obligations, canonical_result. value . certainty ) )
121
114
}
122
115
}
123
116
@@ -129,9 +122,39 @@ where
129
122
130
123
fn fully_perform ( self , infcx : & InferCtxt < ' _ , ' tcx > ) -> Fallible < TypeOpOutput < ' tcx , Self > > {
131
124
let mut region_constraints = QueryRegionConstraints :: default ( ) ;
132
- let ( output, canonicalized_query) =
125
+ let ( output, canonicalized_query, mut obligations , _ ) =
133
126
Q :: fully_perform_into ( self , infcx, & mut region_constraints) ?;
134
127
128
+ // Typically, instantiating NLL query results does not
129
+ // create obligations. However, in some cases there
130
+ // are unresolved type variables, and unify them *can*
131
+ // create obligations. In that case, we have to go
132
+ // fulfill them. We do this via a (recursive) query.
133
+ while !obligations. is_empty ( ) {
134
+ trace ! ( "{:#?}" , obligations) ;
135
+ let mut progress = false ;
136
+ for obligation in std:: mem:: take ( & mut obligations) {
137
+ let obligation = infcx. resolve_vars_if_possible ( obligation) ;
138
+ match ProvePredicate :: fully_perform_into (
139
+ obligation. param_env . and ( ProvePredicate :: new ( obligation. predicate ) ) ,
140
+ infcx,
141
+ & mut region_constraints,
142
+ ) {
143
+ Ok ( ( ( ) , _, new, certainty) ) => {
144
+ obligations. extend ( new) ;
145
+ progress = true ;
146
+ if let Certainty :: Ambiguous = certainty {
147
+ obligations. push ( obligation) ;
148
+ }
149
+ }
150
+ Err ( _) => obligations. push ( obligation) ,
151
+ }
152
+ }
153
+ if !progress {
154
+ return Err ( NoSolution ) ;
155
+ }
156
+ }
157
+
135
158
// Promote the final query-region-constraints into a
136
159
// (optional) ref-counted vector:
137
160
let region_constraints =
0 commit comments