Skip to content

Commit 2c1d7a7

Browse files
committed
Move the upcast routine into traits and use it for method selection; also
move get_method_index into traits and give it a better name (`get_vtable_index_of_object_method`).
1 parent 50ed6c1 commit 2c1d7a7

File tree

4 files changed

+66
-39
lines changed

4 files changed

+66
-39
lines changed

src/librustc/middle/traits/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ pub use self::select::SelectionCache;
3434
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
3535
pub use self::select::{MethodMatchedData}; // intentionally don't export variants
3636
pub use self::util::elaborate_predicates;
37+
pub use self::util::get_vtable_index_of_object_method;
3738
pub use self::util::trait_ref_for_builtin_bound;
3839
pub use self::util::supertraits;
3940
pub use self::util::Supertraits;
4041
pub use self::util::transitive_bounds;
42+
pub use self::util::upcast;
4143

4244
mod coherence;
4345
mod error_reporting;

src/librustc/middle/traits/util.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,58 @@ pub fn predicate_for_builtin_bound<'tcx>(
291291
})
292292
}
293293

294+
/// Cast a trait reference into a reference to one of its super
295+
/// traits; returns `None` if `target_trait_def_id` is not a
296+
/// supertrait.
297+
pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
298+
source_trait_ref: ty::PolyTraitRef<'tcx>,
299+
target_trait_def_id: ast::DefId)
300+
-> Option<ty::PolyTraitRef<'tcx>>
301+
{
302+
if source_trait_ref.def_id() == target_trait_def_id {
303+
return Some(source_trait_ref); // shorcut the most common case
304+
}
305+
306+
for super_trait_ref in supertraits(tcx, source_trait_ref) {
307+
if super_trait_ref.def_id() == target_trait_def_id {
308+
return Some(super_trait_ref);
309+
}
310+
}
311+
312+
None
313+
}
314+
315+
/// Given an object of type `object_trait_ref`, returns the index of
316+
/// the method `n_method` found in the trait `trait_def_id` (which
317+
/// should be a supertrait of `object_trait_ref`) within the vtable
318+
/// for `object_trait_ref`.
319+
pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
320+
object_trait_ref: ty::PolyTraitRef<'tcx>,
321+
trait_def_id: ast::DefId,
322+
method_index_in_trait: uint) -> uint {
323+
// We need to figure the "real index" of the method in a
324+
// listing of all the methods of an object. We do this by
325+
// iterating down the supertraits of the object's trait until
326+
// we find the trait the method came from, counting up the
327+
// methods from them.
328+
let mut method_count = 0;
329+
ty::each_bound_trait_and_supertraits(tcx, &[object_trait_ref], |bound_ref| {
330+
if bound_ref.def_id() == trait_def_id {
331+
false
332+
} else {
333+
let trait_items = ty::trait_items(tcx, bound_ref.def_id());
334+
for trait_item in trait_items.iter() {
335+
match *trait_item {
336+
ty::MethodTraitItem(_) => method_count += 1,
337+
ty::TypeTraitItem(_) => {}
338+
}
339+
}
340+
true
341+
}
342+
});
343+
method_count + method_index_in_trait
344+
}
345+
294346
impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
295347
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
296348
format!("Obligation(predicate={},depth={})",

src/librustc_typeck/check/method/confirm.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -633,17 +633,16 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
633633
target_trait_def_id: ast::DefId)
634634
-> ty::PolyTraitRef<'tcx>
635635
{
636-
for super_trait_ref in traits::supertraits(self.tcx(), source_trait_ref.clone()) {
637-
if super_trait_ref.def_id() == target_trait_def_id {
638-
return super_trait_ref;
636+
match traits::upcast(self.tcx(), source_trait_ref.clone(), target_trait_def_id) {
637+
Some(super_trait_ref) => super_trait_ref,
638+
None => {
639+
self.tcx().sess.span_bug(
640+
self.span,
641+
format!("cannot upcast `{}` to `{}`",
642+
source_trait_ref.repr(self.tcx()),
643+
target_trait_def_id.repr(self.tcx()))[]);
639644
}
640645
}
641-
642-
self.tcx().sess.span_bug(
643-
self.span,
644-
format!("cannot upcast `{}` to `{}`",
645-
source_trait_ref.repr(self.tcx()),
646-
target_trait_def_id.repr(self.tcx()))[]);
647646
}
648647

649648
fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T

src/librustc_typeck/check/method/probe.rs

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
308308
let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
309309
self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
310310
let vtable_index =
311-
get_method_index(tcx, &new_trait_ref, trait_ref.clone(), method_num);
311+
traits::get_vtable_index_of_object_method(tcx,
312+
trait_ref.clone(),
313+
new_trait_ref.def_id(),
314+
method_num);
312315

313316
let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs());
314317

@@ -996,35 +999,6 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
996999
.and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
9971000
}
9981001

999-
// Determine the index of a method in the list of all methods belonging
1000-
// to a trait and its supertraits.
1001-
fn get_method_index<'tcx>(tcx: &ty::ctxt<'tcx>,
1002-
trait_ref: &ty::PolyTraitRef<'tcx>,
1003-
subtrait: ty::PolyTraitRef<'tcx>,
1004-
n_method: uint) -> uint {
1005-
// We need to figure the "real index" of the method in a
1006-
// listing of all the methods of an object. We do this by
1007-
// iterating down the supertraits of the object's trait until
1008-
// we find the trait the method came from, counting up the
1009-
// methods from them.
1010-
let mut method_count = n_method;
1011-
ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
1012-
if bound_ref.def_id() == trait_ref.def_id() {
1013-
false
1014-
} else {
1015-
let trait_items = ty::trait_items(tcx, bound_ref.def_id());
1016-
for trait_item in trait_items.iter() {
1017-
match *trait_item {
1018-
ty::MethodTraitItem(_) => method_count += 1,
1019-
ty::TypeTraitItem(_) => {}
1020-
}
1021-
}
1022-
true
1023-
}
1024-
});
1025-
method_count
1026-
}
1027-
10281002
impl<'tcx> Candidate<'tcx> {
10291003
fn to_unadjusted_pick(&self) -> Pick<'tcx> {
10301004
Pick {

0 commit comments

Comments
 (0)