Rollup merge of #149949 - JonathanBrouwer:error_cleanup, r=jdonszelmann

Cleanup of attribute parsing errors

Removes the specific `UnknownMetaItem` and `IllFormedAttributeInputLint` errors.
Note that `IllFormedAttributeInputLint` is not a lint, contrary to its name

r? ``````@jdonszelmann``````
This commit is contained in:
Matthias Krüger 2025-12-14 20:04:56 +01:00 committed by GitHub
commit 185f7dc044
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 288 additions and 308 deletions

View file

@ -50,11 +50,6 @@ attr_parsing_expects_feature_list =
attr_parsing_expects_features =
`{$name}` expects feature names
attr_parsing_ill_formed_attribute_input = {$num_suggestions ->
[1] attribute must be of the form {$suggestions}
*[other] valid forms for the attribute are {$suggestions}
}
attr_parsing_import_name_type_raw =
import name type can only be used with link kind `raw-dylib`
@ -213,10 +208,6 @@ attr_parsing_stability_outside_std = stability attributes may not be used outsid
attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
attr_parsing_unknown_meta_item =
unknown meta item '{$item}'
.label = expected one of {$expected}
attr_parsing_unknown_version_literal =
unknown version literal format, assuming it refers to a future version

View file

@ -42,7 +42,7 @@ pub fn parse_cfg<S: Stage>(
args: &ArgParser,
) -> Option<CfgEntry> {
let ArgParser::List(list) = args else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};
let Some(single) = list.single() else {

View file

@ -25,7 +25,7 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};
@ -478,7 +478,7 @@ fn parse_tf_attribute<S: Stage>(
) -> impl IntoIterator<Item = (Symbol, Span)> {
let mut features = Vec::new();
let ArgParser::List(list) = args else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return features;
};
if list.is_empty() {
@ -601,7 +601,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};

View file

@ -13,7 +13,7 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser {
template!(List: &[r#""name1", "name2", ..."#]),
|this, cx, args| {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return;
};

View file

@ -21,7 +21,7 @@ impl<S: Stage> CombineAttributeParser<S> for DebuggerViualizerParser {
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item> {
let Some(l) = args.list() else {
cx.expected_list(args.span().unwrap_or(cx.attr_span));
cx.expected_list(cx.attr_span, args);
return None;
};
let Some(single) = l.single() else {

View file

@ -110,13 +110,12 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
Some(get(cx, name, param.span(), param.args(), &suggestion)?);
}
_ => {
cx.unknown_key(
cx.expected_specific_argument(
param.span(),
param.path().to_string(),
if features.deprecated_suggestion() {
&["since", "note", "suggestion"]
&[sym::since, sym::note, sym::suggestion]
} else {
&["since", "note"]
&[sym::since, sym::note]
},
);
return None;

View file

@ -106,7 +106,7 @@ impl DocParser {
}
Some(sym::attr) => {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return;
};

View file

@ -76,7 +76,7 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
return None;
}
_ => {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
}
};
@ -379,7 +379,7 @@ impl LinkParser {
return true;
}
let Some(link_cfg) = item.args().list() else {
cx.expected_list(item.span());
cx.expected_list(item.span(), item.args());
return true;
};
let Some(link_cfg) = link_cfg.single() else {

View file

@ -1,9 +1,7 @@
use rustc_errors::DiagArgValue;
use rustc_hir::attrs::MacroUseArgs;
use rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS;
use super::prelude::*;
use crate::session_diagnostics::IllFormedAttributeInputLint;
pub(crate) struct MacroEscapeParser;
impl<S: Stage> NoArgsAttributeParser<S> for MacroEscapeParser {
@ -101,15 +99,8 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
}
}
}
ArgParser::NameValue(_) => {
let suggestions = cx.suggestions();
cx.emit_err(IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
),
span,
});
ArgParser::NameValue(nv) => {
cx.expected_list_or_no_args(nv.args_span());
}
}
},
@ -164,16 +155,8 @@ impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
}
}
}
ArgParser::NameValue(_) => {
let span = cx.attr_span;
let suggestions = cx.suggestions();
cx.emit_err(IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
),
span,
});
ArgParser::NameValue(nv) => {
cx.expected_list_or_no_args(nv.args_span());
return None;
}
};

View file

@ -1,7 +1,4 @@
use rustc_errors::DiagArgValue;
use super::prelude::*;
use crate::session_diagnostics::IllFormedAttributeInputLint;
pub(crate) struct MustUseParser;
@ -44,15 +41,8 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
};
Some(value_str)
}
ArgParser::List(_) => {
let suggestions = cx.suggestions();
cx.emit_err(IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
),
span: cx.attr_span,
});
ArgParser::List(list) => {
cx.expected_nv_or_no_args(list.span);
return None;
}
},

View file

@ -65,7 +65,7 @@ fn parse_derive_like<S: Stage>(
if args.no_args().is_ok() && !trait_name_mandatory {
return Some((None, ThinVec::new()));
}
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};
let mut items = list.mixed();
@ -96,7 +96,7 @@ fn parse_derive_like<S: Stage>(
let mut attributes = ThinVec::new();
if let Some(attrs) = items.next() {
let Some(attr_list) = attrs.meta_item() else {
cx.expected_list(attrs.span());
cx.unexpected_literal(attrs.span());
return None;
};
if !attr_list.path().word_is(sym::attributes) {
@ -104,7 +104,7 @@ fn parse_derive_like<S: Stage>(
return None;
}
let Some(attr_list) = attr_list.args().list() else {
cx.expected_list(attrs.span());
cx.expected_list(attrs.span(), attr_list.args());
return None;
};

View file

@ -27,7 +27,7 @@ impl<S: Stage> SingleAttributeParser<S> for CustomMirParser {
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};
@ -46,9 +46,8 @@ impl<S: Stage> SingleAttributeParser<S> for CustomMirParser {
extract_value(cx, sym::dialect, arg, meta_item.span(), &mut dialect, &mut failed);
} else if let Some(arg) = meta_item.word_is(sym::phase) {
extract_value(cx, sym::phase, arg, meta_item.span(), &mut phase, &mut failed);
} else if let Some(word) = meta_item.path().word() {
let word = word.to_string();
cx.unknown_key(meta_item.span(), word, &["dialect", "phase"]);
} else if let Some(..) = meta_item.path().word() {
cx.expected_specific_argument(meta_item.span(), &[sym::dialect, sym::phase]);
failed = true;
} else {
cx.expected_name_value(meta_item.span(), None);

View file

@ -33,7 +33,7 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser {
let mut reprs = Vec::new();
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return reprs;
};
@ -278,7 +278,7 @@ impl AlignParser {
fn parse<S: Stage>(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) {
match args {
ArgParser::NoArgs | ArgParser::NameValue(_) => {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
}
ArgParser::List(list) => {
let Some(align) = list.single() else {

View file

@ -295,7 +295,7 @@ pub(crate) fn parse_stability<S: Stage>(
let mut since = None;
let ArgParser::List(list) = args else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};
@ -315,11 +315,7 @@ pub(crate) fn parse_stability<S: Stage>(
insert_value_into_option_or_error(cx, &param, &mut since, word.unwrap())?
}
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param_span,
item: param.path().to_string(),
expected: &["feature", "since"],
});
cx.expected_specific_argument(param_span, &[sym::feature, sym::since]);
return None;
}
}
@ -371,7 +367,7 @@ pub(crate) fn parse_unstability<S: Stage>(
let mut old_name = None;
let ArgParser::List(list) = args else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};
@ -426,11 +422,17 @@ pub(crate) fn parse_unstability<S: Stage>(
insert_value_into_option_or_error(cx, &param, &mut old_name, word.unwrap())?
}
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param.span(),
item: param.path().to_string(),
expected: &["feature", "reason", "issue", "soft", "implied_by", "old_name"],
});
cx.expected_specific_argument(
param.span(),
&[
sym::feature,
sym::reason,
sym::issue,
sym::soft,
sym::implied_by,
sym::old_name,
],
);
return None;
}
}

View file

@ -22,7 +22,7 @@ impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
let mut array = false;
let mut boxed_slice = false;
let Some(args) = args.list() else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};
if args.is_empty() {

View file

@ -43,7 +43,7 @@ pub(crate) fn parse_single_integer<S: Stage>(
args: &ArgParser,
) -> Option<u128> {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
cx.expected_list(cx.attr_span, args);
return None;
};
let Some(single) = list.single() else {

View file

@ -77,7 +77,7 @@ use crate::attributes::transparency::TransparencyParser;
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
use crate::parser::{ArgParser, RefPathParser};
use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, ParsedDescription, UnknownMetaItem,
AttributeParseError, AttributeParseErrorReason, ParsedDescription,
};
use crate::target_checking::AllowedTargets;
@ -426,13 +426,20 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
}
impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
pub(crate) fn unknown_key(
fn emit_parse_error(
&self,
span: Span,
found: String,
options: &[&'static str],
reason: AttributeParseErrorReason<'_>,
) -> ErrorGuaranteed {
self.emit_err(UnknownMetaItem { span, item: found, expected: options })
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason,
suggestions: self.suggestions(),
})
}
/// error that a string literal was expected.
@ -444,133 +451,69 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span: Span,
actual_literal: Option<&MetaItemLit>,
) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
self.emit_parse_error(
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedStringLiteral {
AttributeParseErrorReason::ExpectedStringLiteral {
byte_string: actual_literal.and_then(|i| {
i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
}),
},
suggestions: self.suggestions(),
})
)
}
pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
suggestions: self.suggestions(),
})
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIntegerLiteral)
}
pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedList,
suggestions: self.suggestions(),
})
pub(crate) fn expected_list(&self, span: Span, args: &ArgParser) -> ErrorGuaranteed {
let span = match args {
ArgParser::NoArgs => span,
ArgParser::List(list) => list.span,
ArgParser::NameValue(nv) => nv.args_span(),
};
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedList)
}
pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span: args_span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedNoArgs,
suggestions: self.suggestions(),
})
pub(crate) fn expected_list_or_no_args(&self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedListOrNoArgs)
}
pub(crate) fn expected_nv_or_no_args(&self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValueOrNoArgs)
}
pub(crate) fn expected_no_args(&self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNoArgs)
}
/// emit an error that a `name` was expected here
pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedIdentifier,
suggestions: self.suggestions(),
})
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIdentifier)
}
/// emit an error that a `name = value` pair was expected at this span. The symbol can be given for
/// a nicer error message talking about the specific name that was found lacking a value.
pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedNameValue(name),
suggestions: self.suggestions(),
})
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValue(name))
}
/// emit an error that a `name = value` pair was found where that name was already seen.
pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::DuplicateKey(key),
suggestions: self.suggestions(),
})
self.emit_parse_error(span, AttributeParseErrorReason::DuplicateKey(key))
}
/// an error that should be emitted when a [`MetaItemOrLitParser`](crate::parser::MetaItemOrLitParser)
/// was expected *not* to be a literal, but instead a meta item.
pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::UnexpectedLiteral,
suggestions: self.suggestions(),
})
self.emit_parse_error(span, AttributeParseErrorReason::UnexpectedLiteral)
}
pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedSingleArgument,
suggestions: self.suggestions(),
})
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedSingleArgument)
}
pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
suggestions: self.suggestions(),
})
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedAtLeastOneArgument)
}
/// produces an error along the lines of `expected one of [foo, meow]`
@ -579,19 +522,14 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span: Span,
possibilities: &[Symbol],
) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
self.emit_parse_error(
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: false,
list: false,
},
suggestions: self.suggestions(),
})
)
}
/// produces an error along the lines of `expected one of [foo, meow] as an argument`.
@ -601,19 +539,14 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span: Span,
possibilities: &[Symbol],
) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
self.emit_parse_error(
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: false,
list: true,
},
suggestions: self.suggestions(),
})
)
}
/// produces an error along the lines of `expected one of ["foo", "meow"]`
@ -622,19 +555,14 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span: Span,
possibilities: &[Symbol],
) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
self.emit_parse_error(
span,
attr_span: self.attr_span,
template: self.template.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: true,
list: false,
},
suggestions: self.suggestions(),
})
)
}
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {

View file

@ -177,7 +177,7 @@ impl ArgParser {
match self {
Self::NoArgs => Ok(()),
Self::List(args) => Err(args.span),
Self::NameValue(args) => Err(args.eq_span.to(args.value_span)),
Self::NameValue(args) => Err(args.args_span()),
}
}
}
@ -314,6 +314,10 @@ impl NameValueParser {
pub fn value_as_str(&self) -> Option<Symbol> {
self.value_as_lit().kind.str()
}
pub fn args_span(&self) -> Span {
self.eq_span.to(self.value_span)
}
}
fn expr_to_lit(

View file

@ -64,26 +64,6 @@ pub(crate) struct DocAttributeNotAttribute {
pub attribute: Symbol,
}
/// Error code: E0541
pub(crate) struct UnknownMetaItem<'a> {
pub span: Span,
pub item: String,
pub expected: &'a [&'a str],
}
// Manual implementation to be able to format `expected` items correctly.
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnknownMetaItem<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
Diag::new(dcx, level, fluent::attr_parsing_unknown_meta_item)
.with_span(self.span)
.with_code(E0541)
.with_arg("item", self.item)
.with_arg("expected", expected.join(", "))
.with_span_label(self.span, fluent::attr_parsing_label)
}
}
#[derive(Diagnostic)]
#[diag(attr_parsing_missing_since, code = E0542)]
pub(crate) struct MissingSince {
@ -400,15 +380,6 @@ pub(crate) struct UnusedMultiple {
pub name: Symbol,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_ill_formed_attribute_input)]
pub(crate) struct IllFormedAttributeInputLint {
#[primary_span]
pub span: Span,
pub num_suggestions: usize,
pub suggestions: DiagArgValue,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_null_on_export, code = E0648)]
pub(crate) struct NullOnExport {
@ -539,6 +510,8 @@ pub(crate) enum AttributeParseErrorReason<'a> {
ExpectedAtLeastOneArgument,
ExpectedSingleArgument,
ExpectedList,
ExpectedListOrNoArgs,
ExpectedNameValueOrNoArgs,
UnexpectedLiteral,
ExpectedNameValue(Option<Symbol>),
DuplicateKey(Symbol),
@ -611,6 +584,12 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
AttributeParseErrorReason::ExpectedList => {
diag.span_label(self.span, "expected this to be a list");
}
AttributeParseErrorReason::ExpectedListOrNoArgs => {
diag.span_label(self.span, "expected a list or no arguments here");
}
AttributeParseErrorReason::ExpectedNameValueOrNoArgs => {
diag.span_label(self.span, "didn't expect a list here");
}
AttributeParseErrorReason::DuplicateKey(key) => {
diag.span_label(self.span, format!("found `{key}` used as a key more than once"));
diag.code(E0538);

View file

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
An unknown meta item was used.
Erroneous code example:
```compile_fail,E0541
```compile_fail (no longer emitted)
#[deprecated(
since="1.0.0",
// error: unknown meta item

View file

@ -2,7 +2,9 @@ error[E0539]: malformed `doc` attribute input
--> $DIR/invalid-cfg.rs:2:1
|
LL | #[doc(cfg = "x")]
| ^^^^^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^^^^-----^^
| |
| expected this to be a list
error[E0805]: malformed `doc` attribute input
--> $DIR/invalid-cfg.rs:3:1
@ -16,7 +18,9 @@ error[E0539]: malformed `doc` attribute input
--> $DIR/invalid-cfg.rs:7:1
|
LL | #[doc(cfg = "x")]
| ^^^^^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^^^^-----^^
| |
| expected this to be a list
error[E0805]: malformed `doc` attribute input
--> $DIR/invalid-cfg.rs:8:1
@ -30,7 +34,9 @@ error[E0539]: malformed `doc` attribute input
--> $DIR/invalid-cfg.rs:12:1
|
LL | #[doc(cfg = "x")]
| ^^^^^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^^^^-----^^
| |
| expected this to be a list
error[E0805]: malformed `doc` attribute input
--> $DIR/invalid-cfg.rs:13:1
@ -44,7 +50,9 @@ error[E0539]: malformed `doc` attribute input
--> $DIR/invalid-cfg.rs:18:1
|
LL | #[doc(cfg = "x")]
| ^^^^^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^^^^-----^^
| |
| expected this to be a list
error[E0805]: malformed `doc` attribute input
--> $DIR/invalid-cfg.rs:19:1

View file

@ -2,7 +2,9 @@
//~^ NOTE the lint level is defined here
#[macro_use = 5]
//~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
//~^ ERROR malformed `macro_use` attribute input
//~| NOTE expected a list or no arguments here
//~| NOTE for more information, visit
extern crate std as s1;
#[macro_use(5)]

View file

@ -1,23 +1,35 @@
error[E0469]: imported macro not found
--> $DIR/invalid-macro-use.rs:51:13
--> $DIR/invalid-macro-use.rs:53:13
|
LL | #[macro_use(a)]
| ^
error[E0469]: imported macro not found
--> $DIR/invalid-macro-use.rs:53:13
--> $DIR/invalid-macro-use.rs:55:13
|
LL | #[macro_use(b)]
| ^
error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
error[E0539]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:4:1
|
LL | #[macro_use = 5]
| ^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^---^
| |
| expected a list or no arguments here
|
= note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute>
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use = 5]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use = 5]
LL + #[macro_use]
|
error[E0539]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:8:1
--> $DIR/invalid-macro-use.rs:10:1
|
LL | #[macro_use(5)]
| ^^^^^^^^^^^^-^^
@ -35,7 +47,7 @@ LL + #[macro_use]
|
error[E0565]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:14:1
--> $DIR/invalid-macro-use.rs:16:1
|
LL | #[macro_use(a = "b")]
| ^^^^^^^^^^^^^^-----^^
@ -53,7 +65,7 @@ LL + #[macro_use]
|
error[E0565]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:20:1
--> $DIR/invalid-macro-use.rs:22:1
|
LL | #[macro_use(a(b))]
| ^^^^^^^^^^^^^---^^
@ -71,7 +83,7 @@ LL + #[macro_use]
|
error[E0539]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:26:1
--> $DIR/invalid-macro-use.rs:28:1
|
LL | #[macro_use(a::b)]
| ^^^^^^^^^^^^----^^
@ -89,13 +101,13 @@ LL + #[macro_use]
|
error: unused attribute
--> $DIR/invalid-macro-use.rs:32:1
--> $DIR/invalid-macro-use.rs:34:1
|
LL | #[macro_use(a)]
| ^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-macro-use.rs:34:1
--> $DIR/invalid-macro-use.rs:36:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^
@ -106,25 +118,25 @@ LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/invalid-macro-use.rs:40:1
--> $DIR/invalid-macro-use.rs:42:1
|
LL | #[macro_use(a)]
| ^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-macro-use.rs:38:1
--> $DIR/invalid-macro-use.rs:40:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^
error: unused attribute
--> $DIR/invalid-macro-use.rs:46:1
--> $DIR/invalid-macro-use.rs:48:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-macro-use.rs:44:1
--> $DIR/invalid-macro-use.rs:46:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^

View file

@ -59,7 +59,7 @@
#[cold = 1]
//~^ ERROR malformed
#[must_use()]
//~^ ERROR valid forms for the attribute are
//~^ ERROR malformed
#[no_mangle = 1]
//~^ ERROR malformed
#[unsafe(naked())]
@ -214,12 +214,12 @@ static mut TLS: u8 = 42;
#[no_link()]
//~^ ERROR malformed
#[macro_use = 1]
//~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
//~^ ERROR malformed
extern crate wloop;
//~^ ERROR can't find crate for `wloop` [E0463]
#[macro_export = 18]
//~^ ERROR valid forms for the attribute are
//~^ ERROR malformed
#[allow_internal_unsafe = 1]
//~^ ERROR malformed
//~| ERROR allow_internal_unsafe side-steps the unsafe_code lint

View file

@ -314,11 +314,23 @@ LL | #[cold = 1]
| | didn't expect any arguments here
| help: must be of the form: `#[cold]`
error: valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]`
error[E0539]: malformed `must_use` attribute input
--> $DIR/malformed-attrs.rs:61:1
|
LL | #[must_use()]
| ^^^^^^^^^^^^^
| ^^^^^^^^^^--^
| |
| didn't expect a list here
|
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute>
help: try changing it to one of the following valid forms of the attribute
|
LL - #[must_use()]
LL + #[must_use = "reason"]
|
LL - #[must_use()]
LL + #[must_use]
|
error[E0565]: malformed `no_mangle` attribute input
--> $DIR/malformed-attrs.rs:63:1
@ -614,17 +626,40 @@ LL | #[non_exhaustive = 1]
| | didn't expect any arguments here
| help: must be of the form: `#[non_exhaustive]`
error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
error[E0539]: malformed `macro_use` attribute input
--> $DIR/malformed-attrs.rs:216:1
|
LL | #[macro_use = 1]
| ^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^---^
| |
| expected a list or no arguments here
|
= note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute>
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use = 1]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use = 1]
LL + #[macro_use]
|
error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
error[E0539]: malformed `macro_export` attribute input
--> $DIR/malformed-attrs.rs:221:1
|
LL | #[macro_export = 18]
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^----^
| |
| expected a list or no arguments here
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_export = 18]
LL + #[macro_export(local_inner_macros)]
|
LL - #[macro_export = 18]
LL + #[macro_export]
|
error[E0565]: malformed `allow_internal_unsafe` attribute input
--> $DIR/malformed-attrs.rs:223:1

View file

@ -20,9 +20,9 @@ error[E0539]: malformed `rustc_align` attribute input
--> $DIR/malformed-fn-align.rs:17:1
|
LL | #[rustc_align = 16]
| ^^^^^^^^^^^^^^^^^^^
| |
| expected this to be a list
| ^^^^^^^^^^^^^^----^
| | |
| | expected this to be a list
| help: must be of the form: `#[rustc_align(<alignment in bytes>)]`
error[E0589]: invalid alignment value: not an unsuffixed integer

View file

@ -1,4 +1,4 @@
#[must_use()] //~ ERROR valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]`
#[must_use()] //~ ERROR malformed
struct Test;
fn main() {}

View file

@ -1,8 +1,21 @@
error: valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]`
error[E0539]: malformed `must_use` attribute input
--> $DIR/malformed-must_use.rs:1:1
|
LL | #[must_use()]
| ^^^^^^^^^^^^^
| ^^^^^^^^^^--^
| |
| didn't expect a list here
|
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute>
help: try changing it to one of the following valid forms of the attribute
|
LL - #[must_use()]
LL + #[must_use = "reason"]
|
LL - #[must_use()]
LL + #[must_use]
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0539`.

View file

@ -2,9 +2,9 @@ error[E0539]: malformed `rustc_align_static` attribute input
--> $DIR/malformed-static-align.rs:4:1
|
LL | #[rustc_align_static = 16]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected this to be a list
| ^^^^^^^^^^^^^^^^^^^^^----^
| | |
| | expected this to be a list
| help: must be of the form: `#[rustc_align_static(<alignment in bytes>)]`
error[E0589]: invalid alignment value: not an unsuffixed integer

