1
Fork 0

Auto merge of #96531 - kckeiks:remove-item-like-visitor-from-rustc-typeck, r=cjgillot

Remove ItemLikeVisitor impls from rustc_typeck

Issue #95004
cc `@cjgillot`
This commit is contained in:
bors 2022-05-07 01:59:11 +00:00
commit f6e5570460
23 changed files with 512 additions and 553 deletions

View file

@ -6,7 +6,7 @@ use rustc_session::cstore::ForeignModule;
crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> { crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
let mut modules = Vec::new(); let mut modules = Vec::new();
for id in tcx.hir().items() { for id in tcx.hir().items() {
if !matches!(tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) { if !matches!(tcx.def_kind(id.def_id), DefKind::ForeignMod) {
continue; continue;
} }
let item = tcx.hir().item(id); let item = tcx.hir().item(id);

View file

@ -36,7 +36,7 @@ struct Collector<'tcx> {
impl<'tcx> Collector<'tcx> { impl<'tcx> Collector<'tcx> {
fn process_item(&mut self, id: rustc_hir::ItemId) { fn process_item(&mut self, id: rustc_hir::ItemId) {
if !matches!(self.tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) { if !matches!(self.tcx.def_kind(id.def_id), DefKind::ForeignMod) {
return; return;
} }

View file

@ -1813,7 +1813,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
FxHashMap::default(); FxHashMap::default();
for id in tcx.hir().items() { for id in tcx.hir().items() {
if matches!(tcx.hir().def_kind(id.def_id), DefKind::Impl) { if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) { if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
let simplified_self_ty = fast_reject::simplify_type( let simplified_self_ty = fast_reject::simplify_type(
self.tcx, self.tcx,

View file

@ -308,11 +308,6 @@ impl<'hir> Map<'hir> {
Some(def_kind) Some(def_kind)
} }
pub fn def_kind(self, local_def_id: LocalDefId) -> DefKind {
self.opt_def_kind(local_def_id)
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", local_def_id))
}
pub fn find_parent_node(self, id: HirId) -> Option<HirId> { pub fn find_parent_node(self, id: HirId) -> Option<HirId> {
if id.local_id == ItemLocalId::from_u32(0) { if id.local_id == ItemLocalId::from_u32(0) {
Some(self.tcx.hir_owner_parent(id.owner)) Some(self.tcx.hir_owner_parent(id.owner))

View file

@ -2676,7 +2676,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
// Iterate all local crate items no matter where they are defined. // Iterate all local crate items no matter where they are defined.
let hir = tcx.hir(); let hir = tcx.hir();
for id in hir.items() { for id in hir.items() {
if matches!(hir.def_kind(id.def_id), DefKind::Use) { if matches!(tcx.def_kind(id.def_id), DefKind::Use) {
continue; continue;
} }

View file

@ -1164,7 +1164,7 @@ struct RootCollector<'a, 'tcx> {
impl<'v> RootCollector<'_, 'v> { impl<'v> RootCollector<'_, 'v> {
fn process_item(&mut self, id: hir::ItemId) { fn process_item(&mut self, id: hir::ItemId) {
match self.tcx.hir().def_kind(id.def_id) { match self.tcx.def_kind(id.def_id) {
DefKind::Enum | DefKind::Struct | DefKind::Union => { DefKind::Enum | DefKind::Struct | DefKind::Union => {
let item = self.tcx.hir().item(id); let item = self.tcx.hir().item(id);
match item.kind { match item.kind {
@ -1225,7 +1225,7 @@ impl<'v> RootCollector<'_, 'v> {
} }
fn process_impl_item(&mut self, id: hir::ImplItemId) { fn process_impl_item(&mut self, id: hir::ImplItemId) {
if matches!(self.tcx.hir().def_kind(id.def_id), DefKind::AssocFn) { if matches!(self.tcx.def_kind(id.def_id), DefKind::AssocFn) {
self.push_if_root(id.def_id); self.push_if_root(id.def_id);
} }
} }

View file

@ -240,9 +240,9 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
let crate_items = tcx.hir_crate_items(()); let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() { for id in crate_items.items() {
collector.check_for_lang(Target::from_def_kind(tcx.hir().def_kind(id.def_id)), id.hir_id()); collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.def_id)), id.hir_id());
if matches!(tcx.hir().def_kind(id.def_id), DefKind::Enum) { if matches!(tcx.def_kind(id.def_id), DefKind::Enum) {
let item = tcx.hir().item(id); let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(def, ..) = &item.kind { if let hir::ItemKind::Enum(def, ..) = &item.kind {
for variant in def.variants { for variant in def.variants {

View file

@ -27,6 +27,7 @@ use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use rustc_ty_utils::representability::{self, Representability}; use rustc_ty_utils::representability::{self, Representability};
use rustc_hir::def::DefKind;
use std::iter; use std::iter;
use std::ops::ControlFlow; use std::ops::ControlFlow;
@ -711,28 +712,35 @@ fn check_opaque_meets_bounds<'tcx>(
}); });
} }
pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
debug!( debug!(
"check_item_type(it.def_id={:?}, it.name={})", "check_item_type(it.def_id={:?}, it.name={})",
it.def_id, id.def_id,
tcx.def_path_str(it.def_id.to_def_id()) tcx.def_path_str(id.def_id.to_def_id())
); );
let _indenter = indenter(); let _indenter = indenter();
match it.kind { match tcx.def_kind(id.def_id) {
// Consts can play a role in type-checking, so they are included here. DefKind::Static(..) => {
hir::ItemKind::Static(..) => { tcx.ensure().typeck(id.def_id);
tcx.ensure().typeck(it.def_id); maybe_check_static_with_link_section(tcx, id.def_id, tcx.def_span(id.def_id));
maybe_check_static_with_link_section(tcx, it.def_id, it.span); check_static_inhabited(tcx, id.def_id, tcx.def_span(id.def_id));
check_static_inhabited(tcx, it.def_id, it.span);
} }
hir::ItemKind::Const(..) => { DefKind::Const => {
tcx.ensure().typeck(it.def_id); tcx.ensure().typeck(id.def_id);
} }
hir::ItemKind::Enum(ref enum_definition, _) => { DefKind::Enum => {
check_enum(tcx, it.span, &enum_definition.variants, it.def_id); let item = tcx.hir().item(id);
let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else {
return;
};
check_enum(tcx, item.span, &enum_definition.variants, item.def_id);
} }
hir::ItemKind::Fn(..) => {} // entirely within check_item_body DefKind::Fn => {} // entirely within check_item_body
hir::ItemKind::Impl(ref impl_) => { DefKind::Impl => {
let it = tcx.hir().item(id);
let hir::ItemKind::Impl(ref impl_) = it.kind else {
return;
};
debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id); debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id);
if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) { if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) {
check_impl_items_against_trait( check_impl_items_against_trait(
@ -745,7 +753,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
check_on_unimplemented(tcx, it); check_on_unimplemented(tcx, it);
} }
} }
hir::ItemKind::Trait(_, _, _, _, ref items) => { DefKind::Trait => {
let it = tcx.hir().item(id);
let hir::ItemKind::Trait(_, _, _, _, ref items) = it.kind else {
return;
};
check_on_unimplemented(tcx, it); check_on_unimplemented(tcx, it);
for item in items.iter() { for item in items.iter() {
@ -771,28 +783,36 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
} }
} }
} }
hir::ItemKind::Struct(..) => { DefKind::Struct => {
check_struct(tcx, it.def_id, it.span); check_struct(tcx, id.def_id, tcx.def_span(id.def_id));
} }
hir::ItemKind::Union(..) => { DefKind::Union => {
check_union(tcx, it.def_id, it.span); check_union(tcx, id.def_id, tcx.def_span(id.def_id));
} }
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { DefKind::OpaqueTy => {
let item = tcx.hir().item(id);
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
return;
};
// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
// `async-std` (and `pub async fn` in general). // `async-std` (and `pub async fn` in general).
// Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it! // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
// See https://github.com/rust-lang/rust/issues/75100 // See https://github.com/rust-lang/rust/issues/75100
if !tcx.sess.opts.actually_rustdoc { if !tcx.sess.opts.actually_rustdoc {
let substs = InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
check_opaque(tcx, it.def_id, substs, it.span, &origin); check_opaque(tcx, item.def_id, substs, item.span, &origin);
} }
} }
hir::ItemKind::TyAlias(..) => { DefKind::TyAlias => {
let pty_ty = tcx.type_of(it.def_id); let pty_ty = tcx.type_of(id.def_id);
let generics = tcx.generics_of(it.def_id); let generics = tcx.generics_of(id.def_id);
check_type_params_are_used(tcx, &generics, pty_ty); check_type_params_are_used(tcx, &generics, pty_ty);
} }
hir::ItemKind::ForeignMod { abi, items } => { DefKind::ForeignMod => {
let it = tcx.hir().item(id);
let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
return;
};
check_abi(tcx, it.hir_id(), it.span, abi); check_abi(tcx, it.hir_id(), it.span, abi);
if abi == Abi::RustIntrinsic { if abi == Abi::RustIntrinsic {
@ -851,7 +871,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
} }
} }
} }
_ => { /* nothing to do */ } _ => {}
} }
} }
@ -1451,7 +1471,10 @@ pub(super) fn check_type_params_are_used<'tcx>(
} }
pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx }); let module = tcx.hir_module_items(module_def_id);
for id in module.items() {
check_item_type(tcx, id);
}
} }
pub(super) use wfcheck::check_item_well_formed; pub(super) use wfcheck::check_item_well_formed;

View file

@ -151,7 +151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => { Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => {
sugg_call = fields.iter().map(|_| "_").collect::<Vec<_>>().join(", "); sugg_call = fields.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
match def_id.as_local().map(|def_id| hir.def_kind(def_id)) { match def_id.as_local().map(|def_id| self.tcx.def_kind(def_id)) {
Some(DefKind::Ctor(hir::def::CtorOf::Variant, _)) => { Some(DefKind::Ctor(hir::def::CtorOf::Variant, _)) => {
msg = "instantiate this tuple variant"; msg = "instantiate this tuple variant";
} }

View file

@ -111,7 +111,6 @@ use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::{HirIdMap, ImplicitSelfKind, Node}; use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
@ -933,19 +932,6 @@ impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> {
} }
} }
struct CheckItemTypesVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
check_item_type(self.tcx, i);
}
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
}
fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) { fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id)); tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
} }

View file

@ -17,7 +17,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
} }
for id in tcx.hir().items() { for id in tcx.hir().items() {
if matches!(tcx.hir().def_kind(id.def_id), DefKind::Use) { if matches!(tcx.def_kind(id.def_id), DefKind::Use) {
if tcx.visibility(id.def_id).is_public() { if tcx.visibility(id.def_id).is_public() {
continue; continue;
} }
@ -101,7 +101,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
let mut crates_to_lint = vec![]; let mut crates_to_lint = vec![];
for id in tcx.hir().items() { for id in tcx.hir().items() {
if matches!(tcx.hir().def_kind(id.def_id), DefKind::ExternCrate) { if matches!(tcx.def_kind(id.def_id), DefKind::ExternCrate) {
let item = tcx.hir().item(id); let item = tcx.hir().item(id);
if let hir::ItemKind::ExternCrate(orig_name) = item.kind { if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
crates_to_lint.push(ExternCrateToLint { crates_to_lint.push(ExternCrateToLint {

View file

@ -9,8 +9,8 @@
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -19,7 +19,9 @@ use rustc_span::Span;
/// On-demand query: yields a map containing all types mapped to their inherent impls. /// On-demand query: yields a map containing all types mapped to their inherent impls.
pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls {
let mut collect = InherentCollect { tcx, impls_map: Default::default() }; let mut collect = InherentCollect { tcx, impls_map: Default::default() };
tcx.hir().visit_all_item_likes(&mut collect); for id in tcx.hir().items() {
collect.check_item(id);
}
collect.impls_map collect.impls_map
} }
@ -46,79 +48,6 @@ struct InherentCollect<'tcx> {
impls_map: CrateInherentImpls, impls_map: CrateInherentImpls,
} }
impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) {
let hir::ItemKind::Impl(hir::Impl { of_trait: None, self_ty: ty, ref items, .. }) = item.kind else {
return;
};
let self_ty = self.tcx.type_of(item.def_id);
match *self_ty.kind() {
ty::Adt(def, _) => {
self.check_def_id(item, self_ty, def.did());
}
ty::Foreign(did) => {
self.check_def_id(item, self_ty, did);
}
ty::Dynamic(data, ..) if data.principal_def_id().is_some() => {
self.check_def_id(item, self_ty, data.principal_def_id().unwrap());
}
ty::Dynamic(..) => {
struct_span_err!(
self.tcx.sess,
ty.span,
E0785,
"cannot define inherent `impl` for a dyn auto trait"
)
.span_label(ty.span, "impl requires at least one non-auto trait")
.note("define and implement a new trait or type instead")
.emit();
}
ty::Bool
| ty::Char
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_)
| ty::Str
| ty::Array(..)
| ty::Slice(_)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Never
| ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
let mut err = struct_span_err!(
self.tcx.sess,
ty.span,
E0118,
"no nominal type found for inherent implementation"
);
err.span_label(ty.span, "impl requires a nominal type")
.note("either implement a trait on it or create a newtype to wrap it instead");
err.emit();
}
ty::FnDef(..)
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => {
bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty);
}
ty::Error(_) => {}
}
}
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
}
const INTO_CORE: &str = "consider moving this inherent impl into `core` if possible"; const INTO_CORE: &str = "consider moving this inherent impl into `core` if possible";
const INTO_DEFINING_CRATE: &str = const INTO_DEFINING_CRATE: &str =
"consider moving this inherent impl into the crate defining the type if possible"; "consider moving this inherent impl into the crate defining the type if possible";
@ -246,4 +175,74 @@ impl<'tcx> InherentCollect<'tcx> {
bug!("unexpected primitive type: {:?}", ty); bug!("unexpected primitive type: {:?}", ty);
} }
} }
fn check_item(&mut self, id: hir::ItemId) {
if !matches!(self.tcx.def_kind(id.def_id), DefKind::Impl) {
return;
}
let item = self.tcx.hir().item(id);
let hir::ItemKind::Impl(hir::Impl { of_trait: None, self_ty: ty, ref items, .. }) = item.kind else {
return;
};
let self_ty = self.tcx.type_of(item.def_id);
match *self_ty.kind() {
ty::Adt(def, _) => {
self.check_def_id(item, self_ty, def.did());
}
ty::Foreign(did) => {
self.check_def_id(item, self_ty, did);
}
ty::Dynamic(data, ..) if data.principal_def_id().is_some() => {
self.check_def_id(item, self_ty, data.principal_def_id().unwrap());
}
ty::Dynamic(..) => {
struct_span_err!(
self.tcx.sess,
ty.span,
E0785,
"cannot define inherent `impl` for a dyn auto trait"
)
.span_label(ty.span, "impl requires at least one non-auto trait")
.note("define and implement a new trait or type instead")
.emit();
}
ty::Bool
| ty::Char
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_)
| ty::Str
| ty::Array(..)
| ty::Slice(_)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Never
| ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
let mut err = struct_span_err!(
self.tcx.sess,
ty.span,
E0118,
"no nominal type found for inherent implementation"
);
err.span_label(ty.span, "impl requires a nominal type")
.note("either implement a trait on it or create a newtype to wrap it instead");
err.emit();
}
ty::FnDef(..)
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => {
bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty);
}
ty::Error(_) => {}
}
}
} }

View file

@ -1,8 +1,8 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::traits::specialization_graph::OverlapMode;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
@ -12,7 +12,10 @@ use smallvec::SmallVec;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) { pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) {
tcx.hir().visit_all_item_likes(&mut InherentOverlapChecker { tcx }); let mut inherent_overlap_checker = InherentOverlapChecker { tcx };
for id in tcx.hir().items() {
inherent_overlap_checker.check_item(id);
}
} }
struct InherentOverlapChecker<'tcx> { struct InherentOverlapChecker<'tcx> {
@ -121,16 +124,14 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|| true, || true,
); );
} }
fn check_item(&mut self, id: hir::ItemId) {
let def_kind = self.tcx.def_kind(id.def_id);
if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) {
return;
} }
impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> { let impls = self.tcx.inherent_impls(id.def_id);
fn visit_item(&mut self, item: &hir::Item<'_>) {
match item.kind {
hir::ItemKind::Enum(..)
| hir::ItemKind::Struct(..)
| hir::ItemKind::Trait(..)
| hir::ItemKind::Union(..) => {
let impls = self.tcx.inherent_impls(item.def_id);
// If there is only one inherent impl block, // If there is only one inherent impl block,
// there is nothing to overlap check it with // there is nothing to overlap check it with
@ -138,7 +139,7 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> {
return; return;
} }
let overlap_mode = OverlapMode::get(self.tcx, item.def_id.to_def_id()); let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id());
let impls_items = impls let impls_items = impls
.iter() .iter()
@ -279,12 +280,7 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> {
.sum::<usize>(); .sum::<usize>();
s / connected_regions.len() s / connected_regions.len()
}, },
connected_regions connected_regions.iter().flatten().map(|r| r.impl_blocks.len()).max().unwrap()
.iter()
.flatten()
.map(|r| r.impl_blocks.len())
.max()
.unwrap()
); );
// List of connected regions is built. Now, run the overlap check // List of connected regions is built. Now, run the overlap check
// for each pair of impl blocks in the same connected region. // for each pair of impl blocks in the same connected region.
@ -308,13 +304,4 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> {
} }
} }
} }
_ => {}
}
}
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
} }

