Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
@@ -103,11 +103,11 @@ pub enum DepNode<D: Clone + Debug> {
// nodes. Often we map multiple tables to the same node if there
// is no point in distinguishing them (e.g., both the type and
// predicates for an item wind up in `ItemSignature`).
ImplOrTraitItems(D),
AssociatedItems(D),
ItemSignature(D),
FieldTy(D),
SizedConstraint(D),
ImplOrTraitItemDefIds(D),
AssociatedItemDefIds(D),
InherentImpls(D),

// The set of impls for a given trait. Ultimately, it would be
@@ -153,10 +153,10 @@ impl<D: Clone + Debug> DepNode<D> {
TransCrateItem,
TypeckItemType,
TypeckItemBody,
ImplOrTraitItems,
AssociatedItems,
ItemSignature,
FieldTy,
ImplOrTraitItemDefIds,
AssociatedItemDefIds,
InherentImpls,
TraitImpls,
ReprHints,
@@ -219,11 +219,11 @@ impl<D: Clone + Debug> DepNode<D> {
RvalueCheck(ref d) => op(d).map(RvalueCheck),
TransCrateItem(ref d) => op(d).map(TransCrateItem),
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
ImplOrTraitItems(ref d) => op(d).map(ImplOrTraitItems),
AssociatedItems(ref d) => op(d).map(AssociatedItems),
ItemSignature(ref d) => op(d).map(ItemSignature),
FieldTy(ref d) => op(d).map(FieldTy),
SizedConstraint(ref d) => op(d).map(SizedConstraint),
ImplOrTraitItemDefIds(ref d) => op(d).map(ImplOrTraitItemDefIds),
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
InherentImpls(ref d) => op(d).map(InherentImpls),
TraitImpls(ref d) => op(d).map(TraitImpls),
TraitItems(ref d) => op(d).map(TraitItems),
14 changes: 7 additions & 7 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@ pub trait CrateStore<'tcx> {
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;

// impl info
fn impl_or_trait_items(&self, def_id: DefId) -> Vec<DefId>;
fn associated_item_def_ids(&self, def_id: DefId) -> Vec<DefId>;
fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::TraitRef<'tcx>>;
fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity;
@@ -157,8 +157,8 @@ pub trait CrateStore<'tcx> {

// trait/impl-item info
fn trait_of_item(&self, def_id: DefId) -> Option<DefId>;
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::ImplOrTraitItem<'tcx>>;
fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::AssociatedItem>;

// flags
fn is_const_fn(&self, did: DefId) -> bool;
@@ -311,8 +311,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
}

// impl info
fn impl_or_trait_items(&self, def_id: DefId) -> Vec<DefId>
{ bug!("impl_or_trait_items") }
fn associated_item_def_ids(&self, def_id: DefId) -> Vec<DefId>
{ bug!("associated_items") }
fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::TraitRef<'tcx>> { bug!("impl_trait_ref") }
fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { bug!("impl_polarity") }
@@ -323,8 +323,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {

// trait/impl-item info
fn trait_of_item(&self, def_id: DefId) -> Option<DefId> { bug!("trait_of_item") }
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::ImplOrTraitItem<'tcx>> { bug!("impl_or_trait_item") }
fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::AssociatedItem> { bug!("associated_item") }

// flags
fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
5 changes: 2 additions & 3 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
@@ -471,11 +471,10 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
// This is done to handle the case where, for example, the static
// method of a private type is used, but the type itself is never
// called directly.
let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow();
if let Some(impl_list) =
self.tcx.inherent_impls.borrow().get(&self.tcx.map.local_def_id(id)) {
for impl_did in impl_list.iter() {
for &item_did in &impl_items[impl_did][..] {
for &impl_did in impl_list.iter() {
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
if let Some(item_node_id) = self.tcx.map.as_local_node_id(item_did) {
if self.live_symbols.contains(&item_node_id) {
return true;
4 changes: 2 additions & 2 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
@@ -227,8 +227,8 @@ impl OverloadedCallType {
}

fn from_method_id(tcx: TyCtxt, method_id: DefId) -> OverloadedCallType {
let method = tcx.impl_or_trait_item(method_id);
OverloadedCallType::from_trait_id(tcx, method.container().id())
let method = tcx.associated_item(method_id);
OverloadedCallType::from_trait_id(tcx, method.container.id())
}
}

20 changes: 5 additions & 15 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
@@ -529,14 +529,11 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// items.
hir::ItemImpl(.., Some(ref t), _, ref impl_items) => {
let trait_did = tcx.expect_def(t.ref_id).def_id();
let trait_items = tcx.trait_items(trait_did);

for impl_item in impl_items {
let item = trait_items.iter().find(|item| {
item.name() == impl_item.name
}).unwrap();
let item = tcx.associated_items(trait_did)
.find(|item| item.name == impl_item.name).unwrap();
if warn_about_defns {
maybe_do_stability_check(tcx, item.def_id(), impl_item.span, cb);
maybe_do_stability_check(tcx, item.def_id, impl_item.span, cb);
}
}
}
@@ -685,15 +682,8 @@ fn is_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) -> bool {
}

fn is_staged_api<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> bool {
match tcx.trait_item_of_item(id) {
Some(trait_method_id) if trait_method_id != id => {
is_staged_api(tcx, trait_method_id)
}
_ => {
*tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with(
|| tcx.sess.cstore.is_staged_api(id.krate))
}
}
*tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with(
|| tcx.sess.cstore.is_staged_api(id.krate))
}

impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this case not matter anymore?

Copy link
Member Author

@eddyb eddyb Nov 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took me a bit to remember, but it never should've really mattered. Regardless of past practices, we now never refer to associated items in impls of traits, only to the definition in the trait, outside of monomorphization.

14 changes: 6 additions & 8 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
@@ -663,25 +663,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
in the supertrait listing"
}

ObjectSafetyViolation::Method(method,
ObjectSafetyViolation::Method(name,
MethodViolationCode::StaticMethod) => {
buf = format!("method `{}` has no receiver",
method.name);
buf = format!("method `{}` has no receiver", name);
&buf
}

ObjectSafetyViolation::Method(method,
ObjectSafetyViolation::Method(name,
MethodViolationCode::ReferencesSelf) => {
buf = format!("method `{}` references the `Self` type \
in its arguments or return type",
method.name);
name);
&buf
}

ObjectSafetyViolation::Method(method,
ObjectSafetyViolation::Method(name,
MethodViolationCode::Generic) => {
buf = format!("method `{}` has generic type parameters",
method.name);
buf = format!("method `{}` has generic type parameters", name);
&buf
}
};
20 changes: 8 additions & 12 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -578,18 +578,14 @@ pub fn get_vtable_methods<'a, 'tcx>(
supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());

let trait_item_def_ids = tcx.impl_or_trait_items(trait_ref.def_id());
let trait_methods = (0..trait_item_def_ids.len()).filter_map(move |i| {
match tcx.impl_or_trait_item(trait_item_def_ids[i]) {
ty::MethodTraitItem(m) => Some(m),
_ => None
}
});
let trait_methods = tcx.associated_items(trait_ref.def_id())
.filter(|item| item.kind == ty::AssociatedKind::Method);

// Now list each method's DefId and Substs (for within its trait).
// If the method can never be called from this object, produce None.
trait_methods.map(move |trait_method| {
debug!("get_vtable_methods: trait_method={:?}", trait_method);
let def_id = trait_method.def_id;

// Some methods cannot be called on an object; skip those.
if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) {
@@ -599,21 +595,21 @@ pub fn get_vtable_methods<'a, 'tcx>(

// the method may have some early-bound lifetimes, add
// regions for those
let substs = Substs::for_item(tcx, trait_method.def_id,
|_, _| tcx.mk_region(ty::ReErased),
|def, _| trait_ref.substs().type_for_def(def));
let substs = Substs::for_item(tcx, def_id,
|_, _| tcx.mk_region(ty::ReErased),
|def, _| trait_ref.substs().type_for_def(def));

// It's possible that the method 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 (see #23435).
let predicates = trait_method.predicates.instantiate_own(tcx, substs);
let predicates = tcx.lookup_predicates(def_id).instantiate_own(tcx, substs);
if !normalize_and_test_predicates(tcx, predicates.predicates) {
debug!("get_vtable_methods: predicates do not hold");
return None;
}

Some((trait_method.def_id, substs))
Some((def_id, substs))
})
})
}
48 changes: 17 additions & 31 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
@@ -22,11 +22,10 @@ use super::elaborate_predicates;
use hir::def_id::DefId;
use traits;
use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
use std::rc::Rc;
use syntax::ast;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ObjectSafetyViolation<'tcx> {
pub enum ObjectSafetyViolation {
/// Self : Sized declared on the trait
SizedSelf,

@@ -35,7 +34,7 @@ pub enum ObjectSafetyViolation<'tcx> {
SupertraitSelf,

/// Method has something illegal
Method(Rc<ty::Method<'tcx>>, MethodViolationCode),
Method(ast::Name, MethodViolationCode),
}

/// Reasons a method might not be object-safe.
@@ -77,7 +76,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// because `object_safety_violations` can't be used during
/// type collection.
pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
-> Vec<ObjectSafetyViolation<'tcx>>
-> Vec<ObjectSafetyViolation>
{
let mut violations = vec![];

@@ -93,29 +92,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}

pub fn object_safety_violations(self, trait_def_id: DefId)
-> Vec<ObjectSafetyViolation<'tcx>>
-> Vec<ObjectSafetyViolation>
{
traits::supertrait_def_ids(self, trait_def_id)
.flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
.collect()
}

fn object_safety_violations_for_trait(self, trait_def_id: DefId)
-> Vec<ObjectSafetyViolation<'tcx>>
-> Vec<ObjectSafetyViolation>
{
// Check methods for violations.
let mut violations: Vec<_> =
self.trait_items(trait_def_id).iter()
let mut violations: Vec<_> = self.associated_items(trait_def_id)
.filter(|item| item.kind == ty::AssociatedKind::Method)
.filter_map(|item| {
match *item {
ty::MethodTraitItem(ref m) => {
self.object_safety_violation_for_method(trait_def_id, &m)
.map(|code| ObjectSafetyViolation::Method(m.clone(), code))
}
_ => None,
}
})
.collect();
self.object_safety_violation_for_method(trait_def_id, &item)
.map(|code| ObjectSafetyViolation::Method(item.name, code))
}).collect();

// Check the trait itself.
if self.trait_has_sized_self(trait_def_id) {
@@ -198,7 +191,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Returns `Some(_)` if this method makes the containing trait not object safe.
fn object_safety_violation_for_method(self,
trait_def_id: DefId,
method: &ty::Method<'gcx>)
method: &ty::AssociatedItem)
-> Option<MethodViolationCode>
{
// Any method that has a `Self : Sized` requisite is otherwise
@@ -216,7 +209,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// otherwise ensure that they cannot be used when `Self=Trait`.
pub fn is_vtable_safe_method(self,
trait_def_id: DefId,
method: &ty::Method<'gcx>)
method: &ty::AssociatedItem)
-> bool
{
// Any method that has a `Self : Sized` requisite can't be called.
@@ -233,26 +226,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// `Self:Sized`.
fn virtual_call_violation_for_method(self,
trait_def_id: DefId,
method: &ty::Method<'tcx>)
method: &ty::AssociatedItem)
-> Option<MethodViolationCode>
{
// The method's first parameter must be something that derefs (or
// autorefs) to `&self`. For now, we only accept `self`, `&self`
// and `Box<Self>`.
match method.explicit_self {
ty::ExplicitSelfCategory::Static => {
return Some(MethodViolationCode::StaticMethod);
}

ty::ExplicitSelfCategory::ByValue |
ty::ExplicitSelfCategory::ByReference(..) |
ty::ExplicitSelfCategory::ByBox => {
}
if !method.method_has_self_argument {
return Some(MethodViolationCode::StaticMethod);
}

// The `Self` type is erased, so it should not appear in list of
// arguments or return type apart from the receiver.
let ref sig = method.fty.sig;
let ref sig = self.lookup_item_type(method.def_id).ty.fn_sig();
for &input_ty in &sig.0.inputs[1..] {
if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
return Some(MethodViolationCode::ReferencesSelf);
@@ -263,7 +249,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}

// We can't monomorphize things like `fn foo<A>(...)`.
if !method.generics.types.is_empty() {
if !self.lookup_generics(method.def_id).types.is_empty() {
return Some(MethodViolationCode::Generic);
}

26 changes: 12 additions & 14 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
@@ -33,8 +33,6 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder};
use util::common::FN_OUTPUT_NAME;

use std::rc::Rc;

/// Depending on the stage of compilation, we want projection to be
/// more or less conservative.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -945,7 +943,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
// an error when we confirm the candidate
// (which will ultimately lead to `normalize_to_error`
// being invoked).
node_item.item.ty.is_some()
node_item.item.has_value
} else {
node_item.item.defaultness.is_default()
};
@@ -1305,7 +1303,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(

match assoc_ty {
Some(node_item) => {
let ty = node_item.item.ty.unwrap_or_else(|| {
let ty = if !node_item.item.has_value {
// This means that the impl is missing a definition for the
// associated type. This error will be reported by the type
// checker method `check_impl_items_against_trait`, so here we
@@ -1314,7 +1312,9 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
node_item.item.name,
obligation.predicate.trait_ref);
tcx.types.err
});
} else {
tcx.lookup_item_type(node_item.item.def_id).ty
};
let substs = translate_substs(selcx.infcx(), impl_def_id, substs, node_item.node);
Progress {
ty: ty.subst(tcx, substs),
@@ -1339,27 +1339,25 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
selcx: &SelectionContext<'cx, 'gcx, 'tcx>,
impl_def_id: DefId,
assoc_ty_name: ast::Name)
-> Option<specialization_graph::NodeItem<Rc<ty::AssociatedType<'tcx>>>>
-> Option<specialization_graph::NodeItem<ty::AssociatedItem>>
{
let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id;

if selcx.projection_mode() == Reveal::ExactMatch {
let impl_node = specialization_graph::Node::Impl(impl_def_id);
for item in impl_node.items(selcx.tcx()) {
if let ty::TypeTraitItem(assoc_ty) = item {
if assoc_ty.name == assoc_ty_name {
return Some(specialization_graph::NodeItem {
node: specialization_graph::Node::Impl(impl_def_id),
item: assoc_ty,
});
}
if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
return Some(specialization_graph::NodeItem {
node: specialization_graph::Node::Impl(impl_def_id),
item: item,
});
}
}
None
} else {
selcx.tcx().lookup_trait_def(trait_def_id)
.ancestors(impl_def_id)
.type_defs(selcx.tcx(), assoc_ty_name)
.defs(selcx.tcx(), assoc_ty_name, ty::AssociatedKind::Type)
.next()
}
}
3 changes: 2 additions & 1 deletion src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
@@ -120,7 +120,8 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
let trait_def = tcx.lookup_trait_def(trait_def_id);

match trait_def.ancestors(impl_data.impl_def_id).fn_defs(tcx, name).next() {
let ancestors = trait_def.ancestors(impl_data.impl_def_id);
match ancestors.defs(tcx, name, ty::AssociatedKind::Method).next() {
Some(node_item) => {
let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
142 changes: 14 additions & 128 deletions src/librustc/traits/specialize/specialization_graph.rs
Original file line number Diff line number Diff line change
@@ -8,13 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::rc::Rc;

use super::{OverlapError, specializes};

use hir::def_id::DefId;
use traits::{self, Reveal};
use ty::{self, TyCtxt, ImplOrTraitItem, TraitDef, TypeFoldable};
use ty::{self, TyCtxt, TraitDef, TypeFoldable};
use ty::fast_reject::{self, SimplifiedType};
use syntax::ast::Name;
use util::nodemap::{DefIdMap, FxHashMap};
@@ -285,12 +283,10 @@ impl<'a, 'gcx, 'tcx> Node {
}

/// Iterate over the items defined directly by the given (impl or trait) node.
pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> NodeItems<'a, 'gcx> {
NodeItems {
tcx: tcx.global_tcx(),
items: tcx.impl_or_trait_items(self.def_id()),
idx: 0,
}
#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-> impl Iterator<Item = ty::AssociatedItem> + 'a {
tcx.associated_items(self.def_id())
}

pub fn def_id(&self) -> DefId {
@@ -301,28 +297,6 @@ impl<'a, 'gcx, 'tcx> Node {
}
}

/// An iterator over the items defined within a trait or impl.
pub struct NodeItems<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
items: Rc<Vec<DefId>>,
idx: usize
}

impl<'a, 'tcx> Iterator for NodeItems<'a, 'tcx> {
type Item = ImplOrTraitItem<'tcx>;
fn next(&mut self) -> Option<ImplOrTraitItem<'tcx>> {
if self.idx < self.items.len() {
let item_def_id = self.items[self.idx];
let items_table = self.tcx.impl_or_trait_items.borrow();
let item = items_table[&item_def_id].clone();
self.idx += 1;
Some(item)
} else {
None
}
}
}

pub struct Ancestors<'a, 'tcx: 'a> {
trait_def: &'a TraitDef<'tcx>,
current_source: Option<Node>,
@@ -358,104 +332,16 @@ impl<T> NodeItem<T> {
}
}

pub struct TypeDefs<'a, 'tcx: 'a> {
// generally only invoked once or twice, so the box doesn't hurt
iter: Box<Iterator<Item = NodeItem<Rc<ty::AssociatedType<'tcx>>>> + 'a>,
}

impl<'a, 'tcx> Iterator for TypeDefs<'a, 'tcx> {
type Item = NodeItem<Rc<ty::AssociatedType<'tcx>>>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}

pub struct FnDefs<'a, 'tcx: 'a> {
// generally only invoked once or twice, so the box doesn't hurt
iter: Box<Iterator<Item = NodeItem<Rc<ty::Method<'tcx>>>> + 'a>,
}

impl<'a, 'tcx> Iterator for FnDefs<'a, 'tcx> {
type Item = NodeItem<Rc<ty::Method<'tcx>>>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}

pub struct ConstDefs<'a, 'tcx: 'a> {
// generally only invoked once or twice, so the box doesn't hurt
iter: Box<Iterator<Item = NodeItem<Rc<ty::AssociatedConst<'tcx>>>> + 'a>,
}

impl<'a, 'tcx> Iterator for ConstDefs<'a, 'tcx> {
type Item = NodeItem<Rc<ty::AssociatedConst<'tcx>>>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}

impl<'a, 'gcx, 'tcx> Ancestors<'a, 'tcx> {
/// Search the items from the given ancestors, returning each type definition
/// with the given name.
pub fn type_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> TypeDefs<'a, 'gcx> {
let iter = self.flat_map(move |node| {
node.items(tcx)
.filter_map(move |item| {
if let ty::TypeTraitItem(assoc_ty) = item {
if assoc_ty.name == name {
return Some(NodeItem {
node: node,
item: assoc_ty,
});
}
}
None
})

});
TypeDefs { iter: Box::new(iter) }
}

/// Search the items from the given ancestors, returning each fn definition
/// with the given name.
pub fn fn_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> FnDefs<'a, 'gcx> {
let iter = self.flat_map(move |node| {
node.items(tcx)
.filter_map(move |item| {
if let ty::MethodTraitItem(method) = item {
if method.name == name {
return Some(NodeItem {
node: node,
item: method,
});
}
}
None
})

});
FnDefs { iter: Box::new(iter) }
}

/// Search the items from the given ancestors, returning each const
/// definition with the given name.
pub fn const_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> ConstDefs<'a, 'gcx> {
let iter = self.flat_map(move |node| {
node.items(tcx)
.filter_map(move |item| {
if let ty::ConstTraitItem(konst) = item {
if konst.name == name {
return Some(NodeItem {
node: node,
item: konst,
});
}
}
None
})

});
ConstDefs { iter: Box::new(iter) }
/// Search the items from the given ancestors, returning each definition
/// with the given name and the given kind.
#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
pub fn defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name, kind: ty::AssociatedKind)
-> impl Iterator<Item = NodeItem<ty::AssociatedItem>> + 'a {
self.flat_map(move |node| {
node.items(tcx).filter(move |item| item.kind == kind && item.name == name)
.map(move |item| NodeItem { node: node, item: item })
})
}
}

16 changes: 6 additions & 10 deletions src/librustc/traits/util.rs
Original file line number Diff line number Diff line change
@@ -477,8 +477,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
let mut entries = 0;
// Count number of methods and add them to the total offset.
// Skip over associated types and constants.
for trait_item in &self.trait_items(trait_ref.def_id())[..] {
if let ty::MethodTraitItem(_) = *trait_item {
for trait_item in self.associated_items(trait_ref.def_id()) {
if trait_item.kind == ty::AssociatedKind::Method {
entries += 1;
}
}
@@ -495,17 +495,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// add them to the total offset.
// Skip over associated types and constants.
let mut entries = object.vtable_base;
for trait_item in &self.trait_items(object.upcast_trait_ref.def_id())[..] {
if trait_item.def_id() == method_def_id {
for trait_item in self.associated_items(object.upcast_trait_ref.def_id()) {
if trait_item.def_id == method_def_id {
// The item with the ID we were given really ought to be a method.
assert!(match *trait_item {
ty::MethodTraitItem(_) => true,
_ => false
});

assert_eq!(trait_item.kind, ty::AssociatedKind::Method);
return entries;
}
if let ty::MethodTraitItem(_) = *trait_item {
if trait_item.kind == ty::AssociatedKind::Method {
entries += 1;
}
}
22 changes: 4 additions & 18 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
@@ -403,14 +403,10 @@ pub struct GlobalCtxt<'tcx> {
pub tables: RefCell<Tables<'tcx>>,

/// Maps from a trait item to the trait item "descriptor"
pub impl_or_trait_items: RefCell<DepTrackingMap<maps::ImplOrTraitItems<'tcx>>>,
pub associated_items: RefCell<DepTrackingMap<maps::AssociatedItems<'tcx>>>,

/// Maps from an impl/trait def-id to a list of the def-ids of its items
pub impl_or_trait_item_def_ids: RefCell<DepTrackingMap<maps::ImplOrTraitItemDefIds<'tcx>>>,

/// A cache for the trait_items() routine; note that the routine
/// itself pushes the `TraitItems` dependency node.
trait_items_cache: RefCell<DepTrackingMap<maps::TraitItems<'tcx>>>,
pub associated_item_def_ids: RefCell<DepTrackingMap<maps::AssociatedItemDefIds<'tcx>>>,

pub impl_trait_refs: RefCell<DepTrackingMap<maps::ImplTraitRefs<'tcx>>>,
pub trait_defs: RefCell<DepTrackingMap<maps::TraitDefs<'tcx>>>,
@@ -822,9 +818,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
tcache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
rcache: RefCell::new(FxHashMap()),
tc_cache: RefCell::new(FxHashMap()),
impl_or_trait_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
impl_or_trait_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
trait_items_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
associated_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
ty_param_defs: RefCell::new(NodeMap()),
normalized_cache: RefCell::new(FxHashMap()),
lang_items: lang_items,
@@ -1539,15 +1534,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
}

pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> {
self.trait_items_cache.memoize(trait_did, || {
let def_ids = self.impl_or_trait_items(trait_did);
Rc::new(def_ids.iter()
.map(|&def_id| self.impl_or_trait_item(def_id))
.collect())
})
}

/// Obtain the representation annotation for a struct definition.
pub fn lookup_repr_hints(self, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
self.repr_hint_cache.memoize(did, || {
8 changes: 3 additions & 5 deletions src/librustc/ty/maps.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ use ty::{self, Ty};
use std::cell::RefCell;
use std::marker::PhantomData;
use std::rc::Rc;
use syntax::{attr, ast};
use syntax::attr;

macro_rules! dep_map_ty {
($ty_name:ident : $node_name:ident ($key:ty) -> $value:ty) => {
@@ -32,18 +32,16 @@ macro_rules! dep_map_ty {
}
}

dep_map_ty! { ImplOrTraitItems: ImplOrTraitItems(DefId) -> ty::ImplOrTraitItem<'tcx> }
dep_map_ty! { AssociatedItems: AssociatedItems(DefId) -> ty::AssociatedItem }
dep_map_ty! { Tcache: ItemSignature(DefId) -> Ty<'tcx> }
dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> }
dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
dep_map_ty! { ImplOrTraitItemDefIds: ImplOrTraitItemDefIds(DefId) -> Rc<Vec<DefId>> }
dep_map_ty! { AssociatedItemDefIds: AssociatedItemDefIds(DefId) -> Rc<Vec<DefId>> }
dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>> }
dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef<'tcx> }
dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> }
dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc<Vec<ty::Variance>> }
dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec<DefId> }
dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc<Vec<ty::ImplOrTraitItem<'tcx>>> }
dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId }
dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
396 changes: 152 additions & 244 deletions src/librustc/ty/mod.rs

Large diffs are not rendered by default.

26 changes: 0 additions & 26 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
@@ -670,18 +670,6 @@ impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> {
}
}

impl<'tcx> fmt::Debug for ty::ImplOrTraitItem<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ImplOrTraitItem(")?;
match *self {
ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i),
ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i),
ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i),
}?;
write!(f, ")")
}
}

impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "fn")?;
@@ -995,20 +983,6 @@ impl fmt::Display for ty::InferTy {
}
}

impl<'tcx> fmt::Display for ty::ExplicitSelfCategory<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
ty::ExplicitSelfCategory::Static => "static",
ty::ExplicitSelfCategory::ByValue => "self",
ty::ExplicitSelfCategory::ByReference(_, hir::MutMutable) => {
"&mut self"
}
ty::ExplicitSelfCategory::ByReference(_, hir::MutImmutable) => "&self",
ty::ExplicitSelfCategory::ByBox => "Box<self>",
})
}
}