View file

@ -11,9 +11,9 @@ error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
--> $DIR/rustc_skip_during_method_dispatch.rs:7:1
|
LL | #[rustc_skip_during_method_dispatch = "array"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected this to be a list
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------^
| | |
| | expected this to be a list
| help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input

View file

@ -13,9 +13,9 @@ error[E0539]: malformed `cfg` attribute input
--> $DIR/cfg-attr-syntax-validation.rs:7:1
|
LL | #[cfg = 10]
| ^^^^^^^^^^^
| |
| expected this to be a list
| ^^^^^^----^
| | |
| | expected this to be a list
| help: must be of the form: `#[cfg(predicate)]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>

View file

@ -3,7 +3,7 @@
// Various checks that deprecation attributes are used correctly
mod bogus_attribute_types_1 {
#[deprecated(since = "a", note = "a", reason)] //~ ERROR unknown meta item 'reason'
#[deprecated(since = "a", note = "a", reason)] //~ ERROR malformed `deprecated` attribute input [E0539]
fn f1() { }
#[deprecated(since = "a", note)] //~ ERROR malformed `deprecated` attribute input [E0539]

View file

@ -1,8 +1,10 @@
error[E0541]: unknown meta item 'reason'
--> $DIR/deprecation-sanity.rs:6:43
error[E0539]: malformed `deprecated` attribute input
--> $DIR/deprecation-sanity.rs:6:5
|
LL | #[deprecated(since = "a", note = "a", reason)]
| ^^^^^^ expected one of `since`, `note`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^
| |
| valid arguments are `since` or `note`
error[E0539]: malformed `deprecated` attribute input
--> $DIR/deprecation-sanity.rs:9:5
@ -86,5 +88,5 @@ LL | #[deprecated = "hello"]
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0538, E0539, E0541, E0565.
Some errors have detailed explanations: E0538, E0539, E0565.
For more information about an error, try `rustc --explain E0538`.

View file

@ -13,7 +13,7 @@ mod macro_escape {
//~^ ERROR arguments to `macro_use` are not allowed here
#[macro_use = "2700"] struct S;
//~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
//~^ ERROR malformed
//~| WARN cannot be used on
//~| WARN previously accepted

View file

@ -16,11 +16,23 @@ error: arguments to `macro_use` are not allowed here
LL | #![macro_use(my_macro)]
| ^^^^^^^^^^^^^^^^^^^^^^^
error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
error[E0539]: malformed `macro_use` attribute input
--> $DIR/issue-43106-gating-of-macro_use.rs:15:5
|
LL | #[macro_use = "2700"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^--------^
| |
| expected a list or no arguments here
|
= note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute>
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use = "2700"] struct S;
LL + #[macro_use(name1, name2, ...)] struct S;
|
LL - #[macro_use = "2700"] struct S;
LL + #[macro_use] struct S;
|
warning: `#[macro_use]` attribute cannot be used on structs
--> $DIR/issue-43106-gating-of-macro_use.rs:15:5
@ -61,3 +73,4 @@ LL | #[macro_use] impl S { }
error: aborting due to 4 previous errors; 4 warnings emitted
For more information about this error, try `rustc --explain E0539`.

