From fe354e58bdd17ad63f2d9278820eb7ee1ee091d5 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 30 Jun 2015 13:41:13 +0300 Subject: [PATCH 1/8] rustc: remove unused MethodStaticClosure variant of MethodOrigin. --- src/librustc/middle/astencode.rs | 20 ++++---------------- src/librustc/middle/dead.rs | 1 - src/librustc/middle/expr_use_visitor.rs | 15 --------------- src/librustc/middle/stability.rs | 3 --- src/librustc/middle/ty.rs | 3 --- src/librustc/middle/ty_fold.rs | 3 --- src/librustc/util/ppaux.rs | 3 --- src/librustc_lint/builtin.rs | 2 +- src/librustc_privacy/lib.rs | 1 - src/librustc_trans/save/dump_csv.rs | 5 ++--- src/librustc_trans/trans/meth.rs | 3 +-- 11 files changed, 8 insertions(+), 51 deletions(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 03e5ac5c3811e..90ef8e2ad3655 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -755,14 +755,8 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { }) } - ty::MethodStaticClosure(def_id) => { - this.emit_enum_variant("MethodStaticClosure", 1, 1, |this| { - Ok(this.emit_def_id(def_id)) - }) - } - ty::MethodTypeParam(ref p) => { - this.emit_enum_variant("MethodTypeParam", 2, 1, |this| { + 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)) @@ -786,7 +780,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { } ty::MethodTraitObject(ref o) => { - this.emit_enum_variant("MethodTraitObject", 3, 1, |this| { + 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)) @@ -1239,8 +1233,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { -> ty::MethodOrigin<'tcx> { self.read_enum("MethodOrigin", |this| { - let variants = &["MethodStatic", "MethodStaticClosure", - "MethodTypeParam", "MethodTraitObject"]; + let variants = &["MethodStatic", "MethodTypeParam", "MethodTraitObject"]; this.read_enum_variant(variants, |this, i| { Ok(match i { 0 => { @@ -1249,11 +1242,6 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { } 1 => { - let def_id = this.read_def_id(dcx); - ty::MethodStaticClosure(def_id) - } - - 2 => { this.read_struct("MethodTypeParam", 2, |this| { Ok(ty::MethodTypeParam( ty::MethodParam { @@ -1282,7 +1270,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { }).unwrap() } - 3 => { + 2 => { this.read_struct("MethodTraitObject", 2, |this| { Ok(ty::MethodTraitObject( ty::MethodObject { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index d8ee38b847830..ad1bc1c52506c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -105,7 +105,6 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { None => self.check_def_id(def_id) } } - ty::MethodStaticClosure(_) => {} ty::MethodTypeParam(ty::MethodParam { ref trait_ref, method_num: index, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 3edf0490214b9..8c919d7db527d 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -254,27 +254,12 @@ impl OverloadedCallType { OverloadedCallType::from_trait_id(tcx, trait_ref.def_id) } - fn from_closure(tcx: &ty::ctxt, closure_did: ast::DefId) - -> OverloadedCallType { - let trait_did = - tcx.tables - .borrow() - .closure_kinds - .get(&closure_did) - .expect("OverloadedCallType::from_closure: didn't find closure id") - .trait_did(tcx); - OverloadedCallType::from_trait_id(tcx, trait_did) - } - fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin) -> OverloadedCallType { match *origin { MethodStatic(def_id) => { OverloadedCallType::from_method_id(tcx, def_id) } - MethodStaticClosure(def_id) => { - OverloadedCallType::from_closure(tcx, def_id) - } MethodTypeParam(MethodParam { ref trait_ref, .. }) | MethodTraitObject(MethodObject { ref trait_ref, .. }) => { OverloadedCallType::from_trait_id(tcx, trait_ref.def_id) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e6bbae6405bf4..2cb3a7337a447 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -412,9 +412,6 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr, ty::MethodStatic(def_id) => { def_id } - ty::MethodStaticClosure(def_id) => { - def_id - } ty::MethodTypeParam(ty::MethodParam { ref trait_ref, method_num: index, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 544e594dd21b0..5bdf9205d0705 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -631,9 +631,6 @@ pub enum MethodOrigin<'tcx> { // fully statically resolved method MethodStatic(ast::DefId), - // fully statically resolved closure invocation - MethodStaticClosure(ast::DefId), - // method invoked on a type parameter with a bounded trait MethodTypeParam(MethodParam<'tcx>), diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 5e88a0aefd3ab..34bbb92160142 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -316,9 +316,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> { ty::MethodStatic(def_id) => { ty::MethodStatic(def_id) } - ty::MethodStaticClosure(def_id) => { - ty::MethodStaticClosure(def_id) - } ty::MethodTypeParam(ref param) => { ty::MethodTypeParam(ty::MethodParam { trait_ref: param.trait_ref.fold_with(folder), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 44bea1cb621ef..33a93e03ad3a9 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -500,9 +500,6 @@ impl<'tcx> fmt::Debug for ty::MethodOrigin<'tcx> { ty::MethodStatic(def_id) => { write!(f, "MethodStatic({:?})", def_id) } - ty::MethodStaticClosure(def_id) => { - write!(f, "MethodStaticClosure({:?})", def_id) - } ty::MethodTypeParam(ref p) => write!(f, "{:?}", p), ty::MethodTraitObject(ref p) => write!(f, "{:?}", p) } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 8845bd06a0667..e3b696286e51e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -2003,7 +2003,7 @@ impl LintPass for UnconditionalRecursion { ty::MethodTraitObject(_) => return false, // This `did` refers directly to the method definition. - ty::MethodStatic(did) | ty::MethodStaticClosure(did) => did, + ty::MethodStatic(did) => did, // MethodTypeParam are methods from traits: diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 239141df9e8c7..abdae9e215f00 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -854,7 +854,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { MethodStatic(method_id) => { self.check_static_method(span, method_id, name) } - MethodStaticClosure(_) => {} // Trait methods are always all public. The only controlling factor // is whether the trait itself is accessible or not. MethodTypeParam(MethodParam { ref trait_ref, .. }) | diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 4e3b99276a9c7..e07ce230b6ce5 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -889,8 +889,7 @@ 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) | - ty::MethodStaticClosure(def_id) => { + 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) { @@ -907,7 +906,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { _ => self.sess .span_bug(ex.span, "save::process_method_call: non-method \ - DefId in MethodStatic or MethodStaticClosure"), + DefId in MethodStatic"), }; (Some(def_id), decl_id) } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 1b01fb6c7f86d..c18786c1f348a 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -117,8 +117,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, .unwrap(); match origin { - ty::MethodStatic(did) | - ty::MethodStaticClosure(did) => { + ty::MethodStatic(did) => { debug!("trans_method_callee: static, {:?}", did); Callee { bcx: bcx, From 70365ed911d418c22d2d9e6a972929b946b6a3ac Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 2 Jul 2015 08:52:36 +0300 Subject: [PATCH 2/8] 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 90ef8e2ad3655..6b476f92196bd 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 19b688e5ccfb4..fbb7b3f235a34 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 ad1bc1c52506c..040afcac03cc6 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 8c919d7db527d..0d204a823af04 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 34726436ff755..63f31921ec2ec 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 6ea726062cad6..dda33b28cce3b 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 2cb3a7337a447..7cabf50fe0931 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 56798ae6848a5..4e98ef2753105 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 5c9a8d6c1aa3f..e8a24876b18dc 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 5bdf9205d0705..2eb1767c92831 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), - - // method invoked on a type parameter with a bounded trait - MethodTypeParam(MethodParam<'tcx>), - - // 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, +#[derive(Clone, Copy, Debug)] +pub enum MethodOrigin { + /// Inherent impl method call. + Inherent, - // index of the method to be invoked amongst the trait's items - pub method_num: usize, + /// 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), - // 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 34bbb92160142..402f31fc770d9 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 33a93e03ad3a9..9d82b0c2aa8a0 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 e3b696286e51e..7d14bde8a9262 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 abdae9e215f00..cf0a24ed48c61 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 e07ce230b6ce5..2236eda5527fe 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::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::MethodOrigin::Inherent => { + (Some(method_callee.def_id), None) } - 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 dfe807d6c9152..28c2277ed1d4f 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 57af688ef60d7..e7e2793fc7e9d 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 c18786c1f348a..3d727cf3347b6 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 7a887fac9d402..5fa167c792991 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 7ed5c69ad6157..95e60a5fbe19b 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 8eb4716cb2a69..c43046ba0e716 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) - } - ObjectCandidate(def_id, item_num, real_index) => { - ObjectPick(def_id, item_num, real_index) - } - ExtensionImplCandidate(def_id, _, _, index, _) => { - ExtensionImplPick(def_id, index) + InherentImplCandidate(_, _) => InherentImplPick, + ExtensionImplCandidate(def_id, _, _) => { + ExtensionImplPick(def_id) } - 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 d6a8b3583f8ca..4d86a4f7c70ff 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 1fc7224737d2d..8ed99ac916249 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) From a2fe59afd66f032bea04f55fdb8beb00b53b65d7 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 2 Jul 2015 09:11:36 +0300 Subject: [PATCH 3/8] rustc_trans: explicit impl population is unnecessary in fulfill_obligation. --- src/librustc_trans/trans/common.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index ed2d303b5e1b6..8282eb734f2b9 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -874,7 +874,6 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("trans fulfill_obligation: trait_ref={:?} def_id={:?}", trait_ref, trait_ref.def_id()); - tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. From 5620a5879178dab2b929557208e19827eab9bda0 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 2 Jul 2015 13:33:01 +0300 Subject: [PATCH 4/8] rustc_lint: use traits::select for methods in unconditional_recursion. --- src/librustc/middle/astencode.rs | 69 +--------- src/librustc/middle/ty.rs | 8 +- src/librustc_lint/builtin.rs | 144 +++++++++++--------- src/librustc_privacy/lib.rs | 2 +- src/librustc_trans/save/dump_csv.rs | 3 +- src/librustc_trans/trans/meth.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 6 +- src/librustc_typeck/check/method/mod.rs | 2 +- 8 files changed, 92 insertions(+), 144 deletions(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 6b476f92196bd..fa06d50272885 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -617,7 +617,7 @@ fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>, Ok(rbml_w.emit_def_id(method.def_id)) }); rbml_w.emit_struct_field("origin", 2, |rbml_w| { - Ok(rbml_w.emit_method_origin(method.origin)) + method.origin.encode(rbml_w) }); rbml_w.emit_struct_field("ty", 3, |rbml_w| { Ok(rbml_w.emit_ty(ecx, method.ty)) @@ -633,16 +633,14 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> { -> (u32, ty::MethodCallee<'tcx>) { self.read_struct("MethodCallee", 5, |this| { - let autoderef = this.read_struct_field("autoderef", 0, |this| { - Decodable::decode(this) - }).unwrap(); + let autoderef = this.read_struct_field("autoderef", 0, + Decodable::decode).unwrap(); 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(), + origin: this.read_struct_field("origin", 2, + Decodable::decode).unwrap(), ty: this.read_struct_field("ty", 3, |this| { Ok(this.read_ty(dcx)) }).unwrap(), @@ -713,7 +711,6 @@ 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(&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>, @@ -745,37 +742,6 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { }); } - fn emit_method_origin(&mut self, method_origin: ty::MethodOrigin) { - use serialize::Encoder; - - self.emit_enum("MethodOrigin", |this| { - match method_origin { - ty::MethodOrigin::Inherent => { - this.emit_enum_variant("Inherent", 0, 0, |_| Ok(())) - } - - 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)) - }) - } - }) - }) - } - - ty::MethodOrigin::Object(vtable_index) => { - this.emit_enum_variant("Object", 2, 1, |this| { - this.emit_uint(vtable_index) - }) - } - } - }); - } - fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) { self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty))); } @@ -1118,7 +1084,6 @@ impl<'a> doc_decoder_helpers for rbml::Doc<'a> { } trait rbml_decoder_decoder_helpers<'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>) @@ -1202,30 +1167,6 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { }).unwrap() } - fn read_method_origin(&mut self, dcx: &DecodeContext) -> ty::MethodOrigin { - self.read_enum("MethodOrigin", |this| { - let variants = &["Inherent", "Trait", "Object"]; - this.read_enum_variant(variants, |this, i| { - match i { - 0 => Ok(ty::MethodOrigin::Inherent), - - 1 => this.read_option(|this, b| { - Ok(ty::MethodOrigin::Trait(if b { - Some(this.read_def_id(dcx)) - } else { - None - })) - }), - - 2 => this.read_uint().map(|idx| ty::MethodOrigin::Object(idx)), - - _ => panic!("..") - } - }) - }).unwrap() - } - - fn read_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> Ty<'tcx> { // Note: regions types embed local node ids. In principle, we // should translate these node ids into the new decode diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2eb1767c92831..29ab8de5e658e 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -625,17 +625,13 @@ pub enum CustomCoerceUnsized { Struct(usize) } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub enum MethodOrigin { /// Inherent impl method call. Inherent, /// 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), + Trait, /// Dynamically dispatched trait method call. /// The usize is the index into the actual runtime vtable. diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7d14bde8a9262..d92a5c9c76eda 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -33,8 +33,10 @@ use metadata::{csearch, decoder}; use middle::def::*; +use middle::infer; use middle::subst::Substs; use middle::ty::{self, Ty}; +use middle::traits; use middle::{def, pat_util, stability}; use middle::const_eval::{eval_const_expr_partial, ConstVal}; use middle::cfg; @@ -1863,24 +1865,18 @@ impl LintPass for UnconditionalRecursion { fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl, blk: &ast::Block, sp: Span, id: ast::NodeId) { - // FIXME(#23542) Replace with type ascription. - #![allow(trivial_casts)] - type F = for<'tcx> fn(&ty::ctxt<'tcx>, ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool; - let (name, checker) = match fn_kind { - visit::FkItemFn(name, _, _, _, _, _) => (name, id_refers_to_this_fn as F), - visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F), + let method = match fn_kind { + visit::FkItemFn(..) => None, + visit::FkMethod(..) => { + cx.tcx.impl_or_trait_item(local_def(id)).as_opt_method() + } // closures can't recur, so they don't matter. visit::FkFnBlock => return }; - let impl_def_id = cx.tcx.impl_of_method(local_def(id)) - .unwrap_or(local_def(ast::DUMMY_NODE_ID)); - assert!(ast_util::is_local(impl_def_id)); - let impl_node_id = impl_def_id.node; - // Walk through this function (say `f`) looking to see if // every possible path references itself, i.e. the function is // called recursively unconditionally. This is done by trying @@ -1931,7 +1927,17 @@ impl LintPass for UnconditionalRecursion { let node_id = cfg.graph.node_data(idx).id(); // is this a recursive call? - if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) { + let self_recursive = if node_id != ast::DUMMY_NODE_ID { + match method { + Some(ref method) => { + expr_refers_to_this_method(cx.tcx, method, node_id) + } + None => expr_refers_to_this_fn(cx.tcx, id, node_id) + } + } else { + false + }; + if self_recursive { self_call_spans.push(cx.tcx.map.span(node_id)); // this is a self call, so we shouldn't explore past // this node in the CFG. @@ -1970,15 +1976,12 @@ impl LintPass for UnconditionalRecursion { // all done return; - // Functions for identifying if the given NodeId `id` - // represents a call to the function `fn_id`/method - // `method_id`. + // Functions for identifying if the given Expr NodeId `id` + // represents a call to the function `fn_id`/method `method`. - fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>, - _: ast::NodeId, - fn_id: ast::NodeId, - _: ast::Ident, - id: ast::NodeId) -> bool { + fn expr_refers_to_this_fn(tcx: &ty::ctxt, + fn_id: ast::NodeId, + id: ast::NodeId) -> bool { match tcx.map.get(id) { ast_map::NodeExpr(&ast::Expr { node: ast::ExprCall(ref callee, _), .. }) => { tcx.def_map.borrow().get(&callee.id) @@ -1988,59 +1991,68 @@ impl LintPass for UnconditionalRecursion { } } - // check if the method call `id` refers to method `method_id` - // (with name `method_name` contained in impl `impl_id`). - fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>, - impl_id: ast::NodeId, - method_id: ast::NodeId, - method_name: ast::Ident, - id: ast::NodeId) -> bool { - let did = match tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)) { - None => return false, - 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::MethodOrigin::Object(_) => return false, - - // This `did` refers directly to the method definition. - 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::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 + // Check if the method call `id` refers to method `method`. + fn expr_refers_to_this_method(tcx: &ty::ctxt, + method: &ty::Method, + id: ast::NodeId) -> bool { + let tables = tcx.tables.borrow(); + let callee = match tables.method_map.get(&ty::MethodCall::expr(id)) { + Some(m) => m, + None => return false + }; + let callee_item = tcx.impl_or_trait_item(callee.def_id); + + match callee_item.container() { + // This is an inherent method, so the `def_id` refers + // directly to the method definition. + ty::ImplContainer(_) => { + callee.def_id == method.def_id + } + + // A trait method, from any number of possible sources. + // Attempt to select a concrete impl before checking. + ty::TraitContainer(trait_def_id) => { + let trait_substs = callee.substs.clone().method_to_trait(); + let trait_substs = tcx.mk_substs(trait_substs); + let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs); + let trait_ref = ty::Binder(trait_ref); + let span = tcx.map.span(id); + let obligation = + traits::Obligation::new(traits::ObligationCause::misc(span, id), + trait_ref.to_poly_trait_predicate()); + + let param_env = ty::ParameterEnvironment::for_item(tcx, method.def_id.node); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env), false); + let mut selcx = traits::SelectionContext::new(&infcx); + match selcx.select(&obligation) { + // The method comes from a `T: Trait` bound. + // If `T` is `Self`, then this call is inside + // a default method definition. + Ok(Some(traits::VtableParam(_))) => { + let self_ty = callee.substs.self_ty(); + let on_self = self_ty.map_or(false, |t| t.is_self()); + // We can only be recurring in a default // method if we're being called literally // on the `Self` type. - return false + on_self && callee.def_id == method.def_id } - m.def_id - } - - // The `impl` is known, so we check that with a - // special case: - ty::MethodOrigin::Trait(Some(impl_def_id)) => { + // The `impl` is known, so we check that with a + // special case: + Ok(Some(traits::VtableImpl(vtable_impl))) => { + let container = ty::ImplContainer(vtable_impl.impl_def_id); + // It matches if it comes from the same impl, + // and has the same method name. + container == method.container + && callee_item.name() == method.name + } - let name = match tcx.map.expect_expr(id).node { - ast::ExprMethodCall(ref sp_ident, _, _) => sp_ident.node, - _ => tcx.sess.span_bug( - tcx.map.span(id), - "non-method call expr behaving like a method call?") - }; - // It matches if it comes from the same impl, - // and has the same method name. - return ast_util::is_local(impl_def_id) - && impl_def_id.node == impl_id - && method_name.name == name.name + // There's no way to know if this call is + // recursive, so we assume it's not. + _ => return false } } - }; - - ast_util::is_local(did) && did.node == method_id + } } } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index cf0a24ed48c61..dcbe4c35113d0 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -852,7 +852,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { } // Trait methods are always all public. The only controlling factor // is whether the trait itself is accessible or not. - ty::MethodOrigin::Trait(_) | ty::MethodOrigin::Object(_) => { + 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")); diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 2236eda5527fe..bac5ea494df99 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -892,8 +892,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { ty::MethodOrigin::Inherent => { (Some(method_callee.def_id), None) } - ty::MethodOrigin::Trait(_) | - ty::MethodOrigin::Object(_) => { + ty::MethodOrigin::Trait | ty::MethodOrigin::Object(_) => { (None, Some(method_callee.def_id)) } }; diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 3d727cf3347b6..2f415fcf7fd40 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -128,7 +128,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } - ty::MethodOrigin::Trait(_) => { + ty::MethodOrigin::Trait => { let method_item = bcx.tcx().impl_or_trait_item(method_id); let trait_def_id = method_item.container().id(); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 5fa167c792991..26868c16bd85f 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -255,7 +255,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { &impl_polytype.substs, &self.tcx().impl_trait_ref(impl_def_id).unwrap()); let substs = impl_trait_ref.substs.clone(); - (substs, ty::MethodOrigin::Trait(Some(impl_def_id))) + (substs, ty::MethodOrigin::Trait) } probe::TraitPick => { @@ -271,7 +271,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { &trait_def.generics, self.infcx().next_ty_var()); - (substs, ty::MethodOrigin::Trait(None)) + (substs, ty::MethodOrigin::Trait) } probe::WhereClausePick(ref poly_trait_ref) => { @@ -279,7 +279,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // 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(); - (substs, ty::MethodOrigin::Trait(None)) + (substs, ty::MethodOrigin::Trait) } } } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 95e60a5fbe19b..0ba0903172440 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -307,7 +307,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let callee = ty::MethodCallee { def_id: method_item.def_id(), - origin: ty::MethodOrigin::Trait(None), + origin: ty::MethodOrigin::Trait, ty: fty, substs: trait_ref.substs }; From a5447e13aae877d9a8454e5e69de373cf32f8ee7 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 2 Jul 2015 14:34:53 +0300 Subject: [PATCH 5/8] rustc_trans: remove some outdated and unused logic from callee. --- src/librustc_trans/trans/callee.rs | 26 +++++++++++++------------- src/librustc_trans/trans/expr.rs | 12 ++++++------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 28c2277ed1d4f..2c707663a61b2 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -698,12 +698,12 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, _ => panic!("expected bare rust fn or closure in trans_call_inner") }; - let (llfn, llenv, llself) = match callee.data { + let (llfn, llself) = match callee.data { Fn(llfn) => { - (llfn, None, None) + (llfn, None) } TraitItem(d) => { - (d.llfn, None, Some(d.llself)) + (d.llfn, Some(d.llself)) } Intrinsic(node, substs) => { assert!(abi == synabi::RustIntrinsic); @@ -794,11 +794,9 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, } } - // Push the environment (or a trait object's self). - match (llenv, llself) { - (Some(llenv), None) => llargs.push(llenv), - (None, Some(llself)) => llargs.push(llself), - _ => {} + // Push a trait object's self. + if let Some(llself) = llself { + llargs.push(llself); } // Push the arguments. @@ -894,11 +892,11 @@ pub enum CallArgs<'a, 'tcx> { // value. ArgVals(&'a [ValueRef]), - // For overloaded operators: `(lhs, Vec(rhs, rhs_id), autoref)`. `lhs` + // For overloaded operators: `(lhs, Option(rhs, rhs_id), autoref)`. `lhs` // is the left-hand-side and `rhs/rhs_id` is the datum/expr-id of - // the right-hand-side arguments (if any). `autoref` indicates whether the `rhs` + // the right-hand-side argument (if any). `autoref` indicates whether the `rhs` // arguments should be auto-referenced - ArgOverloadedOp(Datum<'tcx, Expr>, Vec<(Datum<'tcx, Expr>, ast::NodeId)>, bool), + ArgOverloadedOp(Datum<'tcx, Expr>, Option<(Datum<'tcx, Expr>, ast::NodeId)>, bool), // Supply value of arguments as a list of expressions that must be // translated, for overloaded call operators. @@ -1077,12 +1075,14 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, DontAutorefArg, llargs); - assert_eq!(arg_tys.len(), 1 + rhs.len()); - for (rhs, rhs_id) in rhs { + if let Some((rhs, rhs_id)) = rhs { + assert_eq!(arg_tys.len(), 2); bcx = trans_arg_datum(bcx, arg_tys[1], rhs, arg_cleanup_scope, if autoref { DoAutorefArg(rhs_id) } else { DontAutorefArg }, llargs); + } else { + assert_eq!(arg_tys.len(), 1); } } ArgVals(vs) => { diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index d7ce50082f1d3..4505c75f6474f 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -805,7 +805,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, index_expr, method_call, base_datum, - vec![(ix_datum, idx.id)], + Some((ix_datum, idx.id)), Some(SaveIn(scratch.val)), false)); let datum = scratch.to_expr_datum(); @@ -1175,21 +1175,21 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let lhs = unpack_datum!(bcx, trans(bcx, &**lhs)); let rhs_datum = unpack_datum!(bcx, trans(bcx, &**rhs)); trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), lhs, - vec![(rhs_datum, rhs.id)], Some(dest), + Some((rhs_datum, rhs.id)), Some(dest), !ast_util::is_by_value_binop(op.node)).bcx } ast::ExprUnary(op, ref subexpr) => { // if not overloaded, would be RvalueDatumExpr let arg = unpack_datum!(bcx, trans(bcx, &**subexpr)); trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), - arg, Vec::new(), Some(dest), !ast_util::is_by_value_unop(op)).bcx + arg, None, Some(dest), !ast_util::is_by_value_unop(op)).bcx } ast::ExprIndex(ref base, ref idx) => { // if not overloaded, would be RvalueDatumExpr let base = unpack_datum!(bcx, trans(bcx, &**base)); let idx_datum = unpack_datum!(bcx, trans(bcx, &**idx)); trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), base, - vec![(idx_datum, idx.id)], Some(dest), true).bcx + Some((idx_datum, idx.id)), Some(dest), true).bcx } ast::ExprCast(..) => { // Trait casts used to come this way, now they should be coercions. @@ -1943,7 +1943,7 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, method_call: MethodCall, lhs: Datum<'tcx, Expr>, - rhs: Vec<(Datum<'tcx, Expr>, ast::NodeId)>, + rhs: Option<(Datum<'tcx, Expr>, ast::NodeId)>, dest: Option, autoref: bool) -> Result<'blk, 'tcx> { @@ -2259,7 +2259,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let scratch = rvalue_scratch_datum(bcx, ref_ty, "overloaded_deref"); unpack_result!(bcx, trans_overloaded_op(bcx, expr, method_call, - datum, Vec::new(), Some(SaveIn(scratch.val)), + datum, None, Some(SaveIn(scratch.val)), false)); scratch.to_expr_datum() } From 96d24a5c58718fbd1800fb56a49166a320f65556 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 3 Jul 2015 05:22:54 +0300 Subject: [PATCH 6/8] rustc: remove MethodOrigin::Object and use traits::VtableObject instead. --- src/librustc/middle/ty.rs | 11 +- src/librustc_privacy/lib.rs | 2 +- src/librustc_trans/save/dump_csv.rs | 2 +- src/librustc_trans/trans/callee.rs | 139 ++++++---------- src/librustc_trans/trans/closure.rs | 13 +- src/librustc_trans/trans/expr.rs | 16 -- src/librustc_trans/trans/meth.rs | 174 +++++++++----------- src/librustc_trans/trans/monomorphize.rs | 8 +- src/librustc_typeck/check/method/confirm.rs | 6 +- 9 files changed, 144 insertions(+), 227 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 29ab8de5e658e..971774336c8b3 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -630,15 +630,8 @@ pub enum MethodOrigin { /// Inherent impl method call. Inherent, - /// Statically dispatched trait method call. - Trait, - - /// 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) + /// Trait method call. + Trait } #[derive(Clone, Debug)] diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index dcbe4c35113d0..4f315b56815c6 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -852,7 +852,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { } // Trait methods are always all public. The only controlling factor // is whether the trait itself is accessible or not. - ty::MethodOrigin::Trait | ty::MethodOrigin::Object(_) => { + ty::MethodOrigin::Trait => { let method = self.tcx.impl_or_trait_item(callee.def_id); self.report_error(self.ensure_public(span, method.container().id(), None, "source trait")); diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index bac5ea494df99..d0f9456b11c3d 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -892,7 +892,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { ty::MethodOrigin::Inherent => { (Some(method_callee.def_id), None) } - ty::MethodOrigin::Trait | ty::MethodOrigin::Object(_) => { + ty::MethodOrigin::Trait => { (None, Some(method_callee.def_id)) } }; diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 2c707663a61b2..dc5b6cf7db883 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -22,7 +22,6 @@ use arena::TypedArena; use back::link; use session; use llvm::{self, ValueRef, get_params}; -use metadata::csearch; use middle::def; use middle::subst; use middle::subst::{Subst, Substs}; @@ -66,7 +65,7 @@ pub struct MethodData { pub enum CalleeData<'tcx> { // Constructor for enum variant/tuple-like-struct // i.e. Some, Ok - NamedTupleConstructor(subst::Substs<'tcx>, ty::Disr), + NamedTupleConstructor(ty::Disr), // Represents a (possibly monomorphized) top-level fn item or method // item. Note that this is just the fn-ptr and is not a Rust closure @@ -81,6 +80,7 @@ pub enum CalleeData<'tcx> { pub struct Callee<'blk, 'tcx: 'blk> { pub bcx: Block<'blk, 'tcx>, pub data: CalleeData<'tcx>, + pub ty: Ty<'tcx> } fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) @@ -104,11 +104,11 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) let DatumBlock { bcx, datum, .. } = expr::trans(bcx, expr); match datum.ty.sty { ty::TyBareFn(..) => { - let llval = datum.to_llscalarish(bcx); - return Callee { + Callee { bcx: bcx, - data: Fn(llval), - }; + ty: datum.ty, + data: Fn(datum.to_llscalarish(bcx)) + } } _ => { bcx.tcx().sess.span_bug( @@ -119,12 +119,13 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } } - fn fn_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llfn: ValueRef) + fn fn_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, datum: Datum<'tcx, Rvalue>) -> Callee<'blk, 'tcx> { - return Callee { + Callee { bcx: bcx, - data: Fn(llfn), - }; + data: Fn(datum.val), + ty: datum.ty + } } fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, @@ -143,12 +144,10 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) _ => false } } => { - let substs = common::node_id_substs(bcx.ccx(), - ExprId(ref_expr.id), - bcx.fcx.param_substs); Callee { bcx: bcx, - data: NamedTupleConstructor(substs, 0) + data: NamedTupleConstructor(0), + ty: expr_ty } } def::DefFn(did, _) if match expr_ty.sty { @@ -159,40 +158,36 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) ExprId(ref_expr.id), bcx.fcx.param_substs); let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did); - Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) } + Callee { bcx: bcx, data: Intrinsic(def_id.node, substs), ty: expr_ty } } def::DefFn(did, _) | def::DefMethod(did, def::FromImpl(_)) => { fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id), - bcx.fcx.param_substs).val) + bcx.fcx.param_substs)) } def::DefMethod(meth_did, def::FromTrait(trait_did)) => { fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(), meth_did, trait_did, ref_expr.id, - bcx.fcx.param_substs).val) + bcx.fcx.param_substs)) } def::DefVariant(tid, vid, _) => { let vinfo = bcx.tcx().enum_variant_with_id(tid, vid); - let substs = common::node_id_substs(bcx.ccx(), - ExprId(ref_expr.id), - bcx.fcx.param_substs); // Nullary variants are not callable assert!(!vinfo.args.is_empty()); Callee { bcx: bcx, - data: NamedTupleConstructor(substs, vinfo.disr_val) + data: NamedTupleConstructor(vinfo.disr_val), + ty: expr_ty } } def::DefStruct(_) => { - let substs = common::node_id_substs(bcx.ccx(), - ExprId(ref_expr.id), - bcx.fcx.param_substs); Callee { bcx: bcx, - data: NamedTupleConstructor(substs, 0) + data: NamedTupleConstructor(0), + ty: expr_ty } } def::DefStatic(..) | @@ -232,21 +227,6 @@ pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trans_fn_ref_with_substs(ccx, def_id, node, param_substs, substs) } -fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - def_id: ast::DefId, - ref_id: ast::NodeId, - substs: subst::Substs<'tcx>) - -> Callee<'blk, 'tcx> { - Callee { - bcx: bcx, - data: Fn(trans_fn_ref_with_substs(bcx.ccx(), - def_id, - ExprId(ref_id), - bcx.fcx.param_substs, - substs).val), - } -} - /// Translates an adapter that implements the `Fn` trait for a fn /// pointer. This is basically the equivalent of something like: /// @@ -356,12 +336,13 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")) ); - bcx = trans_call_inner(bcx, - DebugLoc::None, - bare_fn_ty, - |bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) }, - ArgVals(&llargs[(self_idx + 1)..]), - dest).bcx; + bcx = trans_call_inner(bcx, DebugLoc::None, |bcx, _| { + Callee { + bcx: bcx, + data: Fn(llfnpointer), + ty: bare_fn_ty + } + }, ArgVals(&llargs[(self_idx + 1)..]), dest).bcx; finish_fn(&fcx, bcx, sig.output, DebugLoc::None); @@ -586,17 +567,16 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( // ______________________________________________________________________ // Translating calls -pub fn trans_call<'a, 'blk, 'tcx>(in_cx: Block<'blk, 'tcx>, +pub fn trans_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, call_expr: &ast::Expr, f: &ast::Expr, args: CallArgs<'a, 'tcx>, dest: expr::Dest) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_call"); - trans_call_inner(in_cx, + trans_call_inner(bcx, call_expr.debug_loc(), - common::expr_ty_adjusted(in_cx, f), - |cx, _| trans(cx, f), + |bcx, _| trans(bcx, f), args, Some(dest)).bcx } @@ -610,22 +590,9 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_method_call"); debug!("trans_method_call(call_expr={:?})", call_expr); 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::MethodOrigin::Object(_) => match method.ty.sty { - ty::TyBareFn(_, ref fty) => { - bcx.tcx().mk_fn(None, meth::opaque_method_ty(bcx.tcx(), fty)) - } - _ => method.ty - }, - _ => method.ty - }, - None => panic!("method not found in trans_method_call") - }; trans_call_inner( bcx, call_expr.debug_loc(), - common::monomorphize_type(bcx, method_ty), |cx, arg_cleanup_scope| { meth::trans_method_callee(cx, method_call, Some(rcvr), arg_cleanup_scope) }, @@ -639,22 +606,18 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dest: Option, debug_loc: DebugLoc) -> Result<'blk, 'tcx> { - let fty = if did.krate == ast::LOCAL_CRATE { - bcx.tcx().node_id_to_type(did.node) - } else { - csearch::get_type(bcx.tcx(), did).ty - }; - callee::trans_call_inner(bcx, - debug_loc, - fty, - |bcx, _| { - trans_fn_ref_with_substs_to_callee(bcx, - did, - 0, - subst::Substs::trans_empty()) - }, - ArgVals(args), - dest) + callee::trans_call_inner(bcx, debug_loc, |bcx, _| { + let datum = trans_fn_ref_with_substs(bcx.ccx(), + did, + ExprId(0), + bcx.fcx.param_substs, + subst::Substs::trans_empty()); + Callee { + bcx: bcx, + data: Fn(datum.val), + ty: datum.ty + } + }, ArgVals(args), dest) } /// This behemoth of a function translates function calls. Unfortunately, in order to generate more @@ -669,7 +632,6 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// somewhere. Nonetheless we return the actual return value of the function. pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, debug_loc: DebugLoc, - callee_ty: Ty<'tcx>, get_callee: F, args: CallArgs<'a, 'tcx>, dest: Option) @@ -690,7 +652,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let callee = get_callee(bcx, cleanup::CustomScope(arg_cleanup_scope)); let mut bcx = callee.bcx; - let (abi, ret_ty) = match callee_ty.sty { + let (abi, ret_ty) = match callee.ty.sty { ty::TyBareFn(_, ref f) => { let output = bcx.tcx().erase_late_bound_regions(&f.sig.output()); (f.abi, output) @@ -716,18 +678,17 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, } }; - return intrinsic::trans_intrinsic_call(bcx, node, callee_ty, + return intrinsic::trans_intrinsic_call(bcx, node, callee.ty, arg_cleanup_scope, args, dest.unwrap(), substs, call_info); } - NamedTupleConstructor(substs, disr) => { + NamedTupleConstructor(disr) => { assert!(dest.is_some()); fcx.pop_custom_cleanup_scope(arg_cleanup_scope); - let ctor_ty = callee_ty.subst(bcx.tcx(), &substs); return base::trans_named_tuple_constructor(bcx, - ctor_ty, + callee.ty, disr, args, dest.unwrap(), @@ -802,7 +763,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, // Push the arguments. bcx = trans_args(bcx, args, - callee_ty, + callee.ty, &mut llargs, cleanup::CustomScope(arg_cleanup_scope), llself.is_some(), @@ -814,7 +775,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let (llret, b) = base::invoke(bcx, llfn, &llargs[..], - callee_ty, + callee.ty, debug_loc); bcx = b; llresult = llret; @@ -843,7 +804,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, }; bcx = trans_args(bcx, args, - callee_ty, + callee.ty, &mut llargs, cleanup::CustomScope(arg_cleanup_scope), false, @@ -851,7 +812,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); bcx = foreign::trans_native_call(bcx, - callee_ty, + callee.ty, llfn, opt_llretslot.unwrap(), &llargs[..], diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 5fd0f92400f84..d813e9dbf40fa 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -429,12 +429,13 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( let callee_data = TraitItem(MethodData { llfn: llreffn, llself: env_datum.val }); - bcx = callee::trans_call_inner(bcx, - DebugLoc::None, - llref_fn_ty, - |bcx, _| Callee { bcx: bcx, data: callee_data }, - ArgVals(&llargs[(self_idx + 1)..]), - dest).bcx; + bcx = callee::trans_call_inner(bcx, DebugLoc::None, |bcx, _| { + Callee { + bcx: bcx, + data: callee_data, + ty: llref_fn_ty + } + }, ArgVals(&llargs[(self_idx + 1)..]), dest).bcx; fcx.pop_custom_cleanup_scope(self_scope); diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 4505c75f6474f..7722cb322c9e6 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -1947,15 +1947,8 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dest: Option, autoref: bool) -> Result<'blk, 'tcx> { - let method_ty = bcx.tcx() - .tables - .borrow() - .method_map - .get(&method_call).unwrap().ty; - callee::trans_call_inner(bcx, expr.debug_loc(), - monomorphize_type(bcx, method_ty), |bcx, arg_cleanup_scope| { meth::trans_method_callee(bcx, method_call, @@ -1974,20 +1967,11 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, -> Block<'blk, 'tcx> { debug!("trans_overloaded_call {}", expr.id); let method_call = MethodCall::expr(expr.id); - let method_type = bcx.tcx() - .tables - .borrow() - .method_map - .get(&method_call) - .unwrap() - .ty; let mut all_args = vec!(callee); all_args.extend(args.iter().map(|e| &**e)); unpack_result!(bcx, callee::trans_call_inner(bcx, expr.debug_loc(), - monomorphize_type(bcx, - method_type), |bcx, arg_cleanup_scope| { meth::trans_method_callee( bcx, diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 2f415fcf7fd40..ece5682c6ba9b 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -39,7 +39,6 @@ use trans::type_of::*; use middle::ty::{self, Ty, HasTypeFlags}; use middle::ty::MethodCall; -use syntax::abi::{Rust, RustCall}; use syntax::parse::token; use syntax::{ast, attr, visit}; use syntax::codemap::DUMMY_SP; @@ -119,12 +118,14 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, match origin { ty::MethodOrigin::Inherent => { debug!("trans_method_callee: static, {:?}", method_id); + let datum = callee::trans_fn_ref(bcx.ccx(), + method_id, + MethodCallKey(method_call), + bcx.fcx.param_substs); Callee { bcx: bcx, - data: Fn(callee::trans_fn_ref(bcx.ccx(), - method_id, - MethodCallKey(method_call), - bcx.fcx.param_substs).val), + data: Fn(datum.val), + ty: datum.ty } } @@ -149,26 +150,27 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debug!("origin = {:?}", origin); trans_monomorphized_callee(bcx, method_call, + self_expr, trait_def_id, method_id, - origin) + method_ty, + origin, + arg_cleanup_scope) } + } +} - ty::MethodOrigin::Object(vtable_index) => { - let self_expr = match self_expr { - Some(self_expr) => self_expr, - None => { - bcx.sess().span_bug(bcx.tcx().map.span(method_call.expr_id), - "self expr wasn't provided for trait object \ - callee (trying to call overloaded op?)") - } - }; - trans_trait_callee(bcx, - monomorphize_type(bcx, method_ty), - vtable_index, - self_expr, - arg_cleanup_scope) - } +fn method_offset_in_object_vtable<'tcx>(tcx: &ty::ctxt<'tcx>, + object_ty: Ty<'tcx>, + method_id: ast::DefId) + -> usize { + if let ty::TyTrait(ref data) = object_ty.sty { + let trait_ref = data.principal_trait_ref_with_self_ty(tcx, object_ty); + traits::get_vtable_index_of_object_method(tcx, trait_ref, method_id) + } else { + tcx.sess.bug(&format!( + "trans::methd::object_ty_to_trait_ref() called on non-object: {:?}", + object_ty)); } } @@ -237,8 +239,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, Vec::new())); let trait_substs = tcx.mk_substs(trait_substs); debug!("trait_substs={:?}", trait_substs); - let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_id, - substs: trait_substs }); + let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, trait_substs)); let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref); @@ -284,12 +285,11 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, callee_substs) } traits::VtableObject(ref data) => { - let (llfn, ty) = - trans_object_shim(ccx, - data.object_ty, - data.upcast_trait_ref.clone(), - method_id); - immediate_rvalue(llfn, ty) + let idx = method_offset_in_object_vtable(tcx, data.object_ty, method_id); + trans_object_shim(ccx, + data.upcast_trait_ref.clone(), + method_id, + idx) } _ => { tcx.sess.bug(&format!("static call to invalid vtable: {:?}", @@ -322,9 +322,12 @@ 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, + self_expr: Option<&ast::Expr>, trait_id: ast::DefId, method_id: ast::DefId, - vtable: traits::Vtable<'tcx, ()>) + method_ty: Ty<'tcx>, + vtable: traits::Vtable<'tcx, ()>, + arg_cleanup_scope: cleanup::ScopeId) -> Callee<'blk, 'tcx> { let _icx = push_ctxt("meth::trans_monomorphized_callee"); match vtable { @@ -347,13 +350,13 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx, MethodCallKey(method_call), vtable_impl.substs); // translate the function - let llfn = trans_fn_ref_with_substs(bcx.ccx(), - mth_id, - MethodCallKey(method_call), - bcx.fcx.param_substs, - callee_substs).val; + let datum = trans_fn_ref_with_substs(bcx.ccx(), + mth_id, + MethodCallKey(method_call), + bcx.fcx.param_substs, + callee_substs); - Callee { bcx: bcx, data: Fn(llfn) } + Callee { bcx: bcx, data: Fn(datum.val), ty: datum.ty } } traits::VtableClosure(vtable_closure) => { // The substitutions should have no type parameters remaining @@ -368,19 +371,31 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Callee { bcx: bcx, data: Fn(llfn), + ty: monomorphize_type(bcx, method_ty) } } traits::VtableFnPointer(fn_ty) => { let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap(); let llfn = trans_fn_pointer_shim(bcx.ccx(), trait_closure_kind, fn_ty); - Callee { bcx: bcx, data: Fn(llfn) } + Callee { + bcx: bcx, + data: Fn(llfn), + ty: monomorphize_type(bcx, method_ty) + } } traits::VtableObject(ref data) => { - let (llfn, _) = trans_object_shim(bcx.ccx(), - data.object_ty, - data.upcast_trait_ref.clone(), - method_id); - Callee { bcx: bcx, data: Fn(llfn) } + let idx = method_offset_in_object_vtable(bcx.tcx(), data.object_ty, method_id); + if let Some(self_expr) = self_expr { + if let ty::TyBareFn(_, ref fty) = monomorphize_type(bcx, method_ty).sty { + let ty = bcx.tcx().mk_fn(None, opaque_method_ty(bcx.tcx(), fty)); + return trans_trait_callee(bcx, ty, idx, self_expr, arg_cleanup_scope); + } + } + let datum = trans_object_shim(bcx.ccx(), + data.upcast_trait_ref.clone(), + method_id, + idx); + Callee { bcx: bcx, data: Fn(datum.val), ty: datum.ty } } traits::VtableBuiltin(..) | traits::VtableDefaultImpl(..) | @@ -434,7 +449,7 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// object. Objects are represented as a pair, so we first evaluate the self expression and then /// extract the self data and vtable out of the pair. fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - method_ty: Ty<'tcx>, + opaque_fn_ty: Ty<'tcx>, vtable_index: usize, self_expr: &ast::Expr, arg_cleanup_scope: cleanup::ScopeId) @@ -467,51 +482,39 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llself = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR])); let llvtable = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA])); - trans_trait_callee_from_llval(bcx, method_ty, vtable_index, llself, llvtable) + trans_trait_callee_from_llval(bcx, opaque_fn_ty, vtable_index, llself, llvtable) } /// Same as `trans_trait_callee()` above, except that it is given a by-ref pointer to the object /// pair. -pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - callee_ty: Ty<'tcx>, - vtable_index: usize, - llself: ValueRef, - llvtable: ValueRef) - -> Callee<'blk, 'tcx> { +fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + opaque_fn_ty: Ty<'tcx>, + vtable_index: usize, + llself: ValueRef, + llvtable: ValueRef) + -> Callee<'blk, 'tcx> { let _icx = push_ctxt("meth::trans_trait_callee"); let ccx = bcx.ccx(); // Load the data pointer from the object. debug!("trans_trait_callee_from_llval(callee_ty={}, vtable_index={}, llself={}, llvtable={})", - callee_ty, + opaque_fn_ty, vtable_index, bcx.val_to_string(llself), bcx.val_to_string(llvtable)); // Replace the self type (&Self or Box) with an opaque pointer. - let llcallee_ty = match callee_ty.sty { - ty::TyBareFn(_, ref f) if f.abi == Rust || f.abi == RustCall => { - let fake_sig = - ty::Binder(ty::FnSig { - inputs: f.sig.0.inputs[1..].to_vec(), - output: f.sig.0.output, - variadic: f.sig.0.variadic, - }); - type_of_rust_fn(ccx, Some(Type::i8p(ccx)), &fake_sig, f.abi) - } - _ => { - ccx.sess().bug("meth::trans_trait_callee given non-bare-rust-fn"); - } - }; let mptr = Load(bcx, GEPi(bcx, llvtable, &[vtable_index + VTABLE_OFFSET])); + let llcallee_ty = type_of_fn_from_ty(ccx, opaque_fn_ty); - return Callee { + Callee { bcx: bcx, data: TraitItem(MethodData { llfn: PointerCast(bcx, mptr, llcallee_ty.ptr_to()), llself: PointerCast(bcx, llself, Type::i8p(ccx)), - }) - }; + }), + ty: opaque_fn_ty + } } /// Generate a shim function that allows an object type like `SomeTrait` to @@ -538,30 +541,18 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// that go through this shim function. fn trans_object_shim<'a, 'tcx>( ccx: &'a CrateContext<'a, 'tcx>, - object_ty: Ty<'tcx>, upcast_trait_ref: ty::PolyTraitRef<'tcx>, - method_id: ast::DefId) - -> (ValueRef, Ty<'tcx>) + method_id: ast::DefId, + vtable_index: usize) + -> Datum<'tcx, Rvalue> { let _icx = push_ctxt("trans_object_shim"); let tcx = ccx.tcx(); - debug!("trans_object_shim(object_ty={:?}, upcast_trait_ref={:?}, method_id={:?})", - object_ty, + debug!("trans_object_shim(upcast_trait_ref={:?}, method_id={:?})", upcast_trait_ref, method_id); - let object_trait_ref = - match object_ty.sty { - ty::TyTrait(ref data) => { - data.principal_trait_ref_with_self_ty(tcx, object_ty) - } - _ => { - tcx.sess.bug(&format!("trans_object_shim() called on non-object: {:?}", - object_ty)); - } - }; - // Upcast to the trait in question and extract out the substitutions. let upcast_trait_ref = tcx.erase_late_bound_regions(&upcast_trait_ref); let object_substs = upcast_trait_ref.substs.clone().erase_regions(); @@ -617,26 +608,21 @@ fn trans_object_shim<'a, 'tcx>( fcx.llretslotptr.get().map( |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot"))); - let method_offset_in_vtable = - traits::get_vtable_index_of_object_method(bcx.tcx(), - object_trait_ref.clone(), - method_id); debug!("trans_object_shim: method_offset_in_vtable={}", - method_offset_in_vtable); + vtable_index); bcx = trans_call_inner(bcx, DebugLoc::None, - method_bare_fn_ty, |bcx, _| trans_trait_callee_from_llval(bcx, method_bare_fn_ty, - method_offset_in_vtable, + vtable_index, llself, llvtable), ArgVals(&llargs[(self_idx + 2)..]), dest).bcx; finish_fn(&fcx, bcx, sig.output, DebugLoc::None); - (llfn, method_bare_fn_ty) + immediate_rvalue(llfn, shim_fn_ty) } /// Creates a returns a dynamic vtable for the given type and vtable origin. @@ -819,8 +805,8 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } /// Replace the self type (&Self or Box) with an opaque pointer. -pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>) - -> &'tcx ty::BareFnTy<'tcx> { +fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>) + -> &'tcx ty::BareFnTy<'tcx> { let mut inputs = method_ty.sig.0.inputs.clone(); inputs[0] = tcx.mk_mut_ptr(tcx.mk_mach_int(ast::TyI8)); diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 3ef72e2c4af3a..98fe57ec31446 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -59,7 +59,8 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let item_ty = ccx.tcx().lookup_item_type(fn_id).ty; debug!("monomorphic_fn about to subst into {:?}", item_ty); - let mono_ty = item_ty.subst(ccx.tcx(), psubsts); + let mono_ty = apply_param_substs(ccx.tcx(), psubsts, &item_ty); + debug!("mono_ty = {:?} (post-substitution)", mono_ty); match ccx.monomorphized().borrow().get(&hash_id) { Some(&val) => { @@ -96,11 +97,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } - debug!("mono_ty = {:?} (post-substitution)", mono_ty); - - let mono_ty = normalize_associated_type(ccx.tcx(), &mono_ty); - debug!("mono_ty = {:?} (post-normalization)", mono_ty); - ccx.stats().n_monos.set(ccx.stats().n_monos.get() + 1); let depth; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 26868c16bd85f..625db8d8128c0 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -230,11 +230,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { trait_def_id); let substs = upcast_trait_ref.substs.clone(); - 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)) + (substs, ty::MethodOrigin::Trait) }) } From 536e71b78f46acb75e08481708a93bd07c0a107a Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 4 Jul 2015 05:46:54 +0300 Subject: [PATCH 7/8] rustc: compute the vtable base of a supertrait during selection. Fixes #26339. --- src/librustc/middle/traits/mod.rs | 8 ++- src/librustc/middle/traits/project.rs | 10 ++-- src/librustc/middle/traits/select.rs | 73 +++++++++++-------------- src/librustc/middle/traits/util.rs | 67 +++++++++++------------ src/librustc/middle/ty_fold.rs | 2 +- src/librustc_trans/trans/meth.rs | 18 +----- src/test/run-pass/traits-issue-26339.rs | 40 ++++++++++++++ 7 files changed, 117 insertions(+), 101 deletions(-) create mode 100644 src/test/run-pass/traits-issue-26339.rs diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 5126a549887ed..b5f01ada7e178 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -291,11 +291,13 @@ pub struct VtableBuiltinData { /// for the object type `Foo`. #[derive(PartialEq,Eq,Clone)] pub struct VtableObjectData<'tcx> { - /// the object type `Foo`. - pub object_ty: Ty<'tcx>, - /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, + + /// The vtable is formed by concatenating together the method lists of + /// the base object trait and all supertraits; this is the start of + /// `upcast_trait_ref`'s methods in that vtable. + pub vtable_base: usize } /// Creates predicate obligations from the generic bounds. diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index e5f7542aa84c9..e29d9646509f9 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -629,9 +629,10 @@ fn assemble_candidates_from_object_type<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, obligation: &ProjectionTyObligation<'tcx>, obligation_trait_ref: &ty::TraitRef<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, - object_ty: Ty<'tcx>) + candidate_set: &mut ProjectionTyCandidateSet<'tcx>) { + let self_ty = obligation_trait_ref.self_ty(); + let object_ty = selcx.infcx().shallow_resolve(self_ty); debug!("assemble_candidates_from_object_type(object_ty={:?})", object_ty); let data = match object_ty.sty { @@ -684,10 +685,9 @@ fn assemble_candidates_from_impls<'cx,'tcx>( candidate_set.vec.push( ProjectionTyCandidate::Impl(data)); } - super::VtableObject(data) => { + super::VtableObject(_) => { assemble_candidates_from_object_type( - selcx, obligation, obligation_trait_ref, candidate_set, - data.object_ty); + selcx, obligation, obligation_trait_ref, candidate_set); } super::VtableClosure(data) => { candidate_set.vec.push( diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index abc300869adca..ad91f664af2db 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1362,12 +1362,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}", poly_trait_ref); - // see whether the object trait can be upcast to the trait we are looking for - let upcast_trait_refs = self.upcast(poly_trait_ref, obligation); - if upcast_trait_refs.len() > 1 { + // Count only those upcast versions that match the trait-ref + // we are looking for. Specifically, do not only check for the + // correct trait, but also the correct type parameters. + // For example, we may be trying to upcast `Foo` to `Bar`, + // but `Foo` is declared as `trait Foo : Bar`. + let upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref) + .filter(|upcast_trait_ref| self.infcx.probe(|_| { + let upcast_trait_ref = upcast_trait_ref.clone(); + self.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok() + })).count(); + + if upcast_trait_refs > 1 { // can be upcast in many ways; need more type information candidates.ambiguous = true; - } else if upcast_trait_refs.len() == 1 { + } else if upcast_trait_refs == 1 { candidates.vec.push(ObjectCandidate); } @@ -2305,20 +2314,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // be exactly one applicable trait-reference; if this were not // the case, we would have reported an ambiguity error rather // than successfully selecting one of the candidates. - let upcast_trait_refs = self.upcast(poly_trait_ref.clone(), obligation); - assert_eq!(upcast_trait_refs.len(), 1); - let upcast_trait_ref = upcast_trait_refs.into_iter().next().unwrap(); + let mut upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref) + .map(|upcast_trait_ref| { + (upcast_trait_ref.clone(), self.infcx.probe(|_| { + self.match_poly_trait_ref(obligation, upcast_trait_ref) + }).is_ok()) + }); + let mut upcast_trait_ref = None; + let mut vtable_base = 0; - match self.match_poly_trait_ref(obligation, upcast_trait_ref.clone()) { - Ok(()) => { } - Err(()) => { - self.tcx().sess.span_bug(obligation.cause.span, - "failed to match trait refs"); + while let Some((supertrait, matches)) = upcast_trait_refs.next() { + if matches { + upcast_trait_ref = Some(supertrait); + break; } + vtable_base += util::count_own_vtable_entries(self.tcx(), supertrait); } + assert!(upcast_trait_refs.all(|(_, matches)| !matches)); - VtableObjectData { object_ty: self_ty, - upcast_trait_ref: upcast_trait_ref } + VtableObjectData { + upcast_trait_ref: upcast_trait_ref.unwrap(), + vtable_base: vtable_base + } } fn confirm_fn_pointer_candidate(&mut self, @@ -2719,7 +2736,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Returns `Ok` if `poly_trait_ref` being true implies that the /// obligation is satisfied. - fn match_poly_trait_ref(&mut self, + fn match_poly_trait_ref(&self, obligation: &TraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Result<(),()> @@ -2930,32 +2947,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone() } } - - /// Upcasts an object trait-reference into those that match the obligation. - fn upcast(&mut self, obj_trait_ref: ty::PolyTraitRef<'tcx>, obligation: &TraitObligation<'tcx>) - -> Vec> - { - debug!("upcast(obj_trait_ref={:?}, obligation={:?})", - obj_trait_ref, - obligation); - - let obligation_def_id = obligation.predicate.def_id(); - let mut upcast_trait_refs = util::upcast(self.tcx(), obj_trait_ref, obligation_def_id); - - // Retain only those upcast versions that match the trait-ref - // we are looking for. In particular, we know that all of - // `upcast_trait_refs` apply to the correct trait, but - // possibly with incorrect type parameters. For example, we - // may be trying to upcast `Foo` to `Bar`, but `Foo` is - // declared as `trait Foo : Bar`. - upcast_trait_refs.retain(|upcast_trait_ref| { - let upcast_trait_ref = upcast_trait_ref.clone(); - self.infcx.probe(|_| self.match_poly_trait_ref(obligation, upcast_trait_ref)).is_ok() - }); - - debug!("upcast: upcast_trait_refs={:?}", upcast_trait_refs); - upcast_trait_refs - } } impl<'tcx> SelectionCache<'tcx> { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index e8a24876b18dc..af9d5e5157d28 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -396,38 +396,34 @@ pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>, .collect() } -/// Given an object of type `object_trait_ref`, returns the index of -/// 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>, - 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 - // we find the trait the method came from, counting up the - // 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; - } - - let trait_items = tcx.trait_items(bound_ref.def_id()); - for trait_item in trait_items.iter() { - match *trait_item { - ty::MethodTraitItem(_) => method_count += 1, - _ => {} - } +/// Given an trait `trait_ref`, returns the number of vtable entries +/// that come from `trait_ref`, excluding its supertraits. Used in +/// computing the vtable base for an upcast trait of a trait object. +pub fn count_own_vtable_entries<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>) + -> usize { + let mut entries = 0; + // Count number of methods and add them to the total offset. + // Skip over associated types and constants. + for trait_item in &tcx.trait_items(trait_ref.def_id())[..] { + if let ty::MethodTraitItem(_) = *trait_item { + entries += 1; } } + entries +} - // count number of methods preceding the one we are selecting and - // add them to the total offset; skip over associated types. - for trait_item in &tcx.trait_items(trait_def_id)[..] { +/// Given an upcast trait object described by `object`, returns the +/// index of the method `method_def_id` (which should be part of +/// `object.upcast_trait_ref`) within the vtable for `object`. +pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>, + object: &super::VtableObjectData<'tcx>, + method_def_id: ast::DefId) -> usize { + // Count number of methods preceding the one we are selecting and + // add them to the total offset. + // Skip over associated types and constants. + let mut entries = object.vtable_base; + for trait_item in &tcx.trait_items(object.upcast_trait_ref.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 { @@ -435,11 +431,10 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>, _ => false }); - return method_count; + return entries; } - match *trait_item { - ty::MethodTraitItem(_) => method_count += 1, - _ => {} + if let ty::MethodTraitItem(_) = *trait_item { + entries += 1; } } @@ -493,7 +488,7 @@ impl<'tcx, N:fmt::Debug> fmt::Debug for super::Vtable<'tcx, N> { write!(f, "VtableFnPointer({:?})", d), super::VtableObject(ref d) => - write!(f, "VtableObject({:?})", d), + write!(f, "{:?}", d), super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n), @@ -538,7 +533,9 @@ impl<'tcx, N:fmt::Debug> fmt::Debug for super::VtableDefaultImplData { impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "VtableObject(object_ty={:?})", self.object_ty) + write!(f, "VtableObject(upcast={:?}, vtable_base={})", + self.upcast_trait_ref, + self.vtable_base) } } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 402f31fc770d9..7016c1484659b 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -492,8 +492,8 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> { fn fold_with>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> { traits::VtableObjectData { - object_ty: self.object_ty.fold_with(folder), upcast_trait_ref: self.upcast_trait_ref.fold_with(folder), + vtable_base: self.vtable_base } } } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index ece5682c6ba9b..2cab7d2a1c84a 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -160,20 +160,6 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn method_offset_in_object_vtable<'tcx>(tcx: &ty::ctxt<'tcx>, - object_ty: Ty<'tcx>, - method_id: ast::DefId) - -> usize { - if let ty::TyTrait(ref data) = object_ty.sty { - let trait_ref = data.principal_trait_ref_with_self_ty(tcx, object_ty); - traits::get_vtable_index_of_object_method(tcx, trait_ref, method_id) - } else { - tcx.sess.bug(&format!( - "trans::methd::object_ty_to_trait_ref() called on non-object: {:?}", - object_ty)); - } -} - pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, method_id: ast::DefId, trait_id: ast::DefId, @@ -285,7 +271,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, callee_substs) } traits::VtableObject(ref data) => { - let idx = method_offset_in_object_vtable(tcx, data.object_ty, method_id); + let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id); trans_object_shim(ccx, data.upcast_trait_ref.clone(), method_id, @@ -384,7 +370,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } traits::VtableObject(ref data) => { - let idx = method_offset_in_object_vtable(bcx.tcx(), data.object_ty, method_id); + let idx = traits::get_vtable_index_of_object_method(bcx.tcx(), data, method_id); if let Some(self_expr) = self_expr { if let ty::TyBareFn(_, ref fty) = monomorphize_type(bcx, method_ty).sty { let ty = bcx.tcx().mk_fn(None, opaque_method_ty(bcx.tcx(), fty)); diff --git a/src/test/run-pass/traits-issue-26339.rs b/src/test/run-pass/traits-issue-26339.rs new file mode 100644 index 0000000000000..f2cf1779d6241 --- /dev/null +++ b/src/test/run-pass/traits-issue-26339.rs @@ -0,0 +1,40 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the right implementation is called through a trait +// object when supertraits include multiple references to the +// same trait, with different type parameters. + +trait A: PartialEq + PartialEq { } + +struct Foo; +struct Bar; + +struct Aimpl; + +impl PartialEq for Aimpl { + fn eq(&self, _rhs: &Foo) -> bool { + true + } +} + +impl PartialEq for Aimpl { + fn eq(&self, _rhs: &Bar) -> bool { + false + } +} + +impl A for Aimpl { } + +fn main() { + let a = &Aimpl as &A; + + assert!(*a == Foo); +} From d256eb1c5ddd6740140b6538a018a0171f45fdae Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 4 Jul 2015 07:07:10 +0300 Subject: [PATCH 8/8] rustc: remove MethodOrigin and use the container to distinguish inherent methods. --- src/librustc/middle/astencode.rs | 17 +++++------- src/librustc/middle/check_const.rs | 9 +++---- src/librustc/middle/dead.rs | 15 +++-------- src/librustc/middle/effect.rs | 2 +- src/librustc/middle/liveness.rs | 2 +- src/librustc/middle/reachable.rs | 7 ++--- src/librustc/middle/stability.rs | 5 +--- src/librustc/middle/ty.rs | 12 +-------- src/librustc_lint/builtin.rs | 6 ++--- src/librustc_privacy/lib.rs | 27 +++++++------------ src/librustc_trans/save/dump_csv.rs | 14 ++++------ src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/common.rs | 2 +- src/librustc_trans/trans/meth.rs | 30 +++++++-------------- src/librustc_typeck/check/method/confirm.rs | 29 +++++++------------- src/librustc_typeck/check/method/mod.rs | 1 - src/librustc_typeck/check/writeback.rs | 1 - 17 files changed, 60 insertions(+), 121 deletions(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index fa06d50272885..7c76f4fe289df 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -609,20 +609,17 @@ fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>, method: &ty::MethodCallee<'tcx>) { use serialize::Encoder; - rbml_w.emit_struct("MethodCallee", 5, |rbml_w| { + rbml_w.emit_struct("MethodCallee", 4, |rbml_w| { rbml_w.emit_struct_field("autoderef", 0, |rbml_w| { autoderef.encode(rbml_w) }); rbml_w.emit_struct_field("def_id", 1, |rbml_w| { Ok(rbml_w.emit_def_id(method.def_id)) }); - rbml_w.emit_struct_field("origin", 2, |rbml_w| { - method.origin.encode(rbml_w) - }); - rbml_w.emit_struct_field("ty", 3, |rbml_w| { + rbml_w.emit_struct_field("ty", 2, |rbml_w| { Ok(rbml_w.emit_ty(ecx, method.ty)) }); - rbml_w.emit_struct_field("substs", 4, |rbml_w| { + rbml_w.emit_struct_field("substs", 3, |rbml_w| { Ok(rbml_w.emit_substs(ecx, &method.substs)) }) }).unwrap(); @@ -632,19 +629,17 @@ 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, ty::MethodCallee<'tcx>) { - self.read_struct("MethodCallee", 5, |this| { + self.read_struct("MethodCallee", 4, |this| { let autoderef = this.read_struct_field("autoderef", 0, Decodable::decode).unwrap(); 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, - Decodable::decode).unwrap(), - ty: this.read_struct_field("ty", 3, |this| { + ty: this.read_struct_field("ty", 2, |this| { Ok(this.read_ty(dcx)) }).unwrap(), - substs: this.read_struct_field("substs", 4, |this| { + substs: this.read_struct_field("substs", 3, |this| { Ok(dcx.tcx.mk_substs(this.read_substs(dcx))) }).unwrap() })) diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index fbb7b3f235a34..b5c78340d022d 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -696,11 +696,10 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } } ast::ExprMethodCall(..) => { - 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 + let method = v.tcx.tables.borrow().method_map[&method_call]; + let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() { + ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty), + ty::TraitContainer(_) => 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 040afcac03cc6..8d2d6889b5efa 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -93,17 +93,10 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { }); } - fn lookup_and_handle_method(&mut self, id: ast::NodeId, - span: codemap::Span) { + fn lookup_and_handle_method(&mut self, id: ast::NodeId) { let method_call = ty::MethodCall::expr(id); - match self.tcx.tables.borrow().method_map.get(&method_call) { - Some(method) => self.check_def_id(method.def_id), - None => { - self.tcx.sess.span_bug(span, - "method call expression not \ - in method map?!") - } - } + let method = self.tcx.tables.borrow().method_map[&method_call]; + self.check_def_id(method.def_id); } fn handle_field_access(&mut self, lhs: &ast::Expr, name: ast::Name) { @@ -239,7 +232,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &ast::Expr) { match expr.node { ast::ExprMethodCall(..) => { - self.lookup_and_handle_method(expr.id, expr.span); + self.lookup_and_handle_method(expr.id); } ast::ExprField(ref lhs, ref ident) => { self.handle_field_access(&**lhs, ident.node.name); diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 8084c2b0c39b8..af9e21a47d0b0 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { match expr.node { ast::ExprMethodCall(_, _, _) => { let method_call = MethodCall::expr(expr.id); - let base_type = self.tcx.tables.borrow().method_map.get(&method_call).unwrap().ty; + let base_type = self.tcx.tables.borrow().method_map[&method_call].ty; debug!("effect: method call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 68001ae1564ab..37460531dbdbf 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1148,7 +1148,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ast::ExprMethodCall(_, _, ref args) => { let method_call = ty::MethodCall::expr(expr.id); - let method_ty = self.ir.tcx.tables.borrow().method_map.get(&method_call).unwrap().ty; + let method_ty = self.ir.tcx.tables.borrow().method_map[&method_call].ty; let succ = if method_ty.fn_ret().diverges() { self.s.exit_ln } else { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index dda33b28cce3b..d588f7c6070ce 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -128,8 +128,9 @@ 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[&method_call] { - ty::MethodCallee { def_id, origin: ty::MethodOrigin::Inherent, .. } => { + let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + match self.tcx.impl_or_trait_item(def_id).container() { + ty::ImplContainer(_) => { if is_local(def_id) { if self.def_id_represents_local_inlined_item(def_id) { self.worklist.push(def_id.node) @@ -137,7 +138,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { self.reachable_symbols.insert(def_id.node); } } - _ => {} + ty::TraitContainer(_) => {} } } _ => {} diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 7cabf50fe0931..46be4b752266e 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -406,10 +406,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr, ast::ExprMethodCall(i, _, _) => { span = i.span; let method_call = ty::MethodCall::expr(e.id); - match tcx.tables.borrow().method_map.get(&method_call) { - Some(method) => method.def_id, - None => return - } + tcx.tables.borrow().method_map[&method_call].def_id } ast::ExprField(ref base_e, ref field) => { span = field.span; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 971774336c8b3..715072a12ebd0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -625,20 +625,10 @@ pub enum CustomCoerceUnsized { Struct(usize) } -#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] -pub enum MethodOrigin { - /// Inherent impl method call. - Inherent, - - /// Trait method call. - Trait -} - -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct MethodCallee<'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: &'tcx subst::Substs<'tcx> } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d92a5c9c76eda..fa86c0dde991d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1995,9 +1995,9 @@ impl LintPass for UnconditionalRecursion { fn expr_refers_to_this_method(tcx: &ty::ctxt, method: &ty::Method, id: ast::NodeId) -> bool { - let tables = tcx.tables.borrow(); - let callee = match tables.method_map.get(&ty::MethodCall::expr(id)) { - Some(m) => m, + let method_call = ty::MethodCall::expr(id); + let callee = match tcx.tables.borrow().method_map.get(&method_call) { + Some(&m) => m, None => return false }; let callee_item = tcx.impl_or_trait_item(callee.def_id); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 4f315b56815c6..d90e5a033a187 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -844,17 +844,16 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { } // Checks that a method is in scope. - fn check_method(&mut self, span: Span, callee: &ty::MethodCallee, + fn check_method(&mut self, span: Span, method_def_id: ast::DefId, name: ast::Name) { - match callee.origin { - ty::MethodOrigin::Inherent => { - self.check_static_method(span, callee.def_id, name) + match self.tcx.impl_or_trait_item(method_def_id).container() { + ty::ImplContainer(_) => { + self.check_static_method(span, method_def_id, name) } // Trait methods are always all public. The only controlling factor // is whether the trait itself is accessible or not. - ty::MethodOrigin::Trait => { - let method = self.tcx.impl_or_trait_item(callee.def_id); - self.report_error(self.ensure_public(span, method.container().id(), + ty::TraitContainer(trait_def_id) => { + self.report_error(self.ensure_public(span, trait_def_id, None, "source trait")); } } @@ -899,17 +898,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } ast::ExprMethodCall(ident, _, _) => { 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, - "method call not in \ - method map"); - } - Some(method) => { - debug!("(privacy checking) checking impl method"); - self.check_method(expr.span, method, ident.node.name); - } - } + let method = self.tcx.tables.borrow().method_map[&method_call]; + debug!("(privacy checking) checking impl method"); + self.check_method(expr.span, method.def_id, ident.node.name); } ast::ExprStruct(_, ref fields, _) => { match self.tcx.expr_ty(expr).sty { diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index d0f9456b11c3d..e88b3980737ab 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -886,15 +886,11 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { fn process_method_call(&mut self, ex: &ast::Expr, args: &Vec>) { - 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::MethodOrigin::Inherent => { - (Some(method_callee.def_id), None) - } - ty::MethodOrigin::Trait => { - (None, Some(method_callee.def_id)) - } + let method_call = ty::MethodCall::expr(ex.id); + let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() { + ty::ImplContainer(_) => (Some(method_id), None), + ty::TraitContainer(_) => (None, Some(method_id)) }; let sub_span = self.span.sub_span_for_meth_name(ex.span); self.fmt.meth_call_str(ex.span, diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index dc5b6cf7db883..debc8dd59c04c 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -499,7 +499,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( let ref_ty = match node { ExprId(id) => tcx.node_id_to_type(id), MethodCallKey(method_call) => { - tcx.tables.borrow().method_map.get(&method_call).unwrap().ty + tcx.tables.borrow().method_map[&method_call].ty } }; let ref_ty = monomorphize::apply_param_substs(tcx, diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 8282eb734f2b9..e1c1ac9a772eb 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -1025,7 +1025,7 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, tcx.node_id_item_substs(id).substs } MethodCallKey(method_call) => { - tcx.tables.borrow().method_map.get(&method_call).unwrap().substs.clone() + tcx.tables.borrow().method_map[&method_call].substs.clone() } }; diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 2cab7d2a1c84a..1fa996f76b9a2 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -106,20 +106,13 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, -> Callee<'blk, 'tcx> { let _icx = push_ctxt("meth::trans_method_callee"); - let (method_id, origin, method_substs, method_ty) = - bcx.tcx() - .tables - .borrow() - .method_map - .get(&method_call) - .map(|method| (method.def_id, method.origin, method.substs, method.ty)) - .unwrap(); - - match origin { - ty::MethodOrigin::Inherent => { - debug!("trans_method_callee: static, {:?}", method_id); + let method = bcx.tcx().tables.borrow().method_map[&method_call]; + + match bcx.tcx().impl_or_trait_item(method.def_id).container() { + ty::ImplContainer(_) => { + debug!("trans_method_callee: static, {:?}", method.def_id); let datum = callee::trans_fn_ref(bcx.ccx(), - method_id, + method.def_id, MethodCallKey(method_call), bcx.fcx.param_substs); Callee { @@ -129,11 +122,8 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } - 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(); + ty::TraitContainer(trait_def_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); @@ -152,8 +142,8 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, method_call, self_expr, trait_def_id, - method_id, - method_ty, + method.def_id, + method.ty, origin, arg_cleanup_scope) } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 625db8d8128c0..8db5b5e7c508c 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -84,8 +84,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { self.enforce_illegal_method_limitations(&pick); // Create substitutions for the method's type parameters. - let (rcvr_substs, method_origin) = - self.fresh_receiver_substs(self_ty, &pick); + let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick); let (method_types, method_regions) = self.instantiate_method_substs(&pick, supplied_method_types); let all_substs = rcvr_substs.with_method(method_types, method_regions); @@ -112,7 +111,6 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { })); let callee = ty::MethodCallee { def_id: pick.item.def_id(), - origin: method_origin, ty: fty, substs: self.tcx().mk_substs(all_substs) }; @@ -193,16 +191,14 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { fn fresh_receiver_substs(&mut self, self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) - -> (subst::Substs<'tcx>, ty::MethodOrigin) + -> subst::Substs<'tcx> { match pick.kind { 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, ty::MethodOrigin::Inherent) + check::impl_self_ty(self.fcx, self.span, impl_def_id).substs } probe::ObjectPick => { @@ -228,9 +224,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { original_poly_trait_ref, upcast_trait_ref, trait_def_id); - let substs = upcast_trait_ref.substs.clone(); - - (substs, ty::MethodOrigin::Trait) + upcast_trait_ref.substs.clone() }) } @@ -250,8 +244,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { self.span, &impl_polytype.substs, &self.tcx().impl_trait_ref(impl_def_id).unwrap()); - let substs = impl_trait_ref.substs.clone(); - (substs, ty::MethodOrigin::Trait) + impl_trait_ref.substs.clone() } probe::TraitPick => { @@ -263,19 +256,15 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // the process we will unify the transformed-self-type // of the method with the actual type in order to // unify some of these variables. - let substs = self.infcx().fresh_substs_for_trait(self.span, - &trait_def.generics, - self.infcx().next_ty_var()); - - (substs, ty::MethodOrigin::Trait) + self.infcx().fresh_substs_for_trait(self.span, + &trait_def.generics, + self.infcx().next_ty_var()) } 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(); - (substs, ty::MethodOrigin::Trait) + self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref).substs.clone() } } } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 0ba0903172440..2117cba108730 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -307,7 +307,6 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let callee = ty::MethodCallee { def_id: method_item.def_id(), - origin: ty::MethodOrigin::Trait, ty: fty, substs: trait_ref.substs }; diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 8ed99ac916249..419fa9e160a47 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -303,7 +303,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { method); let new_method = MethodCallee { def_id: method.def_id, - origin: method.origin, ty: self.resolve(&method.ty, reason), substs: self.tcx().mk_substs(self.resolve(method.substs, reason)), };