rustc: unify and simplify managing associated items.
This commit is contained in:
parent
da2ce22768
commit
de0ffadb67
45 changed files with 1035 additions and 1687 deletions
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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") }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,7 +92,7 @@ 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))
|
||||
|
|
@ -101,21 +100,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, || {
|
||||
|
|
|
|||
|
|
@ -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>> }
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@
|
|||
|
||||
pub use self::Variance::*;
|
||||
pub use self::DtorKind::*;
|
||||
pub use self::ImplOrTraitItemContainer::*;
|
||||
pub use self::AssociatedItemContainer::*;
|
||||
pub use self::BorrowKind::*;
|
||||
pub use self::ImplOrTraitItem::*;
|
||||
pub use self::IntVarValue::*;
|
||||
pub use self::LvaluePreference::*;
|
||||
pub use self::fold::TypeFoldable;
|
||||
|
|
@ -135,12 +134,12 @@ impl DtorKind {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum ImplOrTraitItemContainer {
|
||||
pub enum AssociatedItemContainer {
|
||||
TraitContainer(DefId),
|
||||
ImplContainer(DefId),
|
||||
}
|
||||
|
||||
impl ImplOrTraitItemContainer {
|
||||
impl AssociatedItemContainer {
|
||||
pub fn id(&self) -> DefId {
|
||||
match *self {
|
||||
TraitContainer(id) => id,
|
||||
|
|
@ -183,58 +182,34 @@ impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum ImplOrTraitItem<'tcx> {
|
||||
ConstTraitItem(Rc<AssociatedConst<'tcx>>),
|
||||
MethodTraitItem(Rc<Method<'tcx>>),
|
||||
TypeTraitItem(Rc<AssociatedType<'tcx>>),
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct AssociatedItem {
|
||||
pub def_id: DefId,
|
||||
pub name: Name,
|
||||
pub kind: AssociatedKind,
|
||||
pub vis: Visibility,
|
||||
pub defaultness: hir::Defaultness,
|
||||
pub has_value: bool,
|
||||
pub container: AssociatedItemContainer,
|
||||
|
||||
/// Whether this is a method with an explicit self
|
||||
/// as its first argument, allowing method calls.
|
||||
pub method_has_self_argument: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> ImplOrTraitItem<'tcx> {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum AssociatedKind {
|
||||
Const,
|
||||
Method,
|
||||
Type
|
||||
}
|
||||
|
||||
impl AssociatedItem {
|
||||
pub fn def(&self) -> Def {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => Def::AssociatedConst(associated_const.def_id),
|
||||
MethodTraitItem(ref method) => Def::Method(method.def_id),
|
||||
TypeTraitItem(ref ty) => Def::AssociatedTy(ty.def_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_id(&self) -> DefId {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => associated_const.def_id,
|
||||
MethodTraitItem(ref method) => method.def_id,
|
||||
TypeTraitItem(ref associated_type) => associated_type.def_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Name {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => associated_const.name,
|
||||
MethodTraitItem(ref method) => method.name,
|
||||
TypeTraitItem(ref associated_type) => associated_type.name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vis(&self) -> Visibility {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => associated_const.vis,
|
||||
MethodTraitItem(ref method) => method.vis,
|
||||
TypeTraitItem(ref associated_type) => associated_type.vis,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn container(&self) -> ImplOrTraitItemContainer {
|
||||
match *self {
|
||||
ConstTraitItem(ref associated_const) => associated_const.container,
|
||||
MethodTraitItem(ref method) => method.container,
|
||||
TypeTraitItem(ref associated_type) => associated_type.container,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
|
||||
match *self {
|
||||
MethodTraitItem(ref m) => Some((*m).clone()),
|
||||
_ => None,
|
||||
match self.kind {
|
||||
AssociatedKind::Const => Def::AssociatedConst(self.def_id),
|
||||
AssociatedKind::Method => Def::Method(self.def_id),
|
||||
AssociatedKind::Type => Def::AssociatedTy(self.def_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -308,64 +283,6 @@ impl Visibility {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Method<'tcx> {
|
||||
pub name: Name,
|
||||
pub generics: &'tcx Generics<'tcx>,
|
||||
pub predicates: GenericPredicates<'tcx>,
|
||||
pub fty: &'tcx BareFnTy<'tcx>,
|
||||
pub explicit_self: ExplicitSelfCategory<'tcx>,
|
||||
pub vis: Visibility,
|
||||
pub defaultness: hir::Defaultness,
|
||||
pub has_body: bool,
|
||||
pub def_id: DefId,
|
||||
pub container: ImplOrTraitItemContainer,
|
||||
}
|
||||
|
||||
impl<'tcx> Method<'tcx> {
|
||||
pub fn container_id(&self) -> DefId {
|
||||
match self.container {
|
||||
TraitContainer(id) => id,
|
||||
ImplContainer(id) => id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PartialEq for Method<'tcx> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool { self.def_id == other.def_id }
|
||||
}
|
||||
|
||||
impl<'tcx> Eq for Method<'tcx> {}
|
||||
|
||||
impl<'tcx> Hash for Method<'tcx> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
self.def_id.hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct AssociatedConst<'tcx> {
|
||||
pub name: Name,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub vis: Visibility,
|
||||
pub defaultness: hir::Defaultness,
|
||||
pub def_id: DefId,
|
||||
pub container: ImplOrTraitItemContainer,
|
||||
pub has_value: bool
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct AssociatedType<'tcx> {
|
||||
pub name: Name,
|
||||
pub ty: Option<Ty<'tcx>>,
|
||||
pub vis: Visibility,
|
||||
pub defaultness: hir::Defaultness,
|
||||
pub def_id: DefId,
|
||||
pub container: ImplOrTraitItemContainer,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
|
||||
pub enum Variance {
|
||||
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
|
||||
|
|
@ -1288,19 +1205,10 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
|
|||
tcx.region_maps.item_extent(id))
|
||||
}
|
||||
hir::ImplItemKind::Method(_, ref body) => {
|
||||
let method_def_id = tcx.map.local_def_id(id);
|
||||
match tcx.impl_or_trait_item(method_def_id) {
|
||||
MethodTraitItem(ref method_ty) => {
|
||||
tcx.construct_parameter_environment(
|
||||
impl_item.span,
|
||||
method_ty.def_id,
|
||||
tcx.region_maps.call_site_extent(id, body.id))
|
||||
}
|
||||
_ => {
|
||||
bug!("ParameterEnvironment::for_item(): \
|
||||
got non-method item from impl method?!")
|
||||
}
|
||||
}
|
||||
tcx.construct_parameter_environment(
|
||||
impl_item.span,
|
||||
tcx.map.local_def_id(id),
|
||||
tcx.region_maps.call_site_extent(id, body.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1319,27 +1227,17 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
|
|||
// Use call-site for extent (unless this is a
|
||||
// trait method with no default; then fallback
|
||||
// to the method id).
|
||||
let method_def_id = tcx.map.local_def_id(id);
|
||||
match tcx.impl_or_trait_item(method_def_id) {
|
||||
MethodTraitItem(ref method_ty) => {
|
||||
let extent = if let Some(ref body) = *body {
|
||||
// default impl: use call_site extent as free_id_outlive bound.
|
||||
tcx.region_maps.call_site_extent(id, body.id)
|
||||
} else {
|
||||
// no default impl: use item extent as free_id_outlive bound.
|
||||
tcx.region_maps.item_extent(id)
|
||||
};
|
||||
tcx.construct_parameter_environment(
|
||||
trait_item.span,
|
||||
method_ty.def_id,
|
||||
extent)
|
||||
}
|
||||
_ => {
|
||||
bug!("ParameterEnvironment::for_item(): \
|
||||
got non-method item from provided \
|
||||
method?!")
|
||||
}
|
||||
}
|
||||
let extent = if let Some(ref body) = *body {
|
||||
// default impl: use call_site extent as free_id_outlive bound.
|
||||
tcx.region_maps.call_site_extent(id, body.id)
|
||||
} else {
|
||||
// no default impl: use item extent as free_id_outlive bound.
|
||||
tcx.region_maps.item_extent(id)
|
||||
};
|
||||
tcx.construct_parameter_environment(
|
||||
trait_item.span,
|
||||
tcx.map.local_def_id(id),
|
||||
extent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2065,7 +1963,7 @@ impl LvaluePreference {
|
|||
}
|
||||
|
||||
/// Helper for looking things up in the various maps that are populated during
|
||||
/// typeck::collect (e.g., `tcx.impl_or_trait_items`, `tcx.tcache`, etc). All of
|
||||
/// typeck::collect (e.g., `tcx.associated_items`, `tcx.tcache`, etc). All of
|
||||
/// these share the pattern that if the id is local, it should have been loaded
|
||||
/// into the map by the `typeck::collect` phase. If the def-id is external,
|
||||
/// then we have to go consult the crate loading code (and cache the result for
|
||||
|
|
@ -2204,13 +2102,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn provided_trait_methods(self, id: DefId) -> Vec<Rc<Method<'gcx>>> {
|
||||
self.impl_or_trait_items(id).iter().filter_map(|&def_id| {
|
||||
match self.impl_or_trait_item(def_id) {
|
||||
MethodTraitItem(ref m) if m.has_body => Some(m.clone()),
|
||||
_ => None
|
||||
}
|
||||
}).collect()
|
||||
pub fn provided_trait_methods(self, id: DefId) -> Vec<AssociatedItem> {
|
||||
self.associated_items(id)
|
||||
.filter(|item| item.kind == AssociatedKind::Method && item.has_value)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
|
||||
|
|
@ -2243,17 +2138,105 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn impl_or_trait_item(self, id: DefId) -> ImplOrTraitItem<'gcx> {
|
||||
lookup_locally_or_in_crate_store(
|
||||
"impl_or_trait_items", id, &self.impl_or_trait_items,
|
||||
|| self.sess.cstore.impl_or_trait_item(self.global_tcx(), id)
|
||||
.expect("missing ImplOrTraitItem in metadata"))
|
||||
pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
|
||||
self.associated_items.memoize(def_id, || {
|
||||
if !def_id.is_local() {
|
||||
return self.sess.cstore.associated_item(self.global_tcx(), def_id)
|
||||
.expect("missing AssociatedItem in metadata");
|
||||
}
|
||||
|
||||
let id = self.map.as_local_node_id(def_id).unwrap();
|
||||
let parent_id = self.map.get_parent(id);
|
||||
let parent_def_id = self.map.local_def_id(parent_id);
|
||||
match self.map.get(id) {
|
||||
ast_map::NodeTraitItem(trait_item) => {
|
||||
let (kind, has_self, has_value) = match trait_item.node {
|
||||
hir::MethodTraitItem(ref sig, ref body) => {
|
||||
(AssociatedKind::Method, sig.decl.get_self().is_some(),
|
||||
body.is_some())
|
||||
}
|
||||
hir::ConstTraitItem(_, ref value) => {
|
||||
(AssociatedKind::Const, false, value.is_some())
|
||||
}
|
||||
hir::TypeTraitItem(_, ref ty) => {
|
||||
(AssociatedKind::Type, false, ty.is_some())
|
||||
}
|
||||
};
|
||||
|
||||
AssociatedItem {
|
||||
name: trait_item.name,
|
||||
kind: kind,
|
||||
vis: Visibility::from_hir(&hir::Inherited, id, self),
|
||||
defaultness: hir::Defaultness::Default,
|
||||
has_value: has_value,
|
||||
def_id: def_id,
|
||||
container: TraitContainer(parent_def_id),
|
||||
method_has_self_argument: has_self
|
||||
}
|
||||
}
|
||||
ast_map::NodeImplItem(impl_item) => {
|
||||
let (kind, has_self) = match impl_item.node {
|
||||
hir::ImplItemKind::Method(ref sig, _) => {
|
||||
(AssociatedKind::Method, sig.decl.get_self().is_some())
|
||||
}
|
||||
hir::ImplItemKind::Const(..) => (AssociatedKind::Const, false),
|
||||
hir::ImplItemKind::Type(..) => (AssociatedKind::Type, false)
|
||||
};
|
||||
|
||||
// Trait impl items are always public.
|
||||
let public = hir::Public;
|
||||
let parent_item = self.map.expect_item(parent_id);
|
||||
let vis = if let hir::ItemImpl(.., Some(_), _, _) = parent_item.node {
|
||||
&public
|
||||
} else {
|
||||
&impl_item.vis
|
||||
};
|
||||
|
||||
AssociatedItem {
|
||||
name: impl_item.name,
|
||||
kind: kind,
|
||||
vis: Visibility::from_hir(vis, id, self),
|
||||
defaultness: impl_item.defaultness,
|
||||
has_value: true,
|
||||
def_id: def_id,
|
||||
container: ImplContainer(parent_def_id),
|
||||
method_has_self_argument: has_self
|
||||
}
|
||||
}
|
||||
item => bug!("associated_item: {:?} not an associated item", item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn impl_or_trait_items(self, id: DefId) -> Rc<Vec<DefId>> {
|
||||
lookup_locally_or_in_crate_store(
|
||||
"impl_or_trait_items", id, &self.impl_or_trait_item_def_ids,
|
||||
|| Rc::new(self.sess.cstore.impl_or_trait_items(id)))
|
||||
pub fn associated_item_def_ids(self, def_id: DefId) -> Rc<Vec<DefId>> {
|
||||
self.associated_item_def_ids.memoize(def_id, || {
|
||||
if !def_id.is_local() {
|
||||
return Rc::new(self.sess.cstore.associated_item_def_ids(def_id));
|
||||
}
|
||||
|
||||
let id = self.map.as_local_node_id(def_id).unwrap();
|
||||
let item = self.map.expect_item(id);
|
||||
match item.node {
|
||||
hir::ItemTrait(.., ref trait_items) => {
|
||||
Rc::new(trait_items.iter().map(|trait_item| {
|
||||
self.map.local_def_id(trait_item.id)
|
||||
}).collect())
|
||||
}
|
||||
hir::ItemImpl(.., ref impl_items) => {
|
||||
Rc::new(impl_items.iter().map(|impl_item| {
|
||||
self.map.local_def_id(impl_item.id)
|
||||
}).collect())
|
||||
}
|
||||
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
|
||||
pub fn associated_items(self, def_id: DefId)
|
||||
-> impl Iterator<Item = ty::AssociatedItem> + 'a {
|
||||
let def_ids = self.associated_item_def_ids(def_id);
|
||||
(0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))
|
||||
}
|
||||
|
||||
/// Returns the trait-ref corresponding to a given impl, or None if it is
|
||||
|
|
@ -2539,31 +2522,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL)
|
||||
}
|
||||
|
||||
/// Load primitive inherent implementations if necessary
|
||||
pub fn populate_implementations_for_primitive_if_necessary(self,
|
||||
primitive_def_id: DefId) {
|
||||
if primitive_def_id.is_local() {
|
||||
return
|
||||
}
|
||||
|
||||
// The primitive is not local, hence we are reading this out
|
||||
// of metadata.
|
||||
let _ignore = self.dep_graph.in_ignore();
|
||||
|
||||
if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) {
|
||||
return
|
||||
}
|
||||
|
||||
debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}",
|
||||
primitive_def_id);
|
||||
|
||||
let impl_items = self.sess.cstore.impl_or_trait_items(primitive_def_id);
|
||||
|
||||
// Store the implementation info.
|
||||
self.impl_or_trait_item_def_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items));
|
||||
self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
|
||||
}
|
||||
|
||||
/// Populates the type context with all the inherent implementations for
|
||||
/// the given type if necessary.
|
||||
pub fn populate_inherent_implementations_for_type_if_necessary(self,
|
||||
|
|
@ -2584,11 +2542,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
type_id);
|
||||
|
||||
let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);
|
||||
for &impl_def_id in &inherent_impls {
|
||||
// Store the implementation info.
|
||||
let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
|
||||
self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
|
||||
}
|
||||
|
||||
self.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
|
||||
self.populated_external_types.borrow_mut().insert(type_id);
|
||||
|
|
@ -2617,23 +2570,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) {
|
||||
let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
|
||||
let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
|
||||
|
||||
// Record the trait->implementation mapping.
|
||||
let parent = self.sess.cstore.impl_parent(impl_def_id).unwrap_or(trait_id);
|
||||
def.record_remote_impl(self, impl_def_id, trait_ref, parent);
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
// the map. This is a bit unfortunate.
|
||||
for &impl_item_def_id in &impl_items {
|
||||
// load impl items eagerly for convenience
|
||||
// FIXME: we may want to load these lazily
|
||||
self.impl_or_trait_item(impl_item_def_id);
|
||||
}
|
||||
|
||||
// Store the implementation info.
|
||||
self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
|
||||
}
|
||||
|
||||
def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
|
||||
|
|
@ -2679,17 +2620,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
/// ID of the impl that the method belongs to. Otherwise, return `None`.
|
||||
pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
|
||||
if def_id.krate != LOCAL_CRATE {
|
||||
return self.sess.cstore.impl_or_trait_item(self.global_tcx(), def_id)
|
||||
return self.sess.cstore.associated_item(self.global_tcx(), def_id)
|
||||
.and_then(|item| {
|
||||
match item.container() {
|
||||
match item.container {
|
||||
TraitContainer(_) => None,
|
||||
ImplContainer(def_id) => Some(def_id),
|
||||
}
|
||||
});
|
||||
}
|
||||
match self.impl_or_trait_items.borrow().get(&def_id).cloned() {
|
||||
match self.associated_items.borrow().get(&def_id).cloned() {
|
||||
Some(trait_item) => {
|
||||
match trait_item.container() {
|
||||
match trait_item.container {
|
||||
TraitContainer(_) => None,
|
||||
ImplContainer(def_id) => Some(def_id),
|
||||
}
|
||||
|
|
@ -2705,9 +2646,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
if def_id.krate != LOCAL_CRATE {
|
||||
return self.sess.cstore.trait_of_item(def_id);
|
||||
}
|
||||
match self.impl_or_trait_items.borrow().get(&def_id) {
|
||||
Some(impl_or_trait_item) => {
|
||||
match impl_or_trait_item.container() {
|
||||
match self.associated_items.borrow().get(&def_id) {
|
||||
Some(associated_item) => {
|
||||
match associated_item.container {
|
||||
TraitContainer(def_id) => Some(def_id),
|
||||
ImplContainer(_) => None
|
||||
}
|
||||
|
|
@ -2716,30 +2657,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// If the given def ID describes an item belonging to a trait, (either a
|
||||
/// default method or an implementation of a trait method), return the ID of
|
||||
/// the method inside trait definition (this means that if the given def ID
|
||||
/// is already that of the original trait method, then the return value is
|
||||
/// the same).
|
||||
/// Otherwise, return `None`.
|
||||
pub fn trait_item_of_item(self, def_id: DefId) -> Option<DefId> {
|
||||
let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) {
|
||||
Some(m) => m.clone(),
|
||||
None => return None,
|
||||
};
|
||||
match impl_or_trait_item.container() {
|
||||
TraitContainer(_) => Some(impl_or_trait_item.def_id()),
|
||||
ImplContainer(def_id) => {
|
||||
self.trait_id_of_impl(def_id).and_then(|trait_did| {
|
||||
let name = impl_or_trait_item.name();
|
||||
self.trait_items(trait_did).iter()
|
||||
.find(|item| item.name() == name)
|
||||
.map(|item| item.def_id())
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a parameter environment suitable for static contexts or other contexts where there
|
||||
/// are no free type/lifetime parameters in scope.
|
||||
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
|
||||
|
|
@ -2856,15 +2773,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The category of explicit self.
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum ExplicitSelfCategory<'tcx> {
|
||||
Static,
|
||||
ByValue,
|
||||
ByReference(&'tcx Region, hir::Mutability),
|
||||
ByBox,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
|
||||
F: FnOnce(&[hir::Freevar]) -> T,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue