88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use infer:: canonical:: {
12- Canonical , Canonicalized , CanonicalizedQueryResult , QueryRegionConstraint , QueryResult ,
13- } ;
11+ use infer:: canonical:: { Canonical , Canonicalized , CanonicalizedQueryResult , QueryRegionConstraint ,
12+ QueryResult } ;
1413use infer:: { InferCtxt , InferOk } ;
1514use std:: fmt;
1615use std:: rc:: Rc ;
1716use traits:: query:: Fallible ;
1817use traits:: ObligationCause ;
1918use ty:: fold:: TypeFoldable ;
20- use ty:: { Lift , ParamEnv , TyCtxt } ;
19+ use ty:: { Lift , ParamEnvAnd , TyCtxt } ;
2120
2221pub mod custom;
2322pub mod eq;
2423pub mod normalize;
2524pub mod outlives;
2625pub mod prove_predicate;
26+ use self :: prove_predicate:: ProvePredicate ;
2727pub mod subtype;
2828
2929pub trait TypeOp < ' gcx , ' tcx > : Sized + fmt:: Debug {
@@ -38,16 +38,18 @@ pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
3838 ) -> Fallible < ( Self :: Output , Option < Rc < Vec < QueryRegionConstraint < ' tcx > > > > ) > ;
3939}
4040
41- pub trait QueryTypeOp < ' gcx : ' tcx , ' tcx > : fmt:: Debug + Sized {
42- type QueryKey : TypeFoldable < ' tcx > + Lift < ' gcx > ;
41+ pub trait QueryTypeOp < ' gcx : ' tcx , ' tcx > :
42+ fmt:: Debug + Sized + TypeFoldable < ' tcx > + Lift < ' gcx >
43+ {
4344 type QueryResult : TypeFoldable < ' tcx > + Lift < ' gcx > ;
4445
4546 /// Either converts `self` directly into a `QueryResult` (for
4647 /// simple cases) or into a `QueryKey` (for more complex cases
4748 /// where we actually have work to do).
48- fn prequery ( self , tcx : TyCtxt < ' _ , ' gcx , ' tcx > ) -> Result < Self :: QueryResult , Self :: QueryKey > ;
49-
50- fn param_env ( key : & Self :: QueryKey ) -> ParamEnv < ' tcx > ;
49+ fn prequery (
50+ tcx : TyCtxt < ' _ , ' gcx , ' tcx > ,
51+ key : & ParamEnvAnd < ' tcx , Self > ,
52+ ) -> Option < Self :: QueryResult > ;
5153
5254 /// Performs the actual query with the canonicalized key -- the
5355 /// real work happens here. This method is not given an `infcx`
@@ -57,7 +59,7 @@ pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: fmt::Debug + Sized {
5759 /// not captured in the return value.
5860 fn perform_query (
5961 tcx : TyCtxt < ' _ , ' gcx , ' tcx > ,
60- canonicalized : Canonicalized < ' gcx , Self :: QueryKey > ,
62+ canonicalized : Canonicalized < ' gcx , ParamEnvAnd < ' tcx , Self > > ,
6163 ) -> Fallible < CanonicalizedQueryResult < ' gcx , Self :: QueryResult > > ;
6264
6365 /// Casts a lifted query result (which is in the gcx lifetime)
@@ -77,52 +79,53 @@ pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: fmt::Debug + Sized {
7779 ) -> & ' a Canonical < ' tcx , QueryResult < ' tcx , Self :: QueryResult > > ;
7880
7981 fn fully_perform_into (
80- self ,
82+ query_key : ParamEnvAnd < ' tcx , Self > ,
8183 infcx : & InferCtxt < ' _ , ' gcx , ' tcx > ,
8284 output_query_region_constraints : & mut Vec < QueryRegionConstraint < ' tcx > > ,
8385 ) -> Fallible < Self :: QueryResult > {
84- match QueryTypeOp :: prequery ( self , infcx. tcx ) {
85- Ok ( result) => Ok ( result) ,
86- Err ( query_key) => {
87- // FIXME(#33684) -- We need to use
88- // `canonicalize_hr_query_hack` here because of things
89- // like the subtype query, which go awry around
90- // `'static` otherwise.
91- let ( canonical_self, canonical_var_values) =
92- infcx. canonicalize_hr_query_hack ( & query_key) ;
93- let canonical_result = Self :: perform_query ( infcx. tcx , canonical_self) ?;
94- let canonical_result = Self :: shrink_to_tcx_lifetime ( & canonical_result) ;
95-
96- let param_env = Self :: param_env ( & query_key) ;
97-
98- let InferOk { value, obligations } = infcx
99- . instantiate_nll_query_result_and_region_obligations (
100- & ObligationCause :: dummy ( ) ,
101- param_env,
102- & canonical_var_values,
103- canonical_result,
104- output_query_region_constraints,
105- ) ?;
106-
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 ( ) = prove_predicate:: ProvePredicate :: new (
114- obligation. param_env ,
115- obligation. predicate ,
116- ) . fully_perform_into ( infcx, output_query_region_constraints) ?;
117- }
118-
119- Ok ( value)
120- }
86+ if let Some ( result) = QueryTypeOp :: prequery ( infcx. tcx , & query_key) {
87+ return Ok ( result) ;
12188 }
89+
90+ // FIXME(#33684) -- We need to use
91+ // `canonicalize_hr_query_hack` here because of things
92+ // like the subtype query, which go awry around
93+ // `'static` otherwise.
94+ let ( canonical_self, canonical_var_values) = infcx. canonicalize_hr_query_hack ( & query_key) ;
95+ let canonical_result = Self :: perform_query ( infcx. tcx , canonical_self) ?;
96+ let canonical_result = Self :: shrink_to_tcx_lifetime ( & canonical_result) ;
97+
98+ let param_env = query_key. param_env ;
99+
100+ let InferOk { value, obligations } = infcx
101+ . instantiate_nll_query_result_and_region_obligations (
102+ & ObligationCause :: dummy ( ) ,
103+ param_env,
104+ & canonical_var_values,
105+ canonical_result,
106+ output_query_region_constraints,
107+ ) ?;
108+
109+ // Typically, instantiating NLL query results does not
110+ // create obligations. However, in some cases there
111+ // are unresolved type variables, and unify them *can*
112+ // create obligations. In that case, we have to go
113+ // fulfill them. We do this via a (recursive) query.
114+ for obligation in obligations {
115+ let ( ) = ProvePredicate :: fully_perform_into (
116+ obligation
117+ . param_env
118+ . and ( ProvePredicate :: new ( obligation. predicate ) ) ,
119+ infcx,
120+ output_query_region_constraints,
121+ ) ?;
122+ }
123+
124+ Ok ( value)
122125 }
123126}
124127
125- impl < ' gcx : ' tcx , ' tcx , Q > TypeOp < ' gcx , ' tcx > for Q
128+ impl < ' gcx : ' tcx , ' tcx , Q > TypeOp < ' gcx , ' tcx > for ParamEnvAnd < ' tcx , Q >
126129where
127130 Q : QueryTypeOp < ' gcx , ' tcx > ,
128131{
0 commit comments