impl fmt::Display for ty::ParamTy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)
9 changes: 2 additions & 7 deletions src/librustc_const_eval/eval.rs
Original file line number Diff line number Diff line change
@@ -1091,13 +1091,8 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// when constructing the inference context above.
match selection {
traits::VtableImpl(ref impl_data) => {
let ac = tcx.impl_or_trait_items(impl_data.impl_def_id)
.iter().filter_map(|&def_id| {
match tcx.impl_or_trait_item(def_id) {
ty::ConstTraitItem(ic) => Some(ic),
_ => None
}
}).find(|ic| ic.name == ti.name);
let ac = tcx.associated_items(impl_data.impl_def_id)
.find(|item| item.kind == ty::AssociatedKind::Const && item.name == ti.name);
match ac {
Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
None => match ti.node {
4 changes: 2 additions & 2 deletions src/librustc_lint/bad_style.rs
Original file line number Diff line number Diff line change
@@ -29,10 +29,10 @@ pub enum MethodLateContext {

pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext {
let def_id = cx.tcx.map.local_def_id(id);
match cx.tcx.impl_or_trait_items.borrow().get(&def_id) {
match cx.tcx.associated_items.borrow().get(&def_id) {
None => span_bug!(span, "missing method descriptor?!"),
Some(item) => {
match item.container() {
match item.container {
ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl,
ty::ImplContainer(cid) => {
match cx.tcx.impl_trait_ref(cid) {
12 changes: 6 additions & 6 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
@@ -818,7 +818,7 @@ impl LateLintPass for UnconditionalRecursion {
let method = match fn_kind {
FnKind::ItemFn(..) => None,
FnKind::Method(..) => {
cx.tcx.impl_or_trait_item(cx.tcx.map.local_def_id(id)).as_opt_method()
Some(cx.tcx.associated_item(cx.tcx.map.local_def_id(id)))
}
// closures can't recur, so they don't matter.
FnKind::Closure(_) => return,
@@ -937,7 +937,7 @@ impl LateLintPass for UnconditionalRecursion {

// Check if the expression `id` performs a call to `method`.
fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
method: &ty::Method,
method: &ty::AssociatedItem,
id: ast::NodeId)
-> bool {
use rustc::ty::adjustment::*;
@@ -986,14 +986,14 @@ impl LateLintPass for UnconditionalRecursion {
// Check if the method call to the method with the ID `callee_id`
// and instantiated with `callee_substs` refers to method `method`.
fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
method: &ty::Method,
method: &ty::AssociatedItem,
callee_id: DefId,
callee_substs: &Substs<'tcx>,
expr_id: ast::NodeId)
-> bool {
let callee_item = tcx.impl_or_trait_item(callee_id);
let callee_item = tcx.associated_item(callee_id);

match callee_item.container() {
match callee_item.container {
// This is an inherent method, so the `def_id` refers
// directly to the method definition.
ty::ImplContainer(_) => callee_id == method.def_id,
@@ -1034,7 +1034,7 @@ impl LateLintPass for UnconditionalRecursion {
let container = ty::ImplContainer(vtable_impl.impl_def_id);
// It matches if it comes from the same impl,
// and has the same method name.
container == method.container && callee_item.name() == method.name
container == method.container && callee_item.name == method.name
}

// There's no way to know if this call is
12 changes: 6 additions & 6 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
@@ -144,7 +144,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
result
}

fn impl_or_trait_items(&self, def_id: DefId) -> Vec<DefId> {
fn associated_item_def_ids(&self, def_id: DefId) -> Vec<DefId> {
self.dep_graph.read(DepNode::MetaData(def_id));
let mut result = vec![];
self.get_crate_data(def_id.krate)
@@ -182,11 +182,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index)
}

fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::ImplOrTraitItem<'tcx>>
fn associated_item<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::AssociatedItem>
{
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).get_impl_or_trait_item(def.index, tcx)
self.get_crate_data(def.krate).get_associated_item(def.index)
}

fn is_const_fn(&self, did: DefId) -> bool
@@ -427,9 +427,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
// the logic to do that already exists in `middle`. In order to
// reuse that code, it needs to be able to look up the traits for
// inlined items.
let ty_trait_item = tcx.impl_or_trait_item(def_id).clone();
let ty_trait_item = tcx.associated_item(def_id).clone();
let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
tcx.impl_or_trait_items.borrow_mut()
tcx.associated_items.borrow_mut()
.insert(trait_item_def_id, ty_trait_item);
}
Some(&InlinedItem::ImplItem(_, ref impl_item)) => {
45 changes: 16 additions & 29 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
@@ -36,7 +36,6 @@ use std::borrow::Cow;
use std::cell::Ref;
use std::io;
use std::mem;
use std::rc::Rc;
use std::str;
use std::u32;

@@ -792,10 +791,7 @@ impl<'a, 'tcx> CrateMetadata {
self.entry(id).mir.map(|mir| mir.decode((self, tcx)))
}

pub fn get_impl_or_trait_item(&self,
id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> Option<ty::ImplOrTraitItem<'tcx>> {
pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
let item = self.entry(id);
let parent_and_name = || {
let def_key = item.def_key.decode(self);
@@ -806,52 +802,43 @@ impl<'a, 'tcx> CrateMetadata {
Some(match item.kind {
EntryKind::AssociatedConst(container) => {
let (parent, name) = parent_and_name();
ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
ty::AssociatedItem {
name: name,
ty: item.ty.unwrap().decode((self, tcx)),
kind: ty::AssociatedKind::Const,
vis: item.visibility,
defaultness: container.defaultness(),
has_value: container.has_value(),
def_id: self.local_def_id(id),
container: container.with_def_id(parent),
has_value: container.has_body(),
}))
method_has_self_argument: false
}
}
EntryKind::Method(data) => {
let (parent, name) = parent_and_name();
let ity = item.ty.unwrap().decode((self, tcx));
let fty = match ity.sty {
ty::TyFnDef(.., fty) => fty,
_ => {
bug!("the type {:?} of the method {:?} is not a function?",
ity,
name)
}
};

let data = data.decode(self);
ty::MethodTraitItem(Rc::new(ty::Method {
ty::AssociatedItem {
name: name,
generics: tcx.lookup_generics(self.local_def_id(id)),
predicates: item.predicates.unwrap().decode((self, tcx)),
fty: fty,
explicit_self: data.explicit_self.decode((self, tcx)),
kind: ty::AssociatedKind::Method,
vis: item.visibility,
defaultness: data.container.defaultness(),
has_body: data.container.has_body(),
has_value: data.container.has_value(),
def_id: self.local_def_id(id),
container: data.container.with_def_id(parent),
}))
method_has_self_argument: data.has_self
}
}
EntryKind::AssociatedType(container) => {
let (parent, name) = parent_and_name();
ty::TypeTraitItem(Rc::new(ty::AssociatedType {
ty::AssociatedItem {
name: name,
ty: item.ty.map(|ty| ty.decode((self, tcx))),
kind: ty::AssociatedKind::Type,
vis: item.visibility,
defaultness: container.defaultness(),
has_value: container.has_value(),
def_id: self.local_def_id(id),
container: container.with_def_id(parent),
}))
method_has_self_argument: false
}
}
_ => return None,
})
84 changes: 40 additions & 44 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
@@ -457,19 +457,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

let node_id = tcx.map.as_local_node_id(def_id).unwrap();
let ast_item = tcx.map.expect_trait_item(node_id);
let trait_item = tcx.impl_or_trait_item(def_id);
let trait_item = tcx.associated_item(def_id);

let container = |has_body| if has_body {
let container = if trait_item.has_value {
AssociatedContainer::TraitWithDefault
} else {
AssociatedContainer::TraitRequired
};

let kind = match trait_item {
ty::ConstTraitItem(ref associated_const) => {
EntryKind::AssociatedConst(container(associated_const.has_value))
}
ty::MethodTraitItem(ref method_ty) => {
let kind = match trait_item.kind {
ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
ty::AssociatedKind::Method => {
let fn_data = if let hir::MethodTraitItem(ref sig, _) = ast_item.node {
FnData {
constness: hir::Constness::NotConst,
@@ -478,39 +476,44 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} else {
bug!()
};
let data = MethodData {
EntryKind::Method(self.lazy(&MethodData {
fn_data: fn_data,
container: container(method_ty.has_body),
explicit_self: self.lazy(&method_ty.explicit_self),
};
EntryKind::Method(self.lazy(&data))
container: container,
has_self: trait_item.method_has_self_argument,
}))
}
ty::TypeTraitItem(_) => EntryKind::AssociatedType(container(false)),
ty::AssociatedKind::Type => EntryKind::AssociatedType(container),
};

Entry {
kind: kind,
visibility: trait_item.vis().simplify(),
visibility: trait_item.vis.simplify(),
def_key: self.encode_def_key(def_id),
attributes: self.encode_attributes(&ast_item.attrs),
children: LazySeq::empty(),
stability: self.encode_stability(def_id),
deprecation: self.encode_deprecation(def_id),

ty: match trait_item {
ty::ConstTraitItem(_) |
ty::MethodTraitItem(_) => Some(self.encode_item_type(def_id)),
ty::TypeTraitItem(ref associated_type) => {
associated_type.ty.map(|ty| self.lazy(&ty))
ty: match trait_item.kind {
ty::AssociatedKind::Const |
ty::AssociatedKind::Method => {
Some(self.encode_item_type(def_id))
}
ty::AssociatedKind::Type => {
if trait_item.has_value {
Some(self.encode_item_type(def_id))
} else {
None
}
}
},
inherent_impls: LazySeq::empty(),
variances: LazySeq::empty(),
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),

ast: if let ty::ConstTraitItem(_) = trait_item {
let trait_def_id = trait_item.container().id();
ast: if trait_item.kind == ty::AssociatedKind::Const {
let trait_def_id = trait_item.container.id();
Some(self.encode_inlined_item(InlinedItemRef::TraitItem(trait_def_id, ast_item)))
} else {
None
@@ -522,17 +525,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
let ast_item = self.tcx.map.expect_impl_item(node_id);
let impl_item = self.tcx.impl_or_trait_item(def_id);
let impl_def_id = impl_item.container().id();
let impl_item = self.tcx.associated_item(def_id);
let impl_def_id = impl_item.container.id();

let container = match ast_item.defaultness {
let container = match impl_item.defaultness {
hir::Defaultness::Default => AssociatedContainer::ImplDefault,
hir::Defaultness::Final => AssociatedContainer::ImplFinal,
};

let kind = match impl_item {
ty::ConstTraitItem(_) => EntryKind::AssociatedConst(container),
ty::MethodTraitItem(ref method_ty) => {
let kind = match impl_item.kind {
ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
ty::AssociatedKind::Method => {
let fn_data = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
FnData {
constness: sig.constness,
@@ -541,17 +544,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} else {
bug!()
};
let data = MethodData {
EntryKind::Method(self.lazy(&MethodData {
fn_data: fn_data,
container: container,
explicit_self: self.lazy(&method_ty.explicit_self),
};
EntryKind::Method(self.lazy(&data))
has_self: impl_item.method_has_self_argument,
}))
}
ty::TypeTraitItem(_) => EntryKind::AssociatedType(container),
ty::AssociatedKind::Type => EntryKind::AssociatedType(container)
};

let (ast, mir) = if let ty::ConstTraitItem(_) = impl_item {
let (ast, mir) = if impl_item.kind == ty::AssociatedKind::Const {
(true, true)
} else if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
let generics = self.tcx.lookup_generics(def_id);
@@ -565,20 +567,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

Entry {
kind: kind,
visibility: impl_item.vis().simplify(),
visibility: impl_item.vis.simplify(),
def_key: self.encode_def_key(def_id),
attributes: self.encode_attributes(&ast_item.attrs),
children: LazySeq::empty(),
stability: self.encode_stability(def_id),
deprecation: self.encode_deprecation(def_id),

ty: match impl_item {
ty::ConstTraitItem(_) |
ty::MethodTraitItem(_) => Some(self.encode_item_type(def_id)),
ty::TypeTraitItem(ref associated_type) => {
associated_type.ty.map(|ty| self.lazy(&ty))
}
},
ty: Some(self.encode_item_type(def_id)),
inherent_impls: LazySeq::empty(),
variances: LazySeq::empty(),
generics: Some(self.encode_generics(def_id)),
@@ -758,7 +754,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
hir::ItemImpl(..) |
hir::ItemTrait(..) => {
self.lazy_seq(tcx.impl_or_trait_items(def_id).iter().map(|&def_id| {
self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| {
assert!(def_id.is_local());
def_id.index
}))
@@ -880,14 +876,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
self.encode_fields(def_id);
}
hir::ItemImpl(..) => {
for &trait_item_def_id in &self.tcx.impl_or_trait_items(def_id)[..] {
for &trait_item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
self.record(trait_item_def_id,
EncodeContext::encode_info_for_impl_item,
trait_item_def_id);
}
}
hir::ItemTrait(..) => {
for &item_def_id in &self.tcx.impl_or_trait_items(def_id)[..] {
for &item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
self.record(item_def_id,
EncodeContext::encode_info_for_trait_item,
item_def_id);
10 changes: 5 additions & 5 deletions src/librustc_metadata/schema.rs
Original file line number Diff line number Diff line change
@@ -245,7 +245,7 @@ pub enum EntryKind<'tcx> {
Trait(Lazy<TraitData<'tcx>>),
Impl(Lazy<ImplData<'tcx>>),
DefaultImpl(Lazy<ImplData<'tcx>>),
Method(Lazy<MethodData<'tcx>>),
Method(Lazy<MethodData>),
AssociatedType(AssociatedContainer),
AssociatedConst(AssociatedContainer),
}
@@ -300,7 +300,7 @@ pub enum AssociatedContainer {
}

impl AssociatedContainer {
pub fn with_def_id(&self, def_id: DefId) -> ty::ImplOrTraitItemContainer {
pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
match *self {
AssociatedContainer::TraitRequired |
AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
@@ -310,7 +310,7 @@ impl AssociatedContainer {
}
}

pub fn has_body(&self) -> bool {
pub fn has_value(&self) -> bool {
match *self {
AssociatedContainer::TraitRequired => false,

@@ -332,10 +332,10 @@ impl AssociatedContainer {
}

#[derive(RustcEncodable, RustcDecodable)]
pub struct MethodData<'tcx> {
pub struct MethodData {
pub fn_data: FnData,
pub container: AssociatedContainer,
pub explicit_self: Lazy<ty::ExplicitSelfCategory<'tcx>>,
pub has_self: bool,
}

#[derive(RustcEncodable, RustcDecodable)]
22 changes: 8 additions & 14 deletions src/librustc_mir/hair/cx/mod.rs
Original file line number Diff line number Diff line change
@@ -147,20 +147,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
-> (Ty<'tcx>, Literal<'tcx>) {
let method_name = token::intern(method_name);
let substs = self.tcx.mk_substs_trait(self_ty, params);
for trait_item in self.tcx.trait_items(trait_def_id).iter() {
match *trait_item {
ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
if method.name == method_name {
let method_ty = self.tcx.lookup_item_type(method.def_id);
let method_ty = method_ty.ty.subst(self.tcx, substs);
return (method_ty, Literal::Item {
def_id: method.def_id,
substs: substs,
});
}
}
ty::ImplOrTraitItem::ConstTraitItem(..) |
ty::ImplOrTraitItem::TypeTraitItem(..) => {}
for item in self.tcx.associated_items(trait_def_id) {
if item.kind == ty::AssociatedKind::Method && item.name == method_name {
let method_ty = self.tcx.lookup_item_type(item.def_id);
let method_ty = method_ty.ty.subst(self.tcx, substs);
return (method_ty, Literal::Item {
def_id: item.def_id,
substs: substs,
});
}
}

4 changes: 2 additions & 2 deletions src/librustc_passes/consts.rs
Original file line number Diff line number Diff line change
@@ -542,7 +542,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
v.handle_const_fn_call(e, did, node_ty)
}
Some(Def::Method(did)) => {
match v.tcx.impl_or_trait_item(did).container() {
match v.tcx.associated_item(did).container {
ty::ImplContainer(_) => {
v.handle_const_fn_call(e, did, node_ty)
}
@@ -557,7 +557,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
}
hir::ExprMethodCall(..) => {
let method = v.tcx.tables().method_map[&method_call];
let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
let is_const = match v.tcx.associated_item(method.def_id).container {
ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
ty::TraitContainer(_) => false
};
2 changes: 1 addition & 1 deletion src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
@@ -399,7 +399,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {

// Checks that a method is in scope.
fn check_method(&mut self, span: Span, method_def_id: DefId) {
match self.tcx.impl_or_trait_item(method_def_id).container() {
match self.tcx.associated_item(method_def_id).container {
// Trait methods are always all public. The only controlling factor
// is whether the trait itself is accessible or not.
ty::TraitContainer(trait_def_id) if !self.item_is_accessible(trait_def_id) => {
2 changes: 1 addition & 1 deletion src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
@@ -456,7 +456,7 @@ impl<'b> Resolver<'b> {
self.define(parent, name, TypeNS, (module, DUMMY_SP, vis));

// If this is a trait, add all the trait item names to the trait info.
let trait_item_def_ids = self.session.cstore.impl_or_trait_items(def_id);
let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id);
for trait_item_def_id in trait_item_def_ids {
let trait_item_name = self.session.cstore.def_key(trait_item_def_id)
.disambiguated_data.data.get_opt_name()
24 changes: 11 additions & 13 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ use rustc::hir::def::Def;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir::map::{Node, NodeItem};
use rustc::session::Session;
use rustc::ty::{self, TyCtxt, ImplOrTraitItem, ImplOrTraitItemContainer};
use rustc::ty::{self, TyCtxt, AssociatedItemContainer};

use std::collections::HashSet;
use std::collections::hash_map::DefaultHasher;
@@ -402,19 +402,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
// with the right name.
if !self.span.filter_generated(Some(method_data.span), span) {
let container =
self.tcx.impl_or_trait_item(self.tcx.map.local_def_id(id)).container();
self.tcx.associated_item(self.tcx.map.local_def_id(id)).container;
let mut trait_id;
let mut decl_id = None;
match container {
ImplOrTraitItemContainer::ImplContainer(id) => {
AssociatedItemContainer::ImplContainer(id) => {
trait_id = self.tcx.trait_id_of_impl(id);

match trait_id {
Some(id) => {
for item in &**self.tcx.trait_items(id) {
if let &ImplOrTraitItem::MethodTraitItem(ref m) = item {
if m.name == name {
decl_id = Some(m.def_id);
for item in self.tcx.associated_items(id) {
if item.kind == ty::AssociatedKind::Method {
if item.name == name {
decl_id = Some(item.def_id);
break;
}
}
@@ -429,7 +429,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
}
}
}
ImplOrTraitItemContainer::TraitContainer(id) => {
AssociatedItemContainer::TraitContainer(id) => {
trait_id = Some(id);
}
}
@@ -916,11 +916,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
// Modules or types in the path prefix.
match self.tcx.expect_def(id) {
Def::Method(did) => {
let ti = self.tcx.impl_or_trait_item(did);
if let ty::MethodTraitItem(m) = ti {
if m.explicit_self == ty::ExplicitSelfCategory::Static {
self.write_sub_path_trait_truncated(path);
}
let ti = self.tcx.associated_item(did);
if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument {
self.write_sub_path_trait_truncated(path);
}
}
Def::Fn(..) |
57 changes: 15 additions & 42 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
@@ -313,7 +313,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
name: ast::Name, span: Span) -> Option<FunctionData> {
// The qualname for a method is the trait name or name of the struct in an impl in
// which the method is declared in, followed by the method's name.
let (qualname, parent_scope, vis, docs) =
let (qualname, parent_scope, decl_id, vis, docs) =
match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) {
Some(impl_id) => match self.tcx.map.get_if_local(impl_id) {
Some(NodeItem(item)) => {
@@ -323,12 +323,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
result.push_str(&rustc::hir::print::ty_to_string(&ty));

let trait_id = self.tcx.trait_id_of_impl(impl_id);
let mut decl_id = None;
if let Some(def_id) = trait_id {
result.push_str(" as ");
result.push_str(&self.tcx.item_path_str(def_id));
self.tcx.associated_items(def_id)
.find(|item| item.name == name)
.map(|item| decl_id = Some(item.def_id));
}
result.push_str(">");
(result, trait_id, From::from(&item.vis), docs_for_attrs(&item.attrs))

(result, trait_id, decl_id,
From::from(&item.vis),
docs_for_attrs(&item.attrs))
}
_ => {
span_bug!(span,
@@ -351,7 +358,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
match self.tcx.map.get_if_local(def_id) {
Some(NodeItem(item)) => {
(format!("::{}", self.tcx.item_path_str(def_id)),
Some(def_id),
Some(def_id), None,
From::from(&item.vis),
docs_for_attrs(&item.attrs))
}
@@ -373,15 +380,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {

let qualname = format!("{}::{}", qualname, name);

let def_id = self.tcx.map.local_def_id(id);
let decl_id = self.tcx.trait_item_of_item(def_id).and_then(|new_def_id| {
if new_def_id != def_id {
Some(new_def_id)
} else {
None
}
});

let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
filter!(self.span_utils, sub_span, span, None);
Some(FunctionData {
@@ -473,7 +471,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
ast::ExprKind::MethodCall(..) => {
let method_call = ty::MethodCall::expr(expr.id);
let method_id = self.tcx.tables().method_map[&method_call].def_id;
let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() {
let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
ty::ImplContainer(_) => (Some(method_id), None),
ty::TraitContainer(_) => (None, Some(method_id)),
};
@@ -535,21 +533,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
filter!(self.span_utils, sub_span, path.span, None);
let def_id = if decl_id.is_local() {
let ti = self.tcx.impl_or_trait_item(decl_id);
match ti.container() {
ty::TraitContainer(def_id) => {
self.tcx
.trait_items(def_id)
.iter()
.find(|mr| mr.name() == ti.name() && self.trait_method_has_body(mr))
.map(|mr| mr.def_id())
}
ty::ImplContainer(def_id) => {
Some(*self.tcx.impl_or_trait_items(def_id).iter().find(|&&mr| {
self.tcx.impl_or_trait_item(mr).name() == ti.name()
}).unwrap())
}
}
let ti = self.tcx.associated_item(decl_id);
self.tcx.associated_items(ti.container.id())
.find(|item| item.name == ti.name && item.has_value)
.map(|item| item.def_id)
} else {
None
};
@@ -582,20 +569,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
}
}

fn trait_method_has_body(&self, mr: &ty::ImplOrTraitItem) -> bool {
let def_id = mr.def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
let trait_item = self.tcx.map.expect_trait_item(node_id);
if let hir::TraitItem_::MethodTraitItem(_, Some(_)) = trait_item.node {
true
} else {
false
}
} else {
false
}
}

pub fn get_field_ref_data(&self,
field_ref: &ast::Field,
variant: ty::VariantDef,
21 changes: 8 additions & 13 deletions src/librustc_trans/collector.rs
Original file line number Diff line number Diff line change
@@ -844,17 +844,12 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
param_substs);

if let Some(trait_def_id) = scx.tcx().trait_of_item(fn_def_id) {
match scx.tcx().impl_or_trait_item(fn_def_id) {
ty::MethodTraitItem(ref method) => {
debug!(" => trait method, attempting to find impl");
do_static_trait_method_dispatch(scx,
method,
trait_def_id,
fn_substs,
param_substs)
}
_ => bug!()
}
debug!(" => trait method, attempting to find impl");
do_static_trait_method_dispatch(scx,
&scx.tcx().associated_item(fn_def_id),
trait_def_id,
fn_substs,
param_substs)
} else {
debug!(" => regular function");
// The function is not part of an impl or trait, no dispatching
@@ -866,7 +861,7 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
// Given a trait-method and substitution information, find out the actual
// implementation of the trait method.
fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
trait_method: &ty::Method,
trait_method: &ty::AssociatedItem,
trait_id: DefId,
callee_substs: &'tcx Substs<'tcx>,
param_substs: &'tcx Substs<'tcx>)
@@ -1187,7 +1182,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
continue;
}

if !method.generics.types.is_empty() {
if !tcx.lookup_generics(method.def_id).types.is_empty() {
continue;
}

9 changes: 2 additions & 7 deletions src/librustc_trans/mir/constant.rs
Original file line number Diff line number Diff line change
@@ -248,13 +248,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref);
if let traits::VtableImpl(vtable_impl) = vtable {
let name = ccx.tcx().item_name(instance.def);
let ac = ccx.tcx().impl_or_trait_items(vtable_impl.impl_def_id)
.iter().filter_map(|&def_id| {
match ccx.tcx().impl_or_trait_item(def_id) {
ty::ConstTraitItem(ac) => Some(ac),
_ => None
}
}).find(|ic| ic.name == name);
let ac = ccx.tcx().associated_items(vtable_impl.impl_def_id)
.find(|item| item.kind == ty::AssociatedKind::Const && item.name == name);
if let Some(ac) = ac {
instance = Instance::new(ac.def_id, vtable_impl.substs);
}
234 changes: 101 additions & 133 deletions src/librustc_typeck/astconv.rs

Large diffs are not rendered by default.

153 changes: 98 additions & 55 deletions src/librustc_typeck/check/compare_method.rs

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/librustc_typeck/check/dropck.rs
Original file line number Diff line number Diff line change
@@ -553,9 +553,9 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
// attributes attached to the impl's generics.
let dtor_method = adt_def.destructor()
.expect("dtorck type without destructor impossible");
let method = tcx.impl_or_trait_item(dtor_method);
let impl_id: DefId = method.container().id();
let revised_ty = revise_self_ty(tcx, adt_def, impl_id, substs);
let method = tcx.associated_item(dtor_method);
let impl_def_id = method.container.id();
let revised_ty = revise_self_ty(tcx, adt_def, impl_def_id, substs);
return DropckKind::RevisedSelf(revised_ty);
}
ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
90 changes: 34 additions & 56 deletions src/librustc_typeck/check/method/confirm.rs
Original file line number Diff line number Diff line change
@@ -37,16 +37,6 @@ impl<'a, 'gcx, 'tcx> Deref for ConfirmContext<'a, 'gcx, 'tcx> {
}
}

struct InstantiatedMethodSig<'tcx> {
/// Function signature of the method being invoked. The 0th
/// argument is the receiver.
method_sig: ty::FnSig<'tcx>,

/// Generic bounds on the method's parameters which must be added
/// as pending obligations.
method_predicates: ty::InstantiatedPredicates<'tcx>,
}

impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn confirm_method(&self,
span: Span,
@@ -98,31 +88,18 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
debug!("all_substs={:?}", all_substs);

// Create the final signature for the method, replacing late-bound regions.
let InstantiatedMethodSig { method_sig, method_predicates } =
self.instantiate_method_sig(&pick, all_substs);
let method_self_ty = method_sig.inputs[0];
let (method_ty, method_predicates) = self.instantiate_method_sig(&pick, all_substs);

// Unify the (adjusted) self type with what the method expects.
self.unify_receivers(self_ty, method_self_ty);

// Create the method type
let def_id = pick.item.def_id();
let method_ty = pick.item.as_opt_method().unwrap();
let fty = self.tcx.mk_fn_def(def_id,
all_substs,
self.tcx.mk_bare_fn(ty::BareFnTy {
sig: ty::Binder(method_sig),
unsafety: method_ty.fty.unsafety,
abi: method_ty.fty.abi.clone(),
}));
self.unify_receivers(self_ty, method_ty.fn_sig().input(0).skip_binder());

// Add any trait/regions obligations specified on the method's type parameters.
self.add_obligations(fty, all_substs, &method_predicates);
self.add_obligations(method_ty, all_substs, &method_predicates);

// Create the final `MethodCallee`.
let callee = ty::MethodCallee {
def_id: def_id,
ty: fty,
def_id: pick.item.def_id,
ty: method_ty,
substs: all_substs,
};

@@ -193,15 +170,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
-> &'tcx Substs<'tcx> {
match pick.kind {
probe::InherentImplPick => {
let impl_def_id = pick.item.container().id();
let impl_def_id = pick.item.container.id();
assert!(self.tcx.impl_trait_ref(impl_def_id).is_none(),
"impl {:?} is not an inherent impl",
impl_def_id);
self.impl_self_ty(self.span, impl_def_id).substs
}

probe::ObjectPick => {
let trait_def_id = pick.item.container().id();
let trait_def_id = pick.item.container.id();
self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
// The object data has no entry for the Self
// Type. For the purposes of this method call, we
@@ -244,7 +221,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
}

probe::TraitPick => {
let trait_def_id = pick.item.container().id();
let trait_def_id = pick.item.container.id();

// Make a trait reference `$0 : Trait<$1...$n>`
// consisting entirely of type variables. Later on in
@@ -299,8 +276,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// If they were not explicitly supplied, just construct fresh
// variables.
let num_supplied_types = supplied_method_types.len();
let method = pick.item.as_opt_method().unwrap();
let num_method_types = method.generics.types.len();
let method_generics = self.tcx.lookup_generics(pick.item.def_id);
let num_method_types = method_generics.types.len();

if num_supplied_types > 0 && num_supplied_types != num_method_types {
if num_method_types == 0 {
@@ -332,18 +309,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// parameters from the type and those from the method.
//
// FIXME -- permit users to manually specify lifetimes
let supplied_start = substs.params().len() + method.generics.regions.len();
Substs::for_item(self.tcx,
method.def_id,
|def, _| {
let supplied_start = substs.params().len() + method_generics.regions.len();
Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
let i = def.index as usize;
if i < substs.params().len() {
substs.region_at(i)
} else {
self.region_var_for_def(self.span, def)
}
},
|def, cur_substs| {
}, |def, cur_substs| {
let i = def.index as usize;
if i < substs.params().len() {
substs.type_at(i)
@@ -376,44 +350,48 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
fn instantiate_method_sig(&mut self,
pick: &probe::Pick<'tcx>,
all_substs: &'tcx Substs<'tcx>)
-> InstantiatedMethodSig<'tcx> {
-> (Ty<'tcx>, ty::InstantiatedPredicates<'tcx>) {
debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
pick,
all_substs);

// Instantiate the bounds on the method with the
// type/early-bound-regions substitutions performed. There can
// be no late-bound regions appearing here.
let method_predicates = pick.item
.as_opt_method()
.unwrap()
.predicates
.instantiate(self.tcx, all_substs);
let method_predicates = self.normalize_associated_types_in(self.span, &method_predicates);
let def_id = pick.item.def_id;
let method_predicates = self.tcx.lookup_predicates(def_id)
.instantiate(self.tcx, all_substs);
let method_predicates = self.normalize_associated_types_in(self.span,
&method_predicates);

debug!("method_predicates after subst = {:?}", method_predicates);

let fty = match self.tcx.lookup_item_type(def_id).ty.sty {
ty::TyFnDef(_, _, f) => f,
_ => bug!()
};

// Instantiate late-bound regions and substitute the trait
// parameters into the method type to get the actual method type.
//
// NB: Instantiate late-bound regions first so that
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.item
.as_opt_method()
.unwrap()
.fty
.sig);
let method_sig = self.replace_late_bound_regions_with_fresh_var(&fty.sig);
debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
method_sig);

let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig);
debug!("type scheme substituted, method_sig={:?}", method_sig);

InstantiatedMethodSig {
method_sig: method_sig,
method_predicates: method_predicates,
}
let method_ty = self.tcx.mk_fn_def(def_id, all_substs,
self.tcx.mk_bare_fn(ty::BareFnTy {
sig: ty::Binder(method_sig),
unsafety: fty.unsafety,
abi: fty.abi,
}));

(method_ty, method_predicates)
}

fn add_obligations(&mut self,
@@ -587,7 +565,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {

fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) {
// Disallow calls to the method `drop` defined in the `Drop` trait.
match pick.item.container() {
match pick.item.container {
ty::TraitContainer(trait_def_id) => {
callee::check_legal_trait_for_method_call(self.ccx, self.span, trait_def_id)
}
142 changes: 58 additions & 84 deletions src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
@@ -228,37 +228,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Trait must have a method named `m_name` and it should not have
// type parameters or early-bound regions.
let tcx = self.tcx;
let method_item = self.impl_or_trait_item(trait_def_id, m_name).unwrap();
let method_ty = method_item.as_opt_method().unwrap();
assert_eq!(method_ty.generics.types.len(), 0);
assert_eq!(method_ty.generics.regions.len(), 0);
let method_item = self.associated_item(trait_def_id, m_name).unwrap();
let def_id = method_item.def_id;
let generics = tcx.lookup_generics(def_id);
assert_eq!(generics.types.len(), 0);
assert_eq!(generics.regions.len(), 0);

debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
method_item,
method_ty);
debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);

// Instantiate late-bound regions and substitute the trait
// parameters into the method type to get the actual method type.
//
// NB: Instantiate late-bound regions first so that
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
let fn_sig =
self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &method_ty.fty.sig)
.0;
let original_method_ty = tcx.lookup_item_type(def_id).ty;
let fty = match original_method_ty.sty {
ty::TyFnDef(_, _, f) => f,
_ => bug!()
};
let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
infer::FnCall,
&fty.sig).0;
let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
let transformed_self_ty = fn_sig.inputs[0];
let def_id = method_item.def_id();
let fty = tcx.mk_fn_def(def_id,
trait_ref.substs,
tcx.mk_bare_fn(ty::BareFnTy {
sig: ty::Binder(fn_sig),
unsafety: method_ty.fty.unsafety,
abi: method_ty.fty.abi.clone(),
}));

debug!("lookup_in_trait_adjusted: matched method fty={:?} obligation={:?}",
fty,
let method_ty = tcx.mk_fn_def(def_id, trait_ref.substs,
tcx.mk_bare_fn(ty::BareFnTy {
sig: ty::Binder(fn_sig),
unsafety: fty.unsafety,
abi: fty.abi
}));

debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
method_ty,
obligation);

// Register obligations for the parameters. This will include the
@@ -269,75 +271,53 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
//
// Note that as the method comes from a trait, it should not have
// any late-bound regions appearing in its bounds.
let method_bounds = self.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates);
let method_bounds = self.instantiate_bounds(span, def_id, trait_ref.substs);
assert!(!method_bounds.has_escaping_regions());
self.add_obligations_for_parameters(traits::ObligationCause::misc(span, self.body_id),
&method_bounds);

// Also register an obligation for the method type being well-formed.
self.register_wf_obligation(fty, span, traits::MiscObligation);
self.register_wf_obligation(method_ty, span, traits::MiscObligation);

// FIXME(#18653) -- Try to resolve obligations, giving us more
// typing information, which can sometimes be needed to avoid
// pathological region inference failures.
self.select_obligations_where_possible();

// Insert any adjustments needed (always an autoref of some mutability).
match self_expr {
None => {}

Some(self_expr) => {
debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
(self-id={}, autoderefs={}, unsize={}, explicit_self={:?})",
self_expr.id,
autoderefs,
unsize,
method_ty.explicit_self);

let autoref = match method_ty.explicit_self {
ty::ExplicitSelfCategory::ByValue => {
// Trait method is fn(self), no transformation needed.
assert!(!unsize);
None
}

ty::ExplicitSelfCategory::ByReference(..) => {
// Trait method is fn(&self) or fn(&mut self), need an
// autoref. Pull the region etc out of the type of first argument.
match transformed_self_ty.sty {
ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => {
Some(AutoBorrow::Ref(region, mutbl))
}

_ => {
span_bug!(span,
"trait method is &self but first arg is: {}",
transformed_self_ty);
}
}
}

_ => {
span_bug!(span,
"unexpected explicit self type in operator method: {:?}",
method_ty.explicit_self);
}
};

self.write_adjustment(self_expr.id, Adjustment {
kind: Adjust::DerefRef {
autoderefs: autoderefs,
autoref: autoref,
unsize: unsize
},
target: transformed_self_ty
});
}
if let Some(self_expr) = self_expr {
debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
(self-id={}, autoderefs={}, unsize={}, fty={:?})",
self_expr.id, autoderefs, unsize, original_method_ty);

let original_sig = original_method_ty.fn_sig();
let autoref = match (&original_sig.input(0).skip_binder().sty,
&transformed_self_ty.sty) {
(&ty::TyRef(..), &ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ })) => {
// Trait method is fn(&self) or fn(&mut self), need an
// autoref. Pull the region etc out of the type of first argument.
Some(AutoBorrow::Ref(region, mutbl))
}
_ => {
// Trait method is fn(self), no transformation needed.
assert!(!unsize);
None
}
};

self.write_adjustment(self_expr.id, Adjustment {
kind: Adjust::DerefRef {
autoderefs: autoderefs,
autoref: autoref,
unsize: unsize
},
target: transformed_self_ty
});
}

let callee = ty::MethodCallee {
def_id: def_id,
ty: fty,
ty: method_ty,
substs: trait_ref.substs,
};

@@ -361,7 +341,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

let def = pick.item.def();
if let probe::InherentImplPick = pick.kind {
if !pick.item.vis().is_accessible_from(self.body_id, &self.tcx.map) {
if !pick.item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
let msg = format!("{} `{}` is private", def.kind_name(), &method_name.as_str());
self.tcx.sess.span_err(span, &msg);
}
@@ -371,14 +351,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

/// Find item with name `item_name` defined in impl/trait `def_id`
/// and return it, or `None`, if no such item was defined there.
pub fn impl_or_trait_item(&self,
def_id: DefId,
item_name: ast::Name)
-> Option<ty::ImplOrTraitItem<'tcx>> {
self.tcx
.impl_or_trait_items(def_id)
.iter()
.map(|&did| self.tcx.impl_or_trait_item(did))
.find(|m| m.name() == item_name)
pub fn associated_item(&self, def_id: DefId, item_name: ast::Name)
-> Option<ty::AssociatedItem> {
self.tcx.associated_items(def_id).find(|item| item.name == item_name)
}
}
109 changes: 40 additions & 69 deletions src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ struct CandidateStep<'tcx> {
#[derive(Debug)]
struct Candidate<'tcx> {
xform_self_ty: Ty<'tcx>,
item: ty::ImplOrTraitItem<'tcx>,
item: ty::AssociatedItem,
kind: CandidateKind<'tcx>,
import_id: Option<ast::NodeId>,
}
@@ -95,7 +95,7 @@ enum CandidateKind<'tcx> {

#[derive(Debug)]
pub struct Pick<'tcx> {
pub item: ty::ImplOrTraitItem<'tcx>,
pub item: ty::AssociatedItem,
pub kind: PickKind<'tcx>,
pub import_id: Option<ast::NodeId>,

@@ -384,8 +384,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<DefId>) {
if let Some(impl_def_id) = lang_def_id {
self.tcx.populate_implementations_for_primitive_if_necessary(impl_def_id);

self.assemble_inherent_impl_probe(impl_def_id);
}
}
@@ -409,7 +407,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

debug!("assemble_inherent_impl_probe {:?}", impl_def_id);

let item = match self.impl_or_trait_item(impl_def_id) {
let item = match self.associated_item(impl_def_id) {
Some(m) => m,
None => {
return;
@@ -421,7 +419,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
return self.record_static_candidate(ImplSource(impl_def_id));
}

if !item.vis().is_accessible_from(self.body_id, &self.tcx.map) {
if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
self.private_candidate = Some(item.def());
return;
}
@@ -512,17 +510,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

let xform_self_ty = this.xform_self_ty(&item, trait_ref.self_ty(), trait_ref.substs);

if let Some(ref m) = item.as_opt_method() {
debug!("found match: trait_ref={:?} substs={:?} m={:?}",
trait_ref,
trait_ref.substs,
m);
assert_eq!(m.generics.parent_types as usize,
trait_ref.substs.types().count());
assert_eq!(m.generics.parent_regions as usize,
trait_ref.substs.regions().count());
}

// Because this trait derives from a where-clause, it
// should not contain any inference variables or other
// artifacts. This means it is safe to put into the
@@ -544,13 +531,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
fn elaborate_bounds<F>(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F)
where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>,
ty::PolyTraitRef<'tcx>,
ty::ImplOrTraitItem<'tcx>)
ty::AssociatedItem)
{
debug!("elaborate_bounds(bounds={:?})", bounds);

let tcx = self.tcx;
for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) {
let item = match self.associated_item(bound_trait_ref.def_id()) {
Some(v) => v,
None => {
continue;
@@ -601,9 +588,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
trait_def_id);

// Check whether `trait_def_id` defines a method with suitable name:
let trait_items = self.tcx.trait_items(trait_def_id);
let maybe_item = trait_items.iter()
.find(|item| item.name() == self.item_name);
let maybe_item = self.tcx.associated_items(trait_def_id)
.find(|item| item.name == self.item_name);
let item = match maybe_item {
Some(i) => i,
None => {
@@ -612,7 +598,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
};

// Check whether `trait_def_id` defines a method with suitable name:
if !self.has_applicable_self(item) {
if !self.has_applicable_self(&item) {
debug!("method has inapplicable self");
self.record_static_candidate(TraitSource(trait_def_id));
return Ok(());
@@ -631,7 +617,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

fn assemble_extension_candidates_for_trait_impls(&mut self,
trait_def_id: DefId,
item: ty::ImplOrTraitItem<'tcx>) {
item: ty::AssociatedItem) {
let trait_def = self.tcx.lookup_trait_def(trait_def_id);

// FIXME(arielb1): can we use for_each_relevant_impl here?
@@ -700,7 +686,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

fn assemble_closure_candidates(&mut self,
trait_def_id: DefId,
item: ty::ImplOrTraitItem<'tcx>)
item: ty::AssociatedItem)
-> Result<(), MethodError<'tcx>> {
// Check if this is one of the Fn,FnMut,FnOnce traits.
let tcx = self.tcx;
@@ -765,7 +751,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

fn assemble_projection_candidates(&mut self,
trait_def_id: DefId,
item: ty::ImplOrTraitItem<'tcx>) {
item: ty::AssociatedItem) {
debug!("assemble_projection_candidates(\
trait_def_id={:?}, \
item={:?})",
@@ -820,7 +806,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

fn assemble_where_clause_candidates(&mut self,
trait_def_id: DefId,
item: ty::ImplOrTraitItem<'tcx>) {
item: ty::AssociatedItem) {
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
trait_def_id);

@@ -865,7 +851,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
self.assemble_extension_candidates_for_all_traits()?;

let out_of_scope_traits = match self.pick_core() {
Some(Ok(p)) => vec![p.item.container().id()],
Some(Ok(p)) => vec![p.item.container.id()],
Some(Err(MethodError::Ambiguity(v))) => {
v.into_iter()
.map(|source| {
@@ -1065,7 +1051,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
// don't have enough information to fully evaluate).
let (impl_def_id, substs, ref_obligations) = match probe.kind {
InherentImplCandidate(ref substs, ref ref_obligations) => {
(probe.item.container().id(), substs, ref_obligations)
(probe.item.container.id(), substs, ref_obligations)
}

ExtensionImplCandidate(impl_def_id, ref substs, ref ref_obligations) => {
@@ -1128,12 +1114,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
/// use, so it's ok to just commit to "using the method from the trait Foo".
fn collapse_candidates_to_trait_pick(&self, probes: &[&Candidate<'tcx>]) -> Option<Pick<'tcx>> {
// Do all probes correspond to the same trait?
let container = probes[0].item.container();
let container = probes[0].item.container;
match container {
ty::TraitContainer(_) => {}
ty::ImplContainer(_) => return None,
}
if probes[1..].iter().any(|p| p.item.container() != container) {
if probes[1..].iter().any(|p| p.item.container != container) {
return None;
}

@@ -1150,19 +1136,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

///////////////////////////////////////////////////////////////////////////
// MISCELLANY
fn has_applicable_self(&self, item: &ty::ImplOrTraitItem) -> bool {
fn has_applicable_self(&self, item: &ty::AssociatedItem) -> bool {
// "fast track" -- check for usage of sugar
match *item {
ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
match method.explicit_self {
ty::ExplicitSelfCategory::Static => self.mode == Mode::Path,
ty::ExplicitSelfCategory::ByValue |
ty::ExplicitSelfCategory::ByReference(..) |
ty::ExplicitSelfCategory::ByBox => true,
}
}
ty::ImplOrTraitItem::ConstTraitItem(..) => self.mode == Mode::Path,
_ => false,
match self.mode {
Mode::MethodCall => item.method_has_self_argument,
Mode::Path => true
}
// FIXME -- check for types that deref to `Self`,
// like `Rc<Self>` and so on.
@@ -1177,24 +1155,26 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
}

fn xform_self_ty(&self,
item: &ty::ImplOrTraitItem<'tcx>,
item: &ty::AssociatedItem,
impl_ty: Ty<'tcx>,
substs: &Substs<'tcx>)
-> Ty<'tcx> {
match item.as_opt_method() {
Some(ref method) => self.xform_method_self_ty(method, impl_ty, substs),
None => impl_ty,
if item.kind == ty::AssociatedKind::Method && self.mode == Mode::MethodCall {
self.xform_method_self_ty(item.def_id, impl_ty, substs)
} else {
impl_ty
}
}

fn xform_method_self_ty(&self,
method: &Rc<ty::Method<'tcx>>,
method: DefId,
impl_ty: Ty<'tcx>,
substs: &Substs<'tcx>)
-> Ty<'tcx> {
let self_ty = self.tcx.lookup_item_type(method).ty.fn_sig().input(0);
debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
impl_ty,
method.fty.sig.0.inputs.get(0),
self_ty,
substs);

assert!(!substs.has_escaping_regions());
@@ -1204,26 +1184,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
// are given do not include type/lifetime parameters for the
// method yet. So create fresh variables here for those too,
// if there are any.
assert_eq!(substs.types().count(),
method.generics.parent_types as usize);
assert_eq!(substs.regions().count(),
method.generics.parent_regions as usize);

if self.mode == Mode::Path {
return impl_ty;
}
let generics = self.tcx.lookup_generics(method);
assert_eq!(substs.types().count(), generics.parent_types as usize);
assert_eq!(substs.regions().count(), generics.parent_regions as usize);

// Erase any late-bound regions from the method and substitute
// in the values from the substitution.
let xform_self_ty = method.fty.sig.input(0);
let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty);
let xform_self_ty = self.erase_late_bound_regions(&self_ty);

if method.generics.types.is_empty() && method.generics.regions.is_empty() {
if generics.types.is_empty() && generics.regions.is_empty() {
xform_self_ty.subst(self.tcx, substs)
} else {
let substs = Substs::for_item(self.tcx,
method.def_id,
|def, _| {
let substs = Substs::for_item(self.tcx, method, |def, _| {
let i = def.index as usize;
if i < substs.params().len() {
substs.region_at(i)
@@ -1232,8 +1204,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
// `impl_self_ty()` for an explanation.
self.tcx.mk_region(ty::ReErased)
}
},
|def, cur_substs| {
}, |def, cur_substs| {
let i = def.index as usize;
if i < substs.params().len() {
substs.type_at(i)
@@ -1283,8 +1254,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

/// Find item with name `item_name` defined in impl/trait `def_id`
/// and return it, or `None`, if no such item was defined there.
fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::ImplOrTraitItem<'tcx>> {
self.fcx.impl_or_trait_item(def_id, self.item_name)
fn associated_item(&self, def_id: DefId) -> Option<ty::AssociatedItem> {
self.fcx.associated_item(def_id, self.item_name)
}
}

@@ -1317,11 +1288,11 @@ impl<'tcx> Candidate<'tcx> {

fn to_source(&self) -> CandidateSource {
match self.kind {
InherentImplCandidate(..) => ImplSource(self.item.container().id()),
InherentImplCandidate(..) => ImplSource(self.item.container.id()),
ExtensionImplCandidate(def_id, ..) => ImplSource(def_id),
ObjectCandidate |
TraitCandidate |
WhereClauseCandidate(_) => TraitSource(self.item.container().id()),
WhereClauseCandidate(_) => TraitSource(self.item.container.id()),
}
}
}
31 changes: 14 additions & 17 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
@@ -89,20 +89,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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 nothing.
let item = self.impl_or_trait_item(impl_did, item_name)
let item = self.associated_item(impl_did, item_name)
.or_else(|| {
self.impl_or_trait_item(self.tcx
.impl_trait_ref(impl_did)
.unwrap()
.def_id,

item_name)
})
.unwrap();
let note_span = self.tcx
.map
.span_if_local(item.def_id())
.or_else(|| self.tcx.map.span_if_local(impl_did));
self.associated_item(
self.tcx.impl_trait_ref(impl_did).unwrap().def_id,

item_name
)
}).unwrap();
let note_span = self.tcx.map.span_if_local(item.def_id).or_else(|| {
self.tcx.map.span_if_local(impl_did)
});

let impl_ty = self.impl_self_ty(span, impl_did).ty;

@@ -127,8 +124,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}
CandidateSource::TraitSource(trait_did) => {
let item = self.impl_or_trait_item(trait_did, item_name).unwrap();
let item_span = self.tcx.map.def_id_span(item.def_id(), span);
let item = self.associated_item(trait_did, item_name).unwrap();
let item_span = self.tcx.map.def_id_span(item.def_id, span);
span_note!(err,
item_span,
"candidate #{} is defined in the trait `{}`",
@@ -334,8 +331,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// this isn't perfect (that is, there are cases when
// implementing a trait would be legal but is rejected
// here).
(type_is_local || info.def_id.is_local()) &&
self.impl_or_trait_item(info.def_id, item_name).is_some()
(type_is_local || info.def_id.is_local())
&& self.associated_item(info.def_id, item_name).is_some()
})
.collect::<Vec<_>>();

Loading