@@ -14,7 +14,6 @@ use llvm::{ValueRef, get_params};
14
14
use middle:: def_id:: DefId ;
15
15
use middle:: infer;
16
16
use middle:: subst:: { Subst , Substs } ;
17
- use middle:: subst:: VecPerParamSpace ;
18
17
use middle:: subst;
19
18
use middle:: traits;
20
19
use trans:: base:: * ;
@@ -34,7 +33,7 @@ use trans::machine;
34
33
use trans:: monomorphize;
35
34
use trans:: type_:: Type ;
36
35
use trans:: type_of:: * ;
37
- use middle:: ty:: { self , Ty , TypeFoldable } ;
36
+ use middle:: ty:: { self , Ty } ;
38
37
use middle:: ty:: MethodCall ;
39
38
40
39
use syntax:: ast;
@@ -117,20 +116,15 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
117
116
}
118
117
119
118
ty:: TraitContainer ( trait_def_id) => {
120
- let trait_substs = method. substs . clone ( ) . method_to_trait ( ) ;
121
- let trait_substs = bcx. tcx ( ) . mk_substs ( trait_substs) ;
122
- let trait_ref = ty:: TraitRef :: new ( trait_def_id, trait_substs) ;
123
-
119
+ let trait_ref = method. substs . to_trait_ref ( bcx. tcx ( ) , trait_def_id) ;
124
120
let trait_ref = ty:: Binder ( bcx. monomorphize ( & trait_ref) ) ;
125
121
let span = bcx. tcx ( ) . map . span ( method_call. expr_id ) ;
126
122
debug ! ( "method_call={:?} trait_ref={:?} trait_ref id={:?} substs={:?}" ,
127
123
method_call,
128
124
trait_ref,
129
125
trait_ref. 0 . def_id,
130
126
trait_ref. 0 . substs) ;
131
- let origin = fulfill_obligation ( bcx. ccx ( ) ,
132
- span,
133
- trait_ref. clone ( ) ) ;
127
+ let origin = fulfill_obligation ( bcx. ccx ( ) , span, trait_ref) ;
134
128
debug ! ( "origin = {:?}" , origin) ;
135
129
trans_monomorphized_callee ( bcx,
136
130
method_call,
@@ -169,44 +163,9 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
169
163
// type parameters that belong to the trait but also some that
170
164
// belong to the method:
171
165
let rcvr_substs = node_id_substs ( ccx, ExprId ( expr_id) , param_substs) ;
172
- let subst:: SeparateVecsPerParamSpace {
173
- types : rcvr_type,
174
- selfs : rcvr_self,
175
- fns : rcvr_method
176
- } = rcvr_substs. types . split ( ) ;
177
-
178
- // Lookup the precise impl being called. To do that, we need to
179
- // create a trait reference identifying the self type and other
180
- // input type parameters. To create that trait reference, we have
181
- // to pick apart the type parameters to identify just those that
182
- // pertain to the trait. This is easiest to explain by example:
183
- //
184
- // trait Convert {
185
- // fn from<U:Foo>(n: U) -> Option<Self>;
186
- // }
187
- // ...
188
- // let f = <Vec<i32> as Convert>::from::<String>(...)
189
- //
190
- // Here, in this call, which I've written with explicit UFCS
191
- // notation, the set of type parameters will be:
192
- //
193
- // rcvr_type: [] <-- nothing declared on the trait itself
194
- // rcvr_self: [Vec<i32>] <-- the self type
195
- // rcvr_method: [String] <-- method type parameter
196
- //
197
- // So we create a trait reference using the first two,
198
- // basically corresponding to `<Vec<i32> as Convert>`.
199
- // The remaining type parameters (`rcvr_method`) will be used below.
200
- let trait_substs =
201
- Substs :: erased ( VecPerParamSpace :: new ( rcvr_type,
202
- rcvr_self,
203
- Vec :: new ( ) ) ) ;
204
- let trait_substs = tcx. mk_substs ( trait_substs) ;
205
- debug ! ( "trait_substs={:?}" , trait_substs) ;
206
- let trait_ref = ty:: Binder ( ty:: TraitRef :: new ( trait_id, trait_substs) ) ;
207
- let vtbl = fulfill_obligation ( ccx,
208
- DUMMY_SP ,
209
- trait_ref) ;
166
+ debug ! ( "rcvr_substs={:?}" , rcvr_substs) ;
167
+ let trait_ref = ty:: Binder ( rcvr_substs. to_trait_ref ( tcx, trait_id) ) ;
168
+ let vtbl = fulfill_obligation ( ccx, DUMMY_SP , trait_ref) ;
210
169
211
170
// Now that we know which impl is being used, we can dispatch to
212
171
// the actual function:
@@ -216,33 +175,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
216
175
substs : impl_substs,
217
176
nested : _ } ) =>
218
177
{
219
- assert ! ( !impl_substs. types. needs_infer( ) ) ;
220
-
221
- // Create the substitutions that are in scope. This combines
222
- // the type parameters from the impl with those declared earlier.
223
- // To see what I mean, consider a possible impl:
224
- //
225
- // impl<T> Convert for Vec<T> {
226
- // fn from<U:Foo>(n: U) { ... }
227
- // }
228
- //
229
- // Recall that we matched `<Vec<i32> as Convert>`. Trait
230
- // resolution will have given us a substitution
231
- // containing `impl_substs=[[T=i32],[],[]]` (the type
232
- // parameters defined on the impl). We combine
233
- // that with the `rcvr_method` from before, which tells us
234
- // the type parameters from the *method*, to yield
235
- // `callee_substs=[[T=i32],[],[U=String]]`.
236
- let subst:: SeparateVecsPerParamSpace {
237
- types : impl_type,
238
- selfs : impl_self,
239
- fns : _
240
- } = impl_substs. types . split ( ) ;
241
- let callee_substs =
242
- Substs :: erased ( VecPerParamSpace :: new ( impl_type,
243
- impl_self,
244
- rcvr_method) ) ;
245
-
178
+ let callee_substs = impl_substs. with_method_from ( & rcvr_substs) ;
246
179
let mth = tcx. get_impl_method ( impl_did, callee_substs, mname) ;
247
180
trans_fn_ref_with_substs ( ccx, mth. method . def_id , ExprId ( expr_id) ,
248
181
param_substs,
@@ -256,6 +189,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
256
189
idx)
257
190
}
258
191
_ => {
192
+ // FIXME(#20847): handle at least VtableFnPointer
259
193
tcx. sess . bug ( & format ! ( "static call to invalid vtable: {:?}" ,
260
194
vtbl) ) ;
261
195
}
@@ -285,11 +219,11 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
285
219
} ;
286
220
// create a concatenated set of substitutions which includes
287
221
// those from the impl and those from the method:
288
- let callee_substs =
289
- combine_impl_and_methods_tps (
290
- bcx , MethodCallKey ( method_call ) , vtable_impl . substs ) ;
291
-
292
- let mth = bcx. tcx ( ) . get_impl_method ( impl_did, callee_substs , mname) ;
222
+ let meth_substs = node_id_substs ( ccx ,
223
+ MethodCallKey ( method_call ) ,
224
+ bcx . fcx . param_substs ) ;
225
+ let impl_substs = vtable_impl . substs . with_method_from ( & meth_substs ) ;
226
+ let mth = bcx. tcx ( ) . get_impl_method ( impl_did, impl_substs , mname) ;
293
227
// translate the function
294
228
let datum = trans_fn_ref_with_substs ( bcx. ccx ( ) ,
295
229
mth. method . def_id ,
@@ -346,43 +280,6 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
346
280
}
347
281
}
348
282
349
- /// Creates a concatenated set of substitutions which includes those from the impl and those from
350
- /// the method. This are some subtle complications here. Statically, we have a list of type
351
- /// parameters like `[T0, T1, T2, M1, M2, M3]` where `Tn` are type parameters that appear on the
352
- /// receiver. For example, if the receiver is a method parameter `A` with a bound like
353
- /// `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
354
- ///
355
- /// The weird part is that the type `A` might now be bound to any other type, such as `foo<X>`.
356
- /// In that case, the vector we want is: `[X, M1, M2, M3]`. Therefore, what we do now is to slice
357
- /// off the method type parameters and append them to the type parameters from the type that the
358
- /// receiver is mapped to.
359
- fn combine_impl_and_methods_tps < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
360
- node : ExprOrMethodCall ,
361
- rcvr_substs : subst:: Substs < ' tcx > )
362
- -> subst:: Substs < ' tcx >
363
- {
364
- let ccx = bcx. ccx ( ) ;
365
-
366
- let node_substs = node_id_substs ( ccx, node, bcx. fcx . param_substs ) ;
367
-
368
- debug ! ( "rcvr_substs={:?}" , rcvr_substs) ;
369
- debug ! ( "node_substs={:?}" , node_substs) ;
370
-
371
- // Break apart the type parameters from the node and type
372
- // parameters from the receiver.
373
- let node_method = node_substs. types . split ( ) . fns ;
374
- let subst:: SeparateVecsPerParamSpace {
375
- types : rcvr_type,
376
- selfs : rcvr_self,
377
- fns : rcvr_method
378
- } = rcvr_substs. types . clone ( ) . split ( ) ;
379
- assert ! ( rcvr_method. is_empty( ) ) ;
380
- subst:: Substs {
381
- regions : subst:: ErasedRegions ,
382
- types : subst:: VecPerParamSpace :: new ( rcvr_type, rcvr_self, node_method)
383
- }
384
- }
385
-
386
283
/// Create a method callee where the method is coming from a trait object (e.g., Box<Trait> type).
387
284
/// In this case, we must pull the fn pointer out of the vtable that is packaged up with the
388
285
/// object. Objects are represented as a pair, so we first evaluate the self expression and then
0 commit comments