Auto merge of #28778 - arielb1:no-source, r=eddyb
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. I have measured a small, but possibly insignificant, bootstrap performance improvement, and the memory savings grow to about 30M for larger crates (but that is still less as a percentage). r? @eddyb
This commit is contained in:
commit
78edd4f3a0
|
@ -180,7 +180,7 @@ pub const tag_mod_child: usize = 0x7b;
|
|||
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
|
||||
|
|
|
@ -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<DefId> {
|
||||
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<IdentInterner>,
|
|||
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<IdentInterner>,
|
|||
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<IdentInterner>,
|
|||
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<IdentInterner>,
|
|||
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()
|
||||
|
|
|
@ -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<DefId>) {
|
||||
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 encode_info_for_item(ecx: &EncodeContext,
|
|||
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 encode_info_for_item(ecx: &EncodeContext,
|
|||
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));
|
||||
}
|
||||
|
|
|
@ -235,8 +235,6 @@ pub struct ctxt<'tcx> {
|
|||
pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
|
||||
pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, 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<DefIdMap<DefId>>,
|
||||
|
||||
/// Maps from def-id of a type or region parameter to its
|
||||
/// (inferred) variance.
|
||||
|
@ -471,7 +469,6 @@ impl<'tcx> ctxt<'tcx> {
|
|||
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()),
|
||||
|
|
|
@ -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<DefId>
|
||||
}
|
||||
|
||||
impl<'tcx> Method<'tcx> {
|
||||
|
@ -248,8 +245,7 @@ impl<'tcx> Method<'tcx> {
|
|||
explicit_self: ExplicitSelfCategory,
|
||||
vis: hir::Visibility,
|
||||
def_id: DefId,
|
||||
container: ImplOrTraitItemContainer,
|
||||
provided_source: Option<DefId>)
|
||||
container: ImplOrTraitItemContainer)
|
||||
-> Method<'tcx> {
|
||||
Method {
|
||||
name: name,
|
||||
|
@ -260,7 +256,6 @@ impl<'tcx> Method<'tcx> {
|
|||
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<DefId>,
|
||||
pub has_value: bool
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -2105,10 +2100,6 @@ impl<'tcx> ctxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn provided_source(&self, id: DefId) -> Option<DefId> {
|
||||
self.provided_method_sources.borrow().get(&id).cloned()
|
||||
}
|
||||
|
||||
pub fn provided_trait_methods(&self, id: DefId) -> Vec<Rc<Method<'tcx>>> {
|
||||
if id.is_local() {
|
||||
if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id.node).node {
|
||||
|
@ -2477,16 +2468,9 @@ impl<'tcx> ctxt<'tcx> {
|
|||
// 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.
|
||||
|
|
|
@ -14,7 +14,7 @@ use back::svh::Svh;
|
|||
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 util::num::ToPrimitive;
|
|||
|
||||
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 @@ impl<'tcx> ty::ctxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImplMethod<'tcx> {
|
||||
pub method: Rc<ty::Method<'tcx>>,
|
||||
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,
|
||||
|
|
|
@ -725,19 +725,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
|||
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,
|
||||
|
|
|
@ -26,7 +26,7 @@ use middle::def;
|
|||
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))
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -182,7 +182,14 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -22,10 +22,10 @@ use middle::subst::{self, Subst};
|
|||
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 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
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<ImplOrTraitItemId>) {
|
||||
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 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
|
||||
match item.node {
|
||||
ItemImpl(_, _, _, _, _, ref impl_items) => {
|
||||
let mut items: Vec<ImplOrTraitItemId> =
|
||||
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 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
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<DefId>)
|
||||
-> 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,
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue