diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs index 97fcbeb4ccc59..70da96154b013 100644 --- a/compiler/rustc_metadata/src/foreign_modules.rs +++ b/compiler/rustc_metadata/src/foreign_modules.rs @@ -6,7 +6,7 @@ use rustc_session::cstore::ForeignModule; crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut modules = Vec::new(); 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; } let item = tcx.hir().item(id); diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 43b6ecee794cd..f468399930d3a 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -36,7 +36,7 @@ struct Collector<'tcx> { impl<'tcx> Collector<'tcx> { 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; } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b2eafa035db83..77d6ce1e766eb 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1813,7 +1813,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { FxHashMap::default(); 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()) { let simplified_self_ty = fast_reject::simplify_type( self.tcx, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 85e53559c2924..895cd4f0eac6e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -308,11 +308,6 @@ impl<'hir> Map<'hir> { 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 { if id.local_id == ItemLocalId::from_u32(0) { Some(self.tcx.hir_owner_parent(id.owner)) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 991666908f94a..eed90337c0a50 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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. let hir = tcx.hir(); 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; } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1828aecb375c4..c557b7c359ba3 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1167,7 +1167,7 @@ struct RootCollector<'a, 'tcx> { impl<'v> RootCollector<'_, 'v> { 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 => { let item = self.tcx.hir().item(id); match item.kind { @@ -1228,7 +1228,7 @@ impl<'v> RootCollector<'_, 'v> { } 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); } } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 18d9bdf8e1792..79900a90aed63 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -240,9 +240,9 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { let crate_items = tcx.hir_crate_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); if let hir::ItemKind::Enum(def, ..) = &item.kind { for variant in def.variants { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 6a4c0c2091e92..4627b58c9bcd3 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -27,6 +27,7 @@ use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_ty_utils::representability::{self, Representability}; +use rustc_hir::def::DefKind; use std::iter; 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!( "check_item_type(it.def_id={:?}, it.name={})", - it.def_id, - tcx.def_path_str(it.def_id.to_def_id()) + id.def_id, + tcx.def_path_str(id.def_id.to_def_id()) ); let _indenter = indenter(); - match it.kind { - // Consts can play a role in type-checking, so they are included here. - hir::ItemKind::Static(..) => { - tcx.ensure().typeck(it.def_id); - maybe_check_static_with_link_section(tcx, it.def_id, it.span); - check_static_inhabited(tcx, it.def_id, it.span); + match tcx.def_kind(id.def_id) { + DefKind::Static(..) => { + tcx.ensure().typeck(id.def_id); + maybe_check_static_with_link_section(tcx, id.def_id, tcx.def_span(id.def_id)); + check_static_inhabited(tcx, id.def_id, tcx.def_span(id.def_id)); } - hir::ItemKind::Const(..) => { - tcx.ensure().typeck(it.def_id); + DefKind::Const => { + tcx.ensure().typeck(id.def_id); } - hir::ItemKind::Enum(ref enum_definition, _) => { - check_enum(tcx, it.span, &enum_definition.variants, it.def_id); + DefKind::Enum => { + 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 - hir::ItemKind::Impl(ref impl_) => { + DefKind::Fn => {} // entirely within check_item_body + 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); if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) { 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); } } - 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); 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(..) => { - check_struct(tcx, it.def_id, it.span); + DefKind::Struct => { + check_struct(tcx, id.def_id, tcx.def_span(id.def_id)); } - hir::ItemKind::Union(..) => { - check_union(tcx, it.def_id, it.span); + DefKind::Union => { + 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 // `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! // See https://github.com/rust-lang/rust/issues/75100 if !tcx.sess.opts.actually_rustdoc { - let substs = InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); - check_opaque(tcx, it.def_id, substs, it.span, &origin); + let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id()); + check_opaque(tcx, item.def_id, substs, item.span, &origin); } } - hir::ItemKind::TyAlias(..) => { - let pty_ty = tcx.type_of(it.def_id); - let generics = tcx.generics_of(it.def_id); + DefKind::TyAlias => { + let pty_ty = tcx.type_of(id.def_id); + let generics = tcx.generics_of(id.def_id); 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); 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) { - 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; diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 681d1e37f86f1..ceb862b474a5a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -151,7 +151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => { sugg_call = fields.iter().map(|_| "_").collect::>().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, _)) => { msg = "instantiate this tuple variant"; } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 76c955d6f690d..f88083003a28c 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -111,7 +111,6 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirIdMap, ImplicitSelfKind, Node}; use rustc_index::bit_set::BitSet; 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<'_>, (): ()) { tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id)); } diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index d52886a09bd95..1310467aeb968 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -17,7 +17,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } 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() { continue; } @@ -101,7 +101,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { let mut crates_to_lint = vec![]; 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); if let hir::ItemKind::ExternCrate(orig_name) = item.kind { crates_to_lint.push(ExternCrateToLint { diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index de29a851e2fdf..b9d4167dbff09 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -9,8 +9,8 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def::DefKind; 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::{self, CrateInherentImpls, Ty, TyCtxt}; 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. pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { 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 } @@ -46,79 +48,6 @@ struct InherentCollect<'tcx> { 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_DEFINING_CRATE: &str = "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); } } + + 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(_) => {} + } + } } diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs index cf71e0f300c41..db67c1f7c9ed3 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs @@ -1,8 +1,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_index::vec::IndexVec; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::{self, TyCtxt}; @@ -12,7 +12,10 @@ use smallvec::SmallVec; use std::collections::hash_map::Entry; 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> { @@ -121,200 +124,184 @@ impl<'tcx> InherentOverlapChecker<'tcx> { || true, ); } -} -impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> { - 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); + 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; + } - // If there is only one inherent impl block, - // there is nothing to overlap check it with - if impls.len() <= 1 { - return; - } + let impls = self.tcx.inherent_impls(id.def_id); - let overlap_mode = OverlapMode::get(self.tcx, item.def_id.to_def_id()); + // If there is only one inherent impl block, + // there is nothing to overlap check it with + if impls.len() <= 1 { + return; + } - let impls_items = impls - .iter() - .map(|impl_def_id| (impl_def_id, self.tcx.associated_items(*impl_def_id))) - .collect::>(); + let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id()); - // Perform a O(n^2) algorithm for small n, - // otherwise switch to an allocating algorithm with - // faster asymptotic runtime. - const ALLOCATING_ALGO_THRESHOLD: usize = 500; - if impls.len() < ALLOCATING_ALGO_THRESHOLD { - for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() { - for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] { - if self.impls_have_common_items(impl_items1, impl_items2) { - self.check_for_overlapping_inherent_impls( - overlap_mode, - impl1_def_id, - impl2_def_id, - ); - } - } + let impls_items = impls + .iter() + .map(|impl_def_id| (impl_def_id, self.tcx.associated_items(*impl_def_id))) + .collect::>(); + + // Perform a O(n^2) algorithm for small n, + // otherwise switch to an allocating algorithm with + // faster asymptotic runtime. + const ALLOCATING_ALGO_THRESHOLD: usize = 500; + if impls.len() < ALLOCATING_ALGO_THRESHOLD { + for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() { + for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] { + if self.impls_have_common_items(impl_items1, impl_items2) { + self.check_for_overlapping_inherent_impls( + overlap_mode, + impl1_def_id, + impl2_def_id, + ); } - } else { - // Build a set of connected regions of impl blocks. - // Two impl blocks are regarded as connected if they share - // an item with the same unhygienic identifier. - // After we have assembled the connected regions, - // run the O(n^2) algorithm on each connected region. - // This is advantageous to running the algorithm over the - // entire graph when there are many connected regions. + } + } + } else { + // Build a set of connected regions of impl blocks. + // Two impl blocks are regarded as connected if they share + // an item with the same unhygienic identifier. + // After we have assembled the connected regions, + // run the O(n^2) algorithm on each connected region. + // This is advantageous to running the algorithm over the + // entire graph when there are many connected regions. - rustc_index::newtype_index! { - pub struct RegionId { - ENCODABLE = custom + rustc_index::newtype_index! { + pub struct RegionId { + ENCODABLE = custom + } + } + struct ConnectedRegion { + idents: SmallVec<[Symbol; 8]>, + impl_blocks: FxHashSet, + } + let mut connected_regions: IndexVec = Default::default(); + // Reverse map from the Symbol to the connected region id. + let mut connected_region_ids = FxHashMap::default(); + + for (i, &(&_impl_def_id, impl_items)) in impls_items.iter().enumerate() { + if impl_items.len() == 0 { + continue; + } + // First obtain a list of existing connected region ids + let mut idents_to_add = SmallVec::<[Symbol; 8]>::new(); + let mut ids = impl_items + .in_definition_order() + .filter_map(|item| { + let entry = connected_region_ids.entry(item.name); + if let Entry::Occupied(e) = &entry { + Some(*e.get()) + } else { + idents_to_add.push(item.name); + None } + }) + .collect::>(); + // Sort the id list so that the algorithm is deterministic + ids.sort_unstable(); + ids.dedup(); + let ids = ids; + match &ids[..] { + // Create a new connected region + [] => { + let id_to_set = connected_regions.next_index(); + // Update the connected region ids + for ident in &idents_to_add { + connected_region_ids.insert(*ident, id_to_set); + } + connected_regions.insert( + id_to_set, + ConnectedRegion { + idents: idents_to_add, + impl_blocks: std::iter::once(i).collect(), + }, + ); } - struct ConnectedRegion { - idents: SmallVec<[Symbol; 8]>, - impl_blocks: FxHashSet, + // Take the only id inside the list + &[id_to_set] => { + let region = connected_regions[id_to_set].as_mut().unwrap(); + region.impl_blocks.insert(i); + region.idents.extend_from_slice(&idents_to_add); + // Update the connected region ids + for ident in &idents_to_add { + connected_region_ids.insert(*ident, id_to_set); + } } - let mut connected_regions: IndexVec = Default::default(); - // Reverse map from the Symbol to the connected region id. - let mut connected_region_ids = FxHashMap::default(); - - for (i, &(&_impl_def_id, impl_items)) in impls_items.iter().enumerate() { - if impl_items.len() == 0 { - continue; + // We have multiple connected regions to merge. + // In the worst case this might add impl blocks + // one by one and can thus be O(n^2) in the size + // of the resulting final connected region, but + // this is no issue as the final step to check + // for overlaps runs in O(n^2) as well. + &[id_to_set, ..] => { + let mut region = connected_regions.remove(id_to_set).unwrap(); + region.impl_blocks.insert(i); + region.idents.extend_from_slice(&idents_to_add); + // Update the connected region ids + for ident in &idents_to_add { + connected_region_ids.insert(*ident, id_to_set); } - // First obtain a list of existing connected region ids - let mut idents_to_add = SmallVec::<[Symbol; 8]>::new(); - let mut ids = impl_items - .in_definition_order() - .filter_map(|item| { - let entry = connected_region_ids.entry(item.name); - if let Entry::Occupied(e) = &entry { - Some(*e.get()) - } else { - idents_to_add.push(item.name); - None - } - }) - .collect::>(); - // Sort the id list so that the algorithm is deterministic - ids.sort_unstable(); - ids.dedup(); - let ids = ids; - match &ids[..] { - // Create a new connected region - [] => { - let id_to_set = connected_regions.next_index(); - // Update the connected region ids - for ident in &idents_to_add { - connected_region_ids.insert(*ident, id_to_set); - } - connected_regions.insert( - id_to_set, - ConnectedRegion { - idents: idents_to_add, - impl_blocks: std::iter::once(i).collect(), - }, - ); - } - // Take the only id inside the list - &[id_to_set] => { - let region = connected_regions[id_to_set].as_mut().unwrap(); - region.impl_blocks.insert(i); - region.idents.extend_from_slice(&idents_to_add); - // Update the connected region ids - for ident in &idents_to_add { - connected_region_ids.insert(*ident, id_to_set); - } - } - // We have multiple connected regions to merge. - // In the worst case this might add impl blocks - // one by one and can thus be O(n^2) in the size - // of the resulting final connected region, but - // this is no issue as the final step to check - // for overlaps runs in O(n^2) as well. - &[id_to_set, ..] => { - let mut region = connected_regions.remove(id_to_set).unwrap(); - region.impl_blocks.insert(i); - region.idents.extend_from_slice(&idents_to_add); - // Update the connected region ids - for ident in &idents_to_add { - connected_region_ids.insert(*ident, id_to_set); - } - - // Remove other regions from ids. - for &id in ids.iter() { - if id == id_to_set { - continue; - } - let r = connected_regions.remove(id).unwrap(); - for ident in r.idents.iter() { - connected_region_ids.insert(*ident, id_to_set); - } - region.idents.extend_from_slice(&r.idents); - region.impl_blocks.extend(r.impl_blocks); - } - connected_regions.insert(id_to_set, region); + // Remove other regions from ids. + for &id in ids.iter() { + if id == id_to_set { + continue; + } + let r = connected_regions.remove(id).unwrap(); + for ident in r.idents.iter() { + connected_region_ids.insert(*ident, id_to_set); } + region.idents.extend_from_slice(&r.idents); + region.impl_blocks.extend(r.impl_blocks); } + + connected_regions.insert(id_to_set, region); } + } + } - debug!( - "churning through {} components (sum={}, avg={}, var={}, max={})", - connected_regions.len(), - impls.len(), - impls.len() / connected_regions.len(), - { - let avg = impls.len() / connected_regions.len(); - let s = connected_regions - .iter() - .flatten() - .map(|r| r.impl_blocks.len() as isize - avg as isize) - .map(|v| v.abs() as usize) - .sum::(); - s / connected_regions.len() - }, - connected_regions - .iter() - .flatten() - .map(|r| r.impl_blocks.len()) - .max() - .unwrap() - ); - // List of connected regions is built. Now, run the overlap check - // for each pair of impl blocks in the same connected region. - for region in connected_regions.into_iter().flatten() { - let mut impl_blocks = - region.impl_blocks.into_iter().collect::>(); - impl_blocks.sort_unstable(); - for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { - let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; - for &impl2_items_idx in impl_blocks[(i + 1)..].iter() { - let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx]; - if self.impls_have_common_items(impl_items1, impl_items2) { - self.check_for_overlapping_inherent_impls( - overlap_mode, - impl1_def_id, - impl2_def_id, - ); - } - } + debug!( + "churning through {} components (sum={}, avg={}, var={}, max={})", + connected_regions.len(), + impls.len(), + impls.len() / connected_regions.len(), + { + let avg = impls.len() / connected_regions.len(); + let s = connected_regions + .iter() + .flatten() + .map(|r| r.impl_blocks.len() as isize - avg as isize) + .map(|v| v.abs() as usize) + .sum::(); + s / connected_regions.len() + }, + connected_regions.iter().flatten().map(|r| r.impl_blocks.len()).max().unwrap() + ); + // List of connected regions is built. Now, run the overlap check + // for each pair of impl blocks in the same connected region. + for region in connected_regions.into_iter().flatten() { + let mut impl_blocks = + region.impl_blocks.into_iter().collect::>(); + impl_blocks.sort_unstable(); + for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { + let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; + for &impl2_items_idx in impl_blocks[(i + 1)..].iter() { + let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx]; + if self.impls_have_common_items(impl_items1, impl_items2) { + self.check_for_overlapping_inherent_impls( + overlap_mode, + impl1_def_id, + impl2_def_id, + ); } } } } - _ => {} } } - - 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<'_>) {} } diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs index f7aabf2406f37..3cfc96ccbfd28 100644 --- a/compiler/rustc_typeck/src/coherence/unsafety.rs +++ b/compiler/rustc_typeck/src/coherence/unsafety.rs @@ -3,101 +3,83 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_hir::def::DefKind; use rustc_hir::Unsafety; use rustc_middle::ty::TyCtxt; pub fn check(tcx: TyCtxt<'_>) { - let mut unsafety = UnsafetyChecker { tcx }; - tcx.hir().visit_all_item_likes(&mut unsafety); + for id in tcx.hir().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 { + check_unsafety_coherence( + tcx, + item, + Some(&impl_.generics), + impl_.unsafety, + impl_.polarity, + ); + } + } + } } -struct UnsafetyChecker<'tcx> { +fn check_unsafety_coherence<'tcx>( tcx: TyCtxt<'tcx>, -} - -impl<'tcx> UnsafetyChecker<'tcx> { - fn check_unsafety_coherence( - &mut self, - item: &hir::Item<'_>, - impl_generics: Option<&hir::Generics<'_>>, - unsafety: hir::Unsafety, - polarity: hir::ImplPolarity, - ) { - if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id) { - let trait_def = self.tcx.trait_def(trait_ref.def_id); - let unsafe_attr = impl_generics.and_then(|generics| { - generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") - }); - match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { - (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { - struct_span_err!( - self.tcx.sess, - item.span, - E0199, - "implementing the trait `{}` is not unsafe", - trait_ref.print_only_trait_path() - ) - .emit(); - } - - (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { - struct_span_err!( - self.tcx.sess, - item.span, - E0200, - "the trait `{}` requires an `unsafe impl` declaration", - trait_ref.print_only_trait_path() - ) - .emit(); - } + item: &hir::Item<'_>, + impl_generics: Option<&hir::Generics<'_>>, + unsafety: hir::Unsafety, + polarity: hir::ImplPolarity, +) { + if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) { + let trait_def = tcx.trait_def(trait_ref.def_id); + let unsafe_attr = impl_generics.and_then(|generics| { + generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") + }); + match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { + (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { + struct_span_err!( + tcx.sess, + item.span, + E0199, + "implementing the trait `{}` is not unsafe", + trait_ref.print_only_trait_path() + ) + .emit(); + } - ( - Unsafety::Normal, - Some(attr_name), - Unsafety::Normal, - hir::ImplPolarity::Positive, - ) => { - struct_span_err!( - self.tcx.sess, - item.span, - E0569, - "requires an `unsafe impl` declaration due to `#[{}]` attribute", - attr_name - ) - .emit(); - } + (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { + struct_span_err!( + tcx.sess, + item.span, + E0200, + "the trait `{}` requires an `unsafe impl` declaration", + trait_ref.print_only_trait_path() + ) + .emit(); + } - (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => { - // Reported in AST validation - self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); - } - (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_)) - | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) - | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) - | (Unsafety::Normal, None, Unsafety::Normal, _) => { - // OK - } + (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => { + struct_span_err!( + tcx.sess, + item.span, + E0569, + "requires an `unsafe impl` declaration due to `#[{}]` attribute", + attr_name + ) + .emit(); } - } - } -} -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, - ); + (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => { + // Reported in AST validation + tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); + } + (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_)) + | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) + | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) + | (Unsafety::Normal, None, Unsafety::Normal, _) => { + // OK + } } } - - 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<'_>) {} } diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 8b376e26dee97..c089d25d22216 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -14,8 +14,8 @@ use min_specialization::check_min_specialization; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::Span; @@ -63,35 +63,23 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let min_specialization = tcx.features().min_specialization; - tcx.hir() - .visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx, min_specialization }); -} - -pub fn provide(providers: &mut 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); + let module = tcx.hir_module_items(module_def_id); + 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); + } } } } +} - 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>) {} +pub fn provide(providers: &mut Providers) { + *providers = Providers { check_mod_impl_wf, ..*providers }; } fn enforce_impl_params_are_constrained( diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs index 6f842c6e71a5b..96dc83b259f55 100644 --- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs +++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs @@ -35,7 +35,7 @@ pub fn infer_predicates<'tcx>( debug!("InferVisitor::visit_item(item={:?})", item_did); 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 => { let adt_def = tcx.adt_def(item_did.to_def_id()); diff --git a/compiler/rustc_typeck/src/outlives/test.rs b/compiler/rustc_typeck/src/outlives/test.rs index b3efd9f9ec367..eb0e1203405cb 100644 --- a/compiler/rustc_typeck/src/outlives/test.rs +++ b/compiler/rustc_typeck/src/outlives/test.rs @@ -1,28 +1,21 @@ use rustc_errors::struct_span_err; -use rustc_hir as hir; -use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { - tcx.hir().visit_all_item_likes(&mut OutlivesTest { tcx }); -} - -struct OutlivesTest<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> { - fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + for id in tcx.hir().items() { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. - if self.tcx.has_attr(item.def_id.to_def_id(), sym::rustc_outlives) { - let inferred_outlives_of = self.tcx.inferred_outlives_of(item.def_id); - struct_span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of).emit(); + if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_outlives) { + let inferred_outlives_of = tcx.inferred_outlives_of(id.def_id); + 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>) {} } diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index 76755de4964e1..be8e825d990f7 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -5,7 +5,7 @@ use hir::def_id::{DefId, LocalDefId}; 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::{self, Ty, TyCtxt}; @@ -62,61 +62,71 @@ pub fn add_constraints_from_crate<'a, 'tcx>( 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 } -impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { - fn visit_item(&mut self, item: &hir::Item<'_>) { - match item.kind { - hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { - self.visit_node_helper(item.hir_id()); - - if let hir::VariantData::Tuple(..) = *struct_def { - self.visit_node_helper(struct_def.ctor_hir_id().unwrap()); +impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { + fn check_item(&mut self, id: hir::ItemId) { + let def_kind = self.tcx().def_kind(id.def_id); + 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.check_node_helper(item.hir_id()); + + if let hir::VariantData::Tuple(..) = *struct_def { + 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, _) => { - self.visit_node_helper(item.hir_id()); + if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { + self.check_node_helper(item.hir_id()); - for variant in enum_def.variants { - if let hir::VariantData::Tuple(..) = variant.data { - self.visit_node_helper(variant.data.ctor_hir_id().unwrap()); + for variant in enum_def.variants { + if let hir::VariantData::Tuple(..) = variant.data { + 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<'_>) { - 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) { + fn check_node_helper(&mut self, id: hir::HirId) { let tcx = self.terms_cx.tcx; let def_id = tcx.hir().local_def_id(id); self.build_constraints_for_item(def_id); diff --git a/compiler/rustc_typeck/src/variance/terms.rs b/compiler/rustc_typeck/src/variance/terms.rs index 36fbfc21ff58c..ab64befe5dc16 100644 --- a/compiler/rustc_typeck/src/variance/terms.rs +++ b/compiler/rustc_typeck/src/variance/terms.rs @@ -11,7 +11,7 @@ use rustc_arena::DroplessArena; use rustc_hir as hir; -use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_hir::def::DefKind; use rustc_hir::HirIdMap; use rustc_middle::ty::{self, TyCtxt}; 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/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 } @@ -124,54 +146,42 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { (start..(start + count)).map(|i| &*arena.alloc(InferredTerm(InferredIndex(i)))), ); } -} -impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { - fn visit_item(&mut self, item: &hir::Item<'_>) { - debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(item.hir_id())); + fn check_item(&mut self, id: hir::ItemId) { + debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(id.hir_id())); + + let def_kind = self.tcx.def_kind(id.def_id); + match def_kind { + DefKind::Struct | DefKind::Union => { + let item = self.tcx.hir().item(id); - match item.kind { - hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { - self.add_inferreds_for_item(item.hir_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()); - if let hir::VariantData::Tuple(..) = *struct_def { - self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap()); + if let hir::VariantData::Tuple(..) = *struct_def { + 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, _) => { - self.add_inferreds_for_item(item.hir_id()); + if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { + self.add_inferreds_for_item(item.hir_id()); - for variant in enum_def.variants { - if let hir::VariantData::Tuple(..) = variant.data { - self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap()); + for variant in enum_def.variants { + if let hir::VariantData::Tuple(..) = variant.data { + self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap()); + } } } } - - 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()); - } - } } diff --git a/compiler/rustc_typeck/src/variance/test.rs b/compiler/rustc_typeck/src/variance/test.rs index d6959075d8883..2ba87db880b46 100644 --- a/compiler/rustc_typeck/src/variance/test.rs +++ b/compiler/rustc_typeck/src/variance/test.rs @@ -1,28 +1,14 @@ use rustc_errors::struct_span_err; -use rustc_hir as hir; -use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; 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" - // attribute and report an error with various results if found. - if self.tcx.has_attr(item.def_id.to_def_id(), sym::rustc_variance) { - let variances_of = self.tcx.variances_of(item.def_id); - struct_span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of).emit(); + // For unit testing: check for a special "rustc_variance" + // attribute and report an error with various results if found. + for id in tcx.hir().items() { + if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_variance) { + 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>) {} } diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs index 0331e75b2fe8d..590475fa03a3e 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs +++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs @@ -29,7 +29,7 @@ mod x { mod y { use {Foo, Bar}; - #[rustc_then_this_would_need(typeck)] //~ ERROR no path + #[rustc_then_this_would_need(typeck)] //~ ERROR OK pub fn call_bar() { char::bar('a'); } diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr index 08f382cc024c7..4e10437362c6b 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr +++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr @@ -1,4 +1,4 @@ -error: no path from `x::` to `typeck` +error: OK --> $DIR/dep-graph-trait-impl-two-traits.rs:32:5 | LL | #[rustc_then_this_would_need(typeck)] diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index f63925a2f1438..c5c174cc8f614 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -51,14 +51,14 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { let mut map = FxHashMap::::default(); 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 ItemKind::Impl(Impl { - items, - of_trait, - self_ty, - .. - }) = &item.kind + items, + of_trait, + self_ty, + .. + }) = &item.kind && let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind { if !map.contains_key(res) {