@@ -4,7 +4,9 @@ use crate::infer::canonical::{
44use crate :: infer:: { InferCtxt , InferOk } ;
55use crate :: traits:: query:: Fallible ;
66use 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 ;
810use rustc_middle:: ty:: fold:: TypeFoldable ;
911use rustc_middle:: ty:: { ParamEnvAnd , TyCtxt } ;
1012use std:: fmt;
@@ -17,7 +19,6 @@ pub mod implied_outlives_bounds;
1719pub mod normalize;
1820pub mod outlives;
1921pub mod prove_predicate;
20- use self :: prove_predicate:: ProvePredicate ;
2122pub mod subtype;
2223
2324pub use rustc_middle:: traits:: query:: type_op:: * ;
@@ -80,9 +81,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
8081 query_key : ParamEnvAnd < ' tcx , Self > ,
8182 infcx : & InferCtxt < ' _ , ' tcx > ,
8283 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+ ) > {
8490 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 ) ) ;
8692 }
8793
8894 // FIXME(#33684) -- We need to use
@@ -104,20 +110,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
104110 output_query_region_constraints,
105111 ) ?;
106112
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 ) )
121114 }
122115}
123116
@@ -129,9 +122,39 @@ where
129122
130123 fn fully_perform ( self , infcx : & InferCtxt < ' _ , ' tcx > ) -> Fallible < TypeOpOutput < ' tcx , Self > > {
131124 let mut region_constraints = QueryRegionConstraints :: default ( ) ;
132- let ( output, canonicalized_query) =
125+ let ( output, canonicalized_query, mut obligations , _ ) =
133126 Q :: fully_perform_into ( self , infcx, & mut region_constraints) ?;
134127
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+
135158 // Promote the final query-region-constraints into a
136159 // (optional) ref-counted vector:
137160 let region_constraints =
0 commit comments