// 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
TransCrateItem,
TypeckItemType,
TypeckItemBody,
- ImplOrTraitItems,
+ AssociatedItems,
ItemSignature,
FieldTy,
- ImplOrTraitItemDefIds,
+ AssociatedItemDefIds,
InherentImpls,
TraitImpls,
ReprHints,
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),
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;
// 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;
}
// 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") }
// 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") }
// 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;
}
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())
}
}
// 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);
}
}
}
}
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> {
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
}
};
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) {
// 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))
})
})
}
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,
SupertraitSelf,
/// Method has something illegal
- Method(Rc<ty::Method<'tcx>>, MethodViolationCode),
+ Method(ast::Name, MethodViolationCode),
}
/// Reasons a method might not be object-safe.
/// 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![];
}
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))
}
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) {
/// 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
/// 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.
/// `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);
}
// 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);
}
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)]
// 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()
};
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
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),
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()
}
}
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);
// 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};
}
/// 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 {
}
}
-/// 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>,
}
}
-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 })
+ })
}
}
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;
}
}
// 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;
}
}
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>>>,
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,
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, || {
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) => {
}
}
-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>> }
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;
}
#[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,
}
}
-#[derive(Clone)]
-pub enum ImplOrTraitItem<'tcx> {
- ConstTraitItem(Rc<AssociatedConst<'tcx>>),
- MethodTraitItem(Rc<Method<'tcx>>),
- TypeTraitItem(Rc<AssociatedType<'tcx>>),
-}
-
-impl<'tcx> ImplOrTraitItem<'tcx> {
- 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,
- }
- }
+#[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,
- 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,
- }
- }
+ /// Whether this is a method with an explicit self
+ /// as its first argument, allowing method calls.
+ pub method_has_self_argument: bool,
+}
- 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,
- }
- }
+#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
+pub enum AssociatedKind {
+ Const,
+ Method,
+ Type
+}
- pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
- match *self {
- MethodTraitItem(ref m) => Some((*m).clone()),
- _ => None,
+impl AssociatedItem {
+ pub fn def(&self) -> Def {
+ match self.kind {
+ AssociatedKind::Const => Def::AssociatedConst(self.def_id),
+ AssociatedKind::Method => Def::Method(self.def_id),
+ AssociatedKind::Type => Def::AssociatedTy(self.def_id),
}
}
}
}
}
-#[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
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))
}
}
}
// 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)
}
}
}
}
/// 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
}
}
- 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 {
})
}
- 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
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,
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);
}
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);
/// 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),
}
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
}
}
}
- /// 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> {
}
}
-/// 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,
}
}
-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")?;
}
}
-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)
// 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 {
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) {
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,
// 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::*;
// 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,
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
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)
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
// 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)) => {
use std::cell::Ref;
use std::io;
use std::mem;
-use std::rc::Rc;
use std::str;
use std::u32;
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);
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,
})
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,
} 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(),
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
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,
} 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);
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)),
}
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
}))
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);
Trait(Lazy<TraitData<'tcx>>),
Impl(Lazy<ImplData<'tcx>>),
DefaultImpl(Lazy<ImplData<'tcx>>),
- Method(Lazy<MethodData<'tcx>>),
+ Method(Lazy<MethodData>),
AssociatedType(AssociatedContainer),
AssociatedConst(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),
}
}
- pub fn has_body(&self) -> bool {
+ pub fn has_value(&self) -> bool {
match *self {
AssociatedContainer::TraitRequired => false,
}
#[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)]
-> (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,
+ });
}
}
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)
}
}
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
};
// 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) => {
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()
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;
// 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;
}
}
}
}
}
- ImplOrTraitItemContainer::TraitContainer(id) => {
+ AssociatedItemContainer::TraitContainer(id) => {
trait_id = Some(id);
}
}
// 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(..) |
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)) => {
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,
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))
}
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 {
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)),
};
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
};
}
}
- 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,
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
// 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>)
continue;
}
- if !method.generics.types.is_empty() {
+ if !tcx.lookup_generics(method.def_id).types.is_empty() {
continue;
}
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);
}
fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId)
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>;
- /// Returns true if the trait with id `trait_def_id` defines an
- /// associated type with the name `name`.
- fn trait_defines_associated_type_named(&self, trait_def_id: DefId, name: ast::Name)
- -> bool;
-
/// Return an (optional) substitution to convert bound type parameters that
/// are in scope into free ones. This function should only return Some
/// within a fn body.
Some(self_ty))
}
+ fn trait_defines_associated_type_named(&self,
+ trait_def_id: DefId,
+ assoc_name: ast::Name)
+ -> bool
+ {
+ self.tcx().associated_items(trait_def_id).any(|item| {
+ item.kind == ty::AssociatedKind::Type && item.name == assoc_name
+ })
+ }
+
fn ast_type_binding_to_poly_projection_predicate(
&self,
path_id: ast::NodeId,
let mut associated_types = FxHashSet::default();
for tr in traits::supertraits(tcx, principal) {
- if let Some(trait_id) = tcx.map.as_local_node_id(tr.def_id()) {
- use collect::trait_associated_type_names;
-
- associated_types.extend(trait_associated_type_names(tcx, trait_id)
- .map(|name| (tr.def_id(), name)))
- } else {
- let trait_items = tcx.impl_or_trait_items(tr.def_id());
- associated_types.extend(trait_items.iter().filter_map(|&def_id| {
- match tcx.impl_or_trait_item(def_id) {
- ty::TypeTraitItem(ref item) => Some(item.name),
- _ => None
- }
- }).map(|name| (tr.def_id(), name)));
- }
+ associated_types.extend(tcx.associated_items(tr.def_id())
+ .filter(|item| item.kind == ty::AssociatedKind::Type)
+ .map(|item| (tr.def_id(), item.name)));
}
for projection_bound in &projection_bounds {
if bounds.len() > 1 {
let spans = bounds.iter().map(|b| {
- self.tcx().impl_or_trait_items(b.def_id()).iter()
- .find(|&&def_id| {
- match self.tcx().impl_or_trait_item(def_id) {
- ty::TypeTraitItem(ref item) => item.name.as_str() == assoc_name,
- _ => false
- }
+ self.tcx().associated_items(b.def_id()).find(|item| {
+ item.kind == ty::AssociatedKind::Type && item.name.as_str() == assoc_name
})
- .and_then(|&def_id| self.tcx().map.as_local_node_id(def_id))
+ .and_then(|item| self.tcx().map.as_local_node_id(item.def_id))
.and_then(|node_id| self.tcx().map.opt_span(node_id))
});
let trait_did = bound.0.def_id;
let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
- let item_did = if let Some(trait_id) = tcx.map.as_local_node_id(trait_did) {
- // `ty::trait_items` used below requires information generated
- // by type collection, which may be in progress at this point.
- match tcx.map.expect_item(trait_id).node {
- hir::ItemTrait(.., ref trait_items) => {
- let item = trait_items.iter()
- .find(|i| i.name == assoc_name)
- .expect("missing associated type");
- tcx.map.local_def_id(item.id)
- }
- _ => bug!()
- }
- } else {
- let trait_items = tcx.trait_items(trait_did);
- let item = trait_items.iter().find(|i| i.name() == assoc_name);
- item.expect("missing associated type").def_id()
- };
-
- (ty, Def::AssociatedTy(item_did))
+ let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name);
+ (ty, Def::AssociatedTy(item.expect("missing associated type").def_id))
}
fn qpath_to_ty(&self,
hir::TyBareFn(ref bf) => {
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
let anon_scope = rscope.anon_type_scope();
- let (bare_fn_ty, _) =
- self.ty_of_method_or_bare_fn(bf.unsafety,
- bf.abi,
- None,
- &bf.decl,
- anon_scope,
- anon_scope);
+ let bare_fn_ty = self.ty_of_method_or_bare_fn(bf.unsafety,
+ bf.abi,
+ None,
+ &bf.decl,
+ anon_scope,
+ anon_scope);
// Find any late-bound regions declared in return type that do
// not appear in the arguments. These are not wellformed.
sig: &hir::MethodSig,
untransformed_self_ty: Ty<'tcx>,
anon_scope: Option<AnonTypeScope>)
- -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory<'tcx>) {
+ -> &'tcx ty::BareFnTy<'tcx> {
self.ty_of_method_or_bare_fn(sig.unsafety,
sig.abi,
Some(untransformed_self_ty),
decl: &hir::FnDecl,
anon_scope: Option<AnonTypeScope>)
-> &'tcx ty::BareFnTy<'tcx> {
- self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope).0
+ self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope)
}
fn ty_of_method_or_bare_fn(&self,
decl: &hir::FnDecl,
arg_anon_scope: Option<AnonTypeScope>,
ret_anon_scope: Option<AnonTypeScope>)
- -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory<'tcx>)
+ -> &'tcx ty::BareFnTy<'tcx>
{
debug!("ty_of_method_or_bare_fn");
// lifetime elision, we can determine it in two ways. First (determined
// here), if self is by-reference, then the implied output region is the
// region of the self parameter.
- let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, decl.get_self()) {
+ let (self_ty, explicit_self) = match (opt_untransformed_self_ty, decl.get_self()) {
(Some(untransformed_self_ty), Some(explicit_self)) => {
let self_type = self.determine_self_type(&rb, untransformed_self_ty,
&explicit_self);
- (Some(self_type.0), self_type.1)
+ (Some(self_type), Some(ExplicitSelf::determine(untransformed_self_ty, self_type)))
}
- _ => (None, ty::ExplicitSelfCategory::Static),
+ _ => (None, None),
};
// HACK(eddyb) replace the fake self type in the AST with the actual type.
// Second, if there was exactly one lifetime (either a substitution or a
// reference) in the arguments, then any anonymous regions in the output
// have that lifetime.
- let implied_output_region = match explicit_self_category {
- ty::ExplicitSelfCategory::ByReference(region, _) => Ok(*region),
+ let implied_output_region = match explicit_self {
+ Some(ExplicitSelf::ByReference(region, _)) => Ok(*region),
_ => {
// `pat_to_string` is expensive and
// `find_implied_output_region` only needs its result when
debug!("ty_of_method_or_bare_fn: input_tys={:?}", input_tys);
debug!("ty_of_method_or_bare_fn: output_ty={:?}", output_ty);
- (self.tcx().mk_bare_fn(ty::BareFnTy {
+ self.tcx().mk_bare_fn(ty::BareFnTy {
unsafety: unsafety,
abi: abi,
sig: ty::Binder(ty::FnSig {
output: output_ty,
variadic: decl.variadic
}),
- }), explicit_self_category)
+ })
}
fn determine_self_type<'a>(&self,
rscope: &RegionScope,
untransformed_self_ty: Ty<'tcx>,
explicit_self: &hir::ExplicitSelf)
- -> (Ty<'tcx>, ty::ExplicitSelfCategory<'tcx>)
+ -> Ty<'tcx>
{
- return match explicit_self.node {
- SelfKind::Value(..) => {
- (untransformed_self_ty, ty::ExplicitSelfCategory::ByValue)
- }
+ match explicit_self.node {
+ SelfKind::Value(..) => untransformed_self_ty,
SelfKind::Region(ref lifetime, mutability) => {
let region =
self.opt_ast_region_to_region(
rscope,
explicit_self.span,
lifetime);
- (self.tcx().mk_ref(region,
+ self.tcx().mk_ref(region,
ty::TypeAndMut {
ty: untransformed_self_ty,
mutbl: mutability
- }),
- ty::ExplicitSelfCategory::ByReference(region, mutability))
- }
- SelfKind::Explicit(ref ast_type, _) => {
- let explicit_type = self.ast_ty_to_ty(rscope, &ast_type);
-
- // We wish to (for now) categorize an explicit self
- // declaration like `self: SomeType` into either `self`,
- // `&self`, `&mut self`, or `Box<self>`. We do this here
- // by some simple pattern matching. A more precise check
- // is done later in `check_method_self_type()`.
- //
- // Examples:
- //
- // ```
- // impl Foo for &T {
- // // Legal declarations:
- // fn method1(self: &&T); // ExplicitSelfCategory::ByReference
- // fn method2(self: &T); // ExplicitSelfCategory::ByValue
- // fn method3(self: Box<&T>); // ExplicitSelfCategory::ByBox
- //
- // // Invalid cases will be caught later by `check_method_self_type`:
- // fn method_err1(self: &mut T); // ExplicitSelfCategory::ByReference
- // }
- // ```
- //
- // To do the check we just count the number of "modifiers"
- // on each type and compare them. If they are the same or
- // the impl has more, we call it "by value". Otherwise, we
- // look at the outermost modifier on the method decl and
- // call it by-ref, by-box as appropriate. For method1, for
- // example, the impl type has one modifier, but the method
- // type has two, so we end up with
- // ExplicitSelfCategory::ByReference.
-
- let impl_modifiers = count_modifiers(untransformed_self_ty);
- let method_modifiers = count_modifiers(explicit_type);
-
- debug!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \
- explicit_type={:?} \
- modifiers=({},{})",
- untransformed_self_ty,
- explicit_type,
- impl_modifiers,
- method_modifiers);
-
- let category = if impl_modifiers >= method_modifiers {
- ty::ExplicitSelfCategory::ByValue
- } else {
- match explicit_type.sty {
- ty::TyRef(r, mt) => ty::ExplicitSelfCategory::ByReference(r, mt.mutbl),
- ty::TyBox(_) => ty::ExplicitSelfCategory::ByBox,
- _ => ty::ExplicitSelfCategory::ByValue,
- }
- };
-
- (explicit_type, category)
- }
- };
-
- fn count_modifiers(ty: Ty) -> usize {
- match ty.sty {
- ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1,
- ty::TyBox(t) => count_modifiers(t) + 1,
- _ => 0,
+ })
}
+ SelfKind::Explicit(ref ast_type, _) => self.ast_ty_to_ty(rscope, &ast_type)
}
}
vec
}
}
+
+pub enum ExplicitSelf<'tcx> {
+ ByValue,
+ ByReference(&'tcx ty::Region, hir::Mutability),
+ ByBox
+}
+
+impl<'tcx> ExplicitSelf<'tcx> {
+ /// We wish to (for now) categorize an explicit self
+ /// declaration like `self: SomeType` into either `self`,
+ /// `&self`, `&mut self`, or `Box<self>`. We do this here
+ /// by some simple pattern matching. A more precise check
+ /// is done later in `check_method_self_type()`.
+ ///
+ /// Examples:
+ ///
+ /// ```
+ /// impl Foo for &T {
+ /// // Legal declarations:
+ /// fn method1(self: &&T); // ExplicitSelf::ByReference
+ /// fn method2(self: &T); // ExplicitSelf::ByValue
+ /// fn method3(self: Box<&T>); // ExplicitSelf::ByBox
+ ///
+ /// // Invalid cases will be caught later by `check_method_self_type`:
+ /// fn method_err1(self: &mut T); // ExplicitSelf::ByReference
+ /// }
+ /// ```
+ ///
+ /// To do the check we just count the number of "modifiers"
+ /// on each type and compare them. If they are the same or
+ /// the impl has more, we call it "by value". Otherwise, we
+ /// look at the outermost modifier on the method decl and
+ /// call it by-ref, by-box as appropriate. For method1, for
+ /// example, the impl type has one modifier, but the method
+ /// type has two, so we end up with
+ /// ExplicitSelf::ByReference.
+ pub fn determine(untransformed_self_ty: Ty<'tcx>,
+ self_arg_ty: Ty<'tcx>)
+ -> ExplicitSelf<'tcx> {
+ fn count_modifiers(ty: Ty) -> usize {
+ match ty.sty {
+ ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1,
+ ty::TyBox(t) => count_modifiers(t) + 1,
+ _ => 0,
+ }
+ }
+
+ let impl_modifiers = count_modifiers(untransformed_self_ty);
+ let method_modifiers = count_modifiers(self_arg_ty);
+
+ if impl_modifiers >= method_modifiers {
+ ExplicitSelf::ByValue
+ } else {
+ match self_arg_ty.sty {
+ ty::TyRef(r, mt) => ExplicitSelf::ByReference(r, mt.mutbl),
+ ty::TyBox(_) => ExplicitSelf::ByBox,
+ _ => ExplicitSelf::ByValue,
+ }
+ }
+ }
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use rustc::hir;
use rustc::infer::{self, InferOk, TypeOrigin};
use rustc::middle::free_region::FreeRegionMap;
use rustc::ty;
use CrateCtxt;
use super::assoc;
use super::{Inherited, FnCtxt};
+use astconv::ExplicitSelf;
/// Checks that a method from an impl conforms to the signature of
/// the same method as declared in the trait.
/// - impl_trait_ref: the TraitRef corresponding to the trait implementation
pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- impl_m: &ty::Method<'tcx>,
+ impl_m: &ty::AssociatedItem,
impl_m_span: Span,
impl_m_body_id: ast::NodeId,
- trait_m: &ty::Method<'tcx>,
- impl_trait_ref: &ty::TraitRef<'tcx>,
+ trait_m: &ty::AssociatedItem,
+ impl_trait_ref: ty::TraitRef<'tcx>,
trait_item_span: Option<Span>,
old_broken_mode: bool) {
debug!("compare_impl_method(impl_trait_ref={:?})",
if let Err(ErrorReported) = compare_self_type(ccx,
impl_m,
impl_m_span,
- trait_m) {
+ trait_m,
+ impl_trait_ref) {
return;
}
}
fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- impl_m: &ty::Method<'tcx>,
+ impl_m: &ty::AssociatedItem,
impl_m_span: Span,
impl_m_body_id: ast::NodeId,
- trait_m: &ty::Method<'tcx>,
- impl_trait_ref: &ty::TraitRef<'tcx>,
+ trait_m: &ty::AssociatedItem,
+ impl_trait_ref: ty::TraitRef<'tcx>,
old_broken_mode: bool)
-> Result<(), ErrorReported> {
let tcx = ccx.tcx;
- let trait_to_impl_substs = &impl_trait_ref.substs;
+ let trait_to_impl_substs = impl_trait_ref.substs;
// This code is best explained by example. Consider a trait:
//
// Create mapping from trait to skolemized.
let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
- impl_m.container_id(),
+ impl_m.container.id(),
trait_to_impl_substs.subst(tcx,
impl_to_skol_substs));
debug!("compare_impl_method: trait_to_skol_substs={:?}",
trait_to_skol_substs);
+ let impl_m_generics = tcx.lookup_generics(impl_m.def_id);
+ let trait_m_generics = tcx.lookup_generics(trait_m.def_id);
+ let impl_m_predicates = tcx.lookup_predicates(impl_m.def_id);
+ let trait_m_predicates = tcx.lookup_predicates(trait_m.def_id);
+
// Check region bounds.
check_region_bounds_on_impl_method(ccx,
impl_m_span,
impl_m,
- &trait_m.generics,
- &impl_m.generics,
+ &trait_m_generics,
+ &impl_m_generics,
trait_to_skol_substs,
impl_to_skol_substs)?;
// environment. We can't just use `impl_env.caller_bounds`,
// however, because we want to replace all late-bound regions with
// region variables.
- let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap());
+ let impl_predicates = tcx.lookup_predicates(impl_m_predicates.parent.unwrap());
let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
// We then register the obligations from the impl_m and check to see
// if all constraints hold.
hybrid_preds.predicates
- .extend(trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
+ .extend(trait_m_predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
// Construct trait parameter environment and then shift it into the skolemized viewpoint.
// The key step here is to update the caller_bounds's predicates to be
let mut selcx = traits::SelectionContext::new(&infcx);
- let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs);
+ let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs);
let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
infer::HigherRankedType,
&ty::Binder(impl_m_own_bounds.predicates));
let tcx = infcx.tcx;
let origin = TypeOrigin::MethodCompatCheck(impl_m_span);
+ let m_fty = |method: &ty::AssociatedItem| {
+ match tcx.lookup_item_type(method.def_id).ty.sty {
+ ty::TyFnDef(_, _, f) => f,
+ _ => bug!()
+ }
+ };
+ let impl_m_fty = m_fty(impl_m);
+ let trait_m_fty = m_fty(trait_m);
+
let (impl_sig, _) =
infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
infer::HigherRankedType,
- &impl_m.fty.sig);
+ &impl_m_fty.sig);
let impl_sig =
impl_sig.subst(tcx, impl_to_skol_substs);
let impl_sig =
impl_m_body_id,
&impl_sig);
let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
- unsafety: impl_m.fty.unsafety,
- abi: impl_m.fty.abi,
+ unsafety: impl_m_fty.unsafety,
+ abi: impl_m_fty.abi,
sig: ty::Binder(impl_sig.clone()),
}));
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
let trait_sig = tcx.liberate_late_bound_regions(
infcx.parameter_environment.free_id_outlive,
- &trait_m.fty.sig);
+ &trait_m_fty.sig);
let trait_sig =
trait_sig.subst(tcx, trait_to_skol_substs);
let trait_sig =
impl_m_body_id,
&trait_sig);
let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
- unsafety: trait_m.fty.unsafety,
- abi: trait_m.fty.abi,
+ unsafety: trait_m_fty.unsafety,
+ abi: trait_m_fty.abi,
sig: ty::Binder(trait_sig.clone()),
}));
fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
span: Span,
- impl_m: &ty::Method<'tcx>,
+ impl_m: &ty::AssociatedItem,
trait_generics: &ty::Generics<'tcx>,
impl_generics: &ty::Generics<'tcx>,
trait_to_skol_substs: &Substs<'tcx>,
fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
terr: &TypeError,
origin: TypeOrigin,
- impl_m: &ty::Method,
+ impl_m: &ty::AssociatedItem,
impl_sig: ty::FnSig<'tcx>,
- trait_m: &ty::Method,
+ trait_m: &ty::AssociatedItem,
trait_sig: ty::FnSig<'tcx>)
-> (Span, Option<Span>) {
let tcx = infcx.tcx;
}
fn compare_self_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- impl_m: &ty::Method<'tcx>,
+ impl_m: &ty::AssociatedItem,
impl_m_span: Span,
- trait_m: &ty::Method<'tcx>)
+ trait_m: &ty::AssociatedItem,
+ impl_trait_ref: ty::TraitRef<'tcx>)
-> Result<(), ErrorReported>
{
let tcx = ccx.tcx;
// that the error messages you get out of this code are a bit more
// inscrutable, particularly for cases where one method has no
// self.
- match (&trait_m.explicit_self, &impl_m.explicit_self) {
- (&ty::ExplicitSelfCategory::Static, &ty::ExplicitSelfCategory::Static) => {}
- (&ty::ExplicitSelfCategory::Static, _) => {
+
+ let self_string = |method: &ty::AssociatedItem| {
+ let untransformed_self_ty = match method.container {
+ ty::ImplContainer(_) => impl_trait_ref.self_ty(),
+ ty::TraitContainer(_) => tcx.mk_self_type()
+ };
+ let method_ty = tcx.lookup_item_type(method.def_id).ty;
+ let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder();
+ match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) {
+ ExplicitSelf::ByValue => "self".to_string(),
+ ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(),
+ ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(),
+ _ => format!("self: {}", self_arg_ty)
+ }
+ };
+
+ match (trait_m.method_has_self_argument, impl_m.method_has_self_argument) {
+ (false, false) | (true, true) => {}
+
+ (false, true) => {
+ let self_descr = self_string(impl_m);
let mut err = struct_span_err!(tcx.sess,
impl_m_span,
E0185,
"method `{}` has a `{}` declaration in the impl, but \
not in the trait",
trait_m.name,
- impl_m.explicit_self);
- err.span_label(impl_m_span,
- &format!("`{}` used in impl", impl_m.explicit_self));
+ self_descr);
+ err.span_label(impl_m_span, &format!("`{}` used in impl", self_descr));
if let Some(span) = tcx.map.span_if_local(trait_m.def_id) {
- err.span_label(span,
- &format!("trait declared without `{}`", impl_m.explicit_self));
+ err.span_label(span, &format!("trait declared without `{}`", self_descr));
}
err.emit();
return Err(ErrorReported);
}
- (_, &ty::ExplicitSelfCategory::Static) => {
+
+ (true, false) => {
+ let self_descr = self_string(trait_m);
let mut err = struct_span_err!(tcx.sess,
impl_m_span,
E0186,
"method `{}` has a `{}` declaration in the trait, but \
not in the impl",
trait_m.name,
- trait_m.explicit_self);
+ self_descr);
err.span_label(impl_m_span,
- &format!("expected `{}` in impl", trait_m.explicit_self));
+ &format!("expected `{}` in impl", self_descr));
if let Some(span) = tcx.map.span_if_local(trait_m.def_id) {
- err.span_label(span, &format!("`{}` used in trait", trait_m.explicit_self));
+ err.span_label(span, &format!("`{}` used in trait", self_descr));
}
err.emit();
return Err(ErrorReported);
}
- _ => {
- // Let the type checker catch other errors below
- }
}
Ok(())
}
fn compare_number_of_generics<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- impl_m: &ty::Method<'tcx>,
+ impl_m: &ty::AssociatedItem,
impl_m_span: Span,
- trait_m: &ty::Method<'tcx>,
+ trait_m: &ty::AssociatedItem,
trait_item_span: Option<Span>)
-> Result<(), ErrorReported> {
let tcx = ccx.tcx;
- let num_impl_m_type_params = impl_m.generics.types.len();
- let num_trait_m_type_params = trait_m.generics.types.len();
+ let impl_m_generics = tcx.lookup_generics(impl_m.def_id);
+ let trait_m_generics = tcx.lookup_generics(trait_m.def_id);
+ let num_impl_m_type_params = impl_m_generics.types.len();
+ let num_trait_m_type_params = trait_m_generics.types.len();
if num_impl_m_type_params != num_trait_m_type_params {
let impl_m_node_id = tcx.map.as_local_node_id(impl_m.def_id).unwrap();
let span = match tcx.map.expect_impl_item(impl_m_node_id).node {
}
fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- impl_m: &ty::Method<'tcx>,
+ impl_m: &ty::AssociatedItem,
impl_m_span: Span,
- trait_m: &ty::Method<'tcx>,
+ trait_m: &ty::AssociatedItem,
trait_item_span: Option<Span>)
-> Result<(), ErrorReported> {
let tcx = ccx.tcx;
- if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() {
- let trait_number_args = trait_m.fty.sig.0.inputs.len();
- let impl_number_args = impl_m.fty.sig.0.inputs.len();
+ let m_fty = |method: &ty::AssociatedItem| {
+ match tcx.lookup_item_type(method.def_id).ty.sty {
+ ty::TyFnDef(_, _, f) => f,
+ _ => bug!()
+ }
+ };
+ let impl_m_fty = m_fty(impl_m);
+ let trait_m_fty = m_fty(trait_m);
+ if impl_m_fty.sig.0.inputs.len() != trait_m_fty.sig.0.inputs.len() {
+ let trait_number_args = trait_m_fty.sig.0.inputs.len();
+ let impl_number_args = impl_m_fty.sig.0.inputs.len();
let trait_m_node_id = tcx.map.as_local_node_id(trait_m.def_id);
let trait_span = if let Some(trait_id) = trait_m_node_id {
match tcx.map.expect_trait_item(trait_id).node {
}
pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- impl_c: &ty::AssociatedConst<'tcx>,
+ impl_c: &ty::AssociatedItem,
impl_c_span: Span,
- trait_c: &ty::AssociatedConst<'tcx>,
- impl_trait_ref: &ty::TraitRef<'tcx>) {
+ trait_c: &ty::AssociatedItem,
+ impl_trait_ref: ty::TraitRef<'tcx>) {
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
let tcx = ccx.tcx;
// because we shouldn't really have to deal with lifetimes or
// predicates. In fact some of this should probably be put into
// shared functions because of DRY violations...
- let trait_to_impl_substs = &impl_trait_ref.substs;
+ let trait_to_impl_substs = impl_trait_ref.substs;
// Create a parameter environment that represents the implementation's
// method.
trait_to_skol_substs);
// Compute skolemized form of impl and trait const tys.
- let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
- let trait_ty = trait_c.ty.subst(tcx, trait_to_skol_substs);
+ let impl_ty = tcx.lookup_item_type(impl_c.def_id).ty.subst(tcx, impl_to_skol_substs);
+ let trait_ty = tcx.lookup_item_type(trait_c.def_id).ty.subst(tcx, trait_to_skol_substs);
let mut origin = TypeOrigin::Misc(impl_c_span);
let err = infcx.commit_if_ok(|_| {
// 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(..) => {
}
}
-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,
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,
};
-> &'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);
}
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
}
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
// 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 {
// 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)
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,
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)
}
// 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
//
// 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
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,
};
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);
}
/// 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)
}
}
#[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>,
}
#[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>,
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);
}
}
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;
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;
}
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
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;
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 => {
};
// 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(());
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?
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;
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={:?})",
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);
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| {
// 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) => {
/// 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;
}
///////////////////////////////////////////////////////////////////////////
// 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.
}
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());
// 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)
// `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)
/// 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)
}
}
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()),
}
}
}
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;
}
}
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 `{}`",
// 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<_>>();
check_impl_items_against_trait(ccx,
it.span,
impl_def_id,
- &impl_trait_ref,
+ impl_trait_ref,
impl_items);
let trait_def_id = impl_trait_ref.def_id;
check_on_unimplemented(ccx, trait_def_id, it);
{
let ancestors = trait_def.ancestors(impl_id);
- let parent = match impl_item.node {
- hir::ImplItemKind::Const(..) => {
- ancestors.const_defs(tcx, impl_item.name).skip(1).next()
- .map(|node_item| node_item.map(|parent| parent.defaultness))
- }
- hir::ImplItemKind::Method(..) => {
- ancestors.fn_defs(tcx, impl_item.name).skip(1).next()
- .map(|node_item| node_item.map(|parent| parent.defaultness))
-
- }
- hir::ImplItemKind::Type(_) => {
- ancestors.type_defs(tcx, impl_item.name).skip(1).next()
- .map(|node_item| node_item.map(|parent| parent.defaultness))
- }
+ let kind = match impl_item.node {
+ hir::ImplItemKind::Const(..) => ty::AssociatedKind::Const,
+ hir::ImplItemKind::Method(..) => ty::AssociatedKind::Method,
+ hir::ImplItemKind::Type(_) => ty::AssociatedKind::Type
};
+ let parent = ancestors.defs(tcx, impl_item.name, kind).skip(1).next()
+ .map(|node_item| node_item.map(|parent| parent.defaultness));
if let Some(parent) = parent {
if parent.item.is_final() {
fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
impl_span: Span,
impl_id: DefId,
- impl_trait_ref: &ty::TraitRef<'tcx>,
+ impl_trait_ref: ty::TraitRef<'tcx>,
impl_items: &[hir::ImplItem]) {
// If the trait reference itself is erroneous (so the compilation is going
// to fail), skip checking the items here -- the `impl_item` table in `tcx`
// Locate trait definition and items
let tcx = ccx.tcx;
let trait_def = tcx.lookup_trait_def(impl_trait_ref.def_id);
- let trait_items = tcx.trait_items(impl_trait_ref.def_id);
let mut overridden_associated_type = None;
// Check existing impl methods to see if they are both present in trait
// and compatible with trait signature
for impl_item in impl_items {
- let ty_impl_item = tcx.impl_or_trait_item(tcx.map.local_def_id(impl_item.id));
- let ty_trait_item = trait_items.iter()
- .find(|ac| ac.name() == ty_impl_item.name());
+ let ty_impl_item = tcx.associated_item(tcx.map.local_def_id(impl_item.id));
+ let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id)
+ .find(|ac| ac.name == ty_impl_item.name);
// Check that impl definition matches trait definition
if let Some(ty_trait_item) = ty_trait_item {
match impl_item.node {
hir::ImplItemKind::Const(..) => {
- let impl_const = match ty_impl_item {
- ty::ConstTraitItem(ref cti) => cti,
- _ => span_bug!(impl_item.span, "non-const impl-item for const")
- };
-
// Find associated const definition.
- if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
+ if ty_trait_item.kind == ty::AssociatedKind::Const {
compare_const_impl(ccx,
- &impl_const,
+ &ty_impl_item,
impl_item.span,
- trait_const,
- &impl_trait_ref);
+ &ty_trait_item,
+ impl_trait_ref);
} else {
let mut err = struct_span_err!(tcx.sess, impl_item.span, E0323,
"item `{}` is an associated const, \
which doesn't match its trait `{:?}`",
- impl_const.name,
+ ty_impl_item.name,
impl_trait_ref);
err.span_label(impl_item.span, &format!("does not match trait"));
// We can only get the spans from local trait definition
// Same for E0324 and E0325
- if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) {
+ if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id) {
err.span_label(trait_span, &format!("item in trait"));
}
err.emit()
}
}
hir::ImplItemKind::Method(_, ref body) => {
- let impl_method = match ty_impl_item {
- ty::MethodTraitItem(ref mti) => mti,
- _ => span_bug!(impl_item.span, "non-method impl-item for method")
- };
-
- let trait_span = tcx.map.span_if_local(ty_trait_item.def_id());
- if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
+ let trait_span = tcx.map.span_if_local(ty_trait_item.def_id);
+ if ty_trait_item.kind == ty::AssociatedKind::Method {
let err_count = tcx.sess.err_count();
compare_impl_method(ccx,
- &impl_method,
+ &ty_impl_item,
impl_item.span,
body.id,
- &trait_method,
- &impl_trait_ref,
+ &ty_trait_item,
+ impl_trait_ref,
trait_span,
true); // start with old-broken-mode
if err_count == tcx.sess.err_count() {
// old broken mode did not report an error. Try with the new mode.
compare_impl_method(ccx,
- &impl_method,
+ &ty_impl_item,
impl_item.span,
body.id,
- &trait_method,
- &impl_trait_ref,
+ &ty_trait_item,
+ impl_trait_ref,
trait_span,
false); // use the new mode
}
let mut err = struct_span_err!(tcx.sess, impl_item.span, E0324,
"item `{}` is an associated method, \
which doesn't match its trait `{:?}`",
- impl_method.name,
+ ty_impl_item.name,
impl_trait_ref);
err.span_label(impl_item.span, &format!("does not match trait"));
- if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) {
+ if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id) {
err.span_label(trait_span, &format!("item in trait"));
}
err.emit()
}
}
hir::ImplItemKind::Type(_) => {
- let impl_type = match ty_impl_item {
- ty::TypeTraitItem(ref tti) => tti,
- _ => span_bug!(impl_item.span, "non-type impl-item for type")
- };
-
- if let &ty::TypeTraitItem(ref at) = ty_trait_item {
- if let Some(_) = at.ty {
+ if ty_trait_item.kind == ty::AssociatedKind::Type {
+ if ty_trait_item.has_value {
overridden_associated_type = Some(impl_item);
}
} else {
let mut err = struct_span_err!(tcx.sess, impl_item.span, E0325,
"item `{}` is an associated type, \
which doesn't match its trait `{:?}`",
- impl_type.name,
+ ty_impl_item.name,
impl_trait_ref);
err.span_label(impl_item.span, &format!("does not match trait"));
- if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) {
+ if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id) {
err.span_label(trait_span, &format!("item in trait"));
}
err.emit()
}
// Check for missing items from trait
- let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
let mut missing_items = Vec::new();
let mut invalidated_items = Vec::new();
let associated_type_overridden = overridden_associated_type.is_some();
- for trait_item in trait_items.iter() {
- let is_implemented;
- let is_provided;
-
- match *trait_item {
- ty::ConstTraitItem(ref associated_const) => {
- is_provided = associated_const.has_value;
- is_implemented = impl_items.iter().any(|ii| {
- match ii.node {
- hir::ImplItemKind::Const(..) => {
- ii.name == associated_const.name
- }
- _ => false,
- }
- });
- }
- ty::MethodTraitItem(ref trait_method) => {
- is_provided = provided_methods.iter().any(|m| m.name == trait_method.name);
- is_implemented = trait_def.ancestors(impl_id)
- .fn_defs(tcx, trait_method.name)
- .next()
- .map(|node_item| !node_item.node.is_from_trait())
- .unwrap_or(false);
- }
- ty::TypeTraitItem(ref trait_assoc_ty) => {
- is_provided = trait_assoc_ty.ty.is_some();
- is_implemented = trait_def.ancestors(impl_id)
- .type_defs(tcx, trait_assoc_ty.name)
- .next()
- .map(|node_item| !node_item.node.is_from_trait())
- .unwrap_or(false);
- }
- }
+ for trait_item in tcx.associated_items(impl_trait_ref.def_id) {
+ let is_implemented = trait_def.ancestors(impl_id)
+ .defs(tcx, trait_item.name, trait_item.kind)
+ .next()
+ .map(|node_item| !node_item.node.is_from_trait())
+ .unwrap_or(false);
if !is_implemented {
- if !is_provided {
+ if !trait_item.has_value {
missing_items.push(trait_item);
} else if associated_type_overridden {
- invalidated_items.push(trait_item.name());
+ invalidated_items.push(trait_item.name);
}
}
}
+ let signature = |item: &ty::AssociatedItem| {
+ match item.kind {
+ ty::AssociatedKind::Method => {
+ format!("{}", tcx.lookup_item_type(item.def_id).ty.fn_sig().0)
+ }
+ ty::AssociatedKind::Type => format!("type {};", item.name.to_string()),
+ ty::AssociatedKind::Const => {
+ format!("const {}: {:?};", item.name.to_string(),
+ tcx.lookup_item_type(item.def_id).ty)
+ }
+ }
+ };
+
if !missing_items.is_empty() {
let mut err = struct_span_err!(tcx.sess, impl_span, E0046,
"not all trait items implemented, missing: `{}`",
missing_items.iter()
- .map(|trait_item| trait_item.name().to_string())
+ .map(|trait_item| trait_item.name.to_string())
.collect::<Vec<_>>().join("`, `"));
err.span_label(impl_span, &format!("missing `{}` in implementation",
missing_items.iter()
- .map(|trait_item| trait_item.name().to_string())
+ .map(|trait_item| trait_item.name.to_string())
.collect::<Vec<_>>().join("`, `")));
for trait_item in missing_items {
- if let Some(span) = tcx.map.span_if_local(trait_item.def_id()) {
- err.span_label(span, &format!("`{}` from trait", trait_item.name()));
+ if let Some(span) = tcx.map.span_if_local(trait_item.def_id) {
+ err.span_label(span, &format!("`{}` from trait", trait_item.name));
} else {
err.note(&format!("`{}` from trait: `{}`",
- trait_item.name(),
- signature(trait_item)));
+ trait_item.name,
+ signature(&trait_item)));
}
}
err.emit();
}
}
-fn signature<'a, 'tcx>(item: &ty::ImplOrTraitItem) -> String {
- match *item {
- ty::MethodTraitItem(ref item) => format!("{}", item.fty.sig.0),
- ty::TypeTraitItem(ref item) => format!("type {};", item.name.to_string()),
- ty::ConstTraitItem(ref item) => format!("const {}: {:?};", item.name.to_string(), item.ty),
- }
-}
-
/// Checks a constant with a given type.
fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
expr: &'tcx hir::Expr,
Ok(r)
}
- fn trait_defines_associated_type_named(&self,
- trait_def_id: DefId,
- assoc_name: ast::Name)
- -> bool
- {
- self.tcx().impl_or_trait_items(trait_def_id).iter().any(|&def_id| {
- match self.tcx().impl_or_trait_item(def_id) {
- ty::TypeTraitItem(ref item) => item.name == assoc_name,
- _ => false
- }
- })
- }
-
fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
self.next_ty_var()
}
/// As `instantiate_type_scheme`, but for the bounds found in a
/// generic type scheme.
- fn instantiate_bounds(&self,
- span: Span,
- substs: &Substs<'tcx>,
- bounds: &ty::GenericPredicates<'tcx>)
- -> ty::InstantiatedPredicates<'tcx>
- {
+ fn instantiate_bounds(&self, span: Span, def_id: DefId, substs: &Substs<'tcx>)
+ -> ty::InstantiatedPredicates<'tcx> {
+ let bounds = self.tcx.lookup_predicates(def_id);
let result = bounds.instantiate(self.tcx, substs);
let result = self.normalize_associated_types_in(span, &result.predicates);
debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
if let Some((variant, did, substs)) = variant {
// Check bounds on type arguments used in the path.
- let type_predicates = self.tcx.lookup_predicates(did);
- let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
+ let bounds = self.instantiate_bounds(path.span, did, substs);
let cause = traits::ObligationCause::new(path.span, self.body_id,
traits::ItemObligation(did));
self.add_obligations_for_parameters(cause, &bounds);
// Case 3. Reference to a method or associated const.
Def::Method(def_id) |
Def::AssociatedConst(def_id) => {
- let container = self.tcx.impl_or_trait_item(def_id).container();
+ let container = self.tcx.associated_item(def_id).container;
match container {
ty::TraitContainer(trait_did) => {
callee::check_legal_trait_for_method_call(self.ccx, span, trait_did)
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let scheme = self.tcx.lookup_item_type(def.def_id());
- let type_predicates = self.tcx.lookup_predicates(def.def_id());
assert!(!substs.has_escaping_regions());
assert!(!scheme.ty.has_escaping_regions());
// Add all the obligations that are required, substituting and
// normalized appropriately.
- let bounds = self.instantiate_bounds(span, &substs, &type_predicates);
+ let bounds = self.instantiate_bounds(span, def.def_id(), &substs);
self.add_obligations_for_parameters(
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def.def_id())),
&bounds);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use astconv::ExplicitSelf;
use check::FnCtxt;
use constrained_type_params::{identify_constrained_type_params, Parameter};
use CrateCtxt;
+
use hir::def_id::DefId;
use middle::region::{CodeExtent};
use rustc::infer::TypeOrigin;
self.check_variances_for_type_defn(item, ast_generics);
}
- hir::ItemTrait(.., ref items) => {
- self.check_trait(item, items);
+ hir::ItemTrait(..) => {
+ self.check_trait(item);
}
_ => {}
}
let free_substs = &fcx.parameter_environment.free_substs;
let free_id_outlive = fcx.parameter_environment.free_id_outlive;
- let item = fcx.tcx.impl_or_trait_item(fcx.tcx.map.local_def_id(item_id));
+ let item = fcx.tcx.associated_item(fcx.tcx.map.local_def_id(item_id));
- let (mut implied_bounds, self_ty) = match item.container() {
+ let (mut implied_bounds, self_ty) = match item.container {
ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
fcx.tcx.lookup_item_type(def_id).ty)
};
- match item {
- ty::ConstTraitItem(assoc_const) => {
- let ty = fcx.instantiate_type_scheme(span, free_substs, &assoc_const.ty);
+ match item.kind {
+ ty::AssociatedKind::Const => {
+ let ty = fcx.tcx.lookup_item_type(item.def_id).ty;
+ let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
fcx.register_wf_obligation(ty, span, code.clone());
}
- ty::MethodTraitItem(method) => {
- reject_shadowing_type_parameters(fcx.tcx, span, &method.generics);
- let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
- let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates);
- this.check_fn_or_method(fcx, span, &method_ty, &predicates,
+ ty::AssociatedKind::Method => {
+ reject_shadowing_type_parameters(fcx.tcx, span, item.def_id);
+ let method_ty = fcx.tcx.lookup_item_type(item.def_id).ty;
+ let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
+ let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs);
+ let fty = match method_ty.sty {
+ ty::TyFnDef(_, _, f) => f,
+ _ => bug!()
+ };
+ this.check_fn_or_method(fcx, span, fty, &predicates,
free_id_outlive, &mut implied_bounds);
let sig_if_method = sig_if_method.expect("bad signature for method");
- this.check_method_receiver(fcx, sig_if_method, &method,
+ this.check_method_receiver(fcx, sig_if_method, &item,
free_id_outlive, self_ty);
}
- ty::TypeTraitItem(assoc_type) => {
- if let Some(ref ty) = assoc_type.ty {
- let ty = fcx.instantiate_type_scheme(span, free_substs, ty);
+ ty::AssociatedKind::Type => {
+ if item.has_value {
+ let ty = fcx.tcx.lookup_item_type(item.def_id).ty;
+ let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
fcx.register_wf_obligation(ty, span, code.clone());
}
}
}
let free_substs = &fcx.parameter_environment.free_substs;
- let predicates = fcx.tcx.lookup_predicates(fcx.tcx.map.local_def_id(item.id));
- let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
+ let def_id = fcx.tcx.map.local_def_id(item.id);
+ let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
this.check_where_clauses(fcx, item.span, &predicates);
vec![] // no implied bounds in a struct def'n
});
}
- fn check_auto_trait(&mut self,
- trait_def_id: DefId,
- items: &[hir::TraitItem],
- span: Span)
- {
+ fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) {
// We want to ensure:
//
// 1) that there are no items contained within
// extraneous predicates created by things like
// an associated type inside the trait.
let mut err = None;
- if !items.is_empty() {
+ if !self.tcx().associated_item_def_ids(trait_def_id).is_empty() {
error_380(self.ccx, span);
} else if has_ty_params {
err = Some(struct_span_err!(self.tcx().sess, span, E0567,
}
}
- fn check_trait(&mut self,
- item: &hir::Item,
- items: &[hir::TraitItem])
- {
+ fn check_trait(&mut self, item: &hir::Item) {
let trait_def_id = self.tcx().map.local_def_id(item.id);
if self.tcx().trait_has_default_impl(trait_def_id) {
- self.check_auto_trait(trait_def_id, items, item.span);
+ self.check_auto_trait(trait_def_id, item.span);
}
self.for_item(item).with_fcx(|fcx, this| {
let free_substs = &fcx.parameter_environment.free_substs;
- let predicates = fcx.tcx.lookup_predicates(trait_def_id);
- let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
+ let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs);
this.check_where_clauses(fcx, item.span, &predicates);
vec![]
});
{
self.for_item(item).with_fcx(|fcx, this| {
let free_substs = &fcx.parameter_environment.free_substs;
- let type_scheme = fcx.tcx.lookup_item_type(fcx.tcx.map.local_def_id(item.id));
+ let def_id = fcx.tcx.map.local_def_id(item.id);
+ let type_scheme = fcx.tcx.lookup_item_type(def_id);
let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &type_scheme.ty);
let bare_fn_ty = match item_ty.sty {
ty::TyFnDef(.., ref bare_fn_ty) => bare_fn_ty,
}
};
- let predicates = fcx.tcx.lookup_predicates(fcx.tcx.map.local_def_id(item.id));
- let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
+ let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
let mut implied_bounds = vec![];
let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body.id);
}
}
- let predicates = fcx.tcx.lookup_predicates(item_def_id);
- let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
+ let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs);
this.check_where_clauses(fcx, item.span, &predicates);
fcx.impl_implied_bounds(fcx.tcx.map.local_def_id(item.id), item.span)
fn check_method_receiver<'fcx, 'tcx>(&mut self,
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
method_sig: &hir::MethodSig,
- method: &ty::Method<'tcx>,
+ method: &ty::AssociatedItem,
free_id_outlive: CodeExtent,
self_ty: ty::Ty<'tcx>)
{
// check that the type of the method's receiver matches the
// method's first parameter.
- debug!("check_method_receiver({:?},cat={:?},self_ty={:?})",
- method.name, method.explicit_self, self_ty);
+ debug!("check_method_receiver({:?}, self_ty={:?})",
+ method, self_ty);
- let rcvr_ty = match method.explicit_self {
- ty::ExplicitSelfCategory::Static => return,
- ty::ExplicitSelfCategory::ByValue => self_ty,
- ty::ExplicitSelfCategory::ByReference(region, mutability) => {
- fcx.tcx.mk_ref(region, ty::TypeAndMut {
- ty: self_ty,
- mutbl: mutability
- })
- }
- ty::ExplicitSelfCategory::ByBox => fcx.tcx.mk_box(self_ty)
- };
+ if !method.method_has_self_argument {
+ return;
+ }
let span = method_sig.decl.inputs[0].pat.span;
let free_substs = &fcx.parameter_environment.free_substs;
- let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
- let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig);
+ let method_ty = fcx.tcx.lookup_item_type(method.def_id).ty;
+ let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
+ let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.fn_sig());
debug!("check_method_receiver: sig={:?}", sig);
+ let self_arg_ty = sig.inputs[0];
+ let rcvr_ty = match ExplicitSelf::determine(self_ty, self_arg_ty) {
+ ExplicitSelf::ByValue => self_ty,
+ ExplicitSelf::ByReference(region, mutbl) => {
+ fcx.tcx.mk_ref(region, ty::TypeAndMut {
+ ty: self_ty,
+ mutbl: mutbl
+ })
+ }
+ ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
+ };
let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
&ty::Binder(rcvr_ty));
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
let origin = TypeOrigin::MethodReceiver(span);
- fcx.demand_eqtype_with_origin(origin, rcvr_ty, sig.inputs[0]);
+ fcx.demand_eqtype_with_origin(origin, rcvr_ty, self_arg_ty);
}
fn check_variances_for_type_defn(&self,
}
}
-fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) {
+fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, def_id: DefId) {
+ let generics = tcx.lookup_generics(def_id);
let parent = tcx.lookup_generics(generics.parent.unwrap());
let impl_params: FxHashMap<_, _> = parent.types
.iter()
use rustc::hir::{Item, ItemImpl};
use rustc::hir;
-use std::rc::Rc;
-
mod orphan;
mod overlap;
mod unsafety;
// If there are no traits, then this implementation must have a
// base type.
- let impl_items = self.create_impl_from_item(item);
-
if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(impl_did) {
debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
trait_ref,
self.add_inherent_impl(base_def_id, impl_did);
}
}
-
- tcx.impl_or_trait_item_def_ids.borrow_mut().insert(impl_did, Rc::new(impl_items));
}
fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
trait_def.record_local_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref);
}
- // Converts an implementation in the AST to a vector of items.
- fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
- match item.node {
- ItemImpl(.., ref impl_items) => {
- impl_items.iter()
- .map(|impl_item| self.crate_context.tcx.map.local_def_id(impl_item.id))
- .collect()
- }
- _ => {
- span_bug!(item.span, "can't convert a non-impl to an impl");
- }
- }
- }
-
// Destructors
//
tcx.populate_implementations_for_trait_if_necessary(drop_trait);
let drop_trait = tcx.lookup_trait_def(drop_trait);
- let impl_items = tcx.impl_or_trait_item_def_ids.borrow();
-
drop_trait.for_each_impl(tcx, |impl_did| {
- let items = impl_items.get(&impl_did).unwrap();
+ let items = tcx.associated_item_def_ids(impl_did);
if items.is_empty() {
// We'll error out later. For now, just don't ICE.
return;
Value,
}
- fn name_and_namespace<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_id: DefId)
- -> (ast::Name, Namespace) {
- let item = tcx.impl_or_trait_item(def_id);
- (item.name(),
- match item {
- ty::TypeTraitItem(..) => Namespace::Type,
- ty::ConstTraitItem(..) => Namespace::Value,
- ty::MethodTraitItem(..) => Namespace::Value,
- })
- }
+ let name_and_namespace = |def_id| {
+ let item = self.tcx.associated_item(def_id);
+ (item.name, match item.kind {
+ ty::AssociatedKind::Type => Namespace::Type,
+ ty::AssociatedKind::Const |
+ ty::AssociatedKind::Method => Namespace::Value,
+ })
+ };
- let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow();
+ let impl_items1 = self.tcx.associated_item_def_ids(impl1);
+ let impl_items2 = self.tcx.associated_item_def_ids(impl2);
- for &item1 in &impl_items[&impl1][..] {
- let (name, namespace) = name_and_namespace(self.tcx, item1);
+ for &item1 in &impl_items1[..] {
+ let (name, namespace) = name_and_namespace(item1);
- for &item2 in &impl_items[&impl2][..] {
- if (name, namespace) == name_and_namespace(self.tcx, item2) {
+ for &item2 in &impl_items2[..] {
+ if (name, namespace) == name_and_namespace(item2) {
let msg = format!("duplicate definitions with name `{}`", name);
let node_id = self.tcx.map.as_local_node_id(item1).unwrap();
self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
use rustc_const_eval::EvalHint::UncheckedExprHint;
use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
use rustc::ty::subst::Substs;
-use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
+use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer};
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
use rustc::ty::util::IntTypeExt;
use rscope::*;
use std::cell::RefCell;
use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::rc::Rc;
use syntax::{abi, ast, attr};
use syntax::parse::token::keywords;
})
}
- fn trait_defines_associated_type_named(&self,
- trait_def_id: DefId,
- assoc_name: ast::Name)
- -> bool
- {
- if let Some(trait_id) = self.tcx().map.as_local_node_id(trait_def_id) {
- trait_associated_type_names(self.tcx(), trait_id)
- .any(|name| name == assoc_name)
- } else {
- self.tcx().impl_or_trait_items(trait_def_id).iter().any(|&def_id| {
- match self.tcx().impl_or_trait_item(def_id) {
- ty::TypeTraitItem(ref item) => item.name == assoc_name,
- _ => false
- }
- })
- }
- }
-
fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
None
}
}
}
-fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- container: ImplOrTraitItemContainer,
- name: ast::Name,
- id: ast::NodeId,
- vis: &hir::Visibility,
- sig: &hir::MethodSig,
- defaultness: hir::Defaultness,
- has_body: bool,
- untransformed_rcvr_ty: Ty<'tcx>,
- rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
- let def_id = ccx.tcx.map.local_def_id(id);
- let ty_generics = generics_of_def_id(ccx, def_id);
-
- let ty_generic_predicates =
- ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false);
-
- let (fty, explicit_self_category) = {
- let anon_scope = match container {
- ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
- TraitContainer(_) => None
- };
- AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
- sig, untransformed_rcvr_ty, anon_scope)
- };
-
- let ty_method = ty::Method {
- name: name,
- generics: ty_generics,
- predicates: ty_generic_predicates,
- fty: fty,
- explicit_self: explicit_self_category,
- vis: ty::Visibility::from_hir(vis, id, ccx.tcx),
- defaultness: defaultness,
- has_body: has_body,
- def_id: def_id,
- container: container,
- };
-
- let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
- ccx.tcx.map.span(id), def_id);
- let fty = ccx.tcx.mk_fn_def(def_id, substs, ty_method.fty);
- debug!("method {} (id {}) has type {:?}",
- name, id, fty);
- ccx.tcx.tcache.borrow_mut().insert(def_id, fty);
- write_ty_to_tcx(ccx, id, fty);
- ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
-
- debug!("writing method type: def_id={:?} mty={:?}",
- def_id, ty_method);
-
- ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id,
- ty::MethodTraitItem(Rc::new(ty_method)));
-}
-
fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
struct_generics: &'tcx ty::Generics<'tcx>,
struct_predicates: &ty::GenericPredicates<'tcx>,
struct_predicates.clone());
}
+fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+ container: AssociatedItemContainer,
+ id: ast::NodeId,
+ sig: &hir::MethodSig,
+ untransformed_rcvr_ty: Ty<'tcx>,
+ rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
+ let def_id = ccx.tcx.map.local_def_id(id);
+ let ty_generics = generics_of_def_id(ccx, def_id);
+
+ let ty_generic_predicates =
+ ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false);
+
+ let anon_scope = match container {
+ ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
+ TraitContainer(_) => None
+ };
+ let fty = AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
+ sig, untransformed_rcvr_ty, anon_scope);
+
+ let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
+ ccx.tcx.map.span(id), def_id);
+ let fty = ccx.tcx.mk_fn_def(def_id, substs, fty);
+ ccx.tcx.tcache.borrow_mut().insert(def_id, fty);
+ write_ty_to_tcx(ccx, id, fty);
+ ccx.tcx.predicates.borrow_mut().insert(def_id, ty_generic_predicates);
+}
+
fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- container: ImplOrTraitItemContainer,
- name: ast::Name,
+ container: AssociatedItemContainer,
id: ast::NodeId,
- vis: &hir::Visibility,
- defaultness: hir::Defaultness,
- ty: ty::Ty<'tcx>,
- has_value: bool)
+ ty: ty::Ty<'tcx>)
{
let predicates = ty::GenericPredicates {
parent: Some(container.id()),
predicates: vec![]
};
- ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
- predicates);
+ let def_id = ccx.tcx.map.local_def_id(id);
+ ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
+ ccx.tcx.tcache.borrow_mut().insert(def_id, ty);
write_ty_to_tcx(ccx, id, ty);
-
- let associated_const = Rc::new(ty::AssociatedConst {
- name: name,
- vis: ty::Visibility::from_hir(vis, id, ccx.tcx),
- defaultness: defaultness,
- def_id: ccx.tcx.map.local_def_id(id),
- container: container,
- ty: ty,
- has_value: has_value
- });
- ccx.tcx.impl_or_trait_items.borrow_mut()
- .insert(ccx.tcx.map.local_def_id(id), ty::ConstTraitItem(associated_const));
}
fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- container: ImplOrTraitItemContainer,
- name: ast::Name,
+ container: AssociatedItemContainer,
id: ast::NodeId,
- vis: &hir::Visibility,
- defaultness: hir::Defaultness,
ty: Option<Ty<'tcx>>)
{
let predicates = ty::GenericPredicates {
parent: Some(container.id()),
predicates: vec![]
};
- ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
- predicates);
+ let def_id = ccx.tcx.map.local_def_id(id);
+ ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
- let associated_type = Rc::new(ty::AssociatedType {
- name: name,
- vis: ty::Visibility::from_hir(vis, id, ccx.tcx),
- defaultness: defaultness,
- ty: ty,
- def_id: ccx.tcx.map.local_def_id(id),
- container: container
- });
- ccx.tcx.impl_or_trait_items.borrow_mut()
- .insert(ccx.tcx.map.local_def_id(id), ty::TypeTraitItem(associated_type));
+ if let Some(ty) = ty {
+ ccx.tcx.tcache.borrow_mut().insert(def_id, ty);
+ write_ty_to_tcx(ccx, id, ty);
+ }
}
fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
generics: ty_generics,
ty: ty,
});
- // Trait-associated constants are always public.
- let public = &hir::Public;
- let visibility = if opt_trait_ref.is_some() { public } else { &impl_item.vis };
convert_associated_const(ccx, ImplContainer(def_id),
- impl_item.name, impl_item.id,
- visibility,
- impl_item.defaultness,
- ty, true /* has_value */);
+ impl_item.id, ty);
}
}
let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
- convert_associated_type(ccx, ImplContainer(def_id),
- impl_item.name, impl_item.id, &impl_item.vis,
- impl_item.defaultness, Some(typ));
+ convert_associated_type(ccx, ImplContainer(def_id), impl_item.id, Some(typ));
}
}
for impl_item in impl_items {
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
- // Trait methods are always public.
- let public = &hir::Public;
- let method_vis = if opt_trait_ref.is_some() { public } else { &impl_item.vis };
-
convert_method(ccx, ImplContainer(def_id),
- impl_item.name, impl_item.id, method_vis,
- sig, impl_item.defaultness, true, selfty,
+ impl_item.id, sig, selfty,
&ty_predicates);
}
}
// Convert all the associated constants.
for trait_item in trait_items {
- if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node {
+ if let hir::ConstTraitItem(ref ty, _) = trait_item.node {
let const_def_id = ccx.tcx.map.local_def_id(trait_item.id);
let ty_generics = generics_of_def_id(ccx, const_def_id);
let ty = ccx.icx(&trait_predicates)
generics: ty_generics,
ty: ty,
});
- convert_associated_const(ccx,
- container,
- trait_item.name,
- trait_item.id,
- &hir::Public,
- hir::Defaultness::Default,
- ty,
- default.is_some())
+ convert_associated_const(ccx, container, trait_item.id, ty)
}
}
|ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
});
- convert_associated_type(ccx,
- container,
- trait_item.name,
- trait_item.id,
- &hir::Public,
- hir::Defaultness::Default,
- typ);
+ convert_associated_type(ccx, container, trait_item.id, typ);
}
}
// Convert all the methods
for trait_item in trait_items {
- if let hir::MethodTraitItem(ref sig, ref body) = trait_item.node {
+ if let hir::MethodTraitItem(ref sig, _) = trait_item.node {
convert_method(ccx,
container,
- trait_item.name,
trait_item.id,
- &hir::Inherited,
sig,
- hir::Defaultness::Default,
- body.is_some(),
tcx.mk_self_type(),
&trait_predicates);
-
}
}
-
- // Add an entry mapping
- let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
- ccx.tcx.map.local_def_id(trait_item.id)
- }).collect());
- tcx.impl_or_trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
- trait_item_def_ids);
},
hir::ItemStruct(ref struct_def, _) |
hir::ItemUnion(ref struct_def, _) => {
tcx.intern_trait_def(trait_def)
}
-pub fn trait_associated_type_names<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- trait_node_id: ast::NodeId)
- -> impl Iterator<Item=ast::Name> + 'a
-{
- let item = match tcx.map.get(trait_node_id) {
- hir_map::NodeItem(item) => item,
- _ => bug!("trait_node_id {} is not an item", trait_node_id)
- };
-
- let trait_items = match item.node {
- hir::ItemTrait(.., ref trait_items) => trait_items,
- _ => bug!("trait_node_id {} is not a trait", trait_node_id)
- };
-
- trait_items.iter().filter_map(|trait_item| {
- match trait_item.node {
- hir::TypeTraitItem(..) => Some(trait_item.name),
- _ => None,
- }
- })
-}
-
fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) {
let tcx = ccx.tcx;
let trait_def = trait_def_of_item(ccx, it);
&impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
let lifetimes_in_associated_types: FxHashSet<_> = impl_items.iter()
- .map(|item| ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(item.id)))
- .filter_map(|item| match item {
- ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
- ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
+ .map(|item| ccx.tcx.map.local_def_id(item.id))
+ .filter(|&def_id| {
+ let item = ccx.tcx.associated_item(def_id);
+ item.kind == ty::AssociatedKind::Type && item.has_value
})
- .flat_map(|ty| ctp::parameters_for(&ty, true))
- .collect();
+ .flat_map(|def_id| {
+ ctp::parameters_for(&ccx.tcx.lookup_item_type(def_id).ty, true)
+ }).collect();
for (ty_lifetime, lifetime) in impl_scheme.generics.regions.iter()
.zip(&ast_generics.lifetimes)
pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
did: DefId) -> clean::Trait {
let def = tcx.lookup_trait_def(did);
- let trait_items = tcx.trait_items(did).clean(cx);
+ let trait_items = tcx.associated_items(did).map(|item| item.clean(cx)).collect();
let predicates = tcx.lookup_predicates(did);
let generics = (def.generics, &predicates).clean(cx);
let generics = filter_non_trait_generics(did, generics);
for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
if !def_id.is_local() {
- tcx.populate_implementations_for_primitive_if_necessary(def_id);
build_impl(cx, tcx, def_id, &mut impls);
}
}
}
let predicates = tcx.lookup_predicates(did);
- let trait_items = tcx.sess.cstore.impl_or_trait_items(did)
- .iter()
- .filter_map(|&did| {
- match tcx.impl_or_trait_item(did) {
- ty::ConstTraitItem(ref assoc_const) => {
- let did = assoc_const.def_id;
- let type_scheme = tcx.lookup_item_type(did);
- let default = if assoc_const.has_value {
+ let trait_items = tcx.associated_items(did).filter_map(|item| {
+ match item.kind {
+ ty::AssociatedKind::Const => {
+ let type_scheme = tcx.lookup_item_type(item.def_id);
+ let default = if item.has_value {
Some(pprust::expr_to_string(
- lookup_const_by_id(tcx, did, None).unwrap().0))
+ lookup_const_by_id(tcx, item.def_id, None).unwrap().0))
} else {
None
};
Some(clean::Item {
- name: Some(assoc_const.name.clean(cx)),
+ name: Some(item.name.clean(cx)),
inner: clean::AssociatedConstItem(
type_scheme.ty.clean(cx),
default,
source: clean::Span::empty(),
attrs: vec![],
visibility: None,
- stability: tcx.lookup_stability(did).clean(cx),
- deprecation: tcx.lookup_deprecation(did).clean(cx),
- def_id: did
+ stability: tcx.lookup_stability(item.def_id).clean(cx),
+ deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
+ def_id: item.def_id
})
}
- ty::MethodTraitItem(method) => {
- if method.vis != ty::Visibility::Public && associated_trait.is_none() {
+ ty::AssociatedKind::Method => {
+ if item.vis != ty::Visibility::Public && associated_trait.is_none() {
return None
}
- let mut item = method.clean(cx);
- item.inner = match item.inner.clone() {
+ let mut cleaned = item.clean(cx);
+ cleaned.inner = match cleaned.inner.clone() {
clean::TyMethodItem(clean::TyMethod {
unsafety, decl, generics, abi
}) => {
- let constness = if tcx.sess.cstore.is_const_fn(did) {
+ let constness = if tcx.sess.cstore.is_const_fn(item.def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
}
_ => panic!("not a tymethod"),
};
- Some(item)
+ Some(cleaned)
}
- ty::TypeTraitItem(ref assoc_ty) => {
- let did = assoc_ty.def_id;
+ ty::AssociatedKind::Type => {
let typedef = clean::Typedef {
- type_: assoc_ty.ty.unwrap().clean(cx),
+ type_: tcx.lookup_item_type(item.def_id).ty.clean(cx),
generics: clean::Generics {
lifetimes: vec![],
type_params: vec![],
}
};
Some(clean::Item {
- name: Some(assoc_ty.name.clean(cx)),
+ name: Some(item.name.clean(cx)),
inner: clean::TypedefItem(typedef, true),
source: clean::Span::empty(),
attrs: vec![],
visibility: None,
- stability: tcx.lookup_stability(did).clean(cx),
- deprecation: tcx.lookup_deprecation(did).clean(cx),
- def_id: did
+ stability: tcx.lookup_stability(item.def_id).clean(cx),
+ deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
+ def_id: item.def_id
})
}
}
}
}
-impl<'tcx> Clean<Item> for ty::Method<'tcx> {
+impl<'tcx> Clean<Item> for ty::AssociatedItem {
fn clean(&self, cx: &DocContext) -> Item {
- let generics = (self.generics, &self.predicates).clean(cx);
- let mut decl = (self.def_id, &self.fty.sig).clean(cx);
- match self.explicit_self {
- ty::ExplicitSelfCategory::ByValue => {
- decl.inputs.values[0].type_ = Infer;
+ let inner = match self.kind {
+ ty::AssociatedKind::Const => {
+ let ty = cx.tcx().lookup_item_type(self.def_id).ty;
+ AssociatedConstItem(ty.clean(cx), None)
}
- ty::ExplicitSelfCategory::ByReference(..) => {
- match decl.inputs.values[0].type_ {
- BorrowedRef{ref mut type_, ..} => **type_ = Infer,
- _ => unreachable!(),
+ ty::AssociatedKind::Method => {
+ let generics = (cx.tcx().lookup_generics(self.def_id),
+ &cx.tcx().lookup_predicates(self.def_id)).clean(cx);
+ let fty = match cx.tcx().lookup_item_type(self.def_id).ty.sty {
+ ty::TyFnDef(_, _, f) => f,
+ _ => unreachable!()
+ };
+ let mut decl = (self.def_id, &fty.sig).clean(cx);
+
+ if self.method_has_self_argument {
+ let self_ty = match self.container {
+ ty::ImplContainer(def_id) => {
+ cx.tcx().lookup_item_type(def_id).ty
+ }
+ ty::TraitContainer(_) => cx.tcx().mk_self_type()
+ };
+ let self_arg_ty = *fty.sig.input(0).skip_binder();
+ if self_arg_ty == self_ty {
+ decl.inputs.values[0].type_ = Infer;
+ } else if let ty::TyRef(_, mt) = self_arg_ty.sty {
+ if mt.ty == self_ty {
+ match decl.inputs.values[0].type_ {
+ BorrowedRef{ref mut type_, ..} => **type_ = Infer,
+ _ => unreachable!(),
+ }
+ }
+ }
+ }
+ let provided = match self.container {
+ ty::ImplContainer(_) => false,
+ ty::TraitContainer(_) => self.has_value
+ };
+ if provided {
+ MethodItem(Method {
+ unsafety: fty.unsafety,
+ generics: generics,
+ decl: decl,
+ abi: fty.abi,
+
+ // trait methods canot (currently, at least) be const
+ constness: hir::Constness::NotConst,
+ })
+ } else {
+ TyMethodItem(TyMethod {
+ unsafety: fty.unsafety,
+ generics: generics,
+ decl: decl,
+ abi: fty.abi,
+ })
}
}
- _ => {}
- }
- let provided = match self.container {
- ty::ImplContainer(..) => false,
- ty::TraitContainer(did) => {
- cx.tcx().provided_trait_methods(did).iter().any(|m| {
- m.def_id == self.def_id
- })
+ ty::AssociatedKind::Type => {
+ let my_name = self.name.clean(cx);
+
+ let mut bounds = if let ty::TraitContainer(did) = self.container {
+ // When loading a cross-crate associated type, the bounds for this type
+ // are actually located on the trait/impl itself, so we need to load
+ // all of the generics from there and then look for bounds that are
+ // applied to this associated type in question.
+ let def = cx.tcx().lookup_trait_def(did);
+ let predicates = cx.tcx().lookup_predicates(did);
+ let generics = (def.generics, &predicates).clean(cx);
+ generics.where_predicates.iter().filter_map(|pred| {
+ let (name, self_type, trait_, bounds) = match *pred {
+ WherePredicate::BoundPredicate {
+ ty: QPath { ref name, ref self_type, ref trait_ },
+ ref bounds
+ } => (name, self_type, trait_, bounds),
+ _ => return None,
+ };
+ if *name != my_name { return None }
+ match **trait_ {
+ ResolvedPath { did, .. } if did == self.container.id() => {}
+ _ => return None,
+ }
+ match **self_type {
+ Generic(ref s) if *s == "Self" => {}
+ _ => return None,
+ }
+ Some(bounds)
+ }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
+ } else {
+ vec![]
+ };
+
+ // Our Sized/?Sized bound didn't get handled when creating the generics
+ // because we didn't actually get our whole set of bounds until just now
+ // (some of them may have come from the trait). If we do have a sized
+ // bound, we remove it, and if we don't then we add the `?Sized` bound
+ // at the end.
+ match bounds.iter().position(|b| b.is_sized_bound(cx)) {
+ Some(i) => { bounds.remove(i); }
+ None => bounds.push(TyParamBound::maybe_sized(cx)),
+ }
+
+ let ty = if self.has_value {
+ Some(cx.tcx().lookup_item_type(self.def_id).ty)
+ } else {
+ None
+ };
+
+ AssociatedTypeItem(bounds, ty.clean(cx))
}
};
- let inner = if provided {
- MethodItem(Method {
- unsafety: self.fty.unsafety,
- generics: generics,
- decl: decl,
- abi: self.fty.abi,
-
- // trait methods canot (currently, at least) be const
- constness: hir::Constness::NotConst,
- })
- } else {
- TyMethodItem(TyMethod {
- unsafety: self.fty.unsafety,
- generics: generics,
- decl: decl,
- abi: self.fty.abi,
- })
- };
Item {
name: Some(self.name.clean(cx)),
}
}
-impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
- fn clean(&self, cx: &DocContext) -> Item {
- match *self {
- ty::ConstTraitItem(ref cti) => cti.clean(cx),
- ty::MethodTraitItem(ref mti) => mti.clean(cx),
- ty::TypeTraitItem(ref tti) => tti.clean(cx),
- }
- }
-}
-
/// A trait reference, which may have higher ranked lifetimes.
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub struct PolyTrait {
}
}
-impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
- fn clean(&self, cx: &DocContext) -> Item {
- Item {
- source: DUMMY_SP.clean(cx),
- name: Some(self.name.clean(cx)),
- attrs: Vec::new(),
- inner: AssociatedConstItem(self.ty.clean(cx), None),
- visibility: None,
- def_id: self.def_id,
- stability: None,
- deprecation: None,
- }
- }
-}
-
-impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
- fn clean(&self, cx: &DocContext) -> Item {
- let my_name = self.name.clean(cx);
-
- let mut bounds = if let ty::TraitContainer(did) = self.container {
- // When loading a cross-crate associated type, the bounds for this type
- // are actually located on the trait/impl itself, so we need to load
- // all of the generics from there and then look for bounds that are
- // applied to this associated type in question.
- let def = cx.tcx().lookup_trait_def(did);
- let predicates = cx.tcx().lookup_predicates(did);
- let generics = (def.generics, &predicates).clean(cx);
- generics.where_predicates.iter().filter_map(|pred| {
- let (name, self_type, trait_, bounds) = match *pred {
- WherePredicate::BoundPredicate {
- ty: QPath { ref name, ref self_type, ref trait_ },
- ref bounds
- } => (name, self_type, trait_, bounds),
- _ => return None,
- };
- if *name != my_name { return None }
- match **trait_ {
- ResolvedPath { did, .. } if did == self.container.id() => {}
- _ => return None,
- }
- match **self_type {
- Generic(ref s) if *s == "Self" => {}
- _ => return None,
- }
- Some(bounds)
- }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
- } else {
- vec![]
- };
-
- // Our Sized/?Sized bound didn't get handled when creating the generics
- // because we didn't actually get our whole set of bounds until just now
- // (some of them may have come from the trait). If we do have a sized
- // bound, we remove it, and if we don't then we add the `?Sized` bound
- // at the end.
- match bounds.iter().position(|b| b.is_sized_bound(cx)) {
- Some(i) => { bounds.remove(i); }
- None => bounds.push(TyParamBound::maybe_sized(cx)),
- }
-
- Item {
- source: DUMMY_SP.clean(cx),
- name: Some(self.name.clean(cx)),
- attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
- inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
- visibility: self.vis.clean(cx),
- def_id: self.def_id,
- stability: cx.tcx().lookup_stability(self.def_id).clean(cx),
- deprecation: cx.tcx().lookup_deprecation(self.def_id).clean(cx),
- }
- }
-}
-
fn lang_struct(cx: &DocContext, did: Option<DefId>,
t: ty::Ty, name: &str,
fallback: fn(Box<Type>) -> Type) -> Type {