Skip to content

Commit b821fd2

Browse files
Rollup merge of #157088 - ariagivens:deprecated-attr-forms, r=JonathanBrouwer
Improve suggestions for malformed deprecated attribute When the deprecated attribute is supplied a single string as an argument, suggest using the NameValueStr syntax. ``` error[E0565]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:24:5 | LL | #[deprecated("test")] | ^^^^^^^^^^^^^------^^ | | | didn't expect a literal here | help: try using `=` instead | LL - #[deprecated("test")] LL + #[deprecated = "test"] | ``` If the string looked like a version (e.g. `"1.2.3"` or `"TBD"`), suggest using the since field instead. ``` error[E0565]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:27:5 | LL | #[deprecated("1.2.3")] | ^^^^^^^^^^^^^-------^^ | | | didn't expect a literal here | help: try specifying a deprecated since version | LL | #[deprecated(since = "1.2.3")] | +++++++ ```
2 parents 88b5580 + 9bfbf34 commit b821fd2

4 files changed

Lines changed: 83 additions & 15 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/deprecation.rs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_ast::LitKind;
12
use rustc_hir::attrs::{DeprecatedSince, Deprecation};
23
use rustc_hir::{RustcVersion, VERSION_PLACEHOLDER};
34

@@ -76,6 +77,38 @@ impl SingleAttributeParser for DeprecatedParser {
7677
// ok
7778
}
7879
ArgParser::List(list) => {
80+
// If the argument list contains a single string literal:
81+
// check whether it may be a version and suggest since field
82+
// otherwise, suggest using NameValue syntax
83+
if let Some(elem) = list.as_single()
84+
&& let Some(lit) = elem.as_lit()
85+
&& let LitKind::Str(text, _) = lit.kind
86+
{
87+
let mut adcx = cx.adcx();
88+
89+
match parse_since(text, true) {
90+
DeprecatedSince::Future | DeprecatedSince::RustcVersion(_) => {
91+
adcx.push_suggestion(
92+
String::from("try specifying a deprecated since version"),
93+
elem.span(),
94+
format!("since = {}", lit.kind),
95+
);
96+
}
97+
_ => {
98+
if let Some(span) = args.span() {
99+
adcx.push_suggestion(
100+
String::from("try using `=` instead"),
101+
span,
102+
format!(" = {}", lit.kind),
103+
);
104+
}
105+
}
106+
};
107+
108+
adcx.expected_not_literal(elem.span());
109+
return None;
110+
}
111+
79112
for param in list.mixed() {
80113
let Some(param) = param.meta_item() else {
81114
cx.adcx().expected_not_literal(param.span());
@@ -133,18 +166,11 @@ impl SingleAttributeParser for DeprecatedParser {
133166
}
134167

135168
let since = if let Some(since) = since {
136-
if since.as_str() == "TBD" {
137-
DeprecatedSince::Future
138-
} else if !is_rustc {
139-
DeprecatedSince::NonStandard(since)
140-
} else if since.as_str() == VERSION_PLACEHOLDER {
141-
DeprecatedSince::RustcVersion(RustcVersion::CURRENT)
142-
} else if let Some(version) = parse_version(since) {
143-
DeprecatedSince::RustcVersion(version)
144-
} else {
169+
let since = parse_since(since, is_rustc);
170+
if matches!(since, DeprecatedSince::Err) {
145171
cx.emit_err(InvalidSince { span: cx.attr_span });
146-
DeprecatedSince::Err
147172
}
173+
since
148174
} else if is_rustc {
149175
cx.emit_err(MissingSince { span: cx.attr_span });
150176
DeprecatedSince::Err
@@ -163,3 +189,17 @@ impl SingleAttributeParser for DeprecatedParser {
163189
})
164190
}
165191
}
192+
193+
fn parse_since(since: Symbol, is_rustc: bool) -> DeprecatedSince {
194+
if since.as_str() == "TBD" {
195+
DeprecatedSince::Future
196+
} else if !is_rustc {
197+
DeprecatedSince::NonStandard(since)
198+
} else if since.as_str() == VERSION_PLACEHOLDER {
199+
DeprecatedSince::RustcVersion(RustcVersion::CURRENT)
200+
} else if let Some(version) = parse_version(since) {
201+
DeprecatedSince::RustcVersion(version)
202+
} else {
203+
DeprecatedSince::Err
204+
}
205+
}

tests/ui/deprecation/deprecation-sanity.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ mod bogus_attribute_types_1 {
2323

2424
#[deprecated("test")] //~ ERROR malformed `deprecated` attribute input [E0565]
2525
fn f8() { }
26+
27+
#[deprecated("1.2.3")] //~ ERROR malformed `deprecated` attribute input [E0565]
28+
fn f9() { }
2629
}
2730

2831
#[deprecated(since = "a", note = "b")]

tests/ui/deprecation/deprecation-sanity.stderr

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,29 +55,48 @@ LL | #[deprecated("test")]
5555
| ^^^^^^^^^^^^^------^^
5656
| |
5757
| didn't expect a literal here
58+
|
59+
help: try using `=` instead
60+
|
61+
LL - #[deprecated("test")]
62+
LL + #[deprecated = "test"]
63+
|
64+
65+
error[E0565]: malformed `deprecated` attribute input
66+
--> $DIR/deprecation-sanity.rs:27:5
67+
|
68+
LL | #[deprecated("1.2.3")]
69+
| ^^^^^^^^^^^^^-------^^
70+
| |
71+
| didn't expect a literal here
72+
|
73+
help: try specifying a deprecated since version
74+
|
75+
LL | #[deprecated(since = "1.2.3")]
76+
| +++++++
5877

5978
error: multiple `deprecated` attributes
60-
--> $DIR/deprecation-sanity.rs:29:1
79+
--> $DIR/deprecation-sanity.rs:32:1
6180
|
6281
LL | #[deprecated(since = "a", note = "b")]
6382
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
6483
|
6584
note: attribute also specified here
66-
--> $DIR/deprecation-sanity.rs:28:1
85+
--> $DIR/deprecation-sanity.rs:31:1
6786
|
6887
LL | #[deprecated(since = "a", note = "b")]
6988
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7089

7190
error[E0538]: malformed `deprecated` attribute input
72-
--> $DIR/deprecation-sanity.rs:32:1
91+
--> $DIR/deprecation-sanity.rs:35:1
7392
|
7493
LL | #[deprecated(since = "a", since = "b", note = "c")]
7594
| ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^
7695
| |
7796
| found `since` used as a key more than once
7897

7998
error: `#[deprecated]` attribute cannot be used on trait impl blocks
80-
--> $DIR/deprecation-sanity.rs:37:1
99+
--> $DIR/deprecation-sanity.rs:40:1
81100
|
82101
LL | #[deprecated = "hello"]
83102
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +105,7 @@ LL | #[deprecated = "hello"]
86105
= help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements
87106
= note: `#[deny(useless_deprecated)]` on by default
88107

89-
error: aborting due to 10 previous errors
108+
error: aborting due to 11 previous errors
90109

91110
Some errors have detailed explanations: E0538, E0539, E0565.
92111
For more information about an error, try `rustc --explain E0538`.

tests/ui/error-codes/E0565-1.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ LL | #[deprecated("since")]
55
| ^^^^^^^^^^^^^-------^^
66
| |
77
| didn't expect a literal here
8+
|
9+
help: try using `=` instead
10+
|
11+
LL - #[deprecated("since")]
12+
LL + #[deprecated = "since"]
13+
|
814

915
error: aborting due to 1 previous error
1016

0 commit comments

Comments
 (0)