Skip to content

Commit b4a2579

Browse files
committed
Auto merge of #31072 - arielb1:method-callee-cleanup, r=michaelwoerister
The old code was terribly ugly and was duplicated in several places. r? @michaelwoerister
2 parents 00ee90f + 0a01d0b commit b4a2579

File tree

8 files changed

+76
-187
lines changed

8 files changed

+76
-187
lines changed

src/librustc/middle/const_eval.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -1233,20 +1233,11 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
12331233
rcvr_substs: subst::Substs<'tcx>)
12341234
-> Option<&'tcx Expr>
12351235
{
1236-
let subst::SeparateVecsPerParamSpace {
1237-
types: rcvr_type,
1238-
selfs: rcvr_self,
1239-
fns: _,
1240-
} = rcvr_substs.types.split();
1241-
let trait_substs =
1242-
subst::Substs::erased(subst::VecPerParamSpace::new(rcvr_type,
1243-
rcvr_self,
1244-
Vec::new()));
1245-
let trait_substs = tcx.mk_substs(trait_substs);
1246-
debug!("resolve_trait_associated_const: trait_substs={:?}",
1247-
trait_substs);
1248-
let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_id,
1249-
substs: trait_substs });
1236+
let trait_ref = ty::Binder(
1237+
rcvr_substs.erase_regions().to_trait_ref(tcx, trait_id)
1238+
);
1239+
debug!("resolve_trait_associated_const: trait_ref={:?}",
1240+
trait_ref);
12501241

12511242
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
12521243
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);

src/librustc/middle/subst.rs

+30-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub use self::ParamSpace::*;
1414
pub use self::RegionSubsts::*;
1515

1616
use middle::cstore;
17+
use middle::def_id::DefId;
1718
use middle::ty::{self, Ty};
1819
use middle::ty::fold::{TypeFoldable, TypeFolder};
1920

@@ -142,16 +143,34 @@ impl<'tcx> Substs<'tcx> {
142143
-> Substs<'tcx>
143144
{
144145
let Substs { types, regions } = self;
145-
let types = types.with_vec(FnSpace, m_types);
146-
let regions = regions.map(|r| r.with_vec(FnSpace, m_regions));
146+
let types = types.with_slice(FnSpace, &m_types);
147+
let regions = regions.map(|r| r.with_slice(FnSpace, &m_regions));
147148
Substs { types: types, regions: regions }
148149
}
149150

150-
pub fn method_to_trait(self) -> Substs<'tcx> {
151-
let Substs { mut types, regions } = self;
151+
pub fn with_method_from(self,
152+
meth_substs: &Substs<'tcx>)
153+
-> Substs<'tcx>
154+
{
155+
let Substs { types, regions } = self;
156+
let types = types.with_slice(FnSpace, meth_substs.types.get_slice(FnSpace));
157+
let regions = regions.map(|r| {
158+
r.with_slice(FnSpace, meth_substs.regions().get_slice(FnSpace))
159+
});
160+
Substs { types: types, regions: regions }
161+
}
162+
163+
/// Creates a trait-ref out of this substs, ignoring the FnSpace substs
164+
pub fn to_trait_ref(&self, tcx: &ty::ctxt<'tcx>, trait_id: DefId)
165+
-> ty::TraitRef<'tcx> {
166+
let Substs { mut types, regions } = self.clone();
152167
types.truncate(FnSpace, 0);
153168
let regions = regions.map(|mut r| { r.truncate(FnSpace, 0); r });
154-
Substs { types: types, regions: regions }
169+
170+
ty::TraitRef {
171+
def_id: trait_id,
172+
substs: tcx.mk_substs(Substs { types: types, regions: regions })
173+
}
155174
}
156175
}
157176

@@ -290,10 +309,6 @@ impl<T> VecPerParamSpace<T> {
290309
}
291310
}
292311

293-
pub fn params_from_type(types: Vec<T>) -> VecPerParamSpace<T> {
294-
VecPerParamSpace::empty().with_vec(TypeSpace, types)
295-
}
296-
297312
/// `t` is the type space.
298313
/// `s` is the self space.
299314
/// `f` is the fn space.
@@ -483,11 +498,15 @@ impl<T> VecPerParamSpace<T> {
483498
}
484499
}
485500

486-
pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
501+
pub fn with_slice(mut self, space: ParamSpace, slice: &[T])
487502
-> VecPerParamSpace<T>
503+
where T: Clone
488504
{
489505
assert!(self.is_empty_in(space));
490-
self.replace(space, vec);
506+
for t in slice {
507+
self.push(space, t.clone());
508+
}
509+
491510
self
492511
}
493512
}

src/librustc/middle/ty/util.rs

-1
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,6 @@ pub struct ImplMethod<'tcx> {
604604
}
605605

606606
impl<'tcx> ty::ctxt<'tcx> {
607-
#[inline(never)] // is this perfy enough?
608607
pub fn get_impl_method(&self,
609608
impl_def_id: DefId,
610609
substs: Substs<'tcx>,

src/librustc_lint/builtin.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -855,9 +855,7 @@ impl LateLintPass for UnconditionalRecursion {
855855
// A trait method, from any number of possible sources.
856856
// Attempt to select a concrete impl before checking.
857857
ty::TraitContainer(trait_def_id) => {
858-
let trait_substs = callee_substs.clone().method_to_trait();
859-
let trait_substs = tcx.mk_substs(trait_substs);
860-
let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
858+
let trait_ref = callee_substs.to_trait_ref(tcx, trait_def_id);
861859
let trait_ref = ty::Binder(trait_ref);
862860
let span = tcx.map.span(expr_id);
863861
let obligation =

src/librustc_trans/trans/common.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1049,9 +1049,9 @@ pub enum ExprOrMethodCall {
10491049
}
10501050

10511051
pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1052-
node: ExprOrMethodCall,
1053-
param_substs: &subst::Substs<'tcx>)
1054-
-> subst::Substs<'tcx> {
1052+
node: ExprOrMethodCall,
1053+
param_substs: &subst::Substs<'tcx>)
1054+
-> subst::Substs<'tcx> {
10551055
let tcx = ccx.tcx();
10561056

10571057
let substs = match node {
@@ -1064,13 +1064,13 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
10641064
};
10651065

10661066
if substs.types.needs_infer() {
1067-
tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
1068-
node, substs));
1069-
}
1067+
tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
1068+
node, substs));
1069+
}
10701070

1071-
monomorphize::apply_param_substs(tcx,
1072-
param_substs,
1073-
&substs.erase_regions())
1071+
monomorphize::apply_param_substs(tcx,
1072+
param_substs,
1073+
&substs.erase_regions())
10741074
}
10751075

10761076
pub fn langcall(bcx: Block,

src/librustc_trans/trans/meth.rs

+13-116
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use llvm::{ValueRef, get_params};
1414
use middle::def_id::DefId;
1515
use middle::infer;
1616
use middle::subst::{Subst, Substs};
17-
use middle::subst::VecPerParamSpace;
1817
use middle::subst;
1918
use middle::traits;
2019
use trans::base::*;
@@ -34,7 +33,7 @@ use trans::machine;
3433
use trans::monomorphize;
3534
use trans::type_::Type;
3635
use trans::type_of::*;
37-
use middle::ty::{self, Ty, TypeFoldable};
36+
use middle::ty::{self, Ty};
3837
use middle::ty::MethodCall;
3938

4039
use 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

Comments
 (0)