View file

@ -3,36 +3,43 @@
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::def::DefKind;
use rustc_hir::Unsafety; use rustc_hir::Unsafety;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
pub fn check(tcx: TyCtxt<'_>) { pub fn check(tcx: TyCtxt<'_>) {
let mut unsafety = UnsafetyChecker { tcx }; for id in tcx.hir().items() {
tcx.hir().visit_all_item_likes(&mut unsafety); if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(ref impl_) = item.kind {
check_unsafety_coherence(
tcx,
item,
Some(&impl_.generics),
impl_.unsafety,
impl_.polarity,
);
}
}
}
} }
struct UnsafetyChecker<'tcx> { fn check_unsafety_coherence<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
}
impl<'tcx> UnsafetyChecker<'tcx> {
fn check_unsafety_coherence(
&mut self,
item: &hir::Item<'_>, item: &hir::Item<'_>,
impl_generics: Option<&hir::Generics<'_>>, impl_generics: Option<&hir::Generics<'_>>,
unsafety: hir::Unsafety, unsafety: hir::Unsafety,
polarity: hir::ImplPolarity, polarity: hir::ImplPolarity,
) { ) {
if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id) { if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
let trait_def = self.tcx.trait_def(trait_ref.def_id); let trait_def = tcx.trait_def(trait_ref.def_id);
let unsafe_attr = impl_generics.and_then(|generics| { let unsafe_attr = impl_generics.and_then(|generics| {
generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
}); });
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
struct_span_err!( struct_span_err!(
self.tcx.sess, tcx.sess,
item.span, item.span,
E0199, E0199,
"implementing the trait `{}` is not unsafe", "implementing the trait `{}` is not unsafe",
@ -43,7 +50,7 @@ impl<'tcx> UnsafetyChecker<'tcx> {
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
struct_span_err!( struct_span_err!(
self.tcx.sess, tcx.sess,
item.span, item.span,
E0200, E0200,
"the trait `{}` requires an `unsafe impl` declaration", "the trait `{}` requires an `unsafe impl` declaration",
@ -52,14 +59,9 @@ impl<'tcx> UnsafetyChecker<'tcx> {
.emit(); .emit();
} }
( (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
Unsafety::Normal,
Some(attr_name),
Unsafety::Normal,
hir::ImplPolarity::Positive,
) => {
struct_span_err!( struct_span_err!(
self.tcx.sess, tcx.sess,
item.span, item.span,
E0569, E0569,
"requires an `unsafe impl` declaration due to `#[{}]` attribute", "requires an `unsafe impl` declaration due to `#[{}]` attribute",
@ -70,7 +72,7 @@ impl<'tcx> UnsafetyChecker<'tcx> {
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => { (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
// Reported in AST validation // Reported in AST validation
self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
} }
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_)) (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
| (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
@ -81,23 +83,3 @@ impl<'tcx> UnsafetyChecker<'tcx> {
} }
} }
} }
}
impl<'tcx> ItemLikeVisitor<'_> for UnsafetyChecker<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) {
if let hir::ItemKind::Impl(ref impl_) = item.kind {
self.check_unsafety_coherence(
item,
Some(&impl_.generics),
impl_.unsafety,
impl_.polarity,
);
}
}
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
}

View file

@ -14,8 +14,8 @@ use min_specialization::check_min_specialization;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_span::Span; use rustc_span::Span;
@ -63,37 +63,25 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) {
fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
let min_specialization = tcx.features().min_specialization; let min_specialization = tcx.features().min_specialization;
tcx.hir() let module = tcx.hir_module_items(module_def_id);
.visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx, min_specialization }); for id in module.items() {
if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(ref impl_) = item.kind {
enforce_impl_params_are_constrained(tcx, item.def_id, impl_.items);
enforce_impl_items_are_distinct(tcx, impl_.items);
if min_specialization {
check_min_specialization(tcx, item.def_id.to_def_id(), item.span);
}
}
}
}
} }
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_impl_wf, ..*providers }; *providers = Providers { check_mod_impl_wf, ..*providers };
} }
struct ImplWfCheck<'tcx> {
tcx: TyCtxt<'tcx>,
min_specialization: bool,
}
impl<'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
if let hir::ItemKind::Impl(ref impl_) = item.kind {
enforce_impl_params_are_constrained(self.tcx, item.def_id, impl_.items);
enforce_impl_items_are_distinct(self.tcx, impl_.items);
if self.min_specialization {
check_min_specialization(self.tcx, item.def_id.to_def_id(), item.span);
}
}
}
fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {}
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {}
fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {}
}
fn enforce_impl_params_are_constrained( fn enforce_impl_params_are_constrained(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
impl_def_id: LocalDefId, impl_def_id: LocalDefId,

View file

@ -35,7 +35,7 @@ pub fn infer_predicates<'tcx>(
debug!("InferVisitor::visit_item(item={:?})", item_did); debug!("InferVisitor::visit_item(item={:?})", item_did);
let mut item_required_predicates = RequiredPredicates::default(); let mut item_required_predicates = RequiredPredicates::default();
match tcx.hir().def_kind(item_did) { match tcx.def_kind(item_did) {
DefKind::Union | DefKind::Enum | DefKind::Struct => { DefKind::Union | DefKind::Enum | DefKind::Struct => {
let adt_def = tcx.adt_def(item_did.to_def_id()); let adt_def = tcx.adt_def(item_did.to_def_id());

View file

@ -1,28 +1,21 @@
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
tcx.hir().visit_all_item_likes(&mut OutlivesTest { tcx }); for id in tcx.hir().items() {
}
struct OutlivesTest<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
// For unit testing: check for a special "rustc_outlives" // For unit testing: check for a special "rustc_outlives"
// attribute and report an error with various results if found. // attribute and report an error with various results if found.
if self.tcx.has_attr(item.def_id.to_def_id(), sym::rustc_outlives) { if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_outlives) {
let inferred_outlives_of = self.tcx.inferred_outlives_of(item.def_id); let inferred_outlives_of = tcx.inferred_outlives_of(id.def_id);
struct_span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of).emit(); struct_span_err!(
tcx.sess,
tcx.def_span(id.def_id),
E0640,
"{:?}",
inferred_outlives_of
)
.emit();
} }
} }
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
} }

View file

@ -5,7 +5,7 @@
use hir::def_id::{DefId, LocalDefId}; use hir::def_id::{DefId, LocalDefId};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::def::DefKind;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
@ -62,61 +62,71 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
constraints: Vec::new(), constraints: Vec::new(),
}; };
tcx.hir().visit_all_item_likes(&mut constraint_cx); let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
constraint_cx.check_item(id);
}
for id in crate_items.trait_items() {
if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
constraint_cx.check_node_helper(id.hir_id());
}
}
for id in crate_items.impl_items() {
if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
constraint_cx.check_node_helper(id.hir_id());
}
}
for id in crate_items.foreign_items() {
if let DefKind::Fn = tcx.def_kind(id.def_id) {
constraint_cx.check_node_helper(id.hir_id());
}
}
constraint_cx constraint_cx
} }
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) { fn check_item(&mut self, id: hir::ItemId) {
match item.kind { let def_kind = self.tcx().def_kind(id.def_id);
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { match def_kind {
self.visit_node_helper(item.hir_id()); DefKind::Struct | DefKind::Union => {
let item = self.tcx().hir().item(id);
if let hir::ItemKind::Struct(ref struct_def, _)
| hir::ItemKind::Union(ref struct_def, _) = item.kind
{
self.check_node_helper(item.hir_id());
if let hir::VariantData::Tuple(..) = *struct_def { if let hir::VariantData::Tuple(..) = *struct_def {
self.visit_node_helper(struct_def.ctor_hir_id().unwrap()); self.check_node_helper(struct_def.ctor_hir_id().unwrap());
} }
} }
}
DefKind::Enum => {
let item = self.tcx().hir().item(id);
hir::ItemKind::Enum(ref enum_def, _) => { if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
self.visit_node_helper(item.hir_id()); self.check_node_helper(item.hir_id());
for variant in enum_def.variants { for variant in enum_def.variants {
if let hir::VariantData::Tuple(..) = variant.data { if let hir::VariantData::Tuple(..) = variant.data {
self.visit_node_helper(variant.data.ctor_hir_id().unwrap()); self.check_node_helper(variant.data.ctor_hir_id().unwrap());
} }
} }
} }
hir::ItemKind::Fn(..) => {
self.visit_node_helper(item.hir_id());
} }
DefKind::Fn => {
self.check_node_helper(id.hir_id());
}
_ => {} _ => {}
} }
} }
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) { fn check_node_helper(&mut self, id: hir::HirId) {
if let hir::TraitItemKind::Fn(..) = trait_item.kind {
self.visit_node_helper(trait_item.hir_id());
}
}
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
if let hir::ImplItemKind::Fn(..) = impl_item.kind {
self.visit_node_helper(impl_item.hir_id());
}
}
fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
self.visit_node_helper(foreign_item.hir_id());
}
}
}
impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
fn visit_node_helper(&mut self, id: hir::HirId) {
let tcx = self.terms_cx.tcx; let tcx = self.terms_cx.tcx;
let def_id = tcx.hir().local_def_id(id); let def_id = tcx.hir().local_def_id(id);
self.build_constraints_for_item(def_id); self.build_constraints_for_item(def_id);

View file

@ -11,7 +11,7 @@
use rustc_arena::DroplessArena; use rustc_arena::DroplessArena;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::def::DefKind;
use rustc_hir::HirIdMap; use rustc_hir::HirIdMap;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use std::fmt; use std::fmt;
@ -79,7 +79,29 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
// //
// - https://rustc-dev-guide.rust-lang.org/query.html // - https://rustc-dev-guide.rust-lang.org/query.html
// - https://rustc-dev-guide.rust-lang.org/variance.html // - https://rustc-dev-guide.rust-lang.org/variance.html
tcx.hir().visit_all_item_likes(&mut terms_cx); let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
terms_cx.check_item(id);
}
for id in crate_items.trait_items() {
if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
terms_cx.add_inferreds_for_item(id.hir_id());
}
}
for id in crate_items.impl_items() {
if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
terms_cx.add_inferreds_for_item(id.hir_id());
}
}
for id in crate_items.foreign_items() {
if let DefKind::Fn = tcx.def_kind(id.def_id) {
terms_cx.add_inferreds_for_item(id.hir_id());
}
}
terms_cx terms_cx
} }
@ -124,22 +146,29 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
(start..(start + count)).map(|i| &*arena.alloc(InferredTerm(InferredIndex(i)))), (start..(start + count)).map(|i| &*arena.alloc(InferredTerm(InferredIndex(i)))),
); );
} }
}
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { fn check_item(&mut self, id: hir::ItemId) {
fn visit_item(&mut self, item: &hir::Item<'_>) { debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(id.hir_id()));
debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(item.hir_id()));
match item.kind { let def_kind = self.tcx.def_kind(id.def_id);
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { match def_kind {
DefKind::Struct | DefKind::Union => {
let item = self.tcx.hir().item(id);
if let hir::ItemKind::Struct(ref struct_def, _)
| hir::ItemKind::Union(ref struct_def, _) = item.kind
{
self.add_inferreds_for_item(item.hir_id()); self.add_inferreds_for_item(item.hir_id());
if let hir::VariantData::Tuple(..) = *struct_def { if let hir::VariantData::Tuple(..) = *struct_def {
self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap()); self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap());
} }
} }
}
DefKind::Enum => {
let item = self.tcx.hir().item(id);
hir::ItemKind::Enum(ref enum_def, _) => { if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
self.add_inferreds_for_item(item.hir_id()); self.add_inferreds_for_item(item.hir_id());
for variant in enum_def.variants { for variant in enum_def.variants {
@ -148,30 +177,11 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
} }
} }
} }
hir::ItemKind::Fn(..) => {
self.add_inferreds_for_item(item.hir_id());
} }
DefKind::Fn => {
self.add_inferreds_for_item(id.hir_id());
}
_ => {} _ => {}
} }
} }
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
if let hir::TraitItemKind::Fn(..) = trait_item.kind {
self.add_inferreds_for_item(trait_item.hir_id());
}
}
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
if let hir::ImplItemKind::Fn(..) = impl_item.kind {
self.add_inferreds_for_item(impl_item.hir_id());
}
}
fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
self.add_inferreds_for_item(foreign_item.hir_id());
}
}
} }

