Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 63 additions & 51 deletions compiler/rustc_attr_parsing/src/attributes/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use thin_vec::ThinVec;

use crate::attributes::{AcceptMapping, AttributeParser, AttributeStability};
use crate::context::{AcceptContext, ExpectStringLiteral, FinalizeContext};
use crate::parser::ArgParser;
use crate::parser::{ArgParser, MetaItemOrLitParser};
use crate::target_checking::AllowedTargets;
use crate::target_checking::Policy::{Allow, Warn};
use crate::{AttributeTemplate, diagnostics, template};
Expand Down Expand Up @@ -37,7 +37,7 @@ impl LintParser {
if !p.path().word_is(sym::reason) {
cx.emit_err(diagnostics::MalformedAttribute {
span: p.span(),
sub: diagnostics::MalformedAttributeSub::BadAttributeArgument(p.span()),
kind: diagnostics::MalformedAttributeKind::BadAttributeArgument(p.span()),
});
} else {
parsers = &parsers[..(parsers.len() - 1)];
Expand All @@ -48,58 +48,70 @@ impl LintParser {
};

for item in parsers {
if let Some(p) = item.meta_item() {
match p.args() {
ArgParser::NoArgs => {
let (tool, lint_name, rest) = match &*p.path().0.segments {
[] => unreachable!(),
[lint_name] => (None, lint_name.ident.name, None),
[tool, lint_name] => (Some(tool.ident), lint_name.ident.name, None),
[tool, lint_name, rest @ ..] => {
let rest = rest
.iter()
.map(|s| s.ident.name)
.collect::<Vec<_>>()
.into();
(Some(tool.ident), lint_name.ident.name, Some(rest))
}
};
match item {
MetaItemOrLitParser::MetaItemParser(p) => {
match p.args() {
ArgParser::NoArgs => {
let (tool, lint_name, rest) = match &*p.path().0.segments {
[] => unreachable!(),
[lint_name] => (None, lint_name.ident.name, None),
[tool, lint_name] => {
(Some(tool.ident), lint_name.ident.name, None)
}
[tool, lint_name, rest @ ..] => {
let rest = rest
.iter()
.map(|s| s.ident.name)
.collect::<Vec<_>>()
.into();
(Some(tool.ident), lint_name.ident.name, Some(rest))
}
};

self.lints.push(LintCheck {
tool,
lint_name,
lint_span: p.span(),
kind,
attr_id,
reason,
attr_span,
rest,
})
}
// We're found a `reason = "reason"` but we're not the last element.
ArgParser::NameValue(nv) if p.path().word_is(sym::reason) => {
cx.emit_err(diagnostics::MalformedAttribute {
span: p.span(),
sub: diagnostics::MalformedAttributeSub::ReasonMustComeLast(
item.span(),
),
});
nv.expect_string_literal(cx);
}
ArgParser::NameValue(_) | ArgParser::List(_) => {
cx.emit_err(diagnostics::MalformedAttribute {
span: p.span(),
sub: diagnostics::MalformedAttributeSub::BadAttributeArgument(
item.span(),
),
});
self.lints.push(LintCheck {
tool,
lint_name,
lint_span: p.span(),
kind,
attr_id,
reason,
attr_span,
rest,
})
}
// We've found a `reason = "reason"` but we're not the last element.
ArgParser::NameValue(nv) if p.path().word_is(sym::reason) => {
cx.emit_err(diagnostics::MalformedAttribute {
span: p.span(),
kind: diagnostics::MalformedAttributeKind::ReasonMustComeLast(
item.span(),
),
});
nv.expect_string_literal(cx);
}
ArgParser::NameValue(_) | ArgParser::List(_) => {
cx.emit_err(diagnostics::MalformedAttribute {
span: p.span(),
kind: diagnostics::MalformedAttributeKind::BadAttributeArgument(
item.span(),
),
});
}
}
}
} else {
cx.emit_err(diagnostics::MalformedAttribute {
span: item.span(),
sub: diagnostics::MalformedAttributeSub::BadAttributeArgument(item.span()),
});
MetaItemOrLitParser::Lit(lit) => {
cx.emit_err(diagnostics::BadAttributeLit {
span: item.span(),
help: if lit.kind.is_str() {
diagnostics::BadAttributeLitHelp::StrLit {
sym: lit.symbol,
kind: kind.sym(),
}
} else {
diagnostics::BadAttributeLitHelp::Other { kind: kind.sym() }
},
});
}
}
}
if parsers.is_empty() {
Expand Down
22 changes: 20 additions & 2 deletions compiler/rustc_attr_parsing/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2139,17 +2139,35 @@ pub(crate) struct MalformedAttribute {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sub: MalformedAttributeSub,
pub kind: MalformedAttributeKind,
}

#[derive(Subdiagnostic)]
pub(crate) enum MalformedAttributeSub {
pub(crate) enum MalformedAttributeKind {
#[label("bad attribute argument")]
BadAttributeArgument(#[primary_span] Span),
#[label("reason in lint attribute must come last")]
ReasonMustComeLast(#[primary_span] Span),
}

#[derive(Diagnostic)]
#[diag("expected a lint, found literal")]
pub(crate) struct BadAttributeLit {
#[primary_span]
#[label("not the name of a lint")]
pub span: Span,
#[subdiagnostic]
pub help: BadAttributeLitHelp,
}

#[derive(Subdiagnostic)]
pub(crate) enum BadAttributeLitHelp {
#[help("try using `#[{$kind}({$sym})]`")]
StrLit { sym: Symbol, kind: Symbol },
#[help("for example, write `#[{$kind}(dead_code)]` for `dead_code`")]
Comment thread
annieversary marked this conversation as resolved.
Other { kind: Symbol },
}

#[derive(Subdiagnostic)]
pub(crate) enum UnusedNote {
#[note("attribute `{$name}` with an empty list has no effect")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error[E0452]: malformed lint attribute input
error: expected a lint, found literal
--> $DIR/deduplicate-diagnostics.rs:10:8
|
LL | #[deny("literal")]
| ^^^^^^^^^ bad attribute argument
| ^^^^^^^^^ not the name of a lint
|
= help: try using `#[deny(literal)]`

error: cannot find derive macro `Unresolved` in this scope
--> $DIR/deduplicate-diagnostics.rs:6:10
Expand All @@ -12,4 +14,3 @@ LL | #[derive(Unresolved)]

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0452`.
17 changes: 10 additions & 7 deletions tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error[E0452]: malformed lint attribute input
error: expected a lint, found literal
--> $DIR/deduplicate-diagnostics.rs:10:8
|
LL | #[deny("literal")]
| ^^^^^^^^^ bad attribute argument
| ^^^^^^^^^ not the name of a lint
|
= help: try using `#[deny(literal)]`

error: cannot find derive macro `Unresolved` in this scope
--> $DIR/deduplicate-diagnostics.rs:6:10
Expand All @@ -18,22 +20,23 @@ LL | #[derive(Unresolved)]
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0452]: malformed lint attribute input
error: expected a lint, found literal
--> $DIR/deduplicate-diagnostics.rs:10:8
|
LL | #[deny("literal")]
| ^^^^^^^^^ bad attribute argument
| ^^^^^^^^^ not the name of a lint
|
= help: try using `#[deny(literal)]`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0452]: malformed lint attribute input
error: expected a lint, found literal
--> $DIR/deduplicate-diagnostics.rs:10:8
|
LL | #[deny("literal")]
| ^^^^^^^^^ bad attribute argument
| ^^^^^^^^^ not the name of a lint
|
= help: try using `#[deny(literal)]`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0452`.
6 changes: 3 additions & 3 deletions tests/ui/diagnostic-flags/deduplicate-diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope
struct S;

#[deny("literal")] //~ ERROR malformed lint attribute input
//[duplicate]~| ERROR malformed lint attribute input
//[duplicate]~| ERROR malformed lint attribute input
#[deny("literal")] //~ ERROR expected a lint, found literal
//[duplicate]~| ERROR expected a lint, found literal
//[duplicate]~| ERROR expected a lint, found literal
fn main() {}
11 changes: 11 additions & 0 deletions tests/ui/lint/lint-attribute-literals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Checks that lint attributes with literals have an explanatory error

#[allow("literal")]
//~^ ERROR expected a lint, found literal
//~| ERROR expected a lint, found literal
//~| ERROR expected a lint, found literal
#[deny(1.0)]
//~^ ERROR expected a lint, found literal
//~| ERROR expected a lint, found literal
//~| ERROR expected a lint, found literal
fn main() {}
54 changes: 54 additions & 0 deletions tests/ui/lint/lint-attribute-literals.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
error: expected a lint, found literal
--> $DIR/lint-attribute-literals.rs:3:9
|
LL | #[allow("literal")]
| ^^^^^^^^^ not the name of a lint
|
= help: try using `#[allow(literal)]`

error: expected a lint, found literal
--> $DIR/lint-attribute-literals.rs:7:8
|
LL | #[deny(1.0)]
| ^^^ not the name of a lint
|
= help: for example, write `#[deny(dead_code)]` for `dead_code`

error: expected a lint, found literal
--> $DIR/lint-attribute-literals.rs:3:9
|
LL | #[allow("literal")]
| ^^^^^^^^^ not the name of a lint
|
= help: try using `#[allow(literal)]`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: expected a lint, found literal
--> $DIR/lint-attribute-literals.rs:7:8
|
LL | #[deny(1.0)]
| ^^^ not the name of a lint
|
= help: for example, write `#[deny(dead_code)]` for `dead_code`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: expected a lint, found literal
--> $DIR/lint-attribute-literals.rs:3:9
|
LL | #[allow("literal")]
| ^^^^^^^^^ not the name of a lint
|
= help: try using `#[allow(literal)]`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: expected a lint, found literal
--> $DIR/lint-attribute-literals.rs:7:8
|
LL | #[deny(1.0)]
| ^^^ not the name of a lint
|
= help: for example, write `#[deny(dead_code)]` for `dead_code`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 6 previous errors

Loading