From 70365ed911d418c22d2d9e6a972929b946b6a3ac Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 2 Jul 2015 08:52:36 +0300 Subject: [PATCH] rustc: simplify ty::MethodOrigin and avoid trait item indices. --- src/librustc/middle/astencode.rs | 187 ++++---------- src/librustc/middle/check_const.rs | 12 +- src/librustc/middle/dead.rs | 24 +- src/librustc/middle/expr_use_visitor.rs | 51 +--- src/librustc/middle/infer/mod.rs | 9 +- src/librustc/middle/reachable.rs | 4 +- src/librustc/middle/stability.rs | 20 +- src/librustc/middle/subst.rs | 16 +- src/librustc/middle/traits/util.rs | 31 ++- src/librustc/middle/ty.rs | 87 ++----- src/librustc/middle/ty_fold.rs | 25 -- src/librustc/util/ppaux.rs | 29 --- src/librustc_lint/builtin.rs | 17 +- src/librustc_privacy/lib.rs | 24 +- src/librustc_trans/save/dump_csv.rs | 36 +-- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/consts.rs | 5 +- src/librustc_trans/trans/meth.rs | 61 ++--- src/librustc_typeck/check/method/confirm.rs | 65 ++--- src/librustc_typeck/check/method/mod.rs | 39 ++- src/librustc_typeck/check/method/probe.rs | 268 ++++++++------------ src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/writeback.rs | 5 +- 23 files changed, 328 insertions(+), 691 deletions(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 90ef8e2ad36..6b476f92196 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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>; 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 }; diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 19b688e5ccf..fbb7b3f235a 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -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); diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index ad1bc1c5250..040afcac03c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -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 \ diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 8c919d7db52..0d204a823af 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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( diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 34726436ff7..63f31921ec2 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -1327,7 +1327,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn node_method_ty(&self, method_call: ty::MethodCall) - -> Option> { + -> Option> { 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> - { + pub fn node_method_id(&self, method_call: ty::MethodCall) + -> Option { self.tables .borrow() .method_map .get(&method_call) - .map(|method| method.origin.clone()) + .map(|method| method.def_id) } pub fn adjustments(&self) -> Ref>> { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 6ea726062ca..dda33b28cce 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -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) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 2cb3a7337a4..7cabf50fe09 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -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 } } diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 56798ae6848..4e98ef27531 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -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(self, a: A, op: F) -> RegionSubsts where - F: FnOnce(VecPerParamSpace, A) -> VecPerParamSpace, + fn map(self, op: F) -> RegionSubsts where + F: FnOnce(VecPerParamSpace) -> VecPerParamSpace, { match self { ErasedRegions => ErasedRegions, - NonerasedRegions(r) => NonerasedRegions(op(r, a)) + NonerasedRegions(r) => NonerasedRegions(op(r)) } } diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 5c9a8d6c1aa..e8a24876b18 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -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 } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 5bdf9205d07..2eb1767c928 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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), - // 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, -} - -// 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>> { 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 } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 34bbb921601..402f31fc770 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -310,31 +310,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::AutoRef<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> { - fn fold_with>(&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>(&self, _folder: &mut F) -> ty::BuiltinBounds { *self diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 33a93e03ad3..9d82b0c2aa8 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index e3b696286e5..7d14bde8a92 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index abdae9e215f..cf0a24ed48c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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); } } } diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index e07ce230b6c..2236eda5527 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -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); diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index dfe807d6c91..28c2277ed1d 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -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)) } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 57af688ef60..e7e2793fc7e 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -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) } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index c18786c1f34..3d727cf3347 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -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); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 7a887fac9d4..5fa167c7929 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -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>) - -> 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>) - -> 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, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 7ed5c69ad61..95e60a5fbe1 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -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> { 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>, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 8eb4716cb2a..c43046ba0e7 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -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>), - 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>), - 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, 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> { // 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> { 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()), } } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index d6a8b3583f8..4d86a4f7c70 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -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 `{}`", diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 1fc7224737d..8ed99ac9162 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -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)