View file

@ -1,28 +1,14 @@
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
pub fn test_variance(tcx: TyCtxt<'_>) { pub fn test_variance(tcx: TyCtxt<'_>) {
tcx.hir().visit_all_item_likes(&mut VarianceTest { tcx });
}
struct VarianceTest<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
// For unit testing: check for a special "rustc_variance" // For unit testing: check for a special "rustc_variance"
// attribute and report an error with various results if found. // attribute and report an error with various results if found.
if self.tcx.has_attr(item.def_id.to_def_id(), sym::rustc_variance) { for id in tcx.hir().items() {
let variances_of = self.tcx.variances_of(item.def_id); if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_variance) {
struct_span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of).emit(); let variances_of = tcx.variances_of(id.def_id);
struct_span_err!(tcx.sess, tcx.def_span(id.def_id), E0208, "{:?}", variances_of).emit();
} }
} }
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
} }

View file

@ -29,7 +29,7 @@ mod x {
mod y { mod y {
use {Foo, Bar}; use {Foo, Bar};
#[rustc_then_this_would_need(typeck)] //~ ERROR no path #[rustc_then_this_would_need(typeck)] //~ ERROR OK
pub fn call_bar() { pub fn call_bar() {
char::bar('a'); char::bar('a');
} }

View file

@ -1,4 +1,4 @@
error: no path from `x::<impl Foo for char>` to `typeck` error: OK
--> $DIR/dep-graph-trait-impl-two-traits.rs:32:5 --> $DIR/dep-graph-trait-impl-two-traits.rs:32:5
| |
LL | #[rustc_then_this_would_need(typeck)] LL | #[rustc_then_this_would_need(typeck)]

View file

@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
let mut map = FxHashMap::<Res, ExistingName>::default(); let mut map = FxHashMap::<Res, ExistingName>::default();
for id in cx.tcx.hir().items() { for id in cx.tcx.hir().items() {
if matches!(cx.tcx.hir().def_kind(id.def_id), DefKind::Impl) if matches!(cx.tcx.def_kind(id.def_id), DefKind::Impl)
&& let item = cx.tcx.hir().item(id) && let item = cx.tcx.hir().item(id)
&& let ItemKind::Impl(Impl { && let ItemKind::Impl(Impl {
items, items,