8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use astconv:: AstConv ;
12
-
13
11
use super :: { FnCtxt , PlaceOp , Needs } ;
14
12
use super :: method:: MethodCallee ;
15
13
16
- use rustc:: infer:: InferOk ;
14
+ use rustc:: infer:: { InferCtxt , InferOk } ;
17
15
use rustc:: session:: DiagnosticMessageId ;
18
- use rustc:: traits;
16
+ use rustc:: traits:: { self , TraitEngine } ;
19
17
use rustc:: ty:: { self , Ty , TraitRef } ;
20
18
use rustc:: ty:: { ToPredicate , TypeFoldable } ;
21
19
use rustc:: ty:: adjustment:: { Adjustment , Adjust , OverloadedDeref } ;
22
20
23
21
use syntax_pos:: Span ;
24
- use syntax:: ast:: Ident ;
22
+ use syntax:: ast:: { self , Ident } ;
25
23
26
24
use std:: iter;
27
25
@@ -32,7 +30,9 @@ enum AutoderefKind {
32
30
}
33
31
34
32
pub 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 > ,
36
36
steps : Vec < ( Ty < ' tcx > , AutoderefKind ) > ,
37
37
cur_ty : Ty < ' tcx > ,
38
38
obligations : Vec < traits:: PredicateObligation < ' tcx > > ,
@@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
45
45
type Item = ( Ty < ' tcx > , usize ) ;
46
46
47
47
fn next ( & mut self ) -> Option < Self :: Item > {
48
- let tcx = self . fcx . tcx ;
48
+ let tcx = self . infcx . tcx ;
49
49
50
50
debug ! ( "autoderef: steps={:?}, cur_ty={:?}" ,
51
51
self . steps,
@@ -107,74 +107,103 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
107
107
}
108
108
109
109
impl < ' 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
+
110
130
fn overloaded_deref_ty ( & mut self , ty : Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
111
131
debug ! ( "overloaded_deref_ty({:?})" , ty) ;
112
132
113
- let tcx = self . fcx . tcx ( ) ;
133
+ let tcx = self . infcx . tcx ;
114
134
115
135
// <cur_ty as Deref>
116
136
let trait_ref = TraitRef {
117
137
def_id : tcx. lang_items ( ) . deref_trait ( ) ?,
118
138
substs : tcx. mk_substs_trait ( self . cur_ty , & [ ] ) ,
119
139
} ;
120
140
121
- let cause = traits:: ObligationCause :: misc ( self . span , self . fcx . body_id ) ;
141
+ let cause = traits:: ObligationCause :: misc ( self . span , self . body_id ) ;
122
142
123
143
let obligation = traits:: Obligation :: new ( cause. clone ( ) ,
124
- self . fcx . param_env ,
144
+ self . param_env ,
125
145
trait_ref. to_predicate ( ) ) ;
126
- if !self . fcx . predicate_may_hold ( & obligation) {
146
+ if !self . infcx . predicate_may_hold ( & obligation) {
127
147
debug ! ( "overloaded_deref_ty: cannot match obligation" ) ;
128
148
return None ;
129
149
}
130
150
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) )
146
175
}
147
176
148
177
/// Returns the final type, generating an error if it is an
149
178
/// 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 )
152
181
}
153
182
154
183
/// Returns the final type we ended up with, which may well be an
155
184
/// inference variable (we will resolve it first, if possible).
156
185
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 )
158
187
}
159
188
160
189
pub fn step_count ( & self ) -> usize {
161
190
self . steps . len ( )
162
191
}
163
192
164
193
/// 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 )
166
195
-> 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) )
168
197
}
169
198
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 )
171
200
-> InferOk < ' tcx , Vec < Adjustment < ' tcx > > > {
172
201
let mut obligations = vec ! [ ] ;
173
202
let targets = self . steps . iter ( ) . skip ( 1 ) . map ( |& ( ty, _) | ty)
174
203
. chain ( iter:: once ( self . cur_ty ) ) ;
175
204
let steps: Vec < _ > = self . steps . iter ( ) . map ( |& ( source, kind) | {
176
205
if let AutoderefKind :: Overloaded = kind {
177
- self . fcx . try_overloaded_deref ( self . span , source, needs)
206
+ fcx. try_overloaded_deref ( self . span , source, needs)
178
207
. and_then ( |InferOk { value : method, obligations : o } | {
179
208
obligations. extend ( o) ;
180
209
if let ty:: Ref ( region, _, mutbl) = method. sig . output ( ) . sty {
@@ -211,8 +240,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
211
240
self
212
241
}
213
242
214
- pub fn finalize ( self ) {
215
- let fcx = self . fcx ;
243
+ pub fn finalize ( self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > ) {
216
244
fcx. register_predicates ( self . into_obligations ( ) ) ;
217
245
}
218
246
@@ -223,15 +251,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
223
251
224
252
impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
225
253
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)
235
255
}
236
256
237
257
pub fn try_overloaded_deref ( & self ,
0 commit comments