diff options
Diffstat (limited to 'compiler/rustc_lint')
30 files changed, 251 insertions, 318 deletions
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index ec5f0f06c59..cc5a9029633 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_attr = { path = "../rustc_attr" } +rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 01d9ac20fae..7522e21d0ef 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -536,9 +536,6 @@ lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case nam .suggestion = convert the identifier to upper camel case .label = should have an UpperCamelCase name -lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]` - .help = only existing keywords are allowed in core/std - lint_non_fmt_panic = panic message is not a string literal .note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021 .more_info_note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> @@ -806,14 +803,14 @@ lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_printl lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg} lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}` -lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` +lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}` lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml` lint_unexpected_cfg_doc_cargo = see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration lint_unexpected_cfg_doc_rustc = see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration lint_unexpected_cfg_from_external_macro_origin = using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate -lint_unexpected_cfg_from_external_macro_refer = try refering to `{$macro_name}` crate for guidance on how handle this unexpected cfg +lint_unexpected_cfg_from_external_macro_refer = try referring to `{$macro_name}` crate for guidance on how handle this unexpected cfg lint_unexpected_cfg_name = unexpected `cfg` condition name: `{$name}` lint_unexpected_cfg_name_expected_names = expected names are: {$possibilities}{$and_more -> [0] {""} diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 3543784bc72..6e823957cc6 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -39,8 +39,7 @@ pub use rustc_session::lint::builtin::*; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; -use rustc_span::{BytePos, InnerSpan, Span}; +use rustc_span::{BytePos, Ident, InnerSpan, Span, Symbol, kw, sym}; use rustc_target::asm::InlineAsmArch; use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt}; use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy; @@ -387,7 +386,7 @@ pub struct MissingDoc; impl_lint_pass!(MissingDoc => [MISSING_DOCS]); -fn has_doc(attr: &ast::Attribute) -> bool { +fn has_doc(attr: &hir::Attribute) -> bool { if attr.is_doc_comment() { return true; } @@ -1012,7 +1011,7 @@ declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GEN impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { let attrs = cx.tcx.hir().attrs(it.hir_id()); - let check_no_mangle_on_generic_fn = |no_mangle_attr: &ast::Attribute, + let check_no_mangle_on_generic_fn = |no_mangle_attr: &hir::Attribute, impl_generics: Option<&hir::Generics<'_>>, generics: &hir::Generics<'_>, span| { @@ -1176,7 +1175,7 @@ declare_lint_pass!( ); impl<'tcx> LateLintPass<'tcx> for UnstableFeatures { - fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { + fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &hir::Attribute) { if attr.has_name(sym::feature) && let Some(items) = attr.meta_item_list() { @@ -1814,7 +1813,7 @@ declare_lint! { "detects edition keywords being used as an identifier", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024), - reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>", + reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/gen-keyword.html>", }; } @@ -1829,7 +1828,7 @@ impl KeywordIdents { fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) { // Check if the preceding token is `$`, because we want to allow `$async`, etc. let mut prev_dollar = false; - for tt in tokens.trees() { + for tt in tokens.iter() { match tt { // Only report non-raw idents. TokenTree::Token(token, _) => { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 44c7888a530..50bb1fb942e 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -20,12 +20,11 @@ use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode}; use rustc_session::lint::{ - BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, + FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, }; use rustc_session::{LintStoreMarker, Session}; -use rustc_span::Span; use rustc_span::edit_distance::find_best_match_for_names; -use rustc_span::symbol::{Ident, Symbol, sym}; +use rustc_span::{Ident, Span, Symbol, sym}; use tracing::debug; use {rustc_abi as abi, rustc_hir as hir}; @@ -33,8 +32,6 @@ use self::TargetLint::*; use crate::levels::LintLevelsBuilder; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; -mod diagnostics; - type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync; type LateLintPassFactory = dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync; @@ -511,38 +508,6 @@ pub struct EarlyContext<'a> { pub buffered: LintBuffer, } -impl EarlyContext<'_> { - /// Emit a lint at the appropriate level, with an associated span and an existing - /// diagnostic. - /// - /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature - #[rustc_lint_diagnostics] - pub fn span_lint_with_diagnostics( - &self, - lint: &'static Lint, - span: MultiSpan, - diagnostic: BuiltinLintDiag, - ) { - self.opt_span_lint_with_diagnostics(lint, Some(span), diagnostic); - } - - /// Emit a lint at the appropriate level, with an optional associated span and an existing - /// diagnostic. - /// - /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature - #[rustc_lint_diagnostics] - pub fn opt_span_lint_with_diagnostics( - &self, - lint: &'static Lint, - span: Option<MultiSpan>, - diagnostic: BuiltinLintDiag, - ) { - self.opt_span_lint(lint, span, |diag| { - diagnostics::decorate_lint(self.sess(), diagnostic, diag); - }); - } -} - pub trait LintContext { fn sess(&self) -> &Session; diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index 10769b57a76..98b717a3070 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -4,8 +4,7 @@ use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem}; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::{declare_lint, impl_lint_pass}; -use rustc_span::Span; -use rustc_span::symbol::sym; +use rustc_span::{Span, sym}; use crate::lints::DanglingPointersFromTemporaries; use crate::{LateContext, LateLintPass}; diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index a68a2a7f983..bc7cd3d118c 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -9,35 +9,39 @@ use rustc_ast::visit::{self as ast_visit, Visitor, walk_list}; use rustc_ast::{self as ast, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_feature::Features; -use rustc_middle::ty::RegisteredTools; +use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::Session; use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; -use rustc_span::Span; -use rustc_span::symbol::Ident; +use rustc_span::{Ident, Span}; use tracing::debug; -use crate::context::{EarlyContext, LintStore}; +use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; +mod diagnostics; + macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } /// Implements the AST traversal for early lint passes. `T` provides the /// `check_*` methods. -pub struct EarlyContextAndPass<'a, T: EarlyLintPass> { - context: EarlyContext<'a>, +pub struct EarlyContextAndPass<'ecx, 'tcx, T: EarlyLintPass> { + context: EarlyContext<'ecx>, + tcx: Option<TyCtxt<'tcx>>, pass: T, } -impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { +impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { // This always-inlined function is for the hot call site. #[inline(always)] #[allow(rustc::diagnostic_outside_of_impl)] fn inlined_check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; - self.context.opt_span_lint_with_diagnostics(lint_id.lint, span, diagnostic); + self.context.opt_span_lint(lint_id.lint, span, |diag| { + diagnostics::decorate_lint(self.context.sess(), self.tcx, diagnostic, diag); + }); } } @@ -49,7 +53,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { /// Merge the lints specified by any lint attributes into the /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. - fn with_lint_attrs<F>(&mut self, id: ast::NodeId, attrs: &'a [ast::Attribute], f: F) + fn with_lint_attrs<F>(&mut self, id: ast::NodeId, attrs: &'_ [ast::Attribute], f: F) where F: FnOnce(&mut Self), { @@ -67,19 +71,21 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { } } -impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> { - fn visit_coroutine_kind(&mut self, coroutine_kind: &'a ast::CoroutineKind) -> Self::Result { +impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast> + for EarlyContextAndPass<'ecx, 'tcx, T> +{ + fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast ast::CoroutineKind) -> Self::Result { self.check_id(coroutine_kind.closure_id()); } - fn visit_param(&mut self, param: &'a ast::Param) { + fn visit_param(&mut self, param: &'ast ast::Param) { self.with_lint_attrs(param.id, ¶m.attrs, |cx| { lint_callback!(cx, check_param, param); ast_visit::walk_param(cx, param); }); } - fn visit_item(&mut self, it: &'a ast::Item) { + fn visit_item(&mut self, it: &'ast ast::Item) { self.with_lint_attrs(it.id, &it.attrs, |cx| { lint_callback!(cx, check_item, it); ast_visit::walk_item(cx, it); @@ -87,31 +93,31 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> }) } - fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) { + fn visit_foreign_item(&mut self, it: &'ast ast::ForeignItem) { self.with_lint_attrs(it.id, &it.attrs, |cx| { ast_visit::walk_item(cx, it); }) } - fn visit_pat(&mut self, p: &'a ast::Pat) { + fn visit_pat(&mut self, p: &'ast ast::Pat) { lint_callback!(self, check_pat, p); self.check_id(p.id); ast_visit::walk_pat(self, p); lint_callback!(self, check_pat_post, p); } - fn visit_pat_field(&mut self, field: &'a ast::PatField) { + fn visit_pat_field(&mut self, field: &'ast ast::PatField) { self.with_lint_attrs(field.id, &field.attrs, |cx| { ast_visit::walk_pat_field(cx, field); }); } - fn visit_anon_const(&mut self, c: &'a ast::AnonConst) { + fn visit_anon_const(&mut self, c: &'ast ast::AnonConst) { self.check_id(c.id); ast_visit::walk_anon_const(self, c); } - fn visit_expr(&mut self, e: &'a ast::Expr) { + fn visit_expr(&mut self, e: &'ast ast::Expr) { self.with_lint_attrs(e.id, &e.attrs, |cx| { lint_callback!(cx, check_expr, e); ast_visit::walk_expr(cx, e); @@ -119,13 +125,13 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> }) } - fn visit_expr_field(&mut self, f: &'a ast::ExprField) { + fn visit_expr_field(&mut self, f: &'ast ast::ExprField) { self.with_lint_attrs(f.id, &f.attrs, |cx| { ast_visit::walk_expr_field(cx, f); }) } - fn visit_stmt(&mut self, s: &'a ast::Stmt) { + fn visit_stmt(&mut self, s: &'ast ast::Stmt) { // Add the statement's lint attributes to our // current state when checking the statement itself. // This allows us to handle attributes like @@ -145,33 +151,33 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> ast_visit::walk_stmt(self, s); } - fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) { + fn visit_fn(&mut self, fk: ast_visit::FnKind<'ast>, span: Span, id: ast::NodeId) { lint_callback!(self, check_fn, fk, span, id); self.check_id(id); ast_visit::walk_fn(self, fk); } - fn visit_variant_data(&mut self, s: &'a ast::VariantData) { + fn visit_variant_data(&mut self, s: &'ast ast::VariantData) { if let Some(ctor_node_id) = s.ctor_node_id() { self.check_id(ctor_node_id); } ast_visit::walk_struct_def(self, s); } - fn visit_field_def(&mut self, s: &'a ast::FieldDef) { + fn visit_field_def(&mut self, s: &'ast ast::FieldDef) { self.with_lint_attrs(s.id, &s.attrs, |cx| { ast_visit::walk_field_def(cx, s); }) } - fn visit_variant(&mut self, v: &'a ast::Variant) { + fn visit_variant(&mut self, v: &'ast ast::Variant) { self.with_lint_attrs(v.id, &v.attrs, |cx| { lint_callback!(cx, check_variant, v); ast_visit::walk_variant(cx, v); }) } - fn visit_ty(&mut self, t: &'a ast::Ty) { + fn visit_ty(&mut self, t: &'ast ast::Ty) { lint_callback!(self, check_ty, t); self.check_id(t.id); ast_visit::walk_ty(self, t); @@ -181,55 +187,55 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> lint_callback!(self, check_ident, ident); } - fn visit_local(&mut self, l: &'a ast::Local) { + fn visit_local(&mut self, l: &'ast ast::Local) { self.with_lint_attrs(l.id, &l.attrs, |cx| { lint_callback!(cx, check_local, l); ast_visit::walk_local(cx, l); }) } - fn visit_block(&mut self, b: &'a ast::Block) { + fn visit_block(&mut self, b: &'ast ast::Block) { lint_callback!(self, check_block, b); self.check_id(b.id); ast_visit::walk_block(self, b); } - fn visit_arm(&mut self, a: &'a ast::Arm) { + fn visit_arm(&mut self, a: &'ast ast::Arm) { self.with_lint_attrs(a.id, &a.attrs, |cx| { lint_callback!(cx, check_arm, a); ast_visit::walk_arm(cx, a); }) } - fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) { + fn visit_generic_arg(&mut self, arg: &'ast ast::GenericArg) { lint_callback!(self, check_generic_arg, arg); ast_visit::walk_generic_arg(self, arg); } - fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { + fn visit_generic_param(&mut self, param: &'ast ast::GenericParam) { self.with_lint_attrs(param.id, ¶m.attrs, |cx| { lint_callback!(cx, check_generic_param, param); ast_visit::walk_generic_param(cx, param); }); } - fn visit_generics(&mut self, g: &'a ast::Generics) { + fn visit_generics(&mut self, g: &'ast ast::Generics) { lint_callback!(self, check_generics, g); ast_visit::walk_generics(self, g); } - fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) { + fn visit_where_predicate(&mut self, p: &'ast ast::WherePredicate) { lint_callback!(self, enter_where_predicate, p); ast_visit::walk_where_predicate(self, p); lint_callback!(self, exit_where_predicate, p); } - fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) { + fn visit_poly_trait_ref(&mut self, t: &'ast ast::PolyTraitRef) { lint_callback!(self, check_poly_trait_ref, t); ast_visit::walk_poly_trait_ref(self, t); } - fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) { + fn visit_assoc_item(&mut self, item: &'ast ast::AssocItem, ctxt: ast_visit::AssocCtxt) { self.with_lint_attrs(item.id, &item.attrs, |cx| { match ctxt { ast_visit::AssocCtxt::Trait => { @@ -243,32 +249,32 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> }); } - fn visit_lifetime(&mut self, lt: &'a ast::Lifetime, _: ast_visit::LifetimeCtxt) { + fn visit_lifetime(&mut self, lt: &'ast ast::Lifetime, _: ast_visit::LifetimeCtxt) { self.check_id(lt.id); ast_visit::walk_lifetime(self, lt); } - fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) { + fn visit_path(&mut self, p: &'ast ast::Path, id: ast::NodeId) { self.check_id(id); ast_visit::walk_path(self, p); } - fn visit_path_segment(&mut self, s: &'a ast::PathSegment) { + fn visit_path_segment(&mut self, s: &'ast ast::PathSegment) { self.check_id(s.id); ast_visit::walk_path_segment(self, s); } - fn visit_attribute(&mut self, attr: &'a ast::Attribute) { + fn visit_attribute(&mut self, attr: &'ast ast::Attribute) { lint_callback!(self, check_attribute, attr); ast_visit::walk_attribute(self, attr); } - fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) { + fn visit_mac_def(&mut self, mac: &'ast ast::MacroDef, id: ast::NodeId) { lint_callback!(self, check_mac_def, mac); self.check_id(id); } - fn visit_mac_call(&mut self, mac: &'a ast::MacCall) { + fn visit_mac_call(&mut self, mac: &'ast ast::MacCall) { lint_callback!(self, check_mac, mac); ast_visit::walk_mac(self, mac); } @@ -310,28 +316,18 @@ crate::early_lint_methods!(impl_early_lint_pass, []); /// This trait generalizes over those nodes. pub trait EarlyCheckNode<'a>: Copy { fn id(self) -> ast::NodeId; - fn attrs<'b>(self) -> &'b [ast::Attribute] - where - 'a: 'b; - fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>) - where - 'a: 'b; + fn attrs(self) -> &'a [ast::Attribute]; + fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>); } impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) { fn id(self) -> ast::NodeId { ast::CRATE_NODE_ID } - fn attrs<'b>(self) -> &'b [ast::Attribute] - where - 'a: 'b, - { + fn attrs(self) -> &'a [ast::Attribute] { self.1 } - fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>) - where - 'a: 'b, - { + fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>) { lint_callback!(cx, check_crate, self.0); ast_visit::walk_crate(cx, self.0); lint_callback!(cx, check_crate_post, self.0); @@ -342,16 +338,10 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast:: fn id(self) -> ast::NodeId { self.0 } - fn attrs<'b>(self) -> &'b [ast::Attribute] - where - 'a: 'b, - { + fn attrs(self) -> &'a [ast::Attribute] { self.1 } - fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>) - where - 'a: 'b, - { + fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>) { walk_list!(cx, visit_attribute, self.1); walk_list!(cx, visit_item, self.2); } @@ -359,6 +349,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast:: pub fn check_ast_node<'a>( sess: &Session, + tcx: Option<TyCtxt<'_>>, features: &Features, pre_expansion: bool, lint_store: &LintStore, @@ -382,22 +373,23 @@ pub fn check_ast_node<'a>( let passes = if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; if passes.is_empty() { - check_ast_node_inner(sess, check_node, context, builtin_lints); + check_ast_node_inner(sess, tcx, check_node, context, builtin_lints); } else { let mut passes: Vec<_> = passes.iter().map(|mk_pass| (mk_pass)()).collect(); passes.push(Box::new(builtin_lints)); let pass = RuntimeCombinedEarlyLintPass { passes: &mut passes[..] }; - check_ast_node_inner(sess, check_node, context, pass); + check_ast_node_inner(sess, tcx, check_node, context, pass); } } fn check_ast_node_inner<'a, T: EarlyLintPass>( sess: &Session, + tcx: Option<TyCtxt<'_>>, check_node: impl EarlyCheckNode<'a>, context: EarlyContext<'_>, pass: T, ) { - let mut cx = EarlyContextAndPass { context, pass }; + let mut cx = EarlyContextAndPass { context, tcx, pass }; cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index a3731e31c2b..6d73715562b 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -8,17 +8,22 @@ use rustc_errors::{ Applicability, Diag, DiagArgValue, LintDiagnostic, elided_lifetime_in_path_suggestion, }; use rustc_middle::middle::stability; +use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution}; -use rustc_span::BytePos; -use rustc_span::symbol::kw; +use rustc_span::{BytePos, kw}; use tracing::debug; use crate::lints::{self, ElidedNamedLifetime}; mod check_cfg; -pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) { +pub(super) fn decorate_lint( + sess: &Session, + tcx: Option<TyCtxt<'_>>, + diagnostic: BuiltinLintDiag, + diag: &mut Diag<'_, ()>, +) { match diagnostic { BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { let spans: Vec<_> = content @@ -199,10 +204,10 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & .decorate_lint(diag); } BuiltinLintDiag::UnexpectedCfgName(name, value) => { - check_cfg::unexpected_cfg_name(sess, name, value).decorate_lint(diag); + check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag); } BuiltinLintDiag::UnexpectedCfgValue(name, value) => { - check_cfg::unexpected_cfg_value(sess, name, value).decorate_lint(diag); + check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag); } BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => { let suggestion = match sugg { diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs index 63a722f6067..eebb131599a 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs @@ -1,10 +1,10 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; +use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::ExpectedValues; use rustc_span::edit_distance::find_best_match_for_name; -use rustc_span::symbol::Ident; -use rustc_span::{ExpnKind, Span, Symbol, sym}; +use rustc_span::{ExpnKind, Ident, Span, Symbol, sym}; use crate::lints; @@ -73,17 +73,20 @@ fn rustc_macro_help(span: Span) -> Option<lints::UnexpectedCfgRustcMacroHelp> { } } -fn cargo_macro_help(span: Span) -> Option<lints::UnexpectedCfgCargoMacroHelp> { +fn cargo_macro_help( + tcx: Option<TyCtxt<'_>>, + span: Span, +) -> Option<lints::UnexpectedCfgCargoMacroHelp> { let oexpn = 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 + && let Some(tcx) = tcx { Some(lints::UnexpectedCfgCargoMacroHelp { macro_kind: macro_kind.descr(), macro_name, - // FIXME: Get access to a `TyCtxt` from an `EarlyContext` - // crate_name: cx.tcx.crate_name(def_id.krate), + crate_name: tcx.crate_name(def_id.krate), }) } else { None @@ -92,6 +95,7 @@ fn cargo_macro_help(span: Span) -> Option<lints::UnexpectedCfgCargoMacroHelp> { pub(super) fn unexpected_cfg_name( sess: &Session, + tcx: Option<TyCtxt<'_>>, (name, name_span): (Symbol, Span), value: Option<(Symbol, Span)>, ) -> lints::UnexpectedCfgName { @@ -223,7 +227,7 @@ pub(super) fn unexpected_cfg_name( }; lints::unexpected_cfg_name::InvocationHelp::Cargo { help, - macro_help: cargo_macro_help(name_span), + macro_help: cargo_macro_help(tcx, name_span), } } else { let help = lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No)); @@ -238,6 +242,7 @@ pub(super) fn unexpected_cfg_name( pub(super) fn unexpected_cfg_value( sess: &Session, + tcx: Option<TyCtxt<'_>>, (name, name_span): (Symbol, Span), value: Option<(Symbol, Span)>, ) -> lints::UnexpectedCfgValue { @@ -339,7 +344,7 @@ pub(super) fn unexpected_cfg_value( }; lints::unexpected_cfg_value::InvocationHelp::Cargo { help, - macro_help: cargo_macro_help(name_span), + macro_help: cargo_macro_help(tcx, name_span), } } else { let help = if can_suggest_adding_value { diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index 8e22a9bdc45..6556a8d8f2d 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -2,8 +2,7 @@ use rustc_hir as hir; use rustc_middle::ty::Ty; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::Span; -use rustc_span::symbol::sym; +use rustc_span::{Span, sym}; use crate::context::LintContext; use crate::lints::{EnumIntrinsicsMemDiscriminate, EnumIntrinsicsMemVariant}; diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 1402129195f..259ea908fc6 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -84,7 +84,7 @@ declare_lint! { rewriting in `match` is an option to preserve the semantics up to Edition 2021", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), - reference: "issue #124085 <https://github.com/rust-lang/rust/issues/124085>", + reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>", }; } diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 1aacdbd448c..b5dd6cf16ee 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -177,7 +177,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { // Lazily compute these two, since they're likely a bit expensive. variances: LazyCell::new(|| { let mut functional_variances = FunctionalVariances { - tcx: tcx, + tcx, variances: FxHashMap::default(), ambient_variance: ty::Covariant, generics: tcx.generics_of(parent_def_id), @@ -325,7 +325,7 @@ where ParamKind::Free(def_id, name) => ty::Region::new_late_param( self.tcx, self.parent_def_id.to_def_id(), - ty::BoundRegionKind::Named(def_id, name), + ty::LateParamRegionKind::Named(def_id, name), ), // Totally ignore late bound args from binders. ParamKind::Late => return true, @@ -475,7 +475,7 @@ fn extract_def_id_from_arg<'tcx>( ) | ty::ReLateParam(ty::LateParamRegion { scope: _, - bound_region: ty::BoundRegionKind::Named(def_id, ..), + kind: ty::LateParamRegionKind::Named(def_id, ..), }) => def_id, _ => unreachable!(), }, @@ -544,7 +544,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> { ) | ty::ReLateParam(ty::LateParamRegion { scope: _, - bound_region: ty::BoundRegionKind::Named(def_id, ..), + kind: ty::LateParamRegionKind::Named(def_id, ..), }) => def_id, _ => { return Ok(a); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 482650e04e8..b31a4c74787 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -10,13 +10,12 @@ use rustc_hir::{ }; use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; use rustc_span::hygiene::{ExpnKind, MacroKind}; -use rustc_span::symbol::{Symbol, kw, sym}; +use rustc_span::{Span, sym}; use tracing::debug; use crate::lints::{ - BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, + BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag, @@ -171,27 +170,11 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { | PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..), .. - }) => { - if let QPath::TypeRelative(qpath_ty, ..) = qpath - && qpath_ty.hir_id == ty.hir_id - { - Some(path.span) - } else { - None - } - } - Node::Expr(Expr { kind: ExprKind::Path(qpath), .. }) => { - if let QPath::TypeRelative(qpath_ty, ..) = qpath - && qpath_ty.hir_id == ty.hir_id - { - Some(path.span) - } else { - None - } - } - // Can't unify these two branches because qpath below is `&&` and above is `&` - // and `A | B` paths don't play well together with adjustments, apparently. - Node::Expr(Expr { kind: ExprKind::Struct(qpath, ..), .. }) => { + }) + | Node::Expr( + Expr { kind: ExprKind::Path(qpath), .. } + | &Expr { kind: ExprKind::Struct(qpath, ..), .. }, + ) => { if let QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { @@ -376,46 +359,6 @@ impl EarlyLintPass for LintPassImpl { } declare_tool_lint! { - /// The `existing_doc_keyword` lint detects use `#[doc()]` keywords - /// that don't exist, e.g. `#[doc(keyword = "..")]`. - pub rustc::EXISTING_DOC_KEYWORD, - Allow, - "Check that documented keywords in std and core actually exist", - report_in_external_macro: true -} - -declare_lint_pass!(ExistingDocKeyword => [EXISTING_DOC_KEYWORD]); - -fn is_doc_keyword(s: Symbol) -> bool { - s <= kw::Union -} - -impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { - fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { - for attr in cx.tcx.hir().attrs(item.hir_id()) { - if !attr.has_name(sym::doc) { - continue; - } - if let Some(list) = attr.meta_item_list() { - for nested in list { - if nested.has_name(sym::keyword) { - let keyword = nested - .value_str() - .expect("#[doc(keyword = \"...\")] expected a value!"); - if is_doc_keyword(keyword) { - return; - } - cx.emit_span_lint(EXISTING_DOC_KEYWORD, attr.span, NonExistentDocKeyword { - keyword, - }); - } - } - } - } - } -} - -declare_tool_lint! { /// The `untranslatable_diagnostic` lint detects messages passed to functions with `impl /// Into<{D,Subd}iagMessage` parameters without using translatable Fluent strings. /// diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 4b1dafbdbee..5a4ed68440a 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,3 +1,4 @@ +use rustc_ast::attr::AttributeExt; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{Diag, LintDiagnostic, MultiSpan}; @@ -19,8 +20,7 @@ use rustc_session::lint::builtin::{ UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES, }; use rustc_session::lint::{Level, Lint, LintExpectationId, LintId}; -use rustc_span::symbol::{Symbol, sym}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use tracing::{debug, instrument}; use {rustc_ast as ast, rustc_hir as hir}; @@ -371,7 +371,7 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> { /// FIXME(blyxyas): In a future revision, we should also graph #![allow]s, /// but that is handled with more care - fn visit_attribute(&mut self, attribute: &'tcx ast::Attribute) { + fn visit_attribute(&mut self, attribute: &'tcx hir::Attribute) { if matches!( Level::from_attr(attribute), Some( @@ -383,10 +383,9 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> { ) ) { let store = unerased_lint_store(self.tcx.sess); - let Some(meta) = attribute.meta() else { return }; // Lint attributes are always a metalist inside a // metalist (even with just one lint). - let Some(meta_item_list) = meta.meta_item_list() else { return }; + let Some(meta_item_list) = attribute.meta_item_list() else { return }; for meta_list in meta_item_list { // Convert Path to String @@ -686,7 +685,12 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; } - fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option<HirId>) { + fn add( + &mut self, + attrs: &[impl AttributeExt], + is_crate_node: bool, + source_hir_id: Option<HirId>, + ) { let sess = self.sess; for (attr_index, attr) in attrs.iter().enumerate() { if attr.has_name(sym::automatically_derived) { @@ -910,7 +914,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let src = LintLevelSource::Node { name, span: sp, reason }; for &id in ids { - if self.check_gated_lint(id, attr.span, false) { + if self.check_gated_lint(id, sp, false) { self.insert_spec(id, (level, src)); } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index a99c94592b3..d7f0d2a6941 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -600,8 +600,6 @@ fn register_internals(store: &mut LintStore) { store.register_late_mod_pass(|_| Box::new(DefaultHashTypes)); store.register_lints(&QueryStability::lint_vec()); store.register_late_mod_pass(|_| Box::new(QueryStability)); - store.register_lints(&ExistingDocKeyword::lint_vec()); - store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword)); store.register_lints(&TyTyKind::lint_vec()); store.register_late_mod_pass(|_| Box::new(TyTyKind)); store.register_lints(&TypeIr::lint_vec()); @@ -629,7 +627,6 @@ fn register_internals(store: &mut LintStore) { LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO), LintId::of(USAGE_OF_QUALIFIED_TY), LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT), - LintId::of(EXISTING_DOC_KEYWORD), LintId::of(BAD_OPT_ACCESS), LintId::of(SPAN_USE_EQ_CTXT), ]); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 5da9f6d2053..ac995b59caf 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -16,8 +16,7 @@ use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::lint::AmbiguityErrorDiag; use rustc_span::edition::Edition; -use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, kw, sym}; use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds}; use crate::errors::{OverruledAttributeSub, RequestedLevel}; @@ -951,13 +950,6 @@ pub(crate) struct NonGlobImportTypeIrInherent { pub(crate) struct LintPassByHand; #[derive(LintDiagnostic)] -#[diag(lint_non_existent_doc_keyword)] -#[help] -pub(crate) struct NonExistentDocKeyword { - pub keyword: Symbol, -} - -#[derive(LintDiagnostic)] #[diag(lint_diag_out_of_impl)] pub(crate) struct DiagOutOfImpl; @@ -1816,14 +1808,14 @@ pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { } #[derive(LintDiagnostic)] -pub(crate) enum UnpredictableFunctionPointerComparisons<'a> { +pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> { #[diag(lint_unpredictable_fn_pointer_comparisons)] #[note(lint_note_duplicated_fn)] #[note(lint_note_deduplicated_fn)] #[note(lint_note_visit_fn_addr_eq)] Suggestion { #[subdiagnostic] - sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a>, + sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>, }, #[diag(lint_unpredictable_fn_pointer_comparisons)] #[note(lint_note_duplicated_fn)] @@ -1833,22 +1825,40 @@ pub(crate) enum UnpredictableFunctionPointerComparisons<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - lint_fn_addr_eq_suggestion, - style = "verbose", - applicability = "maybe-incorrect" -)] -pub(crate) struct UnpredictableFunctionPointerComparisonsSuggestion<'a> { - pub ne: &'a str, - pub cast_right: String, - pub deref_left: &'a str, - pub deref_right: &'a str, - #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] - pub left: Span, - #[suggestion_part(code = ", {deref_right}")] - pub middle: Span, - #[suggestion_part(code = "{cast_right})")] - pub right: Span, +pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { + #[multipart_suggestion( + lint_fn_addr_eq_suggestion, + style = "verbose", + applicability = "maybe-incorrect" + )] + FnAddrEq { + ne: &'a str, + deref_left: &'a str, + deref_right: &'a str, + #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] + left: Span, + #[suggestion_part(code = ", {deref_right}")] + middle: Span, + #[suggestion_part(code = ")")] + right: Span, + }, + #[multipart_suggestion( + lint_fn_addr_eq_suggestion, + style = "verbose", + applicability = "maybe-incorrect" + )] + FnAddrEqWithCast { + ne: &'a str, + deref_left: &'a str, + deref_right: &'a str, + fn_sig: rustc_middle::ty::PolyFnSig<'tcx>, + #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] + left: Span, + #[suggestion_part(code = ", {deref_right}")] + middle: Span, + #[suggestion_part(code = " as {fn_sig})")] + right: Span, + }, } pub(crate) struct ImproperCTypes<'a> { @@ -2187,8 +2197,7 @@ pub(crate) struct UnexpectedCfgRustcMacroHelp { pub(crate) struct UnexpectedCfgCargoMacroHelp { pub macro_kind: &'static str, pub macro_name: Symbol, - // FIXME: Figure out a way to get the crate name - // crate_name: String, + pub crate_name: Symbol, } #[derive(LintDiagnostic)] @@ -2205,8 +2214,7 @@ pub(crate) struct UnexpectedCfgName { pub(crate) mod unexpected_cfg_name { use rustc_errors::DiagSymbolList; use rustc_macros::Subdiagnostic; - use rustc_span::symbol::Ident; - use rustc_span::{Span, Symbol}; + use rustc_span::{Ident, Span, Symbol}; #[derive(Subdiagnostic)] pub(crate) enum CodeSuggestion { @@ -2679,7 +2687,7 @@ impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime { // but currently this lint's suggestions can conflict with those of `clippy::needless_lifetimes`: // https://github.com/rust-lang/rust/pull/129840#issuecomment-2323349119 // HACK: `'static` suggestions will never sonflict, emit only those for now. - if name != rustc_span::symbol::kw::StaticLifetime { + if name != kw::StaticLifetime { return; } match kind { diff --git a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs index 23f4f728906..ce280fef8b6 100644 --- a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs +++ b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs @@ -84,7 +84,7 @@ impl Expr2024 { let mut prev_colon = false; let mut prev_identifier = false; let mut prev_dollar = false; - for tt in tokens.trees() { + for tt in tokens.iter() { debug!( "check_tokens: {:?} - colon {prev_dollar} - ident {prev_identifier} - colon {prev_colon}", tt diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 9b495c19990..593c8616c1d 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -2,7 +2,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordMap; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::symbol::Symbol; +use rustc_span::Symbol; use unicode_security::general_security_profile::IdentifierType; use crate::lints::{ @@ -205,7 +205,7 @@ impl EarlyLintPass for NonAsciiIdents { (IdentifierType::Not_NFKC, "Not_NFKC"), ] { let codepoints: Vec<_> = - chars.extract_if(|(_, ty)| *ty == Some(id_ty)).collect(); + chars.extract_if(.., |(_, ty)| *ty == Some(id_ty)).collect(); if codepoints.is_empty() { continue; } @@ -217,7 +217,7 @@ impl EarlyLintPass for NonAsciiIdents { } let remaining = chars - .extract_if(|(c, _)| !GeneralSecurityProfile::identifier_allowed(*c)) + .extract_if(.., |(c, _)| !GeneralSecurityProfile::identifier_allowed(*c)) .collect::<Vec<_>>(); if !remaining.is_empty() { cx.emit_span_lint(UNCOMMON_CODEPOINTS, sp, IdentifierUncommonCodepoints { diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 36b1ff59c67..6f047b4da49 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -8,8 +8,7 @@ use rustc_parse_format::{ParseMode, Parser, Piece}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::edition::Edition; -use rustc_span::symbol::kw; -use rustc_span::{InnerSpan, Span, Symbol, hygiene, sym}; +use rustc_span::{InnerSpan, Span, Symbol, hygiene, kw, sym}; use rustc_trait_selection::infer::InferCtxtExt; use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused}; diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 3c33b2dd478..a1cc3a85109 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -5,8 +5,7 @@ use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind}; use rustc_middle::ty::TyCtxt; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; -use rustc_span::symbol::kw; -use rustc_span::{ExpnKind, MacroKind, Span, sym}; +use rustc_span::{ExpnKind, MacroKind, Span, kw, sym}; use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 4d8ebf2909e..70dce78b572 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,14 +1,13 @@ use rustc_abi::ExternAbi; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::FnKind; -use rustc_hir::{GenericParamKind, PatKind}; +use rustc_hir::{AttrArgs, AttrItem, AttrKind, GenericParamKind, PatKind}; use rustc_middle::ty; use rustc_session::config::CrateType; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::def_id::LocalDefId; -use rustc_span::symbol::{Ident, sym}; -use rustc_span::{BytePos, Span}; -use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; +use rustc_span::{BytePos, Ident, Span, sym}; +use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir}; use crate::lints::{ NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub, @@ -342,35 +341,35 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name { Some(Ident::from_str(name)) } else { - attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name) - .and_then(|attr| attr.meta()) - .and_then(|meta| { - meta.name_value_literal().and_then(|lit| { - if let ast::LitKind::Str(name, ..) = lit.kind { - // Discard the double quotes surrounding the literal. - let sp = cx - .sess() - .source_map() - .span_to_snippet(lit.span) - .ok() - .and_then(|snippet| { - let left = snippet.find('"')?; - let right = - snippet.rfind('"').map(|pos| snippet.len() - pos)?; - - Some( - lit.span - .with_lo(lit.span.lo() + BytePos(left as u32 + 1)) - .with_hi(lit.span.hi() - BytePos(right as u32)), - ) - }) - .unwrap_or(lit.span); - - Some(Ident::new(name, sp)) - } else { - None - } - }) + ast::attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name) + .and_then(|attr| { + if let AttrKind::Normal(n) = &attr.kind + && let AttrItem { args: AttrArgs::Eq { eq_span: _, expr: ref lit }, .. } = + n.as_ref() + && let ast::LitKind::Str(name, ..) = lit.kind + { + // Discard the double quotes surrounding the literal. + let sp = cx + .sess() + .source_map() + .span_to_snippet(lit.span) + .ok() + .and_then(|snippet| { + let left = snippet.find('"')?; + let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?; + + Some( + lit.span + .with_lo(lit.span.lo() + BytePos(left as u32 + 1)) + .with_hi(lit.span.hi() - BytePos(right as u32)), + ) + }) + .unwrap_or(lit.span); + + Some(Ident::new(name, sp)) + } else { + None + } }) }; @@ -502,7 +501,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { let attrs = cx.tcx.hir().attrs(it.hir_id()); match it.kind { - hir::ItemKind::Static(..) if !attr::contains_name(attrs, sym::no_mangle) => { + hir::ItemKind::Static(..) if !ast::attr::contains_name(attrs, sym::no_mangle) => { NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident); } hir::ItemKind::Const(..) => { diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 76dc96ae00f..fa519281be5 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -3,7 +3,7 @@ use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; use rustc_middle::ty::adjustment::Adjust; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::symbol::sym; +use rustc_span::sym; use crate::context::LintContext; use crate::lints::{ diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 5de0d4bc870..53a411e2b87 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -5,8 +5,7 @@ use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath}; use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::Span; -use rustc_span::symbol::kw; +use rustc_span::{Span, kw}; use rustc_trait_selection::traits::{self, ObligationCtxt}; use crate::{LateContext, LateLintPass, LintContext}; diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index ec306f5f834..3f264859d48 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -3,7 +3,7 @@ use rustc_hir::def::Res; use rustc_hir::{GenericArg, PathSegment, QPath, TyKind}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::symbol::sym; +use rustc_span::sym; use crate::lints::PassByValueDiag; use crate::{LateContext, LateLintPass, LintContext}; diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 9d84d36e779..3a323298bee 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -42,9 +42,9 @@ macro_rules! late_lint_methods { fn check_field_def(a: &'tcx rustc_hir::FieldDef<'tcx>); fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>); fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId); - fn check_attribute(a: &'tcx rustc_ast::Attribute); - fn check_attributes(a: &'tcx [rustc_ast::Attribute]); - fn check_attributes_post(a: &'tcx [rustc_ast::Attribute]); + fn check_attribute(a: &'tcx rustc_hir::Attribute); + fn check_attributes(a: &'tcx [rustc_hir::Attribute]); + fn check_attributes_post(a: &'tcx [rustc_hir::Attribute]); ]); ) } @@ -136,7 +136,7 @@ macro_rules! early_lint_methods { ($macro:path, $args:tt) => ( $macro!($args, [ fn check_param(a: &rustc_ast::Param); - fn check_ident(a: &rustc_span::symbol::Ident); + fn check_ident(a: &rustc_span::Ident); fn check_crate(a: &rustc_ast::Crate); fn check_crate_post(a: &rustc_ast::Crate); fn check_item(a: &rustc_ast::Item); diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index a73904cd776..f5ab44d7469 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -61,6 +61,7 @@ declare_lint! { "detects calling `into_iter` on boxed slices in Rust 2015, 2018, and 2021", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), + reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/intoiterator-box-slice.html>" }; } diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index b793ec6a493..a9797c3b32a 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -1,6 +1,6 @@ use rustc_hir::{self as hir, LangItem}; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::symbol::sym; +use rustc_span::sym; use crate::lints::{DropGlue, DropTraitConstraintsDiag}; use crate::{LateContext, LateLintPass, LintContext}; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 33650be056d..c0371b1f606 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -4,7 +4,7 @@ use std::ops::ControlFlow; use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, Variants, WrappingRange}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagMessage; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton}; use rustc_middle::ty::{ @@ -12,8 +12,7 @@ use rustc_middle::ty::{ }; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::def_id::LocalDefId; -use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol, source_map}; +use rustc_span::{Span, Symbol, source_map, sym}; use tracing::debug; use {rustc_ast as ast, rustc_hir as hir}; @@ -445,7 +444,25 @@ fn lint_fn_pointer<'tcx>( let (l_ty, l_ty_refs) = peel_refs(l_ty); let (r_ty, r_ty_refs) = peel_refs(r_ty); - if !l_ty.is_fn() || !r_ty.is_fn() { + if l_ty.is_fn() && r_ty.is_fn() { + // both operands are function pointers, fallthrough + } else if let ty::Adt(l_def, l_args) = l_ty.kind() + && let ty::Adt(r_def, r_args) = r_ty.kind() + && cx.tcx.is_lang_item(l_def.did(), LangItem::Option) + && cx.tcx.is_lang_item(r_def.did(), LangItem::Option) + && let Some(l_some_arg) = l_args.get(0) + && let Some(r_some_arg) = r_args.get(0) + && l_some_arg.expect_ty().is_fn() + && r_some_arg.expect_ty().is_fn() + { + // both operands are `Option<{function ptr}>` + return cx.emit_span_lint( + UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, + e.span, + UnpredictableFunctionPointerComparisons::Warn, + ); + } else { + // types are not function pointers, nothing to do return; } @@ -483,29 +500,36 @@ fn lint_fn_pointer<'tcx>( let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo()); let right = r_span.shrink_to_hi().until(e.span.shrink_to_hi()); - // We only check for a right cast as `FnDef` == `FnPtr` is not possible, - // only `FnPtr == FnDef` is possible. - let cast_right = if !r_ty.is_fn_ptr() { - let fn_sig = r_ty.fn_sig(cx.tcx); - format!(" as {fn_sig}") - } else { - String::new() - }; + let sugg = + // We only check for a right cast as `FnDef` == `FnPtr` is not possible, + // only `FnPtr == FnDef` is possible. + if !r_ty.is_fn_ptr() { + let fn_sig = r_ty.fn_sig(cx.tcx); - cx.emit_span_lint( - UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, - e.span, - UnpredictableFunctionPointerComparisons::Suggestion { - sugg: UnpredictableFunctionPointerComparisonsSuggestion { + UnpredictableFunctionPointerComparisonsSuggestion::FnAddrEqWithCast { ne, + fn_sig, deref_left, deref_right, left, middle, right, - cast_right, - }, - }, + } + } else { + UnpredictableFunctionPointerComparisonsSuggestion::FnAddrEq { + ne, + deref_left, + deref_right, + left, + middle, + right, + } + }; + + cx.emit_span_lint( + UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, + e.span, + UnpredictableFunctionPointerComparisons::Suggestion { sugg }, ); } diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index dca42fea57d..83942918e3b 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -3,7 +3,7 @@ use rustc_abi::{Integer, Size}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::{bug, ty}; -use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; +use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir}; use crate::LateContext; use crate::context::LintContext; diff --git a/compiler/rustc_lint/src/unqualified_local_imports.rs b/compiler/rustc_lint/src/unqualified_local_imports.rs index bea01a33bd6..c9dd6b32d88 100644 --- a/compiler/rustc_lint/src/unqualified_local_imports.rs +++ b/compiler/rustc_lint/src/unqualified_local_imports.rs @@ -1,7 +1,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir}; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::symbol::kw; +use rustc_span::kw; use crate::{LateContext, LateLintPass, LintContext, lints}; @@ -31,7 +31,7 @@ declare_lint! { /// /// This lint is meant to be used with the (unstable) rustfmt setting `group_imports = "StdExternalCrate"`. /// That setting makes rustfmt group `self::`, `super::`, and `crate::` imports separately from those - /// refering to other crates. However, rustfmt cannot know whether `use c::S;` refers to a local module `c` + /// referring to other crates. However, rustfmt cannot know whether `use c::S;` refers to a local module `c` /// or an external crate `c`, so it always gets categorized as an import from another crate. /// To ensure consistent grouping of imports from the local crate, all local imports must /// start with `self::`, `super::`, or `crate::`. This lint can be used to enforce that style. diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 9cad5d98562..2b3cb14f9e9 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -11,8 +11,7 @@ use rustc_hir::{self as hir, LangItem}; use rustc_infer::traits::util::elaborate; use rustc_middle::ty::{self, Ty, adjustment}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; -use rustc_span::symbol::{Symbol, kw, sym}; -use rustc_span::{BytePos, Span}; +use rustc_span::{BytePos, Span, Symbol, kw, sym}; use tracing::instrument; use crate::lints::{ |
