From 709ce9f96ddd58a71bd7067bf49756e3bf6ac4ec Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 30 Sep 2015 22:28:27 +0300 Subject: [PATCH] kill the fake provided method stubs this simplifies the code while reducing the size of libcore.rlib by 3.3 MiB (~1M of which is bloat a separate patch of mine removes too), while reducing rustc memory usage on small crates by 18MiB. This also simplifies the code considerably. --- src/librustc/metadata/common.rs | 2 +- src/librustc/metadata/decoder.rs | 55 ++++----- src/librustc/metadata/encoder.rs | 20 ++-- src/librustc/middle/ty/context.rs | 3 - src/librustc/middle/ty/mod.rs | 26 +--- src/librustc/middle/ty/util.rs | 55 ++++++++- src/librustc_privacy/lib.rs | 13 -- src/librustc_trans/trans/callee.rs | 82 ++----------- src/librustc_trans/trans/meth.rs | 52 ++------ src/librustc_typeck/check/method/suggest.rs | 9 +- src/librustc_typeck/check/mod.rs | 6 +- src/librustc_typeck/coherence/mod.rs | 124 +------------------- src/librustc_typeck/collect.rs | 14 +-- src/librustdoc/clean/inline.rs | 12 +- 14 files changed, 139 insertions(+), 334 deletions(-) diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index bc54d9ff133..a6cbb4ec504 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -180,7 +180,7 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f pub const tag_misc_info: usize = 0x108; // top-level only pub const tag_misc_info_crate_items: usize = 0x7c; -pub const tag_item_method_provided_source: usize = 0x7d; +// GAP 0x7d pub const tag_item_impl_vtables: usize = 0x7e; pub const tag_impls: usize = 0x109; // top-level only diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 648ebdefffe..77863ee3c87 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -187,12 +187,6 @@ fn item_def_id(d: rbml::Doc, cdata: Cmd) -> DefId { translated_def_id(cdata, reader::get_doc(d, tag_def_id)) } -fn get_provided_source(d: rbml::Doc, cdata: Cmd) -> Option { - reader::maybe_get_doc(d, tag_item_method_provided_source).map(|doc| { - translated_def_id(cdata, doc) - }) -} - fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> { reader::tagged_docs(d, tag_items_data_item_reexport) } @@ -276,11 +270,14 @@ fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike { match fam { Constant => { // Check whether we have an associated const item. - if item_sort(item) == Some('C') { - DlDef(def::DefAssociatedConst(did)) - } else { - // Regular const item. - DlDef(def::DefConst(did)) + match item_sort(item) { + Some('C') | Some('c') => { + DlDef(def::DefAssociatedConst(did)) + } + _ => { + // Regular const item. + DlDef(def::DefConst(did)) + } } } ImmStatic => DlDef(def::DefStatic(did, false)), @@ -818,7 +815,7 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId) reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| { let def_id = item_def_id(doc, cdata); match item_sort(doc) { - Some('C') => ty::ConstTraitItemId(def_id), + Some('C') | Some('c') => ty::ConstTraitItemId(def_id), Some('r') | Some('p') => ty::MethodTraitItemId(def_id), Some('t') => ty::TypeTraitItemId(def_id), _ => panic!("unknown impl item sort"), @@ -864,16 +861,15 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc, let vis = item_visibility(item_doc); match item_sort(item_doc) { - Some('C') => { + sort @ Some('C') | sort @ Some('c') => { let ty = doc_type(item_doc, tcx, cdata); - let default = get_provided_source(item_doc, cdata); ty::ConstTraitItem(Rc::new(ty::AssociatedConst { name: name, ty: ty, vis: vis, def_id: def_id, container: container, - default: default, + has_value: sort == Some('C') })) } Some('r') | Some('p') => { @@ -881,7 +877,6 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc, let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics); let fty = doc_method_fty(item_doc, tcx, cdata); let explicit_self = get_explicit_self(item_doc); - let provided_source = get_provided_source(item_doc, cdata); ty::MethodTraitItem(Rc::new(ty::Method::new(name, generics, @@ -890,8 +885,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc, explicit_self, vis, def_id, - container, - provided_source))) + container))) } Some('t') => { let ty = maybe_doc_type(item_doc, tcx, cdata); @@ -913,7 +907,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId) reader::tagged_docs(item, tag_item_trait_item).map(|mth| { let def_id = item_def_id(mth, cdata); match item_sort(mth) { - Some('C') => ty::ConstTraitItemId(def_id), + Some('C') | Some('c') => ty::ConstTraitItemId(def_id), Some('r') | Some('p') => ty::MethodTraitItemId(def_id), Some('t') => ty::TypeTraitItemId(def_id), _ => panic!("unknown trait item sort"), @@ -967,18 +961,19 @@ pub fn get_associated_consts<'tcx>(intr: Rc, let did = item_def_id(ac_id, cdata); let ac_doc = cdata.lookup_item(did.node); - if item_sort(ac_doc) == Some('C') { - let trait_item = get_impl_or_trait_item(intr.clone(), - cdata, - did.node, - tcx); - if let ty::ConstTraitItem(ref ac) = trait_item { - Some((*ac).clone()) - } else { - None + match item_sort(ac_doc) { + Some('C') | Some('c') => { + let trait_item = get_impl_or_trait_item(intr.clone(), + cdata, + did.node, + tcx); + if let ty::ConstTraitItem(ref ac) = trait_item { + Some((*ac).clone()) + } else { + None + } } - } else { - None + _ => None } }) }).collect() diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 8acdc7e8ce2..0d83103e0bb 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -609,13 +609,6 @@ fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) { rbml_w.wr_tagged_u8(tag_item_trait_parent_sort, sort as u8); } -fn encode_provided_source(rbml_w: &mut Encoder, - source_opt: Option) { - if let Some(source) = source_opt { - rbml_w.wr_tagged_u64(tag_item_method_provided_source, def_to_u64(source)); - } -} - fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, field: ty::FieldDef<'tcx>, @@ -776,7 +769,6 @@ fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, } _ => encode_family(rbml_w, METHOD_FAMILY) } - encode_provided_source(rbml_w, method_ty.provided_source); } fn encode_info_for_associated_const(ecx: &EncodeContext, @@ -795,7 +787,6 @@ fn encode_info_for_associated_const(ecx: &EncodeContext, encode_name(rbml_w, associated_const.name); encode_visibility(rbml_w, associated_const.vis); encode_family(rbml_w, 'C'); - encode_provided_source(rbml_w, associated_const.default); encode_parent_item(rbml_w, DefId::local(parent_id)); encode_item_sort(rbml_w, 'C'); @@ -1367,13 +1358,10 @@ fn add_to_index(item: &hir::Item, rbml_w: &mut Encoder, encode_def_id(rbml_w, associated_const.def_id); encode_visibility(rbml_w, associated_const.vis); - encode_provided_source(rbml_w, associated_const.default); - let elem = ast_map::PathName(associated_const.name); encode_path(rbml_w, path.clone().chain(Some(elem))); - encode_item_sort(rbml_w, 'C'); encode_family(rbml_w, 'C'); encode_bounds_and_type_for_item(rbml_w, ecx, @@ -1429,7 +1417,13 @@ fn add_to_index(item: &hir::Item, rbml_w: &mut Encoder, let trait_item = &*ms[i]; encode_attributes(rbml_w, &trait_item.attrs); match trait_item.node { - hir::ConstTraitItem(_, _) => { + hir::ConstTraitItem(_, ref default) => { + if default.is_some() { + encode_item_sort(rbml_w, 'C'); + } else { + encode_item_sort(rbml_w, 'c'); + } + encode_inlined_item(ecx, rbml_w, InlinedItemRef::TraitItem(def_id, trait_item)); } diff --git a/src/librustc/middle/ty/context.rs b/src/librustc/middle/ty/context.rs index f32e86e276c..57f04af2ba9 100644 --- a/src/librustc/middle/ty/context.rs +++ b/src/librustc/middle/ty/context.rs @@ -235,8 +235,6 @@ pub struct ctxt<'tcx> { pub ty_param_defs: RefCell>>, pub normalized_cache: RefCell, Ty<'tcx>>>, pub lang_items: middle::lang_items::LanguageItems, - /// A mapping of fake provided method def_ids to the default implementation - pub provided_method_sources: RefCell>, /// Maps from def-id of a type or region parameter to its /// (inferred) variance. @@ -471,7 +469,6 @@ pub fn create_and_enter(s: Session, ty_param_defs: RefCell::new(NodeMap()), normalized_cache: RefCell::new(FnvHashMap()), lang_items: lang_items, - provided_method_sources: RefCell::new(DefIdMap()), inherent_impls: RefCell::new(DefIdMap()), impl_items: RefCell::new(DefIdMap()), used_unsafe: RefCell::new(NodeSet()), diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index c3e7fd4ceca..7ec39619d9c 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -235,9 +235,6 @@ pub struct Method<'tcx> { pub vis: hir::Visibility, pub def_id: DefId, pub container: ImplOrTraitItemContainer, - - // If this method is provided, we need to know where it came from - pub provided_source: Option } impl<'tcx> Method<'tcx> { @@ -248,8 +245,7 @@ pub fn new(name: Name, explicit_self: ExplicitSelfCategory, vis: hir::Visibility, def_id: DefId, - container: ImplOrTraitItemContainer, - provided_source: Option) + container: ImplOrTraitItemContainer) -> Method<'tcx> { Method { name: name, @@ -260,7 +256,6 @@ pub fn new(name: Name, vis: vis, def_id: def_id, container: container, - provided_source: provided_source } } @@ -293,7 +288,7 @@ pub struct AssociatedConst<'tcx> { pub vis: hir::Visibility, pub def_id: DefId, pub container: ImplOrTraitItemContainer, - pub default: Option, + pub has_value: bool } #[derive(Clone, Copy, Debug)] @@ -2105,10 +2100,6 @@ pub fn expr_is_lval(&self, expr: &hir::Expr) -> bool { } } - pub fn provided_source(&self, id: DefId) -> Option { - self.provided_method_sources.borrow().get(&id).cloned() - } - pub fn provided_trait_methods(&self, id: DefId) -> Vec>> { if id.is_local() { if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id.node).node { @@ -2477,16 +2468,9 @@ pub fn populate_implementations_for_trait_if_necessary(&self, trait_id: DefId) { // the map. This is a bit unfortunate. for impl_item_def_id in &impl_items { let method_def_id = impl_item_def_id.def_id(); - match self.impl_or_trait_item(method_def_id) { - MethodTraitItem(method) => { - if let Some(source) = method.provided_source { - self.provided_method_sources - .borrow_mut() - .insert(method_def_id, source); - } - } - _ => {} - } + // load impl items eagerly for convenience + // FIXME: we may want to load these lazily + self.impl_or_trait_item(method_def_id); } // Store the implementation info. diff --git a/src/librustc/middle/ty/util.rs b/src/librustc/middle/ty/util.rs index 3a90f3e0136..a431bbaeeb8 100644 --- a/src/librustc/middle/ty/util.rs +++ b/src/librustc/middle/ty/util.rs @@ -14,7 +14,7 @@ use middle::const_eval::{self, ConstVal, ErrKind}; use middle::const_eval::EvalHint::UncheckedExprHint; use middle::def_id::DefId; -use middle::subst; +use middle::subst::{self, Subst, Substs}; use middle::infer; use middle::pat_util; use middle::traits; @@ -26,6 +26,7 @@ use std::cmp; use std::hash::{Hash, SipHasher, Hasher}; +use std::rc::Rc; use syntax::ast::{self, Name}; use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt}; use syntax::codemap::Span; @@ -646,6 +647,58 @@ pub fn is_adt_dtorck(&self, adt: ty::AdtDef<'tcx>) -> bool { } } +#[derive(Debug)] +pub struct ImplMethod<'tcx> { + pub method: Rc>, + pub substs: Substs<'tcx>, + pub is_provided: bool +} + +impl<'tcx> ty::ctxt<'tcx> { + #[inline(never)] // is this perfy enough? + pub fn get_impl_method(&self, + impl_def_id: DefId, + substs: Substs<'tcx>, + name: Name) + -> ImplMethod<'tcx> + { + // there don't seem to be nicer accessors to these: + let impl_or_trait_items_map = self.impl_or_trait_items.borrow(); + + for impl_item in &self.impl_items.borrow()[&impl_def_id] { + if let ty::MethodTraitItem(ref meth) = + impl_or_trait_items_map[&impl_item.def_id()] { + if meth.name == name { + return ImplMethod { + method: meth.clone(), + substs: substs, + is_provided: false + } + } + } + } + + // It is not in the impl - get the default from the trait. + let trait_ref = self.impl_trait_ref(impl_def_id).unwrap(); + for trait_item in self.trait_items(trait_ref.def_id).iter() { + if let &ty::MethodTraitItem(ref meth) = trait_item { + if meth.name == name { + let impl_to_trait_substs = self + .make_substs_for_receiver_types(&trait_ref, meth); + return ImplMethod { + method: meth.clone(), + substs: impl_to_trait_substs.subst(self, &substs), + is_provided: true + } + } + } + } + + self.sess.bug(&format!("method {:?} not found in {:?}", + name, impl_def_id)) + } +} + impl<'tcx> ty::TyS<'tcx> { fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>, bound: ty::BuiltinBound, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index cf964107d16..2090527ca20 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -725,19 +725,6 @@ fn check_static_method(&mut self, span: Span, method_id: DefId, name: ast::Name) { - // If the method is a default method, we need to use the def_id of - // the default implementation. - let method_id = match self.tcx.impl_or_trait_item(method_id) { - ty::MethodTraitItem(method_type) => { - method_type.provided_source.unwrap_or(method_id) - } - _ => { - self.tcx.sess - .span_bug(span, - "got non-method item in check_static_method") - } - }; - self.report_error(self.ensure_public(span, method_id, None, diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 124f50d6603..cfa77d57bf6 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -26,7 +26,7 @@ use middle::def_id::{DefId, LOCAL_CRATE}; use middle::infer::normalize_associated_type; use middle::subst; -use middle::subst::{Subst, Substs}; +use middle::subst::{Substs}; use rustc::front::map as hir_map; use trans::adt; use trans::base; @@ -398,77 +398,14 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( assert!(!substs.types.has_escaping_regions()); let substs = substs.erase_regions(); - // Load the info for the appropriate trait if necessary. - match tcx.trait_of_item(def_id) { - None => {} - Some(trait_id) => { - tcx.populate_implementations_for_trait_if_necessary(trait_id) - } - } - - // We need to do a bunch of special handling for default methods. - // We need to modify the def_id and our substs in order to monomorphize - // the function. - let (is_default, def_id, substs) = match tcx.provided_source(def_id) { - None => { - (false, def_id, tcx.mk_substs(substs)) - } - Some(source_id) => { - // There are two relevant substitutions when compiling - // default methods. First, there is the substitution for - // the type parameters of the impl we are using and the - // method we are calling. This substitution is the substs - // argument we already have. - // In order to compile a default method, though, we need - // to consider another substitution: the substitution for - // the type parameters on trait; the impl we are using - // implements the trait at some particular type - // parameters, and we need to substitute for those first. - // So, what we need to do is find this substitution and - // compose it with the one we already have. - - let impl_id = tcx.impl_or_trait_item(def_id).container() - .id(); - let impl_or_trait_item = tcx.impl_or_trait_item(source_id); - match impl_or_trait_item { - ty::MethodTraitItem(method) => { - let trait_ref = tcx.impl_trait_ref(impl_id).unwrap(); - - // Compute the first substitution - let first_subst = - tcx.make_substs_for_receiver_types(&trait_ref, &*method) - .erase_regions(); - - // And compose them - let new_substs = tcx.mk_substs(first_subst.subst(tcx, &substs)); - - debug!("trans_fn_with_vtables - default method: \ - substs = {:?}, trait_subst = {:?}, \ - first_subst = {:?}, new_subst = {:?}", - substs, trait_ref.substs, - first_subst, new_substs); - - (true, source_id, new_substs) - } - _ => { - tcx.sess.bug("trans_fn_ref_with_vtables() tried \ - to translate a non-method?!") - } - } - } - }; - // Check whether this fn has an inlined copy and, if so, redirect // def_id to the local id of the inlined copy. let def_id = inline::maybe_instantiate_inline(ccx, def_id); - // We must monomorphise if the fn has type parameters, is a default method, - // or is a named tuple constructor. - let must_monomorphise = if !substs.types.is_empty() || is_default { - true - } else if def_id.is_local() { + fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool { + if !def_id.is_local() { return false; } let map_node = session::expect( - ccx.sess(), + &tcx.sess, tcx.map.find(def_id.node), || "local item should be in ast map".to_string()); @@ -480,9 +417,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( hir_map::NodeStructCtor(_) => true, _ => false } - } else { - false - }; + } + let must_monomorphise = + !substs.types.is_empty() || is_named_tuple_constructor(tcx, def_id); debug!("trans_fn_ref_with_substs({:?}) must_monomorphise: {}", def_id, must_monomorphise); @@ -497,6 +434,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( MethodCallKey(_) => None, }; + let substs = tcx.mk_substs(substs); let (val, fn_ty, must_cast) = monomorphize::monomorphic_fn(ccx, def_id, substs, opt_ref_id); if must_cast && node != ExprId(0) { @@ -561,10 +499,10 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( let llty = type_of::type_of_fn_from_ty(ccx, fn_type); let llptrty = llty.ptr_to(); if common::val_ty(val) != llptrty { - debug!("trans_fn_ref_with_vtables(): casting pointer!"); + debug!("trans_fn_ref_with_substs(): casting pointer!"); val = consts::ptrcast(val, llptrty); } else { - debug!("trans_fn_ref_with_vtables(): not casting pointer!"); + debug!("trans_fn_ref_with_substs(): not casting pointer!"); } Datum::new(val, fn_type, Rvalue::new(ByValue)) diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 6dcc60dc962..614453830c6 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -250,10 +250,10 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, impl_self, rcvr_method)); - let mth_id = method_with_name(ccx, impl_did, mname); - trans_fn_ref_with_substs(ccx, mth_id, ExprId(expr_id), + let mth = tcx.get_impl_method(impl_did, callee_substs, mname); + trans_fn_ref_with_substs(ccx, mth.method.def_id, ExprId(expr_id), param_substs, - callee_substs) + mth.substs) } traits::VtableObject(ref data) => { let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id); @@ -269,28 +269,6 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -fn method_with_name(ccx: &CrateContext, impl_id: DefId, name: ast::Name) - -> DefId { - match ccx.impl_method_cache().borrow().get(&(impl_id, name)).cloned() { - Some(m) => return m, - None => {} - } - - let impl_items = ccx.tcx().impl_items.borrow(); - let impl_items = - impl_items.get(&impl_id) - .expect("could not find impl while translating"); - let meth_did = impl_items.iter() - .find(|&did| { - ccx.tcx().impl_or_trait_item(did.def_id()).name() == name - }).expect("could not find method while \ - translating"); - - ccx.impl_method_cache().borrow_mut().insert((impl_id, name), - meth_did.def_id()); - meth_did.def_id() -} - fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, method_call: MethodCall, self_expr: Option<&hir::Expr>, @@ -312,20 +290,19 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, item") } }; - let mth_id = method_with_name(bcx.ccx(), impl_did, mname); - // create a concatenated set of substitutions which includes // those from the impl and those from the method: let callee_substs = combine_impl_and_methods_tps( bcx, MethodCallKey(method_call), vtable_impl.substs); + let mth = bcx.tcx().get_impl_method(impl_did, callee_substs, mname); // translate the function let datum = trans_fn_ref_with_substs(bcx.ccx(), - mth_id, + mth.method.def_id, MethodCallKey(method_call), bcx.fcx.param_substs, - callee_substs); + mth.substs); Callee { bcx: bcx, data: Fn(datum.val), ty: datum.ty } } @@ -738,22 +715,17 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // The substitutions we have are on the impl, so we grab // the method type from the impl to substitute into. - let impl_method_def_id = method_with_name(ccx, impl_id, name); - let impl_method_type = match tcx.impl_or_trait_item(impl_method_def_id) { - ty::MethodTraitItem(m) => m, - _ => ccx.sess().bug("should be a method, not other assoc item"), - }; + let mth = tcx.get_impl_method(impl_id, substs.clone(), name); - debug!("emit_vtable_methods: impl_method_type={:?}", - impl_method_type); + debug!("emit_vtable_methods: mth={:?}", mth); // If this is a default method, it's possible that it // relies on where clauses that do not hold for this // particular set of type parameters. Note that this // method could then never be called, so we do not want to // try and trans it, in that case. Issue #23435. - if tcx.provided_source(impl_method_def_id).is_some() { - let predicates = impl_method_type.predicates.predicates.subst(tcx, &substs); + if mth.is_provided { + let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs); if !normalize_and_test_predicates(ccx, predicates.into_vec()) { debug!("emit_vtable_methods: predicates do not hold"); return nullptr; @@ -761,10 +733,10 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } trans_fn_ref_with_substs(ccx, - impl_method_def_id, + mth.method.def_id, ExprId(0), param_substs, - substs.clone()).val + mth.substs).val }) .collect() } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6961f3444d9..821615d0341 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -182,7 +182,14 @@ fn report_candidates(fcx: &FnCtxt, CandidateSource::ImplSource(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else the call site. - let item = impl_item(fcx.tcx(), impl_did, item_name).unwrap(); + let item = impl_item(fcx.tcx(), impl_did, item_name) + .or_else(|| { + trait_item( + fcx.tcx(), + fcx.tcx().impl_trait_ref(impl_did).unwrap().def_id, + item_name + ) + }).unwrap(); let impl_span = fcx.tcx().map.def_id_span(impl_did, span); let item_span = fcx.tcx().map.def_id_span(item.def_id(), impl_span); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 324a4a4ca08..e62f5b82e7a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -989,7 +989,6 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Check for missing items from trait let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id); - let associated_consts = tcx.associated_consts(impl_trait_ref.def_id); let mut missing_items = Vec::new(); let mut invalidated_items = Vec::new(); let associated_type_overridden = overridden_associated_type.is_some(); @@ -1004,9 +1003,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, _ => false, } }); - let is_provided = - associated_consts.iter().any(|ac| ac.default.is_some() && - ac.name == associated_const.name); + let is_provided = associated_const.has_value; + if !is_implemented { if !is_provided { missing_items.push(associated_const.name); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 0c152a419d2..714bd1d2bc5 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -22,10 +22,10 @@ use middle::traits; use middle::ty; use middle::ty::RegionEscape; -use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId}; +use middle::ty::{ImplOrTraitItemId, ConstTraitItemId}; use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment}; use middle::ty::{Ty, TyBool, TyChar, TyEnum, TyError}; -use middle::ty::{TyParam, TypeScheme, TyRawPtr}; +use middle::ty::{TyParam, TyRawPtr}; use middle::ty::{TyRef, TyStruct, TyTrait, TyTuple}; use middle::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt}; use middle::ty::{TyUint, TyClosure, TyBox, TyBareFn}; @@ -168,65 +168,6 @@ fn check_implementation(&self, item: &Item) { tcx.impl_items.borrow_mut().insert(impl_did, impl_items); } - // Creates default method IDs and performs type substitutions for an impl - // and trait pair. Then, for each provided method in the trait, inserts a - // `ProvidedMethodInfo` instance into the `provided_method_sources` map. - fn instantiate_default_methods( - &self, - impl_id: DefId, - trait_ref: &ty::TraitRef<'tcx>, - all_impl_items: &mut Vec) { - let tcx = self.crate_context.tcx; - debug!("instantiate_default_methods(impl_id={:?}, trait_ref={:?})", - impl_id, trait_ref); - - let impl_type_scheme = tcx.lookup_item_type(impl_id); - - let prov = tcx.provided_trait_methods(trait_ref.def_id); - for trait_method in &prov { - // Synthesize an ID. - let new_id = tcx.sess.next_node_id(); - let new_did = DefId::local(new_id); - - debug!("new_did={:?} trait_method={:?}", new_did, trait_method); - - // Create substitutions for the various trait parameters. - let new_method_ty = - Rc::new(subst_receiver_types_in_method_ty( - tcx, - impl_id, - &impl_type_scheme, - trait_ref, - new_did, - &**trait_method, - Some(trait_method.def_id))); - - debug!("new_method_ty={:?}", new_method_ty); - all_impl_items.push(MethodTraitItemId(new_did)); - - // construct the polytype for the method based on the - // method_ty. it will have all the generics from the - // impl, plus its own. - let new_polytype = ty::TypeScheme { - generics: new_method_ty.generics.clone(), - ty: tcx.mk_fn(Some(new_did), - tcx.mk_bare_fn(new_method_ty.fty.clone())) - }; - debug!("new_polytype={:?}", new_polytype); - - tcx.register_item_type(new_did, new_polytype); - tcx.predicates.borrow_mut().insert(new_did, new_method_ty.predicates.clone()); - tcx.impl_or_trait_items - .borrow_mut() - .insert(new_did, ty::MethodTraitItem(new_method_ty)); - - // Pair the new synthesized ID up with the - // ID of the method. - self.crate_context.tcx.provided_method_sources.borrow_mut() - .insert(new_did, trait_method.def_id); - } - } - fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) { match self.inherent_impls.borrow().get(&base_def_id) { Some(implementation_list) => { @@ -252,8 +193,7 @@ fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { ItemImpl(_, _, _, _, _, ref impl_items) => { - let mut items: Vec = - impl_items.iter().map(|impl_item| { + impl_items.iter().map(|impl_item| { match impl_item.node { hir::ConstImplItem(..) => { ConstTraitItemId(DefId::local(impl_item.id)) @@ -265,14 +205,7 @@ fn create_impl_from_item(&self, item: &Item) -> Vec { TypeTraitItemId(DefId::local(impl_item.id)) } } - }).collect(); - - let def_id = DefId::local(item.id); - if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(def_id) { - self.instantiate_default_methods(def_id, &trait_ref, &mut items); - } - - items + }).collect() } _ => { self.crate_context.tcx.sess.span_bug(item.span, @@ -575,55 +508,6 @@ fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id: "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); } -fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, - impl_id: DefId, - impl_type_scheme: &ty::TypeScheme<'tcx>, - trait_ref: &ty::TraitRef<'tcx>, - new_def_id: DefId, - method: &ty::Method<'tcx>, - provided_source: Option) - -> ty::Method<'tcx> -{ - let combined_substs = tcx.make_substs_for_receiver_types(trait_ref, method); - - debug!("subst_receiver_types_in_method_ty: combined_substs={:?}", - combined_substs); - - let method_predicates = method.predicates.subst(tcx, &combined_substs); - let mut method_generics = method.generics.subst(tcx, &combined_substs); - - // replace the type parameters declared on the trait with those - // from the impl - for &space in &[subst::TypeSpace, subst::SelfSpace] { - method_generics.types.replace( - space, - impl_type_scheme.generics.types.get_slice(space).to_vec()); - method_generics.regions.replace( - space, - impl_type_scheme.generics.regions.get_slice(space).to_vec()); - } - - debug!("subst_receiver_types_in_method_ty: method_generics={:?}", - method_generics); - - let method_fty = method.fty.subst(tcx, &combined_substs); - - debug!("subst_receiver_types_in_method_ty: method_ty={:?}", - method.fty); - - ty::Method::new( - method.name, - method_generics, - method_predicates, - method_fty, - method.explicit_self, - method.vis, - new_def_id, - ImplContainer(impl_id), - provided_source - ) -} - pub fn check_coherence(crate_context: &CrateCtxt) { CoherenceChecker { crate_context: crate_context, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9e1b20258f0..a59e6f54c81 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -599,8 +599,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, explicit_self_category, vis, def_id, - container, - None); + container); let fty = ccx.tcx.mk_fn(Some(def_id), ccx.tcx.mk_bare_fn(ty_method.fty.clone())); @@ -647,13 +646,12 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, id: ast::NodeId, vis: hir::Visibility, ty: ty::Ty<'tcx>, - default: Option<&hir::Expr>) + has_value: bool) { ccx.tcx.predicates.borrow_mut().insert(DefId::local(id), ty::GenericPredicates::empty()); write_ty_to_tcx(ccx.tcx, id, ty); - let default_id = default.map(|expr| DefId::local(expr.id)); let associated_const = Rc::new(ty::AssociatedConst { name: name, @@ -661,7 +659,7 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def_id: DefId::local(id), container: container, ty: ty, - default: default_id, + has_value: has_value }); ccx.tcx.impl_or_trait_items.borrow_mut() .insert(DefId::local(id), ty::ConstTraitItem(associated_const)); @@ -837,7 +835,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { span_err!(tcx.sess, impl_item.span, E0201, "duplicate {}", desc); } - if let hir::ConstImplItem(ref ty, ref expr) = impl_item.node { + if let hir::ConstImplItem(ref ty, _) = impl_item.node { let ty = ccx.icx(&ty_predicates) .to_ty(&ExplicitRscope, &*ty); tcx.register_item_type(DefId::local(impl_item.id), @@ -848,7 +846,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { convert_associated_const(ccx, ImplContainer(DefId::local(it.id)), impl_item.name, impl_item.id, impl_item.vis.inherit_from(parent_visibility), - ty, Some(&*expr)); + ty, true /* has_value */); } } @@ -926,7 +924,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { }); convert_associated_const(ccx, TraitContainer(DefId::local(it.id)), trait_item.name, trait_item.id, - hir::Public, ty, default.as_ref().map(|d| &**d)); + hir::Public, ty, default.is_some()); } _ => {} } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 21895301a6c..ee772411c4e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -317,10 +317,11 @@ pub fn build_impl(cx: &DocContext, ty::ConstTraitItem(ref assoc_const) => { let did = assoc_const.def_id; let type_scheme = tcx.lookup_item_type(did); - let default = match assoc_const.default { - Some(_) => Some(const_eval::lookup_const_by_id(tcx, did, None) - .unwrap().span.to_src(cx)), - None => None, + let default = if assoc_const.has_value { + Some(const_eval::lookup_const_by_id(tcx, did, None) + .unwrap().span.to_src(cx)) + } else { + None }; Some(clean::Item { name: Some(assoc_const.name.clean(cx)), @@ -339,9 +340,6 @@ pub fn build_impl(cx: &DocContext, if method.vis != hir::Public && associated_trait.is_none() { return None } - if method.provided_source.is_some() { - return None - } let mut item = method.clean(cx); item.inner = match item.inner.clone() { clean::TyMethodItem(clean::TyMethod { -- 2.44.0