diff --git a/Cargo.lock b/Cargo.lock index e37e8614af2cd..ab906b3d3c9d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4097,7 +4097,6 @@ dependencies = [ "rustc_target", "rustc_trait_selection", "rustc_type_ir", - "smallvec", "tracing", "unicode-security", ] diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 2271321b8bf22..fa1133e7780ff 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -23,7 +23,6 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_type_ir = { path = "../rustc_type_ir" } -smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" unicode-security = "0.1.0" # tidy-alphabetical-end diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 6cb6fd1cbd550..b166c39224c25 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -2,8 +2,6 @@ use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, Path, QPath, TyKind}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind}; -use smallvec::{smallvec, SmallVec}; - use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; use crate::{LateContext, LateLintPass, LintContext}; @@ -67,24 +65,23 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { return; } - let parent = cx.tcx.parent(item.owner_id.def_id.into()); - let parent_def_kind = cx.tcx.def_kind(parent); - let parent_opt_item_name = cx.tcx.opt_item_name(parent); - - // Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in top-level module. - if self.body_depth == 1 - && parent_def_kind == DefKind::Const - && parent_opt_item_name == Some(kw::Underscore) - { - return; + macro_rules! lazy { + ($ident:ident = $closure:expr) => { + let cache = ::std::cell::RefCell::new(None); + let $ident = || *cache.borrow_mut().get_or_insert_with($closure); + }; } + lazy!(parent = || cx.tcx.parent(item.owner_id.def_id.into())); + lazy!(parent_def_kind = || cx.tcx.def_kind(parent())); + lazy!(parent_opt_item_name = || cx.tcx.opt_item_name(parent())); + let cargo_update = || { let oexpn = item.span.ctxt().outer_expn_data(); if let Some(def_id) = oexpn.macro_def_id && let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind && def_id.krate != LOCAL_CRATE - && std::env::var_os("CARGO").is_some() + && rustc_session::utils::was_invoked_from_cargo() { Some(NonLocalDefinitionsCargoUpdateNote { macro_kind: macro_kind.descr(), @@ -112,26 +109,24 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // If that's the case this means that this impl block declaration // is using local items and so we don't lint on it. - // We also ignore anon-const in item by including the anon-const - // parent as well; and since it's quite uncommon, we use smallvec - // to avoid unnecessary heap allocations. - let local_parents: SmallVec<[DefId; 1]> = if parent_def_kind == DefKind::Const - && parent_opt_item_name == Some(kw::Underscore) - { - smallvec![parent, cx.tcx.parent(parent)] - } else { - smallvec![parent] - }; + lazy!( + parent_is_anon_const = || parent_def_kind() == DefKind::Const + && parent_opt_item_name() == Some(kw::Underscore) + ); + lazy!( + extra_local_parent = || parent_is_anon_const().then(|| cx.tcx.parent(parent())) + ); let self_ty_has_local_parent = match impl_.self_ty.kind { TyKind::Path(QPath::Resolved(_, ty_path)) => { - path_has_local_parent(ty_path, cx, &*local_parents) + path_has_local_parent(ty_path, cx, &parent, &extra_local_parent) } TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => { path_has_local_parent( principle_poly_trait_ref.trait_ref.path, cx, - &*local_parents, + &parent, + &extra_local_parent, ) } TyKind::TraitObject([], _, _) @@ -151,18 +146,27 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { | TyKind::Err(_) => false, }; - let of_trait_has_local_parent = impl_ - .of_trait - .map(|of_trait| path_has_local_parent(of_trait.path, cx, &*local_parents)) - .unwrap_or(false); + let of_trait_has_local_parent = self_ty_has_local_parent + || impl_ + .of_trait + .map(|of_trait| { + path_has_local_parent(of_trait.path, cx, &parent, &extra_local_parent) + }) + .unwrap_or(false); // If none of them have a local parent (LOGICAL NOR) this means that // this impl definition is a non-local definition and so we lint on it. if !(self_ty_has_local_parent || of_trait_has_local_parent) { + // Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in + // top-level module. + if self.body_depth == 1 && parent_is_anon_const() { + return; + } + let const_anon = if self.body_depth == 1 - && parent_def_kind == DefKind::Const - && parent_opt_item_name != Some(kw::Underscore) - && let Some(parent) = parent.as_local() + && parent_def_kind() == DefKind::Const + && parent_opt_item_name() != Some(kw::Underscore) + && let Some(parent) = parent().as_local() && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent) && let ItemKind::Const(ty, _, _) = item.kind && let TyKind::Tup(&[]) = ty.kind @@ -177,8 +181,8 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { item.span, NonLocalDefinitionsDiag::Impl { depth: self.body_depth, - body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent), - body_name: parent_opt_item_name + body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind(), parent()), + body_name: parent_opt_item_name() .map(|s| s.to_ident_string()) .unwrap_or_else(|| "".to_string()), cargo_update: cargo_update(), @@ -195,8 +199,8 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { item.span, NonLocalDefinitionsDiag::MacroRules { depth: self.body_depth, - body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent), - body_name: parent_opt_item_name + body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind(), parent()), + body_name: parent_opt_item_name() .map(|s| s.to_ident_string()) .unwrap_or_else(|| "".to_string()), cargo_update: cargo_update(), @@ -217,6 +221,16 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { /// std::convert::PartialEq> /// ^^^^^^^^^^^^^^^^^^^^^^^ /// ``` -fn path_has_local_parent(path: &Path<'_>, cx: &LateContext<'_>, local_parents: &[DefId]) -> bool { - path.res.opt_def_id().is_some_and(|did| local_parents.contains(&cx.tcx.parent(did))) +fn path_has_local_parent( + path: &Path<'_>, + cx: &LateContext<'_>, + parent: impl Fn() -> DefId, + extra_local_parent: impl Fn() -> Option, +) -> bool { + path.res.opt_def_id().is_some_and(|did| { + did.is_local() && { + let res_parent = cx.tcx.parent(did); + res_parent == parent() || Some(res_parent) == extra_local_parent() + } + }) } diff --git a/tests/ui/lint/non_local_definitions.rs b/tests/ui/lint/non_local_definitions.rs index c9aaa04934631..3a334b6137cca 100644 --- a/tests/ui/lint/non_local_definitions.rs +++ b/tests/ui/lint/non_local_definitions.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2021 //@ aux-build:non_local_macro.rs -//@ rustc-env:CARGO=/usr/bin/cargo +//@ rustc-env:CARGO_CRATE_NAME=non_local_def #![feature(inline_const)]