fallout from separating impl-items from impls
Basically adding `visit_impl_item` in various places and so forth.
This commit is contained in:
parent
b889259e2b
commit
3fd67eba87
@ -56,6 +56,7 @@ use super::intravisit::Visitor;
|
||||
/// needed.
|
||||
pub trait ItemLikeVisitor<'hir> {
|
||||
fn visit_item(&mut self, item: &'hir Item);
|
||||
fn visit_impl_item(&mut self, impl_item: &'hir ImplItem);
|
||||
}
|
||||
|
||||
pub struct DeepVisitor<'v, V: 'v> {
|
||||
@ -76,4 +77,8 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V>
|
||||
fn visit_item(&mut self, item: &'hir Item) {
|
||||
self.visitor.visit_item(item);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) {
|
||||
self.visitor.visit_impl_item(impl_item);
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +99,10 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
|
||||
self.visit_impl_item(self.krate.impl_item(item_id))
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, i: &'ast Item) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
|
||||
|
@ -797,8 +797,13 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
|
||||
/// items in the context of the outer item, so enable
|
||||
/// deep-walking.
|
||||
fn visit_nested_item(&mut self, item: hir::ItemId) {
|
||||
let tcx = self.tcx;
|
||||
self.visit_item(tcx.map.expect_item(item.id))
|
||||
let item = self.tcx.map.expect_item(item.id);
|
||||
self.visit_item(item)
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
|
||||
let impl_item = self.tcx.map.impl_item(item_id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, it: &hir::Item) {
|
||||
|
@ -330,11 +330,12 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
|
||||
// or
|
||||
// 2) We are not sure to be live or not
|
||||
// * Implementation of a trait method
|
||||
struct LifeSeeder {
|
||||
worklist: Vec<ast::NodeId>
|
||||
struct LifeSeeder<'k> {
|
||||
worklist: Vec<ast::NodeId>,
|
||||
krate: &'k hir::Crate,
|
||||
}
|
||||
|
||||
impl<'v> ItemLikeVisitor<'v> for LifeSeeder {
|
||||
impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
let allow_dead_code = has_allow_dead_code_or_lang_attr(&item.attrs);
|
||||
if allow_dead_code {
|
||||
@ -358,17 +359,22 @@ impl<'v> ItemLikeVisitor<'v> for LifeSeeder {
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ItemImpl(.., ref opt_trait, _, ref impl_items) => {
|
||||
for impl_item in impl_items {
|
||||
hir::ItemImpl(.., ref opt_trait, _, ref impl_item_ids) => {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = self.krate.impl_item(impl_item_id);
|
||||
if opt_trait.is_some() ||
|
||||
has_allow_dead_code_or_lang_attr(&impl_item.attrs) {
|
||||
self.worklist.push(impl_item.id);
|
||||
self.worklist.push(impl_item_id.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _item: &hir::ImplItem) {
|
||||
// ignore: we are handling this in `visit_item` above
|
||||
}
|
||||
}
|
||||
|
||||
fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
@ -387,7 +393,8 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
// Seed implemented trait items
|
||||
let mut life_seeder = LifeSeeder {
|
||||
worklist: worklist
|
||||
worklist: worklist,
|
||||
krate: krate,
|
||||
};
|
||||
krate.visit_all_item_likes(&mut life_seeder);
|
||||
|
||||
@ -510,8 +517,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
|
||||
/// an error. We could do this also by checking the parents, but
|
||||
/// this is how the code is setup and it seems harmless enough.
|
||||
fn visit_nested_item(&mut self, item: hir::ItemId) {
|
||||
let tcx = self.tcx;
|
||||
self.visit_item(tcx.map.expect_item(item.id))
|
||||
let item = self.tcx.map.expect_item(item.id);
|
||||
self.visit_item(item)
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
|
||||
let impl_item = self.tcx.map.impl_item(item_id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
|
@ -17,7 +17,7 @@ use syntax::ast::NodeId;
|
||||
use syntax::attr;
|
||||
use syntax::entry::EntryPointType;
|
||||
use syntax_pos::Span;
|
||||
use hir::{Item, ItemFn};
|
||||
use hir::{Item, ItemFn, ImplItem};
|
||||
use hir::itemlikevisit::ItemLikeVisitor;
|
||||
|
||||
struct EntryContext<'a, 'tcx: 'a> {
|
||||
@ -46,6 +46,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
|
||||
let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
|
||||
find_item(item, self, at_root);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) {
|
||||
// entry fn is never an impl item
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
|
||||
|
@ -164,6 +164,10 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
// at present, lang items are always items, not impl items
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
|
||||
|
@ -336,6 +336,10 @@ impl<'a, 'v> ItemLikeVisitor<'v> for CollectPrivateImplItemsVisitor<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
// processed in visit_item above
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
@ -141,6 +141,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> {
|
||||
self.visit_item(item)
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, id: hir::ImplItemId) {
|
||||
let impl_item = self.hir_map.impl_item(id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
// Save labels for nested items.
|
||||
let saved_labels_in_fn = replace(&mut self.labels_in_fn, vec![]);
|
||||
|
@ -239,8 +239,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
|
||||
/// nested items in the context of the outer item, so enable
|
||||
/// deep-walking.
|
||||
fn visit_nested_item(&mut self, item: hir::ItemId) {
|
||||
let tcx = self.tcx;
|
||||
self.visit_item(tcx.map.expect_item(item.id))
|
||||
let item = self.tcx.map.expect_item(item.id);
|
||||
self.visit_item(item)
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
|
||||
let impl_item = self.tcx.map.impl_item(item_id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, i: &Item) {
|
||||
@ -449,8 +454,13 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
|
||||
/// nested items in the context of the outer item, so enable
|
||||
/// deep-walking.
|
||||
fn visit_nested_item(&mut self, item: hir::ItemId) {
|
||||
let tcx = self.tcx;
|
||||
self.visit_item(tcx.map.expect_item(item.id))
|
||||
let item = self.tcx.map.expect_item(item.id);
|
||||
self.visit_item(item)
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
|
||||
let impl_item = self.tcx.map.impl_item(item_id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
@ -527,9 +537,10 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// For implementations of traits, check the stability of each item
|
||||
// individually as it's possible to have a stable trait with unstable
|
||||
// items.
|
||||
hir::ItemImpl(.., Some(ref t), _, ref impl_items) => {
|
||||
hir::ItemImpl(.., Some(ref t), _, ref impl_item_ids) => {
|
||||
let trait_did = tcx.expect_def(t.ref_id).def_id();
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = tcx.map.impl_item(impl_item_id);
|
||||
let item = tcx.associated_items(trait_did)
|
||||
.find(|item| item.name == impl_item.name).unwrap();
|
||||
if warn_about_defns {
|
||||
|
@ -34,4 +34,8 @@ impl<'v> ItemLikeVisitor<'v> for Finder {
|
||||
self.registrar = Some(item.id);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,6 +171,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for IfThisChanged<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||
self.process_attrs(item.id, &item.attrs);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) {
|
||||
// handled in `visit_item` above
|
||||
}
|
||||
}
|
||||
|
||||
fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
@ -503,6 +503,12 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
|
||||
// Each item is hashed independently; ignore nested items.
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, impl_item_id: ImplItemId) {
|
||||
// For now, we hash impl items as part of the containing impl.
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
self.visit_impl_item(impl_item);
|
||||
}
|
||||
|
||||
fn visit_variant_data(&mut self,
|
||||
s: &'tcx VariantData,
|
||||
name: Name,
|
||||
|
@ -184,6 +184,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
@ -225,6 +228,9 @@ impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
|
||||
|
@ -1177,6 +1177,10 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
|
||||
// handled in `visit_item` above
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
@ -277,8 +277,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
.and_then(|impl_node_id| self.tcx.map.find(impl_node_id))
|
||||
.map(|node| {
|
||||
if let hir_map::NodeItem(item) = node {
|
||||
if let hir::ItemImpl(_, _, _, _, _, ref methods) = item.node {
|
||||
span = methods.first().map(|method| method.span);
|
||||
if let hir::ItemImpl(_, _, _, _, _, ref impl_item_ids) = item.node {
|
||||
span = impl_item_ids.first()
|
||||
.map(|&impl_item_id| {
|
||||
self.tcx.map.impl_item(impl_item_id)
|
||||
.span
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -44,6 +44,10 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
|
||||
self.with_context(Normal, |v| intravisit::walk_item(v, i));
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, i: &hir::ImplItem) {
|
||||
self.with_context(Normal, |v| intravisit::walk_impl_item(v, i));
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: &hir::Expr) {
|
||||
match e.node {
|
||||
hir::ExprWhile(ref e, ref b, _) => {
|
||||
|
@ -32,6 +32,9 @@ impl<'v> ItemLikeVisitor<'v> for RegistrarFinder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the function marked with `#[plugin_registrar]`, if any.
|
||||
|
@ -124,6 +124,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||
self.visit_item(tcx.map.expect_item(item.id))
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
|
||||
let impl_item = self.tcx.map.impl_item(item_id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
let inherited_item_level = match item.node {
|
||||
// Impls inherit level from their types and traits
|
||||
@ -159,15 +164,17 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ItemImpl(.., None, _, ref impl_items) => {
|
||||
for impl_item in impl_items {
|
||||
hir::ItemImpl(.., None, _, ref impl_item_ids) => {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
if impl_item.vis == hir::Public {
|
||||
self.update(impl_item.id, item_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ItemImpl(.., Some(_), _, ref impl_items) => {
|
||||
for impl_item in impl_items {
|
||||
hir::ItemImpl(.., Some(_), _, ref impl_item_ids) => {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
self.update(impl_item.id, item_level);
|
||||
}
|
||||
}
|
||||
@ -250,11 +257,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||
// The interface is empty
|
||||
hir::ItemDefaultImpl(..) => {}
|
||||
// Visit everything except for private impl items
|
||||
hir::ItemImpl(.., ref generics, None, _, ref impl_items) => {
|
||||
hir::ItemImpl(.., ref generics, None, _, ref impl_item_ids) => {
|
||||
if item_level.is_some() {
|
||||
self.reach().visit_generics(generics);
|
||||
for impl_item in impl_items {
|
||||
if self.get(impl_item.id).is_some() {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
if self.get(impl_item_id.id).is_some() {
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
self.reach().visit_impl_item(impl_item);
|
||||
}
|
||||
}
|
||||
@ -319,6 +327,12 @@ impl<'b, 'a, 'tcx: 'a> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
|
||||
fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
|
||||
// when we visit an impl, its methods and items are part of its "interface"
|
||||
let impl_item = self.ev.tcx.map.impl_item(item_id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &hir::Ty) {
|
||||
if let hir::TyPath(_, ref path) = ty.node {
|
||||
let def = self.ev.tcx.expect_def(ty.id);
|
||||
@ -421,6 +435,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
self.visit_item(tcx.map.expect_item(item.id))
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
|
||||
let impl_item = self.tcx.map.impl_item(item_id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
let orig_curitem = replace(&mut self.curitem, item.id);
|
||||
intravisit::walk_item(self, item);
|
||||
@ -625,6 +644,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
|
||||
self.visit_item(tcx.map.expect_item(item.id))
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
|
||||
let impl_item = self.tcx.map.impl_item(item_id);
|
||||
self.visit_impl_item(impl_item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
match item.node {
|
||||
// contents of a private mod can be reexported, so we need
|
||||
@ -650,7 +674,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
|
||||
// (i.e. we could just return here to not check them at
|
||||
// all, or some worse estimation of whether an impl is
|
||||
// publicly visible).
|
||||
hir::ItemImpl(.., ref g, ref trait_ref, ref self_, ref impl_items) => {
|
||||
hir::ItemImpl(.., ref g, ref trait_ref, ref self_, ref impl_item_ids) => {
|
||||
// `impl [... for] Private` is never visible.
|
||||
let self_contains_private;
|
||||
// impl [... for] Public<...>, but not `impl [... for]
|
||||
@ -695,16 +719,17 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
|
||||
// are private (because `T` won't be visible externally).
|
||||
let trait_or_some_public_method =
|
||||
trait_ref.is_some() ||
|
||||
impl_items.iter()
|
||||
.any(|impl_item| {
|
||||
match impl_item.node {
|
||||
hir::ImplItemKind::Const(..) |
|
||||
hir::ImplItemKind::Method(..) => {
|
||||
self.access_levels.is_reachable(impl_item.id)
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => false,
|
||||
}
|
||||
});
|
||||
impl_item_ids.iter()
|
||||
.any(|&impl_item_id| {
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
match impl_item.node {
|
||||
hir::ImplItemKind::Const(..) |
|
||||
hir::ImplItemKind::Method(..) => {
|
||||
self.access_levels.is_reachable(impl_item.id)
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => false,
|
||||
}
|
||||
});
|
||||
|
||||
if !self_contains_private &&
|
||||
not_private_trait &&
|
||||
@ -714,12 +739,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
|
||||
|
||||
match *trait_ref {
|
||||
None => {
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
// This is where we choose whether to walk down
|
||||
// further into the impl to check its items. We
|
||||
// should only walk into public items so that we
|
||||
// don't erroneously report errors for private
|
||||
// types in private items.
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
match impl_item.node {
|
||||
hir::ImplItemKind::Const(..) |
|
||||
hir::ImplItemKind::Method(..)
|
||||
@ -751,7 +777,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
|
||||
intravisit::walk_path(self, &tr.path);
|
||||
|
||||
// Those in 3. are warned with this call.
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
if let hir::ImplItemKind::Type(ref ty) = impl_item.node {
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
@ -762,7 +789,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
|
||||
// impl Public<Private> { ... }. Any public static
|
||||
// methods will be visible as `Public::foo`.
|
||||
let mut found_pub_static = false;
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
match impl_item.node {
|
||||
hir::ImplItemKind::Const(..) => {
|
||||
if self.item_is_public(&impl_item.id, &impl_item.vis) {
|
||||
@ -1086,12 +1114,13 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for PrivateItemsInPublicInterfacesVisitor
|
||||
hir::ItemDefaultImpl(..) => {}
|
||||
// An inherent impl is public when its type is public
|
||||
// Subitems of inherent impls have their own publicity
|
||||
hir::ItemImpl(.., ref generics, None, ref ty, ref impl_items) => {
|
||||
hir::ItemImpl(.., ref generics, None, ref ty, ref impl_item_ids) => {
|
||||
let ty_vis = self.ty_visibility(ty);
|
||||
check.required_visibility = ty_vis;
|
||||
check.visit_generics(generics);
|
||||
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
let impl_item_vis =
|
||||
ty::Visibility::from_hir(&impl_item.vis, item.id, self.tcx);
|
||||
check.required_visibility = min(impl_item_vis, ty_vis);
|
||||
@ -1100,16 +1129,21 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for PrivateItemsInPublicInterfacesVisitor
|
||||
}
|
||||
// A trait impl is public when both its type and its trait are public
|
||||
// Subitems of trait impls have inherited publicity
|
||||
hir::ItemImpl(.., ref generics, Some(ref trait_ref), ref ty, ref impl_items) => {
|
||||
hir::ItemImpl(.., ref generics, Some(ref trait_ref), ref ty, ref impl_item_ids) => {
|
||||
let vis = min(self.ty_visibility(ty), self.trait_ref_visibility(trait_ref));
|
||||
check.required_visibility = vis;
|
||||
check.visit_generics(generics);
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = self.tcx.map.impl_item(impl_item_id);
|
||||
check.visit_impl_item(impl_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
|
||||
// handled in `visit_item` above
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
@ -189,7 +189,7 @@
|
||||
//! regardless of whether it is actually needed or not.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::{self, Visitor};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::def_id::DefId;
|
||||
@ -308,7 +308,7 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
output: &mut roots,
|
||||
};
|
||||
|
||||
scx.tcx().map.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
|
||||
scx.tcx().map.krate().visit_all_item_likes(&mut visitor);
|
||||
}
|
||||
|
||||
roots
|
||||
@ -1031,7 +1031,7 @@ struct RootCollector<'b, 'a: 'b, 'tcx: 'a + 'b> {
|
||||
output: &'b mut Vec<TransItem<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'b, 'a, 'v> Visitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||
impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||
fn visit_item(&mut self, item: &'v hir::Item) {
|
||||
match item.node {
|
||||
hir::ItemExternCrate(..) |
|
||||
@ -1089,8 +1089,6 @@ impl<'b, 'a, 'v> Visitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intravisit::walk_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
|
||||
@ -1125,8 +1123,6 @@ impl<'b, 'a, 'v> Visitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||
}
|
||||
_ => { /* Nothing to do here */ }
|
||||
}
|
||||
|
||||
intravisit::walk_impl_item(self, ii)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1151,9 +1147,11 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
|
||||
|
||||
if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
|
||||
let callee_substs = tcx.erase_regions(&trait_ref.substs);
|
||||
let overridden_methods: FxHashSet<_> = items.iter()
|
||||
.map(|item| item.name)
|
||||
.collect();
|
||||
let overridden_methods: FxHashSet<_> =
|
||||
items.iter()
|
||||
.map(|&id| tcx.map.impl_item(id))
|
||||
.map(|item| item.name)
|
||||
.collect();
|
||||
for method in tcx.provided_trait_methods(trait_ref.def_id) {
|
||||
if overridden_methods.contains(&method.name) {
|
||||
continue;
|
||||
|
@ -460,6 +460,9 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
ccx.tcx.map.krate().visit_all_item_likes(&mut Visitor {
|
||||
map: &ccx.tcx.map,
|
||||
|
@ -530,6 +530,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
|
||||
fn visit_item(&mut self, i: &'tcx hir::Item) {
|
||||
check_item_body(self.ccx, i);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _item: &'tcx hir::ImplItem) {
|
||||
// done as part of `visit_item` above
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_wf_new(ccx: &CrateCtxt) -> CompileResult {
|
||||
@ -811,7 +815,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
||||
it.id);
|
||||
}
|
||||
hir::ItemFn(..) => {} // entirely within check_item_body
|
||||
hir::ItemImpl(.., ref impl_items) => {
|
||||
hir::ItemImpl(.., ref impl_item_ids) => {
|
||||
debug!("ItemImpl {} with id {}", it.name, it.id);
|
||||
let impl_def_id = ccx.tcx.map.local_def_id(it.id);
|
||||
if let Some(impl_trait_ref) = ccx.tcx.impl_trait_ref(impl_def_id) {
|
||||
@ -819,7 +823,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
||||
it.span,
|
||||
impl_def_id,
|
||||
impl_trait_ref,
|
||||
impl_items);
|
||||
impl_item_ids);
|
||||
let trait_def_id = impl_trait_ref.def_id;
|
||||
check_on_unimplemented(ccx, trait_def_id, it);
|
||||
}
|
||||
@ -881,10 +885,11 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
||||
hir::ItemFn(ref decl, .., ref body) => {
|
||||
check_bare_fn(ccx, &decl, &body, it.id, it.span);
|
||||
}
|
||||
hir::ItemImpl(.., ref impl_items) => {
|
||||
hir::ItemImpl(.., ref impl_item_ids) => {
|
||||
debug!("ItemImpl {} with id {}", it.name, it.id);
|
||||
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = ccx.tcx.map.impl_item(impl_item_id);
|
||||
match impl_item.node {
|
||||
hir::ImplItemKind::Const(_, ref expr) => {
|
||||
check_const(ccx, &expr, impl_item.id)
|
||||
@ -1021,7 +1026,7 @@ 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_items: &[hir::ImplItem]) {
|
||||
impl_item_ids: &[hir::ImplItemId]) {
|
||||
// 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`
|
||||
// isn't populated for such impls.
|
||||
@ -1032,9 +1037,11 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
let trait_def = tcx.lookup_trait_def(impl_trait_ref.def_id);
|
||||
let mut overridden_associated_type = None;
|
||||
|
||||
let impl_items = || impl_item_ids.iter().map(|&id| ccx.tcx.map.impl_item(id));
|
||||
|
||||
// Check existing impl methods to see if they are both present in trait
|
||||
// and compatible with trait signature
|
||||
for impl_item in impl_items {
|
||||
for impl_item in impl_items() {
|
||||
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);
|
||||
|
@ -58,6 +58,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
|
@ -57,6 +57,9 @@ impl<'a, 'gcx, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCheckVisitor<'a, 'gcx,
|
||||
self.cc.check_implementation(item)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
|
||||
|
@ -384,4 +384,8 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
self.check_item(item);
|
||||
}
|
||||
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
@ -199,4 +199,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
@ -106,4 +106,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +149,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
intravisit::walk_ty(self, ty);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
// handled in `visit_item` above; we may want to break this out later
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -727,7 +731,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
ref generics,
|
||||
ref opt_trait_ref,
|
||||
ref selfty,
|
||||
ref impl_items) => {
|
||||
ref impl_item_ids) => {
|
||||
// Create generics from the generics specified in the impl head.
|
||||
debug!("convert: ast_generics={:?}", generics);
|
||||
let def_id = ccx.tcx.map.local_def_id(it.id);
|
||||
@ -757,7 +761,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
let mut seen_type_items = FxHashMap();
|
||||
let mut seen_value_items = FxHashMap();
|
||||
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = tcx.map.impl_item(impl_item_id);
|
||||
let seen_items = match impl_item.node {
|
||||
hir::ImplItemKind::Type(_) => &mut seen_type_items,
|
||||
_ => &mut seen_value_items,
|
||||
@ -790,7 +795,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
}
|
||||
|
||||
// Convert all the associated types.
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = tcx.map.impl_item(impl_item_id);
|
||||
if let hir::ImplItemKind::Type(ref ty) = impl_item.node {
|
||||
let type_def_id = ccx.tcx.map.local_def_id(impl_item.id);
|
||||
generics_of_def_id(ccx, type_def_id);
|
||||
@ -806,7 +812,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
}
|
||||
}
|
||||
|
||||
for impl_item in impl_items {
|
||||
for &impl_item_id in impl_item_ids {
|
||||
let impl_item = tcx.map.impl_item(impl_item_id);
|
||||
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||
convert_method(ccx, ImplContainer(def_id),
|
||||
impl_item.id, sig, selfty,
|
||||
@ -814,7 +821,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
|
||||
}
|
||||
}
|
||||
|
||||
enforce_impl_lifetimes_are_constrained(ccx, generics, def_id, impl_items);
|
||||
enforce_impl_lifetimes_are_constrained(ccx, generics, def_id, impl_item_ids);
|
||||
},
|
||||
hir::ItemTrait(.., ref trait_items) => {
|
||||
let trait_def = trait_def_of_item(ccx, it);
|
||||
@ -2103,7 +2110,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
ast_generics: &hir::Generics,
|
||||
impl_def_id: DefId,
|
||||
impl_items: &[hir::ImplItem])
|
||||
impl_item_ids: &[hir::ImplItemId])
|
||||
{
|
||||
// Every lifetime used in an associated type must be constrained.
|
||||
let impl_ty = ccx.tcx.item_type(impl_def_id);
|
||||
@ -2118,8 +2125,8 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
ctp::identify_constrained_type_params(
|
||||
&impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
|
||||
|
||||
let lifetimes_in_associated_types: FxHashSet<_> = impl_items.iter()
|
||||
.map(|item| ccx.tcx.map.local_def_id(item.id))
|
||||
let lifetimes_in_associated_types: FxHashSet<_> = impl_item_ids.iter()
|
||||
.map(|item_id| ccx.tcx.map.local_def_id(item_id.id))
|
||||
.filter(|&def_id| {
|
||||
let item = ccx.tcx.associated_item(def_id);
|
||||
item.kind == ty::AssociatedKind::Type && item.has_value
|
||||
|
@ -115,6 +115,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
|
||||
hir::ItemDefaultImpl(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Is `param_id` a lifetime according to `map`?
|
||||
|
@ -257,4 +257,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
|
||||
hir::ItemTy(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
@ -502,10 +502,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
om.traits.push(t);
|
||||
},
|
||||
|
||||
hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref items) => {
|
||||
hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref item_ids) => {
|
||||
// Don't duplicate impls when inlining, we'll pick them up
|
||||
// regardless of where they're located.
|
||||
if !self.inlining {
|
||||
let items = item_ids.iter()
|
||||
.map(|&id| self.cx.map.impl_item(id).clone())
|
||||
.collect();
|
||||
let i = Impl {
|
||||
unsafety: unsafety,
|
||||
polarity: polarity,
|
||||
|
Loading…
x
Reference in New Issue
Block a user