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:
bors 2015-10-01 09:30:54 +00:00
commit 78edd4f3a0
14 changed files with 139 additions and 334 deletions

View File

@ -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

View File

@ -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()

View File

@ -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 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));
}

View File

@ -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 @@ pub fn create_and_enter<F, R>(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()),

View File

@ -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 @@ pub fn new(name: Name,
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 @@ 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<DefId>,
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<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 @@ 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.

View File

@ -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<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,

View File

@ -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,

View File

@ -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))

View File

@ -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()
}

View File

@ -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);

View File

@ -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);

View File

@ -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<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 @@ fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId)
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 @@ fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
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,

View File

@ -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());
}
_ => {}
}

View File

@ -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 {