View file

@ -10,7 +10,9 @@ error[E0539]: malformed `link` attribute input
--> $DIR/link-attr-validation-early.rs:3:1
|
LL | #[link = "foo"]
| ^^^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^-------^
| |
| expected this to be a list
|
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>

View file

@ -142,9 +142,9 @@ error[E0539]: malformed `link` attribute input
--> $DIR/link-attr-validation-late.rs:24:1
|
LL | #[link(name = "...", cfg = "literal")]
| ^^^^^^^^^^^^^^^^^^^^^---------------^^
| |
| expected this to be a list
| ^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^
| |
| expected this to be a list
|
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>

View file

@ -10,7 +10,9 @@ error[E0539]: malformed `link` attribute input
--> $DIR/malformed-regressions.rs:10:1
|
LL | #[link = ""]
| ^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^----^
| |
| expected this to be a list
|
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>

View file

@ -16,7 +16,9 @@ error[E0539]: malformed `proc_macro_derive` attribute input
--> $DIR/attribute.rs:15:1
|
LL | #[proc_macro_derive = ""]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^^^^^^^^^^^^^^----^
| |
| expected this to be a list
|
= note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros>
help: try changing it to one of the following valid forms of the attribute

View file

@ -10,7 +10,9 @@ error[E0539]: malformed `repr` attribute input
--> $DIR/repr.rs:4:1
|
LL | #[repr = "B"]
| ^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^-----^
| |
| expected this to be a list
|
= note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
@ -18,7 +20,9 @@ error[E0539]: malformed `repr` attribute input
--> $DIR/repr.rs:7:1
|
LL | #[repr = "C"]
| ^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^-----^
| |
| expected this to be a list
|
= note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>

