@@ -14,7 +14,6 @@ use llvm::{ValueRef, get_params};
1414use middle:: def_id:: DefId ;
1515use middle:: infer;
1616use middle:: subst:: { Subst , Substs } ;
17- use middle:: subst:: VecPerParamSpace ;
1817use middle:: subst;
1918use middle:: traits;
2019use trans:: base:: * ;
@@ -34,7 +33,7 @@ use trans::machine;
3433use trans:: monomorphize;
3534use trans:: type_:: Type ;
3635use trans:: type_of:: * ;
37- use middle:: ty:: { self , Ty , TypeFoldable } ;
36+ use middle:: ty:: { self , Ty } ;
3837use middle:: ty:: MethodCall ;
3938
4039use syntax:: ast;
@@ -117,20 +116,15 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
117116 }
118117
119118 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) ;
124120 let trait_ref = ty:: Binder ( bcx. monomorphize ( & trait_ref) ) ;
125121 let span = bcx. tcx ( ) . map . span ( method_call. expr_id ) ;
126122 debug ! ( "method_call={:?} trait_ref={:?} trait_ref id={:?} substs={:?}" ,
127123 method_call,
128124 trait_ref,
129125 trait_ref. 0 . def_id,
130126 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) ;
134128 debug ! ( "origin = {:?}" , origin) ;
135129 trans_monomorphized_callee ( bcx,
136130 method_call,
@@ -169,44 +163,9 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
169163 // type parameters that belong to the trait but also some that
170164 // belong to the method:
171165 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) ;
210169
211170 // Now that we know which impl is being used, we can dispatch to
212171 // the actual function:
@@ -216,33 +175,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
216175 substs : impl_substs,
217176 nested : _ } ) =>
218177 {
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) ;
246179 let mth = tcx. get_impl_method ( impl_did, callee_substs, mname) ;
247180 trans_fn_ref_with_substs ( ccx, mth. method . def_id , ExprId ( expr_id) ,
248181 param_substs,
@@ -256,6 +189,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
256189 idx)
257190 }
258191 _ => {
192+ // FIXME(#20847): handle at least VtableFnPointer
259193 tcx. sess . bug ( & format ! ( "static call to invalid vtable: {:?}" ,
260194 vtbl) ) ;
261195 }
@@ -285,11 +219,11 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
285219 } ;
286220 // create a concatenated set of substitutions which includes
287221 // 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) ;
293227 // translate the function
294228 let datum = trans_fn_ref_with_substs ( bcx. ccx ( ) ,
295229 mth. method . def_id ,
@@ -346,43 +280,6 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
346280 }
347281}
348282
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-
386283/// Create a method callee where the method is coming from a trait object (e.g., Box<Trait> type).
387284/// In this case, we must pull the fn pointer out of the vtable that is packaged up with the
388285/// object. Objects are represented as a pair, so we first evaluate the self expression and then
0 commit comments