88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use astconv:: AstConv ;
12-
1311use super :: { FnCtxt , PlaceOp , Needs } ;
1412use super :: method:: MethodCallee ;
1513
16- use rustc:: infer:: InferOk ;
14+ use rustc:: infer:: { InferCtxt , InferOk } ;
1715use rustc:: session:: DiagnosticMessageId ;
18- use rustc:: traits;
16+ use rustc:: traits:: { self , TraitEngine } ;
1917use rustc:: ty:: { self , Ty , TraitRef } ;
2018use rustc:: ty:: { ToPredicate , TypeFoldable } ;
2119use rustc:: ty:: adjustment:: { Adjustment , Adjust , OverloadedDeref } ;
2220
2321use syntax_pos:: Span ;
24- use syntax:: ast:: Ident ;
22+ use syntax:: ast:: { self , Ident } ;
2523
2624use std:: iter;
2725
@@ -32,7 +30,9 @@ enum AutoderefKind {
3230}
3331
3432pub struct Autoderef < ' a , ' gcx : ' tcx , ' tcx : ' a > {
35- fcx : & ' a FnCtxt < ' a , ' gcx , ' tcx > ,
33+ infcx : & ' a InferCtxt < ' a , ' gcx , ' tcx > ,
34+ body_id : ast:: NodeId ,
35+ param_env : ty:: ParamEnv < ' tcx > ,
3636 steps : Vec < ( Ty < ' tcx > , AutoderefKind ) > ,
3737 cur_ty : Ty < ' tcx > ,
3838 obligations : Vec < traits:: PredicateObligation < ' tcx > > ,
@@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
4545 type Item = ( Ty < ' tcx > , usize ) ;
4646
4747 fn next ( & mut self ) -> Option < Self :: Item > {
48- let tcx = self . fcx . tcx ;
48+ let tcx = self . infcx . tcx ;
4949
5050 debug ! ( "autoderef: steps={:?}, cur_ty={:?}" ,
5151 self . steps,
@@ -107,74 +107,103 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
107107}
108108
109109impl < ' a , ' gcx , ' tcx > Autoderef < ' a , ' gcx , ' tcx > {
110+ pub fn new ( infcx : & ' a InferCtxt < ' a , ' gcx , ' tcx > ,
111+ param_env : ty:: ParamEnv < ' tcx > ,
112+ body_id : ast:: NodeId ,
113+ span : Span ,
114+ base_ty : Ty < ' tcx > )
115+ -> Autoderef < ' a , ' gcx , ' tcx >
116+ {
117+ Autoderef {
118+ infcx,
119+ body_id,
120+ param_env,
121+ steps : vec ! [ ] ,
122+ cur_ty : infcx. resolve_type_vars_if_possible ( & base_ty) ,
123+ obligations : vec ! [ ] ,
124+ at_start : true ,
125+ include_raw_pointers : false ,
126+ span,
127+ }
128+ }
129+
110130 fn overloaded_deref_ty ( & mut self , ty : Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
111131 debug ! ( "overloaded_deref_ty({:?})" , ty) ;
112132
113- let tcx = self . fcx . tcx ( ) ;
133+ let tcx = self . infcx . tcx ;
114134
115135 // <cur_ty as Deref>
116136 let trait_ref = TraitRef {
117137 def_id : tcx. lang_items ( ) . deref_trait ( ) ?,
118138 substs : tcx. mk_substs_trait ( self . cur_ty , & [ ] ) ,
119139 } ;
120140
121- let cause = traits:: ObligationCause :: misc ( self . span , self . fcx . body_id ) ;
141+ let cause = traits:: ObligationCause :: misc ( self . span , self . body_id ) ;
122142
123143 let obligation = traits:: Obligation :: new ( cause. clone ( ) ,
124- self . fcx . param_env ,
144+ self . param_env ,
125145 trait_ref. to_predicate ( ) ) ;
126- if !self . fcx . predicate_may_hold ( & obligation) {
146+ if !self . infcx . predicate_may_hold ( & obligation) {
127147 debug ! ( "overloaded_deref_ty: cannot match obligation" ) ;
128148 return None ;
129149 }
130150
131- let mut selcx = traits:: SelectionContext :: new ( self . fcx ) ;
132- let normalized_ty = traits:: normalize_projection_type ( & mut selcx,
133- self . fcx . param_env ,
134- ty:: ProjectionTy :: from_ref_and_name (
135- tcx,
136- trait_ref,
137- Ident :: from_str ( "Target" ) ,
138- ) ,
139- cause,
140- 0 ,
141- & mut self . obligations ) ;
142-
143- debug ! ( "overloaded_deref_ty({:?}) = {:?}" , ty, normalized_ty) ;
144-
145- Some ( self . fcx . resolve_type_vars_if_possible ( & normalized_ty) )
151+ let mut fulfillcx = traits:: FulfillmentContext :: new_in_snapshot ( ) ;
152+ let normalized_ty = fulfillcx. normalize_projection_type (
153+ & self . infcx ,
154+ self . param_env ,
155+ ty:: ProjectionTy :: from_ref_and_name (
156+ tcx,
157+ trait_ref,
158+ Ident :: from_str ( "Target" ) ,
159+ ) ,
160+ cause) ;
161+ if let Err ( e) = fulfillcx. select_where_possible ( & self . infcx ) {
162+ // This shouldn't happen, except for evaluate/fulfill mismatches,
163+ // but that's not a reason for an ICE (`predicate_may_hold` is conservative
164+ // by design).
165+ debug ! ( "overloaded_deref_ty: encountered errors {:?} while fulfilling" ,
166+ e) ;
167+ return None ;
168+ }
169+ let obligations = fulfillcx. pending_obligations ( ) ;
170+ debug ! ( "overloaded_deref_ty({:?}) = ({:?}, {:?})" ,
171+ ty, normalized_ty, obligations) ;
172+ self . obligations . extend ( obligations) ;
173+
174+ Some ( self . infcx . resolve_type_vars_if_possible ( & normalized_ty) )
146175 }
147176
148177 /// Returns the final type, generating an error if it is an
149178 /// unresolved inference variable.
150- pub fn unambiguous_final_ty ( & self ) -> Ty < ' tcx > {
151- self . fcx . structurally_resolved_type ( self . span , self . cur_ty )
179+ pub fn unambiguous_final_ty ( & self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > ) -> Ty < ' tcx > {
180+ fcx. structurally_resolved_type ( self . span , self . cur_ty )
152181 }
153182
154183 /// Returns the final type we ended up with, which may well be an
155184 /// inference variable (we will resolve it first, if possible).
156185 pub fn maybe_ambiguous_final_ty ( & self ) -> Ty < ' tcx > {
157- self . fcx . resolve_type_vars_if_possible ( & self . cur_ty )
186+ self . infcx . resolve_type_vars_if_possible ( & self . cur_ty )
158187 }
159188
160189 pub fn step_count ( & self ) -> usize {
161190 self . steps . len ( )
162191 }
163192
164193 /// Returns the adjustment steps.
165- pub fn adjust_steps ( & self , needs : Needs )
194+ pub fn adjust_steps ( & self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > , needs : Needs )
166195 -> Vec < Adjustment < ' tcx > > {
167- self . fcx . register_infer_ok_obligations ( self . adjust_steps_as_infer_ok ( needs) )
196+ fcx. register_infer_ok_obligations ( self . adjust_steps_as_infer_ok ( fcx , needs) )
168197 }
169198
170- pub fn adjust_steps_as_infer_ok ( & self , needs : Needs )
199+ pub fn adjust_steps_as_infer_ok ( & self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > , needs : Needs )
171200 -> InferOk < ' tcx , Vec < Adjustment < ' tcx > > > {
172201 let mut obligations = vec ! [ ] ;
173202 let targets = self . steps . iter ( ) . skip ( 1 ) . map ( |& ( ty, _) | ty)
174203 . chain ( iter:: once ( self . cur_ty ) ) ;
175204 let steps: Vec < _ > = self . steps . iter ( ) . map ( |& ( source, kind) | {
176205 if let AutoderefKind :: Overloaded = kind {
177- self . fcx . try_overloaded_deref ( self . span , source, needs)
206+ fcx. try_overloaded_deref ( self . span , source, needs)
178207 . and_then ( |InferOk { value : method, obligations : o } | {
179208 obligations. extend ( o) ;
180209 if let ty:: Ref ( region, _, mutbl) = method. sig . output ( ) . sty {
@@ -211,8 +240,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
211240 self
212241 }
213242
214- pub fn finalize ( self ) {
215- let fcx = self . fcx ;
243+ pub fn finalize ( self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > ) {
216244 fcx. register_predicates ( self . into_obligations ( ) ) ;
217245 }
218246
@@ -223,15 +251,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
223251
224252impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
225253 pub fn autoderef ( & ' a self , span : Span , base_ty : Ty < ' tcx > ) -> Autoderef < ' a , ' gcx , ' tcx > {
226- Autoderef {
227- fcx : self ,
228- steps : vec ! [ ] ,
229- cur_ty : self . resolve_type_vars_if_possible ( & base_ty) ,
230- obligations : vec ! [ ] ,
231- at_start : true ,
232- include_raw_pointers : false ,
233- span,
234- }
254+ Autoderef :: new ( self , self . param_env , self . body_id , span, base_ty)
235255 }
236256
237257 pub fn try_overloaded_deref ( & self ,
0 commit comments