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`).
This commit is contained in:
parent
50ed6c1906
commit
2c1d7a7caa
4 changed files with 66 additions and 39 deletions
|
@ -34,10 +34,12 @@ pub use self::select::SelectionCache;
|
|||
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
|
||||
pub use self::select::{MethodMatchedData}; // intentionally don't export variants
|
||||
pub use self::util::elaborate_predicates;
|
||||
pub use self::util::get_vtable_index_of_object_method;
|
||||
pub use self::util::trait_ref_for_builtin_bound;
|
||||
pub use self::util::supertraits;
|
||||
pub use self::util::Supertraits;
|
||||
pub use self::util::transitive_bounds;
|
||||
pub use self::util::upcast;
|
||||
|
||||
mod coherence;
|
||||
mod error_reporting;
|
||||
|
|
|
@ -291,6 +291,58 @@ pub fn predicate_for_builtin_bound<'tcx>(
|
|||
})
|
||||
}
|
||||
|
||||
/// Cast a trait reference into a reference to one of its super
|
||||
/// traits; returns `None` if `target_trait_def_id` is not a
|
||||
/// supertrait.
|
||||
pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
source_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
target_trait_def_id: ast::DefId)
|
||||
-> Option<ty::PolyTraitRef<'tcx>>
|
||||
{
|
||||
if source_trait_ref.def_id() == target_trait_def_id {
|
||||
return Some(source_trait_ref); // shorcut the most common case
|
||||
}
|
||||
|
||||
for super_trait_ref in supertraits(tcx, source_trait_ref) {
|
||||
if super_trait_ref.def_id() == target_trait_def_id {
|
||||
return Some(super_trait_ref);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Given an object of type `object_trait_ref`, returns the index of
|
||||
/// the method `n_method` found in the trait `trait_def_id` (which
|
||||
/// should be a supertrait of `object_trait_ref`) within the vtable
|
||||
/// for `object_trait_ref`.
|
||||
pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
object_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
trait_def_id: ast::DefId,
|
||||
method_index_in_trait: uint) -> uint {
|
||||
// We need to figure the "real index" of the method in a
|
||||
// listing of all the methods of an object. We do this by
|
||||
// iterating down the supertraits of the object's trait until
|
||||
// we find the trait the method came from, counting up the
|
||||
// methods from them.
|
||||
let mut method_count = 0;
|
||||
ty::each_bound_trait_and_supertraits(tcx, &[object_trait_ref], |bound_ref| {
|
||||
if bound_ref.def_id() == trait_def_id {
|
||||
false
|
||||
} else {
|
||||
let trait_items = ty::trait_items(tcx, bound_ref.def_id());
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(_) => method_count += 1,
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
});
|
||||
method_count + method_index_in_trait
|
||||
}
|
||||
|
||||
impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
format!("Obligation(predicate={},depth={})",
|
||||
|
|
|
@ -633,17 +633,16 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
|||
target_trait_def_id: ast::DefId)
|
||||
-> ty::PolyTraitRef<'tcx>
|
||||
{
|
||||
for super_trait_ref in traits::supertraits(self.tcx(), source_trait_ref.clone()) {
|
||||
if super_trait_ref.def_id() == target_trait_def_id {
|
||||
return super_trait_ref;
|
||||
match traits::upcast(self.tcx(), source_trait_ref.clone(), target_trait_def_id) {
|
||||
Some(super_trait_ref) => super_trait_ref,
|
||||
None => {
|
||||
self.tcx().sess.span_bug(
|
||||
self.span,
|
||||
format!("cannot upcast `{}` to `{}`",
|
||||
source_trait_ref.repr(self.tcx()),
|
||||
target_trait_def_id.repr(self.tcx()))[]);
|
||||
}
|
||||
}
|
||||
|
||||
self.tcx().sess.span_bug(
|
||||
self.span,
|
||||
format!("cannot upcast `{}` to `{}`",
|
||||
source_trait_ref.repr(self.tcx()),
|
||||
target_trait_def_id.repr(self.tcx()))[]);
|
||||
}
|
||||
|
||||
fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
|
||||
|
|
|
@ -308,7 +308,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
|||
let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
|
||||
self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
|
||||
let vtable_index =
|
||||
get_method_index(tcx, &new_trait_ref, trait_ref.clone(), method_num);
|
||||
traits::get_vtable_index_of_object_method(tcx,
|
||||
trait_ref.clone(),
|
||||
new_trait_ref.def_id(),
|
||||
method_num);
|
||||
|
||||
let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs());
|
||||
|
||||
|
@ -996,35 +999,6 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
.and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
|
||||
}
|
||||
|
||||
// Determine the index of a method in the list of all methods belonging
|
||||
// to a trait and its supertraits.
|
||||
fn get_method_index<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
subtrait: ty::PolyTraitRef<'tcx>,
|
||||
n_method: uint) -> uint {
|
||||
// We need to figure the "real index" of the method in a
|
||||
// listing of all the methods of an object. We do this by
|
||||
// iterating down the supertraits of the object's trait until
|
||||
// we find the trait the method came from, counting up the
|
||||
// methods from them.
|
||||
let mut method_count = n_method;
|
||||
ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
|
||||
if bound_ref.def_id() == trait_ref.def_id() {
|
||||
false
|
||||
} else {
|
||||
let trait_items = ty::trait_items(tcx, bound_ref.def_id());
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(_) => method_count += 1,
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
});
|
||||
method_count
|
||||
}
|
||||
|
||||
impl<'tcx> Candidate<'tcx> {
|
||||
fn to_unadjusted_pick(&self) -> Pick<'tcx> {
|
||||
Pick {
|
||||
|
|
Loading…
Reference in a new issue