rustc: simplify ty::MethodOrigin and avoid trait item indices.

This commit is contained in:
Eduard Burtescu 2015-07-02 08:52:36 +03:00
parent fe354e58bd
commit 70365ed911
23 changed files with 328 additions and 691 deletions

View File

@ -29,7 +29,7 @@ use middle::check_const::ConstQualif;
use middle::privacy::{AllPublic, LastMod};
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin};
use middle::ty::{self, Ty};
use syntax::{ast, ast_util, codemap, fold};
use syntax::codemap::Span;
@ -600,26 +600,29 @@ impl tr for ty::UpvarCapture {
trait read_method_callee_helper<'tcx> {
fn read_method_callee<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> (u32, MethodCallee<'tcx>);
-> (u32, ty::MethodCallee<'tcx>);
}
fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
autoderef: u32,
method: &MethodCallee<'tcx>) {
method: &ty::MethodCallee<'tcx>) {
use serialize::Encoder;
rbml_w.emit_struct("MethodCallee", 4, |rbml_w| {
rbml_w.emit_struct("MethodCallee", 5, |rbml_w| {
rbml_w.emit_struct_field("autoderef", 0, |rbml_w| {
autoderef.encode(rbml_w)
});
rbml_w.emit_struct_field("origin", 1, |rbml_w| {
Ok(rbml_w.emit_method_origin(ecx, &method.origin))
rbml_w.emit_struct_field("def_id", 1, |rbml_w| {
Ok(rbml_w.emit_def_id(method.def_id))
});
rbml_w.emit_struct_field("ty", 2, |rbml_w| {
rbml_w.emit_struct_field("origin", 2, |rbml_w| {
Ok(rbml_w.emit_method_origin(method.origin))
});
rbml_w.emit_struct_field("ty", 3, |rbml_w| {
Ok(rbml_w.emit_ty(ecx, method.ty))
});
rbml_w.emit_struct_field("substs", 3, |rbml_w| {
rbml_w.emit_struct_field("substs", 4, |rbml_w| {
Ok(rbml_w.emit_substs(ecx, &method.substs))
})
}).unwrap();
@ -627,21 +630,24 @@ fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>,
impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> {
fn read_method_callee<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> (u32, MethodCallee<'tcx>) {
-> (u32, ty::MethodCallee<'tcx>) {
self.read_struct("MethodCallee", 4, |this| {
self.read_struct("MethodCallee", 5, |this| {
let autoderef = this.read_struct_field("autoderef", 0, |this| {
Decodable::decode(this)
}).unwrap();
Ok((autoderef, MethodCallee {
origin: this.read_struct_field("origin", 1, |this| {
Ok((autoderef, ty::MethodCallee {
def_id: this.read_struct_field("def_id", 1, |this| {
Ok(this.read_def_id(dcx))
}).unwrap(),
origin: this.read_struct_field("origin", 2, |this| {
Ok(this.read_method_origin(dcx))
}).unwrap(),
ty: this.read_struct_field("ty", 2, |this| {
ty: this.read_struct_field("ty", 3, |this| {
Ok(this.read_ty(dcx))
}).unwrap(),
substs: this.read_struct_field("substs", 3, |this| {
Ok(this.read_substs(dcx))
substs: this.read_struct_field("substs", 4, |this| {
Ok(dcx.tcx.mk_substs(this.read_substs(dcx)))
}).unwrap()
}))
}).unwrap()
@ -707,9 +713,7 @@ impl<'a, 'tcx> get_ty_str_ctxt<'tcx> for e::EncodeContext<'a, 'tcx> {
trait rbml_writer_helpers<'tcx> {
fn emit_closure_type<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
closure_type: &ty::ClosureTy<'tcx>);
fn emit_method_origin<'a>(&mut self,
ecx: &e::EncodeContext<'a, 'tcx>,
method_origin: &ty::MethodOrigin<'tcx>);
fn emit_method_origin(&mut self, method_origin: ty::MethodOrigin);
fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>);
fn emit_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]);
fn emit_type_param_def<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
@ -741,61 +745,31 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
});
}
fn emit_method_origin<'b>(&mut self,
ecx: &e::EncodeContext<'b, 'tcx>,
method_origin: &ty::MethodOrigin<'tcx>)
{
fn emit_method_origin(&mut self, method_origin: ty::MethodOrigin) {
use serialize::Encoder;
self.emit_enum("MethodOrigin", |this| {
match *method_origin {
ty::MethodStatic(def_id) => {
this.emit_enum_variant("MethodStatic", 0, 1, |this| {
Ok(this.emit_def_id(def_id))
})
match method_origin {
ty::MethodOrigin::Inherent => {
this.emit_enum_variant("Inherent", 0, 0, |_| Ok(()))
}
ty::MethodTypeParam(ref p) => {
this.emit_enum_variant("MethodTypeParam", 1, 1, |this| {
this.emit_struct("MethodParam", 2, |this| {
try!(this.emit_struct_field("trait_ref", 0, |this| {
Ok(this.emit_trait_ref(ecx, &p.trait_ref))
}));
try!(this.emit_struct_field("method_num", 0, |this| {
this.emit_uint(p.method_num)
}));
try!(this.emit_struct_field("impl_def_id", 0, |this| {
this.emit_option(|this| {
match p.impl_def_id {
None => this.emit_option_none(),
Some(did) => this.emit_option_some(|this| {
Ok(this.emit_def_id(did))
})
}
ty::MethodOrigin::Trait(impl_def_id) => {
this.emit_enum_variant("Trait", 1, 1, |this| {
this.emit_option(|this| {
match impl_def_id {
None => this.emit_option_none(),
Some(did) => this.emit_option_some(|this| {
Ok(this.emit_def_id(did))
})
}));
Ok(())
}
})
})
}
ty::MethodTraitObject(ref o) => {
this.emit_enum_variant("MethodTraitObject", 2, 1, |this| {
this.emit_struct("MethodObject", 2, |this| {
try!(this.emit_struct_field("trait_ref", 0, |this| {
Ok(this.emit_trait_ref(ecx, &o.trait_ref))
}));
try!(this.emit_struct_field("object_trait_id", 0, |this| {
Ok(this.emit_def_id(o.object_trait_id))
}));
try!(this.emit_struct_field("method_num", 0, |this| {
this.emit_uint(o.method_num)
}));
try!(this.emit_struct_field("vtable_index", 0, |this| {
this.emit_uint(o.vtable_index)
}));
Ok(())
})
ty::MethodOrigin::Object(vtable_index) => {
this.emit_enum_variant("Object", 2, 1, |this| {
this.emit_uint(vtable_index)
})
}
}
@ -1071,7 +1045,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
})
}
let method_call = MethodCall::expr(id);
let method_call = ty::MethodCall::expr(id);
if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) {
rbml_w.tag(c::tag_table_method_map, |rbml_w| {
rbml_w.id(id);
@ -1083,7 +1057,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
match *adjustment {
ty::AdjustDerefRef(ref adj) => {
for autoderef in 0..adj.autoderefs {
let method_call = MethodCall::autoderef(id, autoderef as u32);
let method_call = ty::MethodCall::autoderef(id, autoderef as u32);
if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) {
rbml_w.tag(c::tag_table_method_map, |rbml_w| {
rbml_w.id(id);
@ -1144,8 +1118,7 @@ impl<'a> doc_decoder_helpers for rbml::Doc<'a> {
}
trait rbml_decoder_decoder_helpers<'tcx> {
fn read_method_origin<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::MethodOrigin<'tcx>;
fn read_method_origin(&mut self, dcx: &DecodeContext) -> ty::MethodOrigin;
fn read_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Ty<'tcx>;
fn read_tys<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Vec<Ty<'tcx>>;
fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@ -1229,77 +1202,25 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
}).unwrap()
}
fn read_method_origin<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> ty::MethodOrigin<'tcx>
{
fn read_method_origin(&mut self, dcx: &DecodeContext) -> ty::MethodOrigin {
self.read_enum("MethodOrigin", |this| {
let variants = &["MethodStatic", "MethodTypeParam", "MethodTraitObject"];
let variants = &["Inherent", "Trait", "Object"];
this.read_enum_variant(variants, |this, i| {
Ok(match i {
0 => {
let def_id = this.read_def_id(dcx);
ty::MethodStatic(def_id)
}
match i {
0 => Ok(ty::MethodOrigin::Inherent),
1 => {
this.read_struct("MethodTypeParam", 2, |this| {
Ok(ty::MethodTypeParam(
ty::MethodParam {
trait_ref: {
this.read_struct_field("trait_ref", 0, |this| {
Ok(this.read_trait_ref(dcx))
}).unwrap()
},
method_num: {
this.read_struct_field("method_num", 1, |this| {
this.read_uint()
}).unwrap()
},
impl_def_id: {
this.read_struct_field("impl_def_id", 2, |this| {
this.read_option(|this, b| {
if b {
Ok(Some(this.read_def_id(dcx)))
} else {
Ok(None)
}
})
}).unwrap()
}
}))
}).unwrap()
}
1 => this.read_option(|this, b| {
Ok(ty::MethodOrigin::Trait(if b {
Some(this.read_def_id(dcx))
} else {
None
}))
}),
2 => {
this.read_struct("MethodTraitObject", 2, |this| {
Ok(ty::MethodTraitObject(
ty::MethodObject {
trait_ref: {
this.read_struct_field("trait_ref", 0, |this| {
Ok(this.read_trait_ref(dcx))
}).unwrap()
},
object_trait_id: {
this.read_struct_field("object_trait_id", 1, |this| {
Ok(this.read_def_id(dcx))
}).unwrap()
},
method_num: {
this.read_struct_field("method_num", 2, |this| {
this.read_uint()
}).unwrap()
},
vtable_index: {
this.read_struct_field("vtable_index", 3, |this| {
this.read_uint()
}).unwrap()
},
}))
}).unwrap()
}
2 => this.read_uint().map(|idx| ty::MethodOrigin::Object(idx)),
_ => panic!("..")
})
}
})
}).unwrap()
}
@ -1651,7 +1572,7 @@ fn decode_side_tables(dcx: &DecodeContext,
}
c::tag_table_method_map => {
let (autoderef, method) = val_dsr.read_method_callee(dcx);
let method_call = MethodCall {
let method_call = ty::MethodCall {
expr_id: id,
autoderef: autoderef
};

View File

@ -696,13 +696,11 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
}
}
ast::ExprMethodCall(..) => {
let method_did = match v.tcx.tables.borrow().method_map[&method_call].origin {
ty::MethodStatic(did) => Some(did),
_ => None
};
let is_const = match method_did {
Some(did) => v.handle_const_fn_call(e, did, node_ty),
None => false
let is_const = match v.tcx.tables.borrow().method_map[&method_call] {
ty::MethodCallee { def_id, origin: ty::MethodOrigin::Inherent, .. } => {
v.handle_const_fn_call(e, def_id, node_ty)
}
_ => false
};
if !is_const {
v.add_qualif(ConstQualif::NOT_CONST);

View File

@ -97,29 +97,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
span: codemap::Span) {
let method_call = ty::MethodCall::expr(id);
match self.tcx.tables.borrow().method_map.get(&method_call) {
Some(method) => {
match method.origin {
ty::MethodStatic(def_id) => {
match self.tcx.provided_source(def_id) {
Some(p_did) => self.check_def_id(p_did),
None => self.check_def_id(def_id)
}
}
ty::MethodTypeParam(ty::MethodParam {
ref trait_ref,
method_num: index,
..
}) |
ty::MethodTraitObject(ty::MethodObject {
ref trait_ref,
method_num: index,
..
}) => {
let trait_item = self.tcx.trait_item(trait_ref.def_id, index);
self.check_def_id(trait_item.def_id());
}
}
}
Some(method) => self.check_def_id(method.def_id),
None => {
self.tcx.sess.span_bug(span,
"method call expression not \

View File

@ -23,10 +23,7 @@ use self::OverloadedCallType::*;
use middle::{def, region, pat_util};
use middle::infer;
use middle::mem_categorization as mc;
use middle::ty::{self};
use middle::ty::{MethodCall, MethodObject, MethodTraitObject};
use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam};
use middle::ty::{MethodStatic, MethodStaticClosure};
use middle::ty;
use syntax::{ast, ast_util};
use syntax::ptr::P;
@ -229,42 +226,8 @@ impl OverloadedCallType {
fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
-> OverloadedCallType {
let method_descriptor = match tcx.impl_or_trait_item(method_id) {
ty::MethodTraitItem(ref method_descriptor) => {
(*method_descriptor).clone()
}
_ => {
tcx.sess.bug("overloaded call method wasn't in method map")
}
};
let impl_id = match method_descriptor.container {
ty::TraitContainer(_) => {
tcx.sess.bug("statically resolved overloaded call method \
belonged to a trait?!")
}
ty::ImplContainer(impl_id) => impl_id,
};
let trait_ref = match tcx.impl_trait_ref(impl_id) {
None => {
tcx.sess.bug("statically resolved overloaded call impl \
didn't implement a trait?!")
}
Some(ref trait_ref) => (*trait_ref).clone(),
};
OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
}
fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin)
-> OverloadedCallType {
match *origin {
MethodStatic(def_id) => {
OverloadedCallType::from_method_id(tcx, def_id)
}
MethodTypeParam(MethodParam { ref trait_ref, .. }) |
MethodTraitObject(MethodObject { ref trait_ref, .. }) => {
OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
}
}
let method = tcx.impl_or_trait_item(method_id);
OverloadedCallType::from_trait_id(tcx, method.container().id())
}
}
@ -614,11 +577,9 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
ty::TyError => { }
_ => {
let overloaded_call_type =
match self.typer.node_method_origin(MethodCall::expr(call.id)) {
Some(method_origin) => {
OverloadedCallType::from_method_origin(
self.tcx(),
&method_origin)
match self.typer.node_method_id(ty::MethodCall::expr(call.id)) {
Some(method_id) => {
OverloadedCallType::from_method_id(self.tcx(), method_id)
}
None => {
self.tcx().sess.span_bug(

View File

@ -1327,7 +1327,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
pub fn node_method_ty(&self, method_call: ty::MethodCall)
-> Option<Ty<'tcx>> {
-> Option<Ty<'tcx>> {
self.tables
.borrow()
.method_map
@ -1336,14 +1336,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.map(|ty| self.resolve_type_vars_if_possible(&ty))
}
pub fn node_method_origin(&self, method_call: ty::MethodCall)
-> Option<ty::MethodOrigin<'tcx>>
{
pub fn node_method_id(&self, method_call: ty::MethodCall)
-> Option<ast::DefId> {
self.tables
.borrow()
.method_map
.get(&method_call)
.map(|method| method.origin.clone())
.map(|method| method.def_id)
}
pub fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {

View File

@ -128,8 +128,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
}
ast::ExprMethodCall(..) => {
let method_call = ty::MethodCall::expr(expr.id);
match self.tcx.tables.borrow().method_map.get(&method_call).unwrap().origin {
ty::MethodStatic(def_id) => {
match self.tcx.tables.borrow().method_map[&method_call] {
ty::MethodCallee { def_id, origin: ty::MethodOrigin::Inherent, .. } => {
if is_local(def_id) {
if self.def_id_represents_local_inlined_item(def_id) {
self.worklist.push(def_id.node)

View File

@ -407,25 +407,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
span = i.span;
let method_call = ty::MethodCall::expr(e.id);
match tcx.tables.borrow().method_map.get(&method_call) {
Some(method) => {
match method.origin {
ty::MethodStatic(def_id) => {
def_id
}
ty::MethodTypeParam(ty::MethodParam {
ref trait_ref,
method_num: index,
..
}) |
ty::MethodTraitObject(ty::MethodObject {
ref trait_ref,
method_num: index,
..
}) => {
tcx.trait_item(trait_ref.def_id, index).def_id()
}
}
}
Some(method) => method.def_id,
None => return
}
}

View File

@ -141,19 +141,25 @@ impl<'tcx> Substs<'tcx> {
{
let Substs { types, regions } = self;
let types = types.with_vec(FnSpace, m_types);
let regions = regions.map(m_regions,
|r, m_regions| r.with_vec(FnSpace, m_regions));
let regions = regions.map(|r| r.with_vec(FnSpace, m_regions));
Substs { types: types, regions: regions }
}
pub fn method_to_trait(self) -> Substs<'tcx> {
let Substs { mut types, regions } = self;
types.truncate(FnSpace, 0);
let regions = regions.map(|mut r| { r.truncate(FnSpace, 0); r });
Substs { types: types, regions: regions }
}
}
impl RegionSubsts {
fn map<A, F>(self, a: A, op: F) -> RegionSubsts where
F: FnOnce(VecPerParamSpace<ty::Region>, A) -> VecPerParamSpace<ty::Region>,
fn map<F>(self, op: F) -> RegionSubsts where
F: FnOnce(VecPerParamSpace<ty::Region>) -> VecPerParamSpace<ty::Region>,
{
match self {
ErasedRegions => ErasedRegions,
NonerasedRegions(r) => NonerasedRegions(op(r, a))
NonerasedRegions(r) => NonerasedRegions(op(r))
}
}

View File

@ -397,13 +397,11 @@ pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
}
/// 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`.
/// the method `method_def_id` (which should be part of 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_offset_in_trait: usize) -> usize {
method_def_id: ast::DefId) -> usize {
// 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
@ -411,6 +409,8 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
// methods from them.
let mut method_count = 0;
let trait_def_id = tcx.impl_or_trait_item(method_def_id).container().id();
for bound_ref in transitive_bounds(tcx, &[object_trait_ref]) {
if bound_ref.def_id() == trait_def_id {
break;
@ -427,21 +427,24 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
// count number of methods preceding the one we are selecting and
// add them to the total offset; skip over associated types.
let trait_items = tcx.trait_items(trait_def_id);
for trait_item in trait_items.iter().take(method_offset_in_trait) {
for trait_item in &tcx.trait_items(trait_def_id)[..] {
if trait_item.def_id() == method_def_id {
// The item with the ID we were given really ought to be a method.
assert!(match *trait_item {
ty::MethodTraitItem(_) => true,
_ => false
});
return method_count;
}
match *trait_item {
ty::MethodTraitItem(_) => method_count += 1,
_ => {}
}
}
// the item at the offset we were given really ought to be a method
assert!(match trait_items[method_offset_in_trait] {
ty::MethodTraitItem(_) => true,
_ => false
});
method_count
tcx.sess.bug(&format!("get_vtable_index_of_object_method: {:?} was not found",
method_def_id));
}
pub enum TupleArgumentsFlag { Yes, No }

View File

@ -30,7 +30,6 @@ pub use self::ImplOrTraitItem::*;
pub use self::BoundRegion::*;
pub use self::TypeVariants::*;
pub use self::IntVarValue::*;
pub use self::MethodOrigin::*;
pub use self::CopyImplementationError::*;
pub use self::BuiltinBound::Send as BoundSend;
@ -330,7 +329,7 @@ impl IntTypeExt for attr::IntType {
}
}
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum ImplOrTraitItemContainer {
TraitContainer(ast::DefId),
ImplContainer(ast::DefId),
@ -626,65 +625,33 @@ pub enum CustomCoerceUnsized {
Struct(usize)
}
#[derive(Clone)]
pub enum MethodOrigin<'tcx> {
// fully statically resolved method
MethodStatic(ast::DefId),
#[derive(Clone, Copy, Debug)]
pub enum MethodOrigin {
/// Inherent impl method call.
Inherent,
// method invoked on a type parameter with a bounded trait
MethodTypeParam(MethodParam<'tcx>),
/// Statically dispatched trait method call.
/// The DefId is the impl for the trait from which the method comes.
/// This should only be used for certain linting/heuristic purposes
/// since there is no guarantee that this is Some in every situation
/// that it could/should be.
Trait(Option<ast::DefId>),
// method invoked on a trait instance
MethodTraitObject(MethodObject<'tcx>),
}
// details for a method invoked with a receiver whose type is a type parameter
// with a bounded trait.
#[derive(Clone)]
pub struct MethodParam<'tcx> {
// the precise trait reference that occurs as a bound -- this may
// be a supertrait of what the user actually typed. Note that it
// never contains bound regions; those regions should have been
// instantiated with fresh variables at this point.
pub trait_ref: ty::TraitRef<'tcx>,
// index of usize in the list of trait items. Note that this is NOT
// the index into the vtable, because the list of trait items
// includes associated types.
pub method_num: usize,
/// The impl for the trait from which the method comes. This
/// should only be used for certain linting/heuristic purposes
/// since there is no guarantee that this is Some in every
/// situation that it could/should be.
pub impl_def_id: Option<ast::DefId>,
}
// details for a method invoked with a receiver whose type is an object
#[derive(Clone)]
pub struct MethodObject<'tcx> {
// the (super)trait containing the method to be invoked
pub trait_ref: TraitRef<'tcx>,
// the actual base trait id of the object
pub object_trait_id: ast::DefId,
// index of the method to be invoked amongst the trait's items
pub method_num: usize,
// index into the actual runtime vtable.
// the vtable is formed by concatenating together the method lists of
// the base object trait and all supertraits; this is the index into
// that vtable
pub vtable_index: usize,
/// Dynamically dispatched trait method call.
/// The usize is the index into the actual runtime vtable.
/// The vtable is formed by concatenating together the method lists of
/// the base object trait and all supertraits; this is the index into
/// that vtable.
Object(usize)
}
#[derive(Clone, Debug)]
pub struct MethodCallee<'tcx> {
pub origin: MethodOrigin<'tcx>,
/// Impl method ID, for inherent methods, or trait method ID, otherwise.
pub def_id: ast::DefId,
pub origin: MethodOrigin,
pub ty: Ty<'tcx>,
pub substs: subst::Substs<'tcx>
pub substs: &'tcx subst::Substs<'tcx>
}
/// With method calls, we store some extra information in
@ -5592,11 +5559,6 @@ impl<'tcx> ctxt<'tcx> {
}
}
pub fn trait_item(&self, trait_did: ast::DefId, idx: usize) -> ImplOrTraitItem<'tcx> {
let method_def_id = self.trait_item_def_ids(trait_did)[idx].def_id();
self.impl_or_trait_item(method_def_id)
}
pub fn trait_items(&self, trait_did: ast::DefId) -> Rc<Vec<ImplOrTraitItem<'tcx>>> {
let mut trait_items = self.trait_items_cache.borrow_mut();
match trait_items.get(&trait_did).cloned() {
@ -6440,10 +6402,9 @@ impl<'tcx> ctxt<'tcx> {
let name = impl_item.name();
match self.trait_of_item(def_id) {
Some(trait_did) => {
let trait_items = self.trait_items(trait_did);
trait_items.iter()
.position(|m| m.name() == name)
.map(|idx| self.trait_item(trait_did, idx).id())
self.trait_items(trait_did).iter()
.find(|item| item.name() == name)
.map(|item| item.id())
}
None => None
}

View File

@ -310,31 +310,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::AutoRef<'tcx> {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::MethodOrigin<'tcx> {
match *self {
ty::MethodStatic(def_id) => {
ty::MethodStatic(def_id)
}
ty::MethodTypeParam(ref param) => {
ty::MethodTypeParam(ty::MethodParam {
trait_ref: param.trait_ref.fold_with(folder),
method_num: param.method_num,
impl_def_id: param.impl_def_id,
})
}
ty::MethodTraitObject(ref object) => {
ty::MethodTraitObject(ty::MethodObject {
trait_ref: object.trait_ref.fold_with(folder),
object_trait_id: object.object_trait_id,
method_num: object.method_num,
vtable_index: object.vtable_index,
})
}
}
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
*self

View File

@ -494,35 +494,6 @@ impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
}
}
impl<'tcx> fmt::Debug for ty::MethodOrigin<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::MethodStatic(def_id) => {
write!(f, "MethodStatic({:?})", def_id)
}
ty::MethodTypeParam(ref p) => write!(f, "{:?}", p),
ty::MethodTraitObject(ref p) => write!(f, "{:?}", p)
}
}
}
impl<'tcx> fmt::Debug for ty::MethodParam<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MethodParam({:?},{})",
self.trait_ref,
self.method_num)
}
}
impl<'tcx> fmt::Debug for ty::MethodObject<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MethodObject({:?},{},{})",
self.trait_ref,
self.method_num,
self.vtable_index)
}
}
impl<'tcx> fmt::Debug for ty::ExistentialBounds<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut empty = true;

View File

@ -2000,20 +2000,16 @@ impl LintPass for UnconditionalRecursion {
Some(m) => match m.origin {
// There's no way to know if a method call via a
// vtable is recursion, so we assume it's not.
ty::MethodTraitObject(_) => return false,
ty::MethodOrigin::Object(_) => return false,
// This `did` refers directly to the method definition.
ty::MethodStatic(did) => did,
// MethodTypeParam are methods from traits:
ty::MethodOrigin::Inherent => m.def_id,
// The `impl ... for ...` of this method call
// isn't known, e.g. it might be a default method
// in a trait, so we get the def-id of the trait
// method instead.
ty::MethodTypeParam(
ty::MethodParam { ref trait_ref, method_num, impl_def_id: None, }) => {
ty::MethodOrigin::Trait(None) => {
let on_self = m.substs.self_ty().map_or(false, |t| t.is_self());
if !on_self {
// we can only be recurring in a default
@ -2021,14 +2017,13 @@ impl LintPass for UnconditionalRecursion {
// on the `Self` type.
return false
}
tcx.trait_item(trait_ref.def_id, method_num).def_id()
m.def_id
}
// The `impl` is known, so we check that with a
// special case:
ty::MethodTypeParam(
ty::MethodParam { impl_def_id: Some(impl_def_id), .. }) => {
ty::MethodOrigin::Trait(Some(impl_def_id)) => {
let name = match tcx.map.expect_expr(id).node {
ast::ExprMethodCall(ref sp_ident, _, _) => sp_ident.node,

View File

@ -40,10 +40,6 @@ use rustc::middle::privacy::ImportUse::*;
use rustc::middle::privacy::LastPrivate::*;
use rustc::middle::privacy::PrivateDep::*;
use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
use rustc::middle::ty::{MethodTypeParam, MethodStatic};
use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
use rustc::middle::ty::{MethodStaticClosure, MethodObject};
use rustc::middle::ty::MethodTraitObject;
use rustc::middle::ty::{self, Ty};
use rustc::util::nodemap::{NodeMap, NodeSet};
@ -53,7 +49,7 @@ use syntax::codemap::Span;
use syntax::parse::token;
use syntax::visit::{self, Visitor};
type Context<'a, 'tcx> = (&'a MethodMap<'tcx>, &'a def::ExportMap);
type Context<'a, 'tcx> = (&'a ty::MethodMap<'tcx>, &'a def::ExportMap);
/// Result of a checking operation - None => no errors were found. Some => an
/// error and contains the span and message for reporting that error and
@ -848,17 +844,17 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
}
// Checks that a method is in scope.
fn check_method(&mut self, span: Span, origin: &MethodOrigin,
fn check_method(&mut self, span: Span, callee: &ty::MethodCallee,
name: ast::Name) {
match *origin {
MethodStatic(method_id) => {
self.check_static_method(span, method_id, name)
match callee.origin {
ty::MethodOrigin::Inherent => {
self.check_static_method(span, callee.def_id, name)
}
// Trait methods are always all public. The only controlling factor
// is whether the trait itself is accessible or not.
MethodTypeParam(MethodParam { ref trait_ref, .. }) |
MethodTraitObject(MethodObject { ref trait_ref, .. }) => {
self.report_error(self.ensure_public(span, trait_ref.def_id,
ty::MethodOrigin::Trait(_) | ty::MethodOrigin::Object(_) => {
let method = self.tcx.impl_or_trait_item(callee.def_id);
self.report_error(self.ensure_public(span, method.container().id(),
None, "source trait"));
}
}
@ -902,7 +898,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
}
}
ast::ExprMethodCall(ident, _, _) => {
let method_call = MethodCall::expr(expr.id);
let method_call = ty::MethodCall::expr(expr.id);
match self.tcx.tables.borrow().method_map.get(&method_call) {
None => {
self.tcx.sess.span_bug(expr.span,
@ -911,7 +907,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
}
Some(method) => {
debug!("(privacy checking) checking impl method");
self.check_method(expr.span, &method.origin, ident.node.name);
self.check_method(expr.span, method, ident.node.name);
}
}
}

View File

@ -889,38 +889,12 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
let method_map = &self.tcx.tables.borrow().method_map;
let method_callee = method_map.get(&ty::MethodCall::expr(ex.id)).unwrap();
let (def_id, decl_id) = match method_callee.origin {
ty::MethodStatic(def_id) => {
// method invoked on an object with a concrete type (not a static method)
let decl_id =
match self.tcx.trait_item_of_item(def_id) {
None => None,
Some(decl_id) => Some(decl_id.def_id()),
};
// This incantation is required if the method referenced is a
// trait's default implementation.
let def_id = match self.tcx.impl_or_trait_item(def_id) {
ty::MethodTraitItem(method) => {
method.provided_source.unwrap_or(def_id)
}
_ => self.sess
.span_bug(ex.span,
"save::process_method_call: non-method \
DefId in MethodStatic"),
};
(Some(def_id), decl_id)
ty::MethodOrigin::Inherent => {
(Some(method_callee.def_id), None)
}
ty::MethodTypeParam(ref mp) => {
// method invoked on a type parameter
let trait_item = self.tcx.trait_item(mp.trait_ref.def_id,
mp.method_num);
(None, Some(trait_item.def_id()))
}
ty::MethodTraitObject(ref mo) => {
// method invoked on a trait instance
let trait_item = self.tcx.trait_item(mo.trait_ref.def_id,
mo.method_num);
(None, Some(trait_item.def_id()))
ty::MethodOrigin::Trait(_) |
ty::MethodOrigin::Object(_) => {
(None, Some(method_callee.def_id))
}
};
let sub_span = self.span.sub_span_for_meth_name(ex.span);

View File

@ -612,7 +612,7 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let method_call = MethodCall::expr(call_expr.id);
let method_ty = match bcx.tcx().tables.borrow().method_map.get(&method_call) {
Some(method) => match method.origin {
ty::MethodTraitObject(_) => match method.ty.sty {
ty::MethodOrigin::Object(_) => match method.ty.sty {
ty::TyBareFn(_, ref fty) => {
bcx.tcx().mk_fn(None, meth::opaque_method_ty(bcx.tcx(), fty))
}

View File

@ -894,10 +894,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ast::ExprMethodCall(_, _, ref args) => {
let arg_vals = map_list(args);
let method_call = ty::MethodCall::expr(e.id);
let method_did = match cx.tcx().tables.borrow().method_map[&method_call].origin {
ty::MethodStatic(did) => did,
_ => cx.sess().span_bug(e.span, "expected a const method def")
};
let method_did = cx.tcx().tables.borrow().method_map[&method_call].def_id;
const_fn_call(cx, MethodCallKey(method_call),
method_did, &arg_vals, param_substs)
}

View File

@ -107,33 +107,36 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-> Callee<'blk, 'tcx> {
let _icx = push_ctxt("meth::trans_method_callee");
let (origin, method_ty) =
let (method_id, origin, method_substs, method_ty) =
bcx.tcx()
.tables
.borrow()
.method_map
.get(&method_call)
.map(|method| (method.origin.clone(), method.ty))
.map(|method| (method.def_id, method.origin, method.substs, method.ty))
.unwrap();
match origin {
ty::MethodStatic(did) => {
debug!("trans_method_callee: static, {:?}", did);
ty::MethodOrigin::Inherent => {
debug!("trans_method_callee: static, {:?}", method_id);
Callee {
bcx: bcx,
data: Fn(callee::trans_fn_ref(bcx.ccx(),
did,
method_id,
MethodCallKey(method_call),
bcx.fcx.param_substs).val),
}
}
ty::MethodTypeParam(ty::MethodParam {
ref trait_ref,
method_num,
impl_def_id: _
}) => {
let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
ty::MethodOrigin::Trait(_) => {
let method_item = bcx.tcx().impl_or_trait_item(method_id);
let trait_def_id = method_item.container().id();
let trait_substs = method_substs.clone().method_to_trait();
let trait_substs = bcx.tcx().mk_substs(trait_substs);
let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
let trait_ref = ty::Binder(bcx.monomorphize(&trait_ref));
let span = bcx.tcx().map.span(method_call.expr_id);
debug!("method_call={:?} trait_ref={:?} trait_ref id={:?} substs={:?}",
method_call,
@ -146,12 +149,12 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debug!("origin = {:?}", origin);
trans_monomorphized_callee(bcx,
method_call,
trait_ref.def_id(),
method_num,
trait_def_id,
method_id,
origin)
}
ty::MethodTraitObject(ref mt) => {
ty::MethodOrigin::Object(vtable_index) => {
let self_expr = match self_expr {
Some(self_expr) => self_expr,
None => {
@ -162,7 +165,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
};
trans_trait_callee(bcx,
monomorphize_type(bcx, method_ty),
mt.vtable_index,
vtable_index,
self_expr,
arg_cleanup_scope)
}
@ -281,17 +284,11 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
callee_substs)
}
traits::VtableObject(ref data) => {
let trait_item_def_ids =
ccx.tcx().trait_item_def_ids(trait_id);
let method_offset_in_trait =
trait_item_def_ids.iter()
.position(|item| item.def_id() == method_id)
.unwrap();
let (llfn, ty) =
trans_object_shim(ccx,
data.object_ty,
data.upcast_trait_ref.clone(),
method_offset_in_trait);
method_id);
immediate_rvalue(llfn, ty)
}
_ => {
@ -326,7 +323,7 @@ fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name)
fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
method_call: MethodCall,
trait_id: ast::DefId,
n_method: usize,
method_id: ast::DefId,
vtable: traits::Vtable<'tcx, ()>)
-> Callee<'blk, 'tcx> {
let _icx = push_ctxt("meth::trans_monomorphized_callee");
@ -334,7 +331,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
traits::VtableImpl(vtable_impl) => {
let ccx = bcx.ccx();
let impl_did = vtable_impl.impl_def_id;
let mname = match ccx.tcx().trait_item(trait_id, n_method) {
let mname = match ccx.tcx().impl_or_trait_item(method_id) {
ty::MethodTraitItem(method) => method.name,
_ => {
bcx.tcx().sess.bug("can't monomorphize a non-method trait \
@ -382,7 +379,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let (llfn, _) = trans_object_shim(bcx.ccx(),
data.object_ty,
data.upcast_trait_ref.clone(),
n_method);
method_id);
Callee { bcx: bcx, data: Fn(llfn) }
}
traits::VtableBuiltin(..) |
@ -539,21 +536,20 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
///
/// In fact, all virtual calls can be thought of as normal trait calls
/// that go through this shim function.
pub fn trans_object_shim<'a, 'tcx>(
fn trans_object_shim<'a, 'tcx>(
ccx: &'a CrateContext<'a, 'tcx>,
object_ty: Ty<'tcx>,
upcast_trait_ref: ty::PolyTraitRef<'tcx>,
method_offset_in_trait: usize)
method_id: ast::DefId)
-> (ValueRef, Ty<'tcx>)
{
let _icx = push_ctxt("trans_object_shim");
let tcx = ccx.tcx();
let trait_id = upcast_trait_ref.def_id();
debug!("trans_object_shim(object_ty={:?}, upcast_trait_ref={:?}, method_offset_in_trait={})",
debug!("trans_object_shim(object_ty={:?}, upcast_trait_ref={:?}, method_id={:?})",
object_ty,
upcast_trait_ref,
method_offset_in_trait);
method_id);
let object_trait_ref =
match object_ty.sty {
@ -572,7 +568,7 @@ pub fn trans_object_shim<'a, 'tcx>(
debug!("trans_object_shim: object_substs={:?}", object_substs);
// Lookup the type of this method as declared in the trait and apply substitutions.
let method_ty = match tcx.trait_item(trait_id, method_offset_in_trait) {
let method_ty = match tcx.impl_or_trait_item(method_id) {
ty::MethodTraitItem(method) => method,
_ => {
tcx.sess.bug("can't create a method shim for a non-method item")
@ -624,8 +620,7 @@ pub fn trans_object_shim<'a, 'tcx>(
let method_offset_in_vtable =
traits::get_vtable_index_of_object_method(bcx.tcx(),
object_trait_ref.clone(),
trait_id,
method_offset_in_trait);
method_id);
debug!("trans_object_shim: method_offset_in_vtable={}",
method_offset_in_vtable);

View File

@ -15,8 +15,6 @@ use check::UnresolvedTypeAction;
use middle::subst::{self};
use middle::traits;
use middle::ty::{self, Ty};
use middle::ty::{MethodCall, MethodCallee, MethodObject, MethodOrigin,
MethodParam, MethodStatic, MethodTraitObject, MethodTypeParam};
use middle::ty_fold::TypeFoldable;
use middle::infer;
use middle::infer::InferCtxt;
@ -52,7 +50,7 @@ pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
unadjusted_self_ty: Ty<'tcx>,
pick: probe::Pick<'tcx>,
supplied_method_types: Vec<Ty<'tcx>>)
-> MethodCallee<'tcx>
-> ty::MethodCallee<'tcx>
{
debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
unadjusted_self_ty,
@ -77,7 +75,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
unadjusted_self_ty: Ty<'tcx>,
pick: probe::Pick<'tcx>,
supplied_method_types: Vec<Ty<'tcx>>)
-> MethodCallee<'tcx>
-> ty::MethodCallee<'tcx>
{
// Adjust the self expression the user provided and obtain the adjusted type.
let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
@ -112,10 +110,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
unsafety: method_ty.fty.unsafety,
abi: method_ty.fty.abi.clone(),
}));
let callee = MethodCallee {
let callee = ty::MethodCallee {
def_id: pick.item.def_id(),
origin: method_origin,
ty: fty,
substs: all_substs
substs: self.tcx().mk_substs(all_substs)
};
// If this is an `&mut self` method, bias the receiver
@ -194,18 +193,20 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
fn fresh_receiver_substs(&mut self,
self_ty: Ty<'tcx>,
pick: &probe::Pick<'tcx>)
-> (subst::Substs<'tcx>, MethodOrigin<'tcx>)
-> (subst::Substs<'tcx>, ty::MethodOrigin)
{
match pick.kind {
probe::InherentImplPick(impl_def_id) => {
probe::InherentImplPick => {
let impl_def_id = pick.item.container().id();
assert!(self.tcx().impl_trait_ref(impl_def_id).is_none(),
"impl {:?} is not an inherent impl", impl_def_id);
let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
(impl_polytype.substs, MethodStatic(pick.item.def_id()))
(impl_polytype.substs, ty::MethodOrigin::Inherent)
}
probe::ObjectPick(trait_def_id, method_num, vtable_index) => {
probe::ObjectPick => {
let trait_def_id = pick.item.container().id();
self.extract_trait_ref(self_ty, |this, object_ty, data| {
// The object data has no entry for the Self
// Type. For the purposes of this method call, we
@ -228,17 +229,16 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
upcast_trait_ref,
trait_def_id);
let substs = upcast_trait_ref.substs.clone();
let origin = MethodTraitObject(MethodObject {
trait_ref: upcast_trait_ref,
object_trait_id: trait_def_id,
method_num: method_num,
vtable_index: vtable_index,
});
(substs, origin)
let vtable_index =
traits::get_vtable_index_of_object_method(this.tcx(),
original_poly_trait_ref,
pick.item.def_id());
(substs, ty::MethodOrigin::Object(vtable_index))
})
}
probe::ExtensionImplPick(impl_def_id, method_num) => {
probe::ExtensionImplPick(impl_def_id) => {
// The method being invoked is the method as defined on the trait,
// so return the substitutions from the trait. Consider:
//
@ -254,13 +254,12 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
self.span,
&impl_polytype.substs,
&self.tcx().impl_trait_ref(impl_def_id).unwrap());
let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
method_num: method_num,
impl_def_id: Some(impl_def_id) });
(impl_trait_ref.substs.clone(), origin)
let substs = impl_trait_ref.substs.clone();
(substs, ty::MethodOrigin::Trait(Some(impl_def_id)))
}
probe::TraitPick(trait_def_id, method_num) => {
probe::TraitPick => {
let trait_def_id = pick.item.container().id();
let trait_def = self.tcx().lookup_trait_def(trait_def_id);
// Make a trait reference `$0 : Trait<$1...$n>`
@ -272,23 +271,15 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
&trait_def.generics,
self.infcx().next_ty_var());
let trait_ref =
ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone()));
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
method_num: method_num,
impl_def_id: None });
(substs, origin)
(substs, ty::MethodOrigin::Trait(None))
}
probe::WhereClausePick(ref poly_trait_ref, method_num) => {
probe::WhereClausePick(ref poly_trait_ref) => {
// Where clauses can have bound regions in them. We need to instantiate
// those to convert from a poly-trait-ref to a trait-ref.
let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
let substs = trait_ref.substs.clone();
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
method_num: method_num,
impl_def_id: None });
(substs, origin)
(substs, ty::MethodOrigin::Trait(None))
}
}
}
@ -450,7 +441,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
/// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut`
/// respectively.
fn fixup_derefs_on_method_receiver_if_necessary(&self,
method_callee: &MethodCallee) {
method_callee: &ty::MethodCallee) {
let sig = match method_callee.ty.sty {
ty::TyBareFn(_, ref f) => f.sig.clone(),
_ => return,
@ -570,7 +561,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
let result = check::try_index_step(
self.fcx,
MethodCall::expr(expr.id),
ty::MethodCall::expr(expr.id),
expr,
&**base_expr,
adjusted_base_ty,
@ -589,7 +580,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
ast::ExprUnary(ast::UnDeref, ref base_expr) => {
// if this is an overloaded deref, then re-evaluate with
// a preference for mut
let method_call = MethodCall::expr(expr.id);
let method_call = ty::MethodCall::expr(expr.id);
if self.fcx.inh.tables.borrow().method_map.contains_key(&method_call) {
check::try_overloaded_deref(
self.fcx,

View File

@ -74,8 +74,6 @@ pub enum CandidateSource {
TraitSource(/* trait id */ ast::DefId),
}
type ItemIndex = usize; // just for doc purposes
/// Determines whether the type `self_ty` supports a method name `method_name` or not.
pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
@ -204,14 +202,13 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// Trait must have a method named `m_name` and it should not have
// type parameters or early-bound regions.
let tcx = fcx.tcx();
let (method_num, method_ty) = trait_item(tcx, trait_def_id, m_name)
.and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
.unwrap();
let method_item = trait_item(tcx, trait_def_id, m_name).unwrap();
let method_ty = method_item.as_opt_method().unwrap();
assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0);
assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0);
debug!("lookup_in_trait_adjusted: method_num={} method_ty={:?}",
method_num, method_ty);
debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
method_item, method_ty);
// Instantiate late-bound regions and substitute the trait
// parameters into the method type to get the actual method type.
@ -309,11 +306,10 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
let callee = ty::MethodCallee {
origin: ty::MethodTypeParam(ty::MethodParam{trait_ref: trait_ref.clone(),
method_num: method_num,
impl_def_id: None}),
def_id: method_item.def_id(),
origin: ty::MethodOrigin::Trait(None),
ty: fty,
substs: trait_ref.substs.clone()
substs: trait_ref.substs
};
debug!("callee = {:?}", callee);
@ -332,14 +328,15 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
let def_id = pick.item.def_id();
let mut lp = LastMod(AllPublic);
let container_def_id = pick.item.container().id();
let provenance = match pick.kind {
probe::InherentImplPick(impl_def_id) => {
probe::InherentImplPick => {
if pick.item.vis() != ast::Public {
lp = LastMod(DependsOn(def_id));
}
def::FromImpl(impl_def_id)
def::FromImpl(container_def_id)
}
_ => def::FromTrait(pick.item.container().id())
_ => def::FromTrait(container_def_id)
};
let def_result = match pick.item {
ty::ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id, provenance),
@ -352,19 +349,17 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
/// Find item with name `item_name` defined in `trait_def_id` and return it, along with its
/// index (or `None`, if no such item).
/// Find item with name `item_name` defined in `trait_def_id`
/// and return it, or `None`, if no such item.
fn trait_item<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: ast::DefId,
item_name: ast::Name)
-> Option<(usize, ty::ImplOrTraitItem<'tcx>)>
-> Option<ty::ImplOrTraitItem<'tcx>>
{
let trait_items = tcx.trait_items(trait_def_id);
trait_items
.iter()
.enumerate()
.find(|&(_, ref item)| item.name() == item_name)
.map(|(num, item)| (num, (*item).clone()))
trait_items.iter()
.find(|item| item.name() == item_name)
.cloned()
}
fn impl_item<'tcx>(tcx: &ty::ctxt<'tcx>,

View File

@ -10,7 +10,6 @@
use super::MethodError;
use super::NoMatchData;
use super::ItemIndex;
use super::{CandidateSource, ImplSource, TraitSource};
use super::suggest;
@ -70,15 +69,13 @@ struct Candidate<'tcx> {
#[derive(Debug)]
enum CandidateKind<'tcx> {
InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>,
InherentImplCandidate(subst::Substs<'tcx>,
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ usize, /* vtable index */ usize),
ExtensionImplCandidate(/* Impl */ ast::DefId, ty::TraitRef<'tcx>,
subst::Substs<'tcx>, ItemIndex,
ExtensionImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>,
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
ClosureCandidate(/* Trait */ ast::DefId, ItemIndex),
WhereClauseCandidate(ty::PolyTraitRef<'tcx>, ItemIndex),
ProjectionCandidate(ast::DefId, ItemIndex),
ObjectCandidate,
TraitCandidate,
WhereClauseCandidate(/* Trait */ ty::PolyTraitRef<'tcx>),
}
#[derive(Debug)]
@ -106,11 +103,11 @@ pub struct Pick<'tcx> {
#[derive(Clone,Debug)]
pub enum PickKind<'tcx> {
InherentImplPick(/* Impl */ ast::DefId),
ObjectPick(/* Trait */ ast::DefId, /* method_num */ usize, /* real_index */ usize),
ExtensionImplPick(/* Impl */ ast::DefId, ItemIndex),
TraitPick(/* Trait */ ast::DefId, ItemIndex),
WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>, ItemIndex),
InherentImplPick,
ExtensionImplPick(/* Impl */ ast::DefId),
ObjectPick,
TraitPick,
WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>),
}
pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>;
@ -430,7 +427,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
self.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item,
kind: InherentImplCandidate(impl_def_id, impl_substs, obligations)
kind: InherentImplCandidate(impl_substs, obligations)
});
}
@ -440,8 +437,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
debug!("assemble_inherent_candidates_from_object(self_ty={:?})",
self_ty);
let tcx = self.tcx();
// It is illegal to invoke a method on a trait instance that
// refers to the `Self` type. An error will be reported by
// `enforce_object_limitations()` if the method refers to the
@ -450,15 +445,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
// itself. Hence, a `&self` method will wind up with an
// argument type like `&Trait`.
let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
self.elaborate_bounds(&[trait_ref.clone()], |this, new_trait_ref, item, item_num| {
self.elaborate_bounds(&[trait_ref], |this, new_trait_ref, item| {
let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
let vtable_index =
traits::get_vtable_index_of_object_method(tcx,
trait_ref.clone(),
new_trait_ref.def_id,
item_num);
let xform_self_ty = this.xform_self_ty(&item,
new_trait_ref.self_ty(),
new_trait_ref.substs);
@ -466,7 +455,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
this.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item,
kind: ObjectCandidate(new_trait_ref.def_id, item_num, vtable_index)
kind: ObjectCandidate
});
});
}
@ -499,7 +488,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
})
.collect();
self.elaborate_bounds(&bounds, |this, poly_trait_ref, item, item_num| {
self.elaborate_bounds(&bounds, |this, poly_trait_ref, item| {
let trait_ref =
this.erase_late_bound_regions(&poly_trait_ref);
@ -533,7 +522,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
this.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item,
kind: WhereClauseCandidate(poly_trait_ref, item_num)
kind: WhereClauseCandidate(poly_trait_ref)
});
});
}
@ -549,16 +538,15 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
&mut ProbeContext<'b, 'tcx>,
ty::PolyTraitRef<'tcx>,
ty::ImplOrTraitItem<'tcx>,
usize,
),
{
debug!("elaborate_bounds(bounds={:?})", bounds);
let tcx = self.tcx();
for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
let (pos, item) = match trait_item(tcx,
bound_trait_ref.def_id(),
self.item_name) {
let item = match trait_item(tcx,
bound_trait_ref.def_id(),
self.item_name) {
Some(v) => v,
None => { continue; }
};
@ -566,7 +554,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
if !self.has_applicable_self(&item) {
self.record_static_candidate(TraitSource(bound_trait_ref.def_id()));
} else {
mk_cand(self, bound_trait_ref, item, pos);
mk_cand(self, bound_trait_ref, item);
}
}
}
@ -607,14 +595,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
// Check whether `trait_def_id` defines a method with suitable name:
let trait_items =
self.tcx().trait_items(trait_def_id);
let matching_index =
let maybe_item =
trait_items.iter()
.position(|item| item.name() == self.item_name);
let matching_index = match matching_index {
.find(|item| item.name() == self.item_name);
let item = match maybe_item {
Some(i) => i,
None => { return Ok(()); }
};
let ref item = (&*trait_items)[matching_index];
// Check whether `trait_def_id` defines a method with suitable name:
if !self.has_applicable_self(item) {
@ -623,29 +610,20 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
return Ok(());
}
self.assemble_extension_candidates_for_trait_impls(trait_def_id,
item.clone(),
matching_index);
self.assemble_extension_candidates_for_trait_impls(trait_def_id, item.clone());
try!(self.assemble_closure_candidates(trait_def_id,
item.clone(),
matching_index));
try!(self.assemble_closure_candidates(trait_def_id, item.clone()));
self.assemble_projection_candidates(trait_def_id,
item.clone(),
matching_index);
self.assemble_projection_candidates(trait_def_id, item.clone());
self.assemble_where_clause_candidates(trait_def_id,
item.clone(),
matching_index);
self.assemble_where_clause_candidates(trait_def_id, item.clone());
Ok(())
}
fn assemble_extension_candidates_for_trait_impls(&mut self,
trait_def_id: ast::DefId,
item: ty::ImplOrTraitItem<'tcx>,
item_index: usize)
item: ty::ImplOrTraitItem<'tcx>)
{
let trait_def = self.tcx().lookup_trait_def(trait_def_id);
@ -690,11 +668,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
self.extension_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: ExtensionImplCandidate(impl_def_id,
impl_trait_ref,
impl_substs,
item_index,
obligations)
kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations)
});
});
}
@ -717,8 +691,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
fn assemble_closure_candidates(&mut self,
trait_def_id: ast::DefId,
item: ty::ImplOrTraitItem<'tcx>,
item_index: usize)
item: ty::ImplOrTraitItem<'tcx>)
-> Result<(), MethodError<'tcx>>
{
// Check if this is one of the Fn,FnMut,FnOnce traits.
@ -770,7 +743,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
self.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: ClosureCandidate(trait_def_id, item_index)
kind: TraitCandidate
});
}
@ -779,16 +752,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
fn assemble_projection_candidates(&mut self,
trait_def_id: ast::DefId,
item: ty::ImplOrTraitItem<'tcx>,
item_index: usize)
item: ty::ImplOrTraitItem<'tcx>)
{
debug!("assemble_projection_candidates(\
trait_def_id={:?}, \
item={:?}, \
item_index={})",
item={:?})",
trait_def_id,
item,
item_index);
item);
for step in self.steps.iter() {
debug!("assemble_projection_candidates: step={:?}",
@ -830,7 +800,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
self.extension_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: ProjectionCandidate(trait_def_id, item_index)
kind: TraitCandidate
});
}
}
@ -839,8 +809,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
fn assemble_where_clause_candidates(&mut self,
trait_def_id: ast::DefId,
item: ty::ImplOrTraitItem<'tcx>,
item_index: usize)
item: ty::ImplOrTraitItem<'tcx>)
{
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
trait_def_id);
@ -862,7 +831,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
self.extension_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: WhereClauseCandidate(poly_bound, item_index)
kind: WhereClauseCandidate(poly_bound)
});
}
}
@ -1048,8 +1017,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
}
applicable_candidates.pop().map(|probe| {
let pick = probe.to_unadjusted_pick();
Ok(pick)
Ok(probe.to_unadjusted_pick())
})
}
@ -1073,48 +1041,52 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
// clauses) that must be considered. Make sure that those
// match as well (or at least may match, sometimes we
// don't have enough information to fully evaluate).
match probe.kind {
InherentImplCandidate(impl_def_id, ref substs, ref ref_obligations) |
ExtensionImplCandidate(impl_def_id, _, ref substs, _, ref ref_obligations) => {
let selcx = &mut traits::SelectionContext::new(self.infcx());
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
// Check whether the impl imposes obligations we have to worry about.
let impl_bounds = self.tcx().lookup_predicates(impl_def_id);
let impl_bounds = impl_bounds.instantiate(self.tcx(), substs);
let traits::Normalized { value: impl_bounds,
obligations: norm_obligations } =
traits::normalize(selcx, cause.clone(), &impl_bounds);
// Convert the bounds into obligations.
let obligations =
traits::predicates_for_generics(cause.clone(),
&impl_bounds);
debug!("impl_obligations={:?}", obligations);
// Evaluate those obligations to see if they might possibly hold.
let mut all_true = true;
for o in obligations.iter()
.chain(norm_obligations.iter())
.chain(ref_obligations.iter()) {
if !selcx.evaluate_obligation(o) {
all_true = false;
if let &ty::Predicate::Trait(ref pred) = &o.predicate {
possibly_unsatisfied_predicates.push(pred.0.trait_ref);
}
}
}
all_true
let (impl_def_id, substs, ref_obligations) = match probe.kind {
InherentImplCandidate(ref substs, ref ref_obligations) => {
(probe.item.container().id(), substs, ref_obligations)
}
ExtensionImplCandidate(impl_def_id, ref substs, ref ref_obligations) => {
(impl_def_id, substs, ref_obligations)
}
ProjectionCandidate(..) |
ObjectCandidate(..) |
ClosureCandidate(..) |
TraitCandidate |
WhereClauseCandidate(..) => {
// These have no additional conditions to check.
true
return true;
}
};
let selcx = &mut traits::SelectionContext::new(self.infcx());
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
// Check whether the impl imposes obligations we have to worry about.
let impl_bounds = self.tcx().lookup_predicates(impl_def_id);
let impl_bounds = impl_bounds.instantiate(self.tcx(), substs);
let traits::Normalized { value: impl_bounds,
obligations: norm_obligations } =
traits::normalize(selcx, cause.clone(), &impl_bounds);
// Convert the bounds into obligations.
let obligations =
traits::predicates_for_generics(cause.clone(),
&impl_bounds);
debug!("impl_obligations={:?}", obligations);
// Evaluate those obligations to see if they might possibly hold.
let mut all_true = true;
for o in obligations.iter()
.chain(norm_obligations.iter())
.chain(ref_obligations.iter()) {
if !selcx.evaluate_obligation(o) {
all_true = false;
if let &ty::Predicate::Trait(ref pred) = &o.predicate {
possibly_unsatisfied_predicates.push(pred.0.trait_ref);
}
}
}
all_true
})
}
@ -1139,20 +1111,19 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
probes: &[&Candidate<'tcx>])
-> Option<Pick<'tcx>> {
// Do all probes correspond to the same trait?
let trait_data = match probes[0].to_trait_data() {
Some(data) => data,
None => return None,
};
if probes[1..].iter().any(|p| p.to_trait_data() != Some(trait_data)) {
let container = probes[0].item.container();
match container {
ty::TraitContainer(_) => {}
ty::ImplContainer(_) => return None
}
if probes[1..].iter().any(|p| p.item.container() != container) {
return None;
}
// If so, just use this trait and call it a day.
let (trait_def_id, item_num) = trait_data;
let item = probes[0].item.clone();
Some(Pick {
item: item,
kind: TraitPick(trait_def_id, item_num),
item: probes[0].item.clone(),
kind: TraitPick,
autoderefs: 0,
autoref: None,
unsize: None
@ -1317,20 +1288,18 @@ fn impl_item<'tcx>(tcx: &ty::ctxt<'tcx>,
.find(|item| item.name() == item_name)
}
/// Find item with name `item_name` defined in `trait_def_id` and return it,
/// along with its index (or `None`, if no such item).
/// Find item with name `item_name` defined in `trait_def_id`
/// and return it, or `None`, if no such item.
fn trait_item<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: ast::DefId,
item_name: ast::Name)
-> Option<(usize, ty::ImplOrTraitItem<'tcx>)>
-> Option<ty::ImplOrTraitItem<'tcx>>
{
let trait_items = tcx.trait_items(trait_def_id);
debug!("trait_method; items: {:?}", trait_items);
trait_items
.iter()
.enumerate()
.find(|&(_, ref item)| item.name() == item_name)
.map(|(num, ref item)| (num, (*item).clone()))
trait_items.iter()
.find(|item| item.name() == item_name)
.cloned()
}
impl<'tcx> Candidate<'tcx> {
@ -1338,19 +1307,13 @@ impl<'tcx> Candidate<'tcx> {
Pick {
item: self.item.clone(),
kind: match self.kind {
InherentImplCandidate(def_id, _, _) => {
InherentImplPick(def_id)
InherentImplCandidate(_, _) => InherentImplPick,
ExtensionImplCandidate(def_id, _, _) => {
ExtensionImplPick(def_id)
}
ObjectCandidate(def_id, item_num, real_index) => {
ObjectPick(def_id, item_num, real_index)
}
ExtensionImplCandidate(def_id, _, _, index, _) => {
ExtensionImplPick(def_id, index)
}
ClosureCandidate(trait_def_id, index) => {
TraitPick(trait_def_id, index)
}
WhereClauseCandidate(ref trait_ref, index) => {
ObjectCandidate => ObjectPick,
TraitCandidate => TraitPick,
WhereClauseCandidate(ref trait_ref) => {
// Only trait derived from where-clauses should
// appear here, so they should not contain any
// inference variables or other artifacts. This
@ -1358,10 +1321,7 @@ impl<'tcx> Candidate<'tcx> {
// `WhereClausePick`.
assert!(!trait_ref.substs().types.needs_infer());
WhereClausePick((*trait_ref).clone(), index)
}
ProjectionCandidate(def_id, index) => {
TraitPick(def_id, index)
WhereClausePick(trait_ref.clone())
}
},
autoderefs: 0,
@ -1372,35 +1332,13 @@ impl<'tcx> Candidate<'tcx> {
fn to_source(&self) -> CandidateSource {
match self.kind {
InherentImplCandidate(def_id, _, _) => ImplSource(def_id),
ObjectCandidate(def_id, _, _) => TraitSource(def_id),
ExtensionImplCandidate(def_id, _, _, _, _) => ImplSource(def_id),
ClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id),
WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()),
ProjectionCandidate(trait_def_id, _) => TraitSource(trait_def_id),
}
}
fn to_trait_data(&self) -> Option<(ast::DefId, ItemIndex)> {
match self.kind {
InherentImplCandidate(..) => {
None
}
ObjectCandidate(trait_def_id, item_num, _) => {
Some((trait_def_id, item_num))
}
ClosureCandidate(trait_def_id, item_num) => {
Some((trait_def_id, item_num))
}
ExtensionImplCandidate(_, ref trait_ref, _, item_num, _) => {
Some((trait_ref.def_id, item_num))
}
WhereClauseCandidate(ref trait_ref, item_num) => {
Some((trait_ref.def_id(), item_num))
}
ProjectionCandidate(trait_def_id, item_num) => {
Some((trait_def_id, item_num))
InherentImplCandidate(_, _) => {
ImplSource(self.item.container().id())
}
ExtensionImplCandidate(def_id, _, _) => ImplSource(def_id),
ObjectCandidate |
TraitCandidate |
WhereClauseCandidate(_) => TraitSource(self.item.container().id()),
}
}
}

View File

@ -203,7 +203,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
impl_ty);
}
CandidateSource::TraitSource(trait_did) => {
let (_, item) = trait_item(fcx.tcx(), trait_did, item_name).unwrap();
let item = trait_item(fcx.tcx(), trait_did, item_name).unwrap();
let item_span = fcx.tcx().map.def_id_span(item.def_id(), span);
span_note!(fcx.sess(), item_span,
"candidate #{} is defined in the trait `{}`",

View File

@ -302,9 +302,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
method_call,
method);
let new_method = MethodCallee {
origin: self.resolve(&method.origin, reason),
def_id: method.def_id,
origin: method.origin,
ty: self.resolve(&method.ty, reason),
substs: self.resolve(&method.substs, reason),
substs: self.tcx().mk_substs(self.resolve(method.substs, reason)),
};
Some(new_method)