View file

@ -42,7 +42,9 @@ error[E0539]: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:18:1
|
LL | #[sanitize = "off"]
| ^^^^^^^^^^^^^^^^^^^ expected this to be a list
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
error[E0539]: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:21:1

View file

@ -7,7 +7,7 @@
#[stable(feature = "a", feature = "b", since = "1.0.0")] //~ ERROR malformed `stable` attribute input [E0538]
fn f1() { }
#[stable(feature = "a", sinse = "1.0.0")] //~ ERROR unknown meta item 'sinse'
#[stable(feature = "a", sinse = "1.0.0")] //~ ERROR malformed `stable` attribute input [E0539]
fn f2() { }
#[unstable(feature = "a", issue = "no")]

View file

@ -7,11 +7,14 @@ LL | #[stable(feature = "a", feature = "b", since = "1.0.0")]
| | found `feature` used as a key more than once
| help: must be of the form: `#[stable(feature = "name", since = "version")]`
error[E0541]: unknown meta item 'sinse'
--> $DIR/stability-attribute-sanity-2.rs:10:25
error[E0539]: malformed `stable` attribute input
--> $DIR/stability-attribute-sanity-2.rs:10:1
|
LL | #[stable(feature = "a", sinse = "1.0.0")]
| ^^^^^^^^^^^^^^^ expected one of `feature`, `since`
| ^^^^^^^^^^^^^^^^^^^^^^^^---------------^^
| | |
| | valid arguments are `feature` or `since`
| help: must be of the form: `#[stable(feature = "name", since = "version")]`
error[E0545]: `issue` must be a non-zero numeric string or "none"
--> $DIR/stability-attribute-sanity-2.rs:13:27
@ -23,5 +26,5 @@ LL | #[unstable(feature = "a", issue = "no")]
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0538, E0541, E0545.
Some errors have detailed explanations: E0538, E0539, E0545.
For more information about an error, try `rustc --explain E0538`.

View file

@ -11,9 +11,9 @@ error[E0539]: malformed `unstable` attribute input
--> $DIR/stability-attribute-sanity-4.rs:11:5
|
LL | #[unstable = "b"]
| ^^^^^^^^^^^^^^^^^
| |
| expected this to be a list
| ^^^^^^^^^^^-----^
| | |
| | expected this to be a list
| help: must be of the form: `#[unstable(feature = "name", reason = "...", issue = "N")]`
error[E0539]: malformed `stable` attribute input
@ -29,9 +29,9 @@ error[E0539]: malformed `stable` attribute input
--> $DIR/stability-attribute-sanity-4.rs:17:5
|
LL | #[stable = "a"]
| ^^^^^^^^^^^^^^^
| |
| expected this to be a list
| ^^^^^^^^^-----^
| | |
| | expected this to be a list
| help: must be of the form: `#[stable(feature = "name", since = "version")]`
error[E0542]: missing 'since'

View file

@ -5,7 +5,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
mod bogus_attribute_types_1 {
#[stable(feature = "a", since = "4.4.4", reason)] //~ ERROR unknown meta item 'reason' [E0541]
#[stable(feature = "a", since = "4.4.4", reason)] //~ ERROR malformed `stable` attribute input [E0539]
fn f1() { }
#[stable(feature = "a", since)] //~ ERROR malformed `stable` attribute input [E0539]

View file

@ -1,8 +1,11 @@
error[E0541]: unknown meta item 'reason'
--> $DIR/stability-attribute-sanity.rs:8:46
error[E0539]: malformed `stable` attribute input
--> $DIR/stability-attribute-sanity.rs:8:5
|
LL | #[stable(feature = "a", since = "4.4.4", reason)]
| ^^^^^^ expected one of `feature`, `since`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^
| | |
| | valid arguments are `feature` or `since`
| help: must be of the form: `#[stable(feature = "name", since = "version")]`
error[E0539]: malformed `stable` attribute input
--> $DIR/stability-attribute-sanity.rs:11:5
@ -138,5 +141,5 @@ LL | #[stable(feature = "a", since = "1.0.0")]
error: aborting due to 20 previous errors
Some errors have detailed explanations: E0539, E0541, E0542, E0543, E0544, E0546, E0547, E0549, E0711.
Some errors have detailed explanations: E0539, E0542, E0543, E0544, E0546, E0547, E0549, E0711.
For more information about an error, try `rustc --explain E0539`.

View file

@ -26,9 +26,9 @@ error[E0539]: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:17:1
|
LL | #[target_feature = "+sse2"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected this to be a list
| ^^^^^^^^^^^^^^^^^---------^
| | |
| | expected this to be a list
| help: must be of the form: `#[target_feature(enable = "feat1, feat2")]`
error[E0539]: malformed `target_feature` attribute input