Support lints in early attribute parsing

This commit is contained in:
Jana Dönszelmann 2025-08-11 11:46:30 +02:00
parent 3bf6144461
commit 4b35cde904
No known key found for this signature in database
11 changed files with 93 additions and 45 deletions

View File

@ -3791,7 +3791,6 @@ dependencies = [
"rustc_error_messages",
"rustc_fluent_macro",
"rustc_hashes",
"rustc_hir_id",
"rustc_index",
"rustc_lexer",
"rustc_lint_defs",

View File

@ -50,6 +50,27 @@ impl<'sess> AttributeParser<'sess, Early> {
target_span: Span,
target_node_id: NodeId,
features: Option<&'sess Features>,
) -> Option<Attribute> {
Self::parse_limited_should_emit(
sess,
attrs,
sym,
target_span,
target_node_id,
features,
ShouldEmit::Nothing,
)
}
/// Usually you want `parse_limited`, which defaults to no errors.
pub fn parse_limited_should_emit(
sess: &'sess Session,
attrs: &[ast::Attribute],
sym: Symbol,
target_span: Span,
target_node_id: NodeId,
features: Option<&'sess Features>,
should_emit: ShouldEmit,
) -> Option<Attribute> {
let mut parsed = Self::parse_limited_all(
sess,
@ -59,7 +80,7 @@ impl<'sess> AttributeParser<'sess, Early> {
target_span,
target_node_id,
features,
ShouldEmit::Nothing,
should_emit,
);
assert!(parsed.len() <= 1);
parsed.pop()
@ -84,9 +105,8 @@ impl<'sess> AttributeParser<'sess, Early> {
target,
OmitDoc::Skip,
std::convert::identity,
|_lint| {
// FIXME: Can't emit lints here for now
// This branch can be hit when an attribute produces a warning during early parsing (such as attributes on macro calls)
|lint| {
crate::lints::emit_attribute_lint(&lint, sess);
},
)
}
@ -121,8 +141,8 @@ impl<'sess> AttributeParser<'sess, Early> {
cx: &mut parser,
target_span,
target_id: target_node_id,
emit_lint: &mut |_lint| {
panic!("can't emit lints here for now (nothing uses this atm)");
emit_lint: &mut |lint| {
crate::lints::emit_attribute_lint(&lint, sess);
},
},
attr_span: attr.span,

View File

@ -1,13 +1,13 @@
use std::borrow::Cow;
use rustc_errors::{DiagArgValue, LintEmitter};
use rustc_hir::Target;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::{HirId, Target};
use rustc_span::sym;
use crate::session_diagnostics;
pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emitter: L) {
pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emitter: L) {
let AttributeLint { id, span, kind } = lint;
match kind {
@ -51,7 +51,7 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
*id,
*span,
session_diagnostics::InvalidTargetLint {
name,
name: name.clone(),
target: target.plural_name(),
applied: DiagArgValue::StrListSepByAnd(
applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),

View File

@ -484,9 +484,9 @@ pub(crate) struct EmptyAttributeList {
#[diag(attr_parsing_invalid_target_lint)]
#[warning]
#[help]
pub(crate) struct InvalidTargetLint<'a> {
pub name: &'a AttrPath,
pub target: &'a str,
pub(crate) struct InvalidTargetLint {
pub name: AttrPath,
pub target: &'static str,
pub applied: DiagArgValue,
pub only: &'static str,
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]

View File

@ -14,7 +14,6 @@ rustc_error_codes = { path = "../rustc_error_codes" }
rustc_error_messages = { path = "../rustc_error_messages" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hashes = { path = "../rustc_hashes" }
rustc_hir_id = { path = "../rustc_hir_id" }
rustc_index = { path = "../rustc_index" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_lint_defs = { path = "../rustc_lint_defs" }

View File

@ -61,7 +61,6 @@ pub use rustc_error_messages::{
fallback_fluent_bundle, fluent_bundle, into_diag_arg_using_display,
};
use rustc_hashes::Hash128;
use rustc_hir_id::HirId;
pub use rustc_lint_defs::{Applicability, listify, pluralize};
use rustc_lint_defs::{Lint, LintExpectationId};
use rustc_macros::{Decodable, Encodable};
@ -110,13 +109,14 @@ rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
/// Used to avoid depending on `rustc_middle` in `rustc_attr_parsing`.
/// Always the `TyCtxt`.
pub trait LintEmitter: Copy {
type Id: Copy;
#[track_caller]
fn emit_node_span_lint(
self,
lint: &'static Lint,
hir_id: HirId,
hir_id: Self::Id,
span: impl Into<MultiSpan>,
decorator: impl for<'a> LintDiagnostic<'a, ()>,
decorator: impl for<'a> LintDiagnostic<'a, ()> + DynSend + 'static,
);
}

View File

@ -1421,6 +1421,8 @@ pub struct TyCtxt<'tcx> {
}
impl<'tcx> LintEmitter for TyCtxt<'tcx> {
type Id = HirId;
fn emit_node_span_lint(
self,
lint: &'static Lint,

View File

@ -7,6 +7,7 @@ use std::sync::atomic::AtomicBool;
use std::{env, fmt, io};
use rand::{RngCore, rng};
use rustc_ast::NodeId;
use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
@ -22,7 +23,7 @@ use rustc_errors::timings::TimingSectionHandler;
use rustc_errors::translation::Translator;
use rustc_errors::{
Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort,
TerminalUrl, fallback_fluent_bundle,
LintEmitter, TerminalUrl, fallback_fluent_bundle,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
@ -223,6 +224,20 @@ pub struct Session {
pub invocation_temp: Option<String>,
}
impl LintEmitter for &'_ Session {
type Id = NodeId;
fn emit_node_span_lint(
self,
lint: &'static rustc_lint_defs::Lint,
node_id: Self::Id,
span: impl Into<rustc_errors::MultiSpan>,
decorator: impl for<'a> rustc_errors::LintDiagnostic<'a, ()> + DynSend + 'static,
) {
self.psess.buffer_lint(lint, span, node_id, decorator);
}
}
#[derive(Clone, Copy)]
pub enum CodegenUnits {
/// Specified by the user. In this case we try fairly hard to produce the

View File

@ -66,6 +66,8 @@ extern "Rust" {
}
//~ ERROR unused attribute
//~^ ERROR `#[must_use]` attribute cannot be used on macro calls
//~| WARN this was previously accepted by the compiler but is being phased out
global_asm!("");
//~ ERROR attribute cannot be used on

View File

@ -66,6 +66,8 @@ extern "Rust" {
}
#[must_use] //~ ERROR unused attribute
//~^ ERROR `#[must_use]` attribute cannot be used on macro calls
//~| WARN this was previously accepted by the compiler but is being phased out
global_asm!("");
#[must_use] //~ ERROR attribute cannot be used on

View File

@ -1,3 +1,17 @@
error: `#[must_use]` attribute cannot be used on macro calls
--> $DIR/unused_attributes-must_use.rs:68:1
|
LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
note: the lint level is defined here
--> $DIR/unused_attributes-must_use.rs:4:9
|
LL | #![deny(unused_attributes, unused_must_use)]
| ^^^^^^^^^^^^^^^^^
error: unused attribute `must_use`
--> $DIR/unused_attributes-must_use.rs:68:1
|
@ -5,15 +19,10 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm`
--> $DIR/unused_attributes-must_use.rs:69:1
--> $DIR/unused_attributes-must_use.rs:71:1
|
LL | global_asm!("");
| ^^^^^^^^^^
note: the lint level is defined here
--> $DIR/unused_attributes-must_use.rs:4:9
|
LL | #![deny(unused_attributes, unused_must_use)]
| ^^^^^^^^^^^^^^^^^
error: `#[must_use]` attribute cannot be used on extern crates
--> $DIR/unused_attributes-must_use.rs:7:1
@ -88,7 +97,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on type aliases
--> $DIR/unused_attributes-must_use.rs:71:1
--> $DIR/unused_attributes-must_use.rs:73:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -97,7 +106,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on function params
--> $DIR/unused_attributes-must_use.rs:75:8
--> $DIR/unused_attributes-must_use.rs:77:8
|
LL | fn qux<#[must_use] T>(_: T) {}
| ^^^^^^^^^^^
@ -106,7 +115,7 @@ LL | fn qux<#[must_use] T>(_: T) {}
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on associated consts
--> $DIR/unused_attributes-must_use.rs:80:5
--> $DIR/unused_attributes-must_use.rs:82:5
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -115,7 +124,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on associated types
--> $DIR/unused_attributes-must_use.rs:83:5
--> $DIR/unused_attributes-must_use.rs:85:5
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -124,7 +133,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on trait impl blocks
--> $DIR/unused_attributes-must_use.rs:93:1
--> $DIR/unused_attributes-must_use.rs:95:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -133,7 +142,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on trait methods in impl blocks
--> $DIR/unused_attributes-must_use.rs:98:5
--> $DIR/unused_attributes-must_use.rs:100:5
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -142,7 +151,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to data types, functions, unions, required trait methods, provided trait methods, inherent methods, foreign functions, and traits
error: `#[must_use]` attribute cannot be used on trait aliases
--> $DIR/unused_attributes-must_use.rs:105:1
--> $DIR/unused_attributes-must_use.rs:107:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -151,7 +160,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on macro defs
--> $DIR/unused_attributes-must_use.rs:109:1
--> $DIR/unused_attributes-must_use.rs:111:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -160,7 +169,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on statements
--> $DIR/unused_attributes-must_use.rs:118:5
--> $DIR/unused_attributes-must_use.rs:120:5
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -169,7 +178,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on closures
--> $DIR/unused_attributes-must_use.rs:123:13
--> $DIR/unused_attributes-must_use.rs:125:13
|
LL | let x = #[must_use]
| ^^^^^^^^^^^
@ -178,7 +187,7 @@ LL | let x = #[must_use]
= help: `#[must_use]` can be applied to methods, data types, functions, unions, foreign functions, and traits
error: `#[must_use]` attribute cannot be used on match arms
--> $DIR/unused_attributes-must_use.rs:146:9
--> $DIR/unused_attributes-must_use.rs:148:9
|
LL | #[must_use]
| ^^^^^^^^^^^
@ -187,7 +196,7 @@ LL | #[must_use]
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on struct fields
--> $DIR/unused_attributes-must_use.rs:155:28
--> $DIR/unused_attributes-must_use.rs:157:28
|
LL | let s = PatternField { #[must_use] foo: 123 };
| ^^^^^^^^^^^
@ -196,7 +205,7 @@ LL | let s = PatternField { #[must_use] foo: 123 };
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on pattern fields
--> $DIR/unused_attributes-must_use.rs:157:24
--> $DIR/unused_attributes-must_use.rs:159:24
|
LL | let PatternField { #[must_use] foo } = s;
| ^^^^^^^^^^^
@ -205,7 +214,7 @@ LL | let PatternField { #[must_use] foo } = s;
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: unused `X` that must be used
--> $DIR/unused_attributes-must_use.rs:128:5
--> $DIR/unused_attributes-must_use.rs:130:5
|
LL | X;
| ^
@ -221,7 +230,7 @@ LL | let _ = X;
| +++++++
error: unused `Y` that must be used
--> $DIR/unused_attributes-must_use.rs:129:5
--> $DIR/unused_attributes-must_use.rs:131:5
|
LL | Y::Z;
| ^^^^
@ -232,7 +241,7 @@ LL | let _ = Y::Z;
| +++++++
error: unused `U` that must be used
--> $DIR/unused_attributes-must_use.rs:130:5
--> $DIR/unused_attributes-must_use.rs:132:5
|
LL | U { unit: () };
| ^^^^^^^^^^^^^^
@ -243,7 +252,7 @@ LL | let _ = U { unit: () };
| +++++++
error: unused return value of `U::method` that must be used
--> $DIR/unused_attributes-must_use.rs:131:5
--> $DIR/unused_attributes-must_use.rs:133:5
|
LL | U::method();
| ^^^^^^^^^^^
@ -254,7 +263,7 @@ LL | let _ = U::method();
| +++++++
error: unused return value of `foo` that must be used
--> $DIR/unused_attributes-must_use.rs:132:5
--> $DIR/unused_attributes-must_use.rs:134:5
|
LL | foo();
| ^^^^^
@ -265,7 +274,7 @@ LL | let _ = foo();
| +++++++
error: unused return value of `foreign_foo` that must be used
--> $DIR/unused_attributes-must_use.rs:135:9
--> $DIR/unused_attributes-must_use.rs:137:9
|
LL | foreign_foo();
| ^^^^^^^^^^^^^
@ -276,7 +285,7 @@ LL | let _ = foreign_foo();
| +++++++
error: unused return value of `Use::get_four` that must be used
--> $DIR/unused_attributes-must_use.rs:143:5
--> $DIR/unused_attributes-must_use.rs:145:5
|
LL | ().get_four();
| ^^^^^^^^^^^^^
@ -286,5 +295,5 @@ help: use `let _ = ...` to ignore the resulting value
LL | let _ = ().get_four();
| +++++++
error: aborting due to 29 previous errors
error: aborting due to 30 previous errors