mirror of https://github.com/rust-lang/rust.git
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
|
@ -34,10 +34,12 @@ pub use self::select::SelectionCache;
|
||||||
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
|
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
|
||||||
pub use self::select::{MethodMatchedData}; // intentionally don't export variants
|
pub use self::select::{MethodMatchedData}; // intentionally don't export variants
|
||||||
pub use self::util::elaborate_predicates;
|
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::trait_ref_for_builtin_bound;
|
||||||
pub use self::util::supertraits;
|
pub use self::util::supertraits;
|
||||||
pub use self::util::Supertraits;
|
pub use self::util::Supertraits;
|
||||||
pub use self::util::transitive_bounds;
|
pub use self::util::transitive_bounds;
|
||||||
|
pub use self::util::upcast;
|
||||||
|
|
||||||
mod coherence;
|
mod coherence;
|
||||||
mod error_reporting;
|
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> {
|
impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
|
||||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||||
format!("Obligation(predicate={},depth={})",
|
format!("Obligation(predicate={},depth={})",
|
||||||
|
|
|
@ -633,17 +633,16 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||||
target_trait_def_id: ast::DefId)
|
target_trait_def_id: ast::DefId)
|
||||||
-> ty::PolyTraitRef<'tcx>
|
-> ty::PolyTraitRef<'tcx>
|
||||||
{
|
{
|
||||||
for super_trait_ref in traits::supertraits(self.tcx(), source_trait_ref.clone()) {
|
match traits::upcast(self.tcx(), source_trait_ref.clone(), target_trait_def_id) {
|
||||||
if super_trait_ref.def_id() == target_trait_def_id {
|
Some(super_trait_ref) => super_trait_ref,
|
||||||
return 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
|
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);
|
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| {
|
self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
|
||||||
let vtable_index =
|
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());
|
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)))
|
.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> {
|
impl<'tcx> Candidate<'tcx> {
|
||||||
fn to_unadjusted_pick(&self) -> Pick<'tcx> {
|
fn to_unadjusted_pick(&self) -> Pick<'tcx> {
|
||||||
Pick {
|
Pick {
|
||||||
|
|
Loading…
Reference in New Issue