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
60 changes: 50 additions & 10 deletions compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_ast::LitKind;
use rustc_hir::attrs::{DeprecatedSince, Deprecation};
use rustc_hir::{RustcVersion, VERSION_PLACEHOLDER};

Expand Down Expand Up @@ -76,6 +77,38 @@ impl SingleAttributeParser for DeprecatedParser {
// ok
}
ArgParser::List(list) => {
// If the argument list contains a single string literal:
// check whether it may be a version and suggest since field
// otherwise, suggest using NameValue syntax
if let Some(elem) = list.as_single()
&& let Some(lit) = elem.as_lit()
&& let LitKind::Str(text, _) = lit.kind
{
let mut adcx = cx.adcx();

match parse_since(text, true) {
DeprecatedSince::Future | DeprecatedSince::RustcVersion(_) => {
adcx.push_suggestion(
String::from("try specifying a deprecated since version"),
elem.span(),
format!("since = {}", lit.kind),
);
}
_ => {
if let Some(span) = args.span() {
adcx.push_suggestion(
String::from("try using `=` instead"),
span,
format!(" = {}", lit.kind),
);
}
}
};

adcx.expected_not_literal(elem.span());
return None;
}

for param in list.mixed() {
let Some(param) = param.meta_item() else {
cx.adcx().expected_not_literal(param.span());
Expand Down Expand Up @@ -133,18 +166,11 @@ impl SingleAttributeParser for DeprecatedParser {
}

let since = if let Some(since) = since {
if since.as_str() == "TBD" {
DeprecatedSince::Future
} else if !is_rustc {
DeprecatedSince::NonStandard(since)
} else if since.as_str() == VERSION_PLACEHOLDER {
DeprecatedSince::RustcVersion(RustcVersion::CURRENT)
} else if let Some(version) = parse_version(since) {
DeprecatedSince::RustcVersion(version)
} else {
let since = parse_since(since, is_rustc);
if matches!(since, DeprecatedSince::Err) {
cx.emit_err(InvalidSince { span: cx.attr_span });
DeprecatedSince::Err
}
since
} else if is_rustc {
cx.emit_err(MissingSince { span: cx.attr_span });
DeprecatedSince::Err
Expand All @@ -163,3 +189,17 @@ impl SingleAttributeParser for DeprecatedParser {
})
}
}

fn parse_since(since: Symbol, is_rustc: bool) -> DeprecatedSince {
if since.as_str() == "TBD" {
DeprecatedSince::Future
} else if !is_rustc {
DeprecatedSince::NonStandard(since)
} else if since.as_str() == VERSION_PLACEHOLDER {
DeprecatedSince::RustcVersion(RustcVersion::CURRENT)
} else if let Some(version) = parse_version(since) {
DeprecatedSince::RustcVersion(version)
} else {
DeprecatedSince::Err
}
}
3 changes: 3 additions & 0 deletions tests/ui/deprecation/deprecation-sanity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ mod bogus_attribute_types_1 {

#[deprecated("test")] //~ ERROR malformed `deprecated` attribute input [E0565]
fn f8() { }

#[deprecated("1.2.3")] //~ ERROR malformed `deprecated` attribute input [E0565]
fn f9() { }
}

#[deprecated(since = "a", note = "b")]
Expand Down
29 changes: 24 additions & 5 deletions tests/ui/deprecation/deprecation-sanity.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,48 @@ LL | #[deprecated("test")]
| ^^^^^^^^^^^^^------^^
| |
| didn't expect a literal here
|
help: try using `=` instead
|
LL - #[deprecated("test")]
LL + #[deprecated = "test"]
|

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")]
| +++++++

error: multiple `deprecated` attributes
--> $DIR/deprecation-sanity.rs:29:1
--> $DIR/deprecation-sanity.rs:32:1
|
LL | #[deprecated(since = "a", note = "b")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/deprecation-sanity.rs:28:1
--> $DIR/deprecation-sanity.rs:31:1
|
LL | #[deprecated(since = "a", note = "b")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

error: `#[deprecated]` attribute cannot be used on trait impl blocks
--> $DIR/deprecation-sanity.rs:37:1
--> $DIR/deprecation-sanity.rs:40:1
|
LL | #[deprecated = "hello"]
| ^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -86,7 +105,7 @@ LL | #[deprecated = "hello"]
= 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
= note: `#[deny(useless_deprecated)]` on by default

error: aborting due to 10 previous errors
error: aborting due to 11 previous errors

Some errors have detailed explanations: E0538, E0539, E0565.
For more information about an error, try `rustc --explain E0538`.
6 changes: 6 additions & 0 deletions tests/ui/error-codes/E0565-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ LL | #[deprecated("since")]
| ^^^^^^^^^^^^^-------^^
| |
| didn't expect a literal here
|
help: try using `=` instead
|
LL - #[deprecated("since")]
LL + #[deprecated = "since"]
|

error: aborting due to 1 previous error

Expand Down
Loading