Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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 path to a lint, found literal")]
Comment thread
annieversary marked this conversation as resolved.
Outdated
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 path to 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 path to 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 path to 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 path to 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 path to a lint, found literal
//[duplicate]~| ERROR expected path to a lint, found literal
Comment thread
annieversary marked this conversation as resolved.
Outdated
//[duplicate]~| ERROR expected path to a lint, found literal
fn main() {}
7 changes: 7 additions & 0 deletions tests/ui/lint/lint-attribute-literals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Checks that lint attributes with literals have an explanatory error

#[allow("literal")]
//~^ ERROR expected path to a lint, found literal
//~| ERROR expected path to a lint, found literal
//~| ERROR expected path to a lint, found literal
fn main() {}
28 changes: 28 additions & 0 deletions tests/ui/lint/lint-attribute-literals.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error: expected path to 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 path to 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 path to 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: aborting due to 3 previous errors

Loading