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
14 changed files with 139 additions and 334 deletions
|
@ -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: usize = 0x108; // top-level only
|
||||||
pub const tag_misc_info_crate_items: usize = 0x7c;
|
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_item_impl_vtables: usize = 0x7e;
|
||||||
|
|
||||||
pub const tag_impls: usize = 0x109; // top-level only
|
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))
|
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> {
|
fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> {
|
||||||
reader::tagged_docs(d, tag_items_data_item_reexport)
|
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 {
|
match fam {
|
||||||
Constant => {
|
Constant => {
|
||||||
// Check whether we have an associated const item.
|
// Check whether we have an associated const item.
|
||||||
if item_sort(item) == Some('C') {
|
match item_sort(item) {
|
||||||
DlDef(def::DefAssociatedConst(did))
|
Some('C') | Some('c') => {
|
||||||
} else {
|
DlDef(def::DefAssociatedConst(did))
|
||||||
// Regular const item.
|
}
|
||||||
DlDef(def::DefConst(did))
|
_ => {
|
||||||
|
// Regular const item.
|
||||||
|
DlDef(def::DefConst(did))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImmStatic => DlDef(def::DefStatic(did, false)),
|
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| {
|
reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| {
|
||||||
let def_id = item_def_id(doc, cdata);
|
let def_id = item_def_id(doc, cdata);
|
||||||
match item_sort(doc) {
|
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('r') | Some('p') => ty::MethodTraitItemId(def_id),
|
||||||
Some('t') => ty::TypeTraitItemId(def_id),
|
Some('t') => ty::TypeTraitItemId(def_id),
|
||||||
_ => panic!("unknown impl item sort"),
|
_ => 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);
|
let vis = item_visibility(item_doc);
|
||||||
|
|
||||||
match item_sort(item_doc) {
|
match item_sort(item_doc) {
|
||||||
Some('C') => {
|
sort @ Some('C') | sort @ Some('c') => {
|
||||||
let ty = doc_type(item_doc, tcx, cdata);
|
let ty = doc_type(item_doc, tcx, cdata);
|
||||||
let default = get_provided_source(item_doc, cdata);
|
|
||||||
ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
|
ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
|
||||||
name: name,
|
name: name,
|
||||||
ty: ty,
|
ty: ty,
|
||||||
vis: vis,
|
vis: vis,
|
||||||
def_id: def_id,
|
def_id: def_id,
|
||||||
container: container,
|
container: container,
|
||||||
default: default,
|
has_value: sort == Some('C')
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Some('r') | Some('p') => {
|
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 predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics);
|
||||||
let fty = doc_method_fty(item_doc, tcx, cdata);
|
let fty = doc_method_fty(item_doc, tcx, cdata);
|
||||||
let explicit_self = get_explicit_self(item_doc);
|
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,
|
ty::MethodTraitItem(Rc::new(ty::Method::new(name,
|
||||||
generics,
|
generics,
|
||||||
|
@ -890,8 +885,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
|
||||||
explicit_self,
|
explicit_self,
|
||||||
vis,
|
vis,
|
||||||
def_id,
|
def_id,
|
||||||
container,
|
container)))
|
||||||
provided_source)))
|
|
||||||
}
|
}
|
||||||
Some('t') => {
|
Some('t') => {
|
||||||
let ty = maybe_doc_type(item_doc, tcx, cdata);
|
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| {
|
reader::tagged_docs(item, tag_item_trait_item).map(|mth| {
|
||||||
let def_id = item_def_id(mth, cdata);
|
let def_id = item_def_id(mth, cdata);
|
||||||
match item_sort(mth) {
|
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('r') | Some('p') => ty::MethodTraitItemId(def_id),
|
||||||
Some('t') => ty::TypeTraitItemId(def_id),
|
Some('t') => ty::TypeTraitItemId(def_id),
|
||||||
_ => panic!("unknown trait item sort"),
|
_ => 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 did = item_def_id(ac_id, cdata);
|
||||||
let ac_doc = cdata.lookup_item(did.node);
|
let ac_doc = cdata.lookup_item(did.node);
|
||||||
|
|
||||||
if item_sort(ac_doc) == Some('C') {
|
match item_sort(ac_doc) {
|
||||||
let trait_item = get_impl_or_trait_item(intr.clone(),
|
Some('C') | Some('c') => {
|
||||||
cdata,
|
let trait_item = get_impl_or_trait_item(intr.clone(),
|
||||||
did.node,
|
cdata,
|
||||||
tcx);
|
did.node,
|
||||||
if let ty::ConstTraitItem(ref ac) = trait_item {
|
tcx);
|
||||||
Some((*ac).clone())
|
if let ty::ConstTraitItem(ref ac) = trait_item {
|
||||||
} else {
|
Some((*ac).clone())
|
||||||
None
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
_ => None
|
||||||
None
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}).collect()
|
}).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);
|
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>,
|
fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
rbml_w: &mut Encoder,
|
rbml_w: &mut Encoder,
|
||||||
field: ty::FieldDef<'tcx>,
|
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_family(rbml_w, METHOD_FAMILY)
|
||||||
}
|
}
|
||||||
encode_provided_source(rbml_w, method_ty.provided_source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_info_for_associated_const(ecx: &EncodeContext,
|
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_name(rbml_w, associated_const.name);
|
||||||
encode_visibility(rbml_w, associated_const.vis);
|
encode_visibility(rbml_w, associated_const.vis);
|
||||||
encode_family(rbml_w, 'C');
|
encode_family(rbml_w, 'C');
|
||||||
encode_provided_source(rbml_w, associated_const.default);
|
|
||||||
|
|
||||||
encode_parent_item(rbml_w, DefId::local(parent_id));
|
encode_parent_item(rbml_w, DefId::local(parent_id));
|
||||||
encode_item_sort(rbml_w, 'C');
|
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_def_id(rbml_w, associated_const.def_id);
|
||||||
encode_visibility(rbml_w, associated_const.vis);
|
encode_visibility(rbml_w, associated_const.vis);
|
||||||
|
|
||||||
encode_provided_source(rbml_w, associated_const.default);
|
|
||||||
|
|
||||||
let elem = ast_map::PathName(associated_const.name);
|
let elem = ast_map::PathName(associated_const.name);
|
||||||
encode_path(rbml_w,
|
encode_path(rbml_w,
|
||||||
path.clone().chain(Some(elem)));
|
path.clone().chain(Some(elem)));
|
||||||
|
|
||||||
encode_item_sort(rbml_w, 'C');
|
|
||||||
encode_family(rbml_w, 'C');
|
encode_family(rbml_w, 'C');
|
||||||
|
|
||||||
encode_bounds_and_type_for_item(rbml_w, ecx,
|
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];
|
let trait_item = &*ms[i];
|
||||||
encode_attributes(rbml_w, &trait_item.attrs);
|
encode_attributes(rbml_w, &trait_item.attrs);
|
||||||
match trait_item.node {
|
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,
|
encode_inlined_item(ecx, rbml_w,
|
||||||
InlinedItemRef::TraitItem(def_id, trait_item));
|
InlinedItemRef::TraitItem(def_id, trait_item));
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,8 +235,6 @@ pub struct ctxt<'tcx> {
|
||||||
pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
|
pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
|
||||||
pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
|
pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
|
||||||
pub lang_items: middle::lang_items::LanguageItems,
|
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
|
/// Maps from def-id of a type or region parameter to its
|
||||||
/// (inferred) variance.
|
/// (inferred) variance.
|
||||||
|
@ -471,7 +469,6 @@ impl<'tcx> ctxt<'tcx> {
|
||||||
ty_param_defs: RefCell::new(NodeMap()),
|
ty_param_defs: RefCell::new(NodeMap()),
|
||||||
normalized_cache: RefCell::new(FnvHashMap()),
|
normalized_cache: RefCell::new(FnvHashMap()),
|
||||||
lang_items: lang_items,
|
lang_items: lang_items,
|
||||||
provided_method_sources: RefCell::new(DefIdMap()),
|
|
||||||
inherent_impls: RefCell::new(DefIdMap()),
|
inherent_impls: RefCell::new(DefIdMap()),
|
||||||
impl_items: RefCell::new(DefIdMap()),
|
impl_items: RefCell::new(DefIdMap()),
|
||||||
used_unsafe: RefCell::new(NodeSet()),
|
used_unsafe: RefCell::new(NodeSet()),
|
||||||
|
|
|
@ -235,9 +235,6 @@ pub struct Method<'tcx> {
|
||||||
pub vis: hir::Visibility,
|
pub vis: hir::Visibility,
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
pub container: ImplOrTraitItemContainer,
|
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> {
|
impl<'tcx> Method<'tcx> {
|
||||||
|
@ -248,8 +245,7 @@ impl<'tcx> Method<'tcx> {
|
||||||
explicit_self: ExplicitSelfCategory,
|
explicit_self: ExplicitSelfCategory,
|
||||||
vis: hir::Visibility,
|
vis: hir::Visibility,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
container: ImplOrTraitItemContainer,
|
container: ImplOrTraitItemContainer)
|
||||||
provided_source: Option<DefId>)
|
|
||||||
-> Method<'tcx> {
|
-> Method<'tcx> {
|
||||||
Method {
|
Method {
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -260,7 +256,6 @@ impl<'tcx> Method<'tcx> {
|
||||||
vis: vis,
|
vis: vis,
|
||||||
def_id: def_id,
|
def_id: def_id,
|
||||||
container: container,
|
container: container,
|
||||||
provided_source: provided_source
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +288,7 @@ pub struct AssociatedConst<'tcx> {
|
||||||
pub vis: hir::Visibility,
|
pub vis: hir::Visibility,
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
pub container: ImplOrTraitItemContainer,
|
pub container: ImplOrTraitItemContainer,
|
||||||
pub default: Option<DefId>,
|
pub has_value: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[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>>> {
|
pub fn provided_trait_methods(&self, id: DefId) -> Vec<Rc<Method<'tcx>>> {
|
||||||
if id.is_local() {
|
if id.is_local() {
|
||||||
if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id.node).node {
|
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.
|
// the map. This is a bit unfortunate.
|
||||||
for impl_item_def_id in &impl_items {
|
for impl_item_def_id in &impl_items {
|
||||||
let method_def_id = impl_item_def_id.def_id();
|
let method_def_id = impl_item_def_id.def_id();
|
||||||
match self.impl_or_trait_item(method_def_id) {
|
// load impl items eagerly for convenience
|
||||||
MethodTraitItem(method) => {
|
// FIXME: we may want to load these lazily
|
||||||
if let Some(source) = method.provided_source {
|
self.impl_or_trait_item(method_def_id);
|
||||||
self.provided_method_sources
|
|
||||||
.borrow_mut()
|
|
||||||
.insert(method_def_id, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the implementation info.
|
// Store the implementation info.
|
||||||
|
|
|
@ -14,7 +14,7 @@ use back::svh::Svh;
|
||||||
use middle::const_eval::{self, ConstVal, ErrKind};
|
use middle::const_eval::{self, ConstVal, ErrKind};
|
||||||
use middle::const_eval::EvalHint::UncheckedExprHint;
|
use middle::const_eval::EvalHint::UncheckedExprHint;
|
||||||
use middle::def_id::DefId;
|
use middle::def_id::DefId;
|
||||||
use middle::subst;
|
use middle::subst::{self, Subst, Substs};
|
||||||
use middle::infer;
|
use middle::infer;
|
||||||
use middle::pat_util;
|
use middle::pat_util;
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
|
@ -26,6 +26,7 @@ use util::num::ToPrimitive;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::hash::{Hash, SipHasher, Hasher};
|
use std::hash::{Hash, SipHasher, Hasher};
|
||||||
|
use std::rc::Rc;
|
||||||
use syntax::ast::{self, Name};
|
use syntax::ast::{self, Name};
|
||||||
use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
|
use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
|
||||||
use syntax::codemap::Span;
|
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> {
|
impl<'tcx> ty::TyS<'tcx> {
|
||||||
fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
|
fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
|
||||||
bound: ty::BuiltinBound,
|
bound: ty::BuiltinBound,
|
||||||
|
|
|
@ -725,19 +725,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
method_id: DefId,
|
method_id: DefId,
|
||||||
name: ast::Name) {
|
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,
|
self.report_error(self.ensure_public(span,
|
||||||
method_id,
|
method_id,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -26,7 +26,7 @@ use middle::def;
|
||||||
use middle::def_id::{DefId, LOCAL_CRATE};
|
use middle::def_id::{DefId, LOCAL_CRATE};
|
||||||
use middle::infer::normalize_associated_type;
|
use middle::infer::normalize_associated_type;
|
||||||
use middle::subst;
|
use middle::subst;
|
||||||
use middle::subst::{Subst, Substs};
|
use middle::subst::{Substs};
|
||||||
use rustc::front::map as hir_map;
|
use rustc::front::map as hir_map;
|
||||||
use trans::adt;
|
use trans::adt;
|
||||||
use trans::base;
|
use trans::base;
|
||||||
|
@ -398,77 +398,14 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
|
||||||
assert!(!substs.types.has_escaping_regions());
|
assert!(!substs.types.has_escaping_regions());
|
||||||
let substs = substs.erase_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
|
// Check whether this fn has an inlined copy and, if so, redirect
|
||||||
// def_id to the local id of the inlined copy.
|
// def_id to the local id of the inlined copy.
|
||||||
let def_id = inline::maybe_instantiate_inline(ccx, def_id);
|
let def_id = inline::maybe_instantiate_inline(ccx, def_id);
|
||||||
|
|
||||||
// We must monomorphise if the fn has type parameters, is a default method,
|
fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool {
|
||||||
// or is a named tuple constructor.
|
if !def_id.is_local() { return false; }
|
||||||
let must_monomorphise = if !substs.types.is_empty() || is_default {
|
|
||||||
true
|
|
||||||
} else if def_id.is_local() {
|
|
||||||
let map_node = session::expect(
|
let map_node = session::expect(
|
||||||
ccx.sess(),
|
&tcx.sess,
|
||||||
tcx.map.find(def_id.node),
|
tcx.map.find(def_id.node),
|
||||||
|| "local item should be in ast map".to_string());
|
|| "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,
|
hir_map::NodeStructCtor(_) => true,
|
||||||
_ => false
|
_ => 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: {}",
|
debug!("trans_fn_ref_with_substs({:?}) must_monomorphise: {}",
|
||||||
def_id, must_monomorphise);
|
def_id, must_monomorphise);
|
||||||
|
@ -497,6 +434,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
|
||||||
MethodCallKey(_) => None,
|
MethodCallKey(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let substs = tcx.mk_substs(substs);
|
||||||
let (val, fn_ty, must_cast) =
|
let (val, fn_ty, must_cast) =
|
||||||
monomorphize::monomorphic_fn(ccx, def_id, substs, opt_ref_id);
|
monomorphize::monomorphic_fn(ccx, def_id, substs, opt_ref_id);
|
||||||
if must_cast && node != ExprId(0) {
|
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 llty = type_of::type_of_fn_from_ty(ccx, fn_type);
|
||||||
let llptrty = llty.ptr_to();
|
let llptrty = llty.ptr_to();
|
||||||
if common::val_ty(val) != llptrty {
|
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);
|
val = consts::ptrcast(val, llptrty);
|
||||||
} else {
|
} 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))
|
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,
|
impl_self,
|
||||||
rcvr_method));
|
rcvr_method));
|
||||||
|
|
||||||
let mth_id = method_with_name(ccx, impl_did, mname);
|
let mth = tcx.get_impl_method(impl_did, callee_substs, mname);
|
||||||
trans_fn_ref_with_substs(ccx, mth_id, ExprId(expr_id),
|
trans_fn_ref_with_substs(ccx, mth.method.def_id, ExprId(expr_id),
|
||||||
param_substs,
|
param_substs,
|
||||||
callee_substs)
|
mth.substs)
|
||||||
}
|
}
|
||||||
traits::VtableObject(ref data) => {
|
traits::VtableObject(ref data) => {
|
||||||
let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id);
|
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>,
|
fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
method_call: MethodCall,
|
method_call: MethodCall,
|
||||||
self_expr: Option<&hir::Expr>,
|
self_expr: Option<&hir::Expr>,
|
||||||
|
@ -312,20 +290,19 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
item")
|
item")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
|
|
||||||
|
|
||||||
// create a concatenated set of substitutions which includes
|
// create a concatenated set of substitutions which includes
|
||||||
// those from the impl and those from the method:
|
// those from the impl and those from the method:
|
||||||
let callee_substs =
|
let callee_substs =
|
||||||
combine_impl_and_methods_tps(
|
combine_impl_and_methods_tps(
|
||||||
bcx, MethodCallKey(method_call), vtable_impl.substs);
|
bcx, MethodCallKey(method_call), vtable_impl.substs);
|
||||||
|
|
||||||
|
let mth = bcx.tcx().get_impl_method(impl_did, callee_substs, mname);
|
||||||
// translate the function
|
// translate the function
|
||||||
let datum = trans_fn_ref_with_substs(bcx.ccx(),
|
let datum = trans_fn_ref_with_substs(bcx.ccx(),
|
||||||
mth_id,
|
mth.method.def_id,
|
||||||
MethodCallKey(method_call),
|
MethodCallKey(method_call),
|
||||||
bcx.fcx.param_substs,
|
bcx.fcx.param_substs,
|
||||||
callee_substs);
|
mth.substs);
|
||||||
|
|
||||||
Callee { bcx: bcx, data: Fn(datum.val), ty: datum.ty }
|
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 substitutions we have are on the impl, so we grab
|
||||||
// the method type from the impl to substitute into.
|
// the method type from the impl to substitute into.
|
||||||
let impl_method_def_id = method_with_name(ccx, impl_id, name);
|
let mth = tcx.get_impl_method(impl_id, substs.clone(), 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"),
|
|
||||||
};
|
|
||||||
|
|
||||||
debug!("emit_vtable_methods: impl_method_type={:?}",
|
debug!("emit_vtable_methods: mth={:?}", mth);
|
||||||
impl_method_type);
|
|
||||||
|
|
||||||
// If this is a default method, it's possible that it
|
// If this is a default method, it's possible that it
|
||||||
// relies on where clauses that do not hold for this
|
// relies on where clauses that do not hold for this
|
||||||
// particular set of type parameters. Note that this
|
// particular set of type parameters. Note that this
|
||||||
// method could then never be called, so we do not want to
|
// method could then never be called, so we do not want to
|
||||||
// try and trans it, in that case. Issue #23435.
|
// try and trans it, in that case. Issue #23435.
|
||||||
if tcx.provided_source(impl_method_def_id).is_some() {
|
if mth.is_provided {
|
||||||
let predicates = impl_method_type.predicates.predicates.subst(tcx, &substs);
|
let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs);
|
||||||
if !normalize_and_test_predicates(ccx, predicates.into_vec()) {
|
if !normalize_and_test_predicates(ccx, predicates.into_vec()) {
|
||||||
debug!("emit_vtable_methods: predicates do not hold");
|
debug!("emit_vtable_methods: predicates do not hold");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -761,10 +733,10 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
trans_fn_ref_with_substs(ccx,
|
trans_fn_ref_with_substs(ccx,
|
||||||
impl_method_def_id,
|
mth.method.def_id,
|
||||||
ExprId(0),
|
ExprId(0),
|
||||||
param_substs,
|
param_substs,
|
||||||
substs.clone()).val
|
mth.substs).val
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,14 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
CandidateSource::ImplSource(impl_did) => {
|
CandidateSource::ImplSource(impl_did) => {
|
||||||
// Provide the best span we can. Use the item, if local to crate, else
|
// 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.
|
// 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 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);
|
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
|
// Check for missing items from trait
|
||||||
let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
|
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 missing_items = Vec::new();
|
||||||
let mut invalidated_items = Vec::new();
|
let mut invalidated_items = Vec::new();
|
||||||
let associated_type_overridden = overridden_associated_type.is_some();
|
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,
|
_ => false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let is_provided =
|
let is_provided = associated_const.has_value;
|
||||||
associated_consts.iter().any(|ac| ac.default.is_some() &&
|
|
||||||
ac.name == associated_const.name);
|
|
||||||
if !is_implemented {
|
if !is_implemented {
|
||||||
if !is_provided {
|
if !is_provided {
|
||||||
missing_items.push(associated_const.name);
|
missing_items.push(associated_const.name);
|
||||||
|
|
|
@ -22,10 +22,10 @@ use middle::subst::{self, Subst};
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::ty::RegionEscape;
|
use middle::ty::RegionEscape;
|
||||||
use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
|
use middle::ty::{ImplOrTraitItemId, ConstTraitItemId};
|
||||||
use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
|
use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
|
||||||
use middle::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
|
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::{TyRef, TyStruct, TyTrait, TyTuple};
|
||||||
use middle::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
|
use middle::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
|
||||||
use middle::ty::{TyUint, TyClosure, TyBox, TyBareFn};
|
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);
|
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) {
|
fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
|
||||||
match self.inherent_impls.borrow().get(&base_def_id) {
|
match self.inherent_impls.borrow().get(&base_def_id) {
|
||||||
Some(implementation_list) => {
|
Some(implementation_list) => {
|
||||||
|
@ -252,8 +193,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||||
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
|
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemImpl(_, _, _, _, _, ref impl_items) => {
|
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 {
|
match impl_item.node {
|
||||||
hir::ConstImplItem(..) => {
|
hir::ConstImplItem(..) => {
|
||||||
ConstTraitItemId(DefId::local(impl_item.id))
|
ConstTraitItemId(DefId::local(impl_item.id))
|
||||||
|
@ -265,14 +205,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||||
TypeTraitItemId(DefId::local(impl_item.id))
|
TypeTraitItemId(DefId::local(impl_item.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).collect();
|
}).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
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.crate_context.tcx.sess.span_bug(item.span,
|
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");
|
"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) {
|
pub fn check_coherence(crate_context: &CrateCtxt) {
|
||||||
CoherenceChecker {
|
CoherenceChecker {
|
||||||
crate_context: crate_context,
|
crate_context: crate_context,
|
||||||
|
|
|
@ -599,8 +599,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
explicit_self_category,
|
explicit_self_category,
|
||||||
vis,
|
vis,
|
||||||
def_id,
|
def_id,
|
||||||
container,
|
container);
|
||||||
None);
|
|
||||||
|
|
||||||
let fty = ccx.tcx.mk_fn(Some(def_id),
|
let fty = ccx.tcx.mk_fn(Some(def_id),
|
||||||
ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
|
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,
|
id: ast::NodeId,
|
||||||
vis: hir::Visibility,
|
vis: hir::Visibility,
|
||||||
ty: ty::Ty<'tcx>,
|
ty: ty::Ty<'tcx>,
|
||||||
default: Option<&hir::Expr>)
|
has_value: bool)
|
||||||
{
|
{
|
||||||
ccx.tcx.predicates.borrow_mut().insert(DefId::local(id),
|
ccx.tcx.predicates.borrow_mut().insert(DefId::local(id),
|
||||||
ty::GenericPredicates::empty());
|
ty::GenericPredicates::empty());
|
||||||
|
|
||||||
write_ty_to_tcx(ccx.tcx, id, ty);
|
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 {
|
let associated_const = Rc::new(ty::AssociatedConst {
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -661,7 +659,7 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
def_id: DefId::local(id),
|
def_id: DefId::local(id),
|
||||||
container: container,
|
container: container,
|
||||||
ty: ty,
|
ty: ty,
|
||||||
default: default_id,
|
has_value: has_value
|
||||||
});
|
});
|
||||||
ccx.tcx.impl_or_trait_items.borrow_mut()
|
ccx.tcx.impl_or_trait_items.borrow_mut()
|
||||||
.insert(DefId::local(id), ty::ConstTraitItem(associated_const));
|
.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);
|
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)
|
let ty = ccx.icx(&ty_predicates)
|
||||||
.to_ty(&ExplicitRscope, &*ty);
|
.to_ty(&ExplicitRscope, &*ty);
|
||||||
tcx.register_item_type(DefId::local(impl_item.id),
|
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)),
|
convert_associated_const(ccx, ImplContainer(DefId::local(it.id)),
|
||||||
impl_item.name, impl_item.id,
|
impl_item.name, impl_item.id,
|
||||||
impl_item.vis.inherit_from(parent_visibility),
|
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)),
|
convert_associated_const(ccx, TraitContainer(DefId::local(it.id)),
|
||||||
trait_item.name, trait_item.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) => {
|
ty::ConstTraitItem(ref assoc_const) => {
|
||||||
let did = assoc_const.def_id;
|
let did = assoc_const.def_id;
|
||||||
let type_scheme = tcx.lookup_item_type(did);
|
let type_scheme = tcx.lookup_item_type(did);
|
||||||
let default = match assoc_const.default {
|
let default = if assoc_const.has_value {
|
||||||
Some(_) => Some(const_eval::lookup_const_by_id(tcx, did, None)
|
Some(const_eval::lookup_const_by_id(tcx, did, None)
|
||||||
.unwrap().span.to_src(cx)),
|
.unwrap().span.to_src(cx))
|
||||||
None => None,
|
} else {
|
||||||
|
None
|
||||||
};
|
};
|
||||||
Some(clean::Item {
|
Some(clean::Item {
|
||||||
name: Some(assoc_const.name.clean(cx)),
|
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() {
|
if method.vis != hir::Public && associated_trait.is_none() {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
if method.provided_source.is_some() {
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
let mut item = method.clean(cx);
|
let mut item = method.clean(cx);
|
||||||
item.inner = match item.inner.clone() {
|
item.inner = match item.inner.clone() {
|
||||||
clean::TyMethodItem(clean::TyMethod {
|
clean::TyMethodItem(clean::TyMethod {
|
||||||
|
|
Loading…
Add table
Reference in a new issue