Skip to content

Commit f011292

Browse files
authored
Rollup merge of #78626 - fusion-engineering-forks:deprecated-trait-impl, r=estebank
Improve errors about #[deprecated] attribute This change: 1. Turns `#[deprecated]` on a trait impl block into an error, which fixes #78625; 2. Changes these and other errors about `#[deprecated]` to use the span of the attribute instead of the item; and 3. Turns this error into a lint, to make sure it can be capped with `--cap-lints` and doesn't break any existing dependencies. Can be reviewed per commit. --- Example: ```rust struct X; #[deprecated = "a"] impl Default for X { #[deprecated = "b"] fn default() -> Self { X } } ``` Before: ``` error: This deprecation annotation is useless --> src/main.rs:6:5 | 6 | / fn default() -> Self { 7 | | X 8 | | } | |_____^ ``` After: ``` error: this `#[deprecated]' annotation has no effect --> src/main.rs:3:1 | 3 | #[deprecated = "a"] | ^^^^^^^^^^^^^^^^^^^ help: try removing the deprecation attribute | = note: `#[deny(useless_deprecated)]` on by default error: this `#[deprecated]' annotation has no effect --> src/main.rs:5:5 | 5 | #[deprecated = "b"] | ^^^^^^^^^^^^^^^^^^^ help: try removing the deprecation attribute ```
2 parents 39f5563 + 9c647d1 commit f011292

File tree

8 files changed

+96
-38
lines changed

8 files changed

+96
-38
lines changed

compiler/rustc_attr/src/builtin.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -637,19 +637,15 @@ pub struct Deprecation {
637637
}
638638

639639
/// Finds the deprecation attribute. `None` if none exists.
640-
pub fn find_deprecation(sess: &Session, attrs: &[Attribute], item_sp: Span) -> Option<Deprecation> {
641-
find_deprecation_generic(sess, attrs.iter(), item_sp)
640+
pub fn find_deprecation(sess: &Session, attrs: &[Attribute]) -> Option<(Deprecation, Span)> {
641+
find_deprecation_generic(sess, attrs.iter())
642642
}
643643

644-
fn find_deprecation_generic<'a, I>(
645-
sess: &Session,
646-
attrs_iter: I,
647-
item_sp: Span,
648-
) -> Option<Deprecation>
644+
fn find_deprecation_generic<'a, I>(sess: &Session, attrs_iter: I) -> Option<(Deprecation, Span)>
649645
where
650646
I: Iterator<Item = &'a Attribute>,
651647
{
652-
let mut depr: Option<Deprecation> = None;
648+
let mut depr: Option<(Deprecation, Span)> = None;
653649
let diagnostic = &sess.parse_sess.span_diagnostic;
654650

655651
'outer: for attr in attrs_iter {
@@ -658,8 +654,11 @@ where
658654
continue;
659655
}
660656

661-
if depr.is_some() {
662-
struct_span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes").emit();
657+
if let Some((_, span)) = &depr {
658+
struct_span_err!(diagnostic, attr.span, E0550, "multiple deprecated attributes")
659+
.span_label(attr.span, "repeated deprecation attribute")
660+
.span_label(*span, "first deprecation attribute")
661+
.emit();
663662
break;
664663
}
665664

@@ -780,7 +779,7 @@ where
780779
sess.mark_attr_used(&attr);
781780

782781
let is_since_rustc_version = sess.check_name(attr, sym::rustc_deprecated);
783-
depr = Some(Deprecation { since, note, suggestion, is_since_rustc_version });
782+
depr = Some((Deprecation { since, note, suggestion, is_since_rustc_version }, attr.span));
784783
}
785784

786785
depr

compiler/rustc_expand/src/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ impl SyntaxExtension {
793793
allow_internal_unsafe: sess.contains_name(attrs, sym::allow_internal_unsafe),
794794
local_inner_macros,
795795
stability,
796-
deprecation: attr::find_deprecation(&sess, attrs, span),
796+
deprecation: attr::find_deprecation(&sess, attrs).map(|(d, _)| d),
797797
helper_attrs,
798798
edition,
799799
is_builtin,

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,6 +2705,32 @@ declare_lint! {
27052705
};
27062706
}
27072707

2708+
declare_lint! {
2709+
/// The `useless_deprecated` lint detects deprecation attributes with no effect.
2710+
///
2711+
/// ### Example
2712+
///
2713+
/// ```rust,compile_fail
2714+
/// struct X;
2715+
///
2716+
/// #[deprecated = "message"]
2717+
/// impl Default for X {
2718+
/// fn default() -> Self {
2719+
/// X
2720+
/// }
2721+
/// }
2722+
/// ```
2723+
///
2724+
/// {{produces}}
2725+
///
2726+
/// ### Explanation
2727+
///
2728+
/// Deprecation attributes have no effect on trait implementations.
2729+
pub USELESS_DEPRECATED,
2730+
Deny,
2731+
"detects deprecation attributes with no effect",
2732+
}
2733+
27082734
declare_tool_lint! {
27092735
pub rustc::INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
27102736
Deny,
@@ -2792,6 +2818,7 @@ declare_lint_pass! {
27922818
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
27932819
UNINHABITED_STATIC,
27942820
FUNCTION_ITEM_REFERENCES,
2821+
USELESS_DEPRECATED,
27952822
]
27962823
}
27972824

compiler/rustc_passes/src/stability.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::middle::privacy::AccessLevels;
1515
use rustc_middle::middle::stability::{DeprecationEntry, Index};
1616
use rustc_middle::ty::{self, query::Providers, TyCtxt};
1717
use rustc_session::lint;
18-
use rustc_session::lint::builtin::INEFFECTIVE_UNSTABLE_TRAIT_IMPL;
18+
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
1919
use rustc_session::parse::feature_err;
2020
use rustc_session::Session;
2121
use rustc_span::symbol::{sym, Symbol};
@@ -31,6 +31,8 @@ enum AnnotationKind {
3131
Required,
3232
// Annotation is useless, reject it
3333
Prohibited,
34+
// Deprecation annotation is useless, reject it. (Stability attribute is still required.)
35+
DeprecationProhibited,
3436
// Annotation itself is useless, but it can be propagated to children
3537
Container,
3638
}
@@ -83,14 +85,22 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
8385
did_error = self.forbid_staged_api_attrs(hir_id, attrs, inherit_deprecation.clone());
8486
}
8587

86-
let depr =
87-
if did_error { None } else { attr::find_deprecation(&self.tcx.sess, attrs, item_sp) };
88+
let depr = if did_error { None } else { attr::find_deprecation(&self.tcx.sess, attrs) };
8889
let mut is_deprecated = false;
89-
if let Some(depr) = &depr {
90+
if let Some((depr, span)) = &depr {
9091
is_deprecated = true;
9192

92-
if kind == AnnotationKind::Prohibited {
93-
self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless");
93+
if kind == AnnotationKind::Prohibited || kind == AnnotationKind::DeprecationProhibited {
94+
self.tcx.struct_span_lint_hir(USELESS_DEPRECATED, hir_id, *span, |lint| {
95+
lint.build("this `#[deprecated]` annotation has no effect")
96+
.span_suggestion_short(
97+
*span,
98+
"remove the unnecessary deprecation attribute",
99+
String::new(),
100+
rustc_errors::Applicability::MachineApplicable,
101+
)
102+
.emit()
103+
});
94104
}
95105

96106
// `Deprecation` is just two pointers, no need to intern it
@@ -114,7 +124,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
114124
}
115125
} else {
116126
self.recurse_with_stability_attrs(
117-
depr.map(|d| DeprecationEntry::local(d, hir_id)),
127+
depr.map(|(d, _)| DeprecationEntry::local(d, hir_id)),
118128
None,
119129
None,
120130
visit_children,
@@ -139,11 +149,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
139149
}
140150
}
141151

142-
if depr.as_ref().map_or(false, |d| d.is_since_rustc_version) {
152+
if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr {
143153
if stab.is_none() {
144154
struct_span_err!(
145155
self.tcx.sess,
146-
item_sp,
156+
*span,
147157
E0549,
148158
"rustc_deprecated attribute must be paired with \
149159
either stable or unstable attribute"
@@ -166,7 +176,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
166176
// Check if deprecated_since < stable_since. If it is,
167177
// this is *almost surely* an accident.
168178
if let (&Some(dep_since), &attr::Stable { since: stab_since }) =
169-
(&depr.as_ref().and_then(|d| d.since), &stab.level)
179+
(&depr.as_ref().and_then(|(d, _)| d.since), &stab.level)
170180
{
171181
// Explicit version of iter::order::lt to handle parse errors properly
172182
for (dep_v, stab_v) in
@@ -212,7 +222,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
212222
}
213223

214224
self.recurse_with_stability_attrs(
215-
depr.map(|d| DeprecationEntry::local(d, hir_id)),
225+
depr.map(|(d, _)| DeprecationEntry::local(d, hir_id)),
216226
stab,
217227
const_stab,
218228
visit_children,
@@ -322,6 +332,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
322332
}
323333
hir::ItemKind::Impl { of_trait: Some(_), .. } => {
324334
self.in_trait_impl = true;
335+
kind = AnnotationKind::DeprecationProhibited;
325336
}
326337
hir::ItemKind::Struct(ref sd, _) => {
327338
if let Some(ctor_hir_id) = sd.ctor_hir_id() {

src/test/ui/deprecation/deprecation-sanity.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,19 @@ mod bogus_attribute_types_1 {
2424
}
2525

2626
#[deprecated(since = "a", note = "b")]
27-
#[deprecated(since = "a", note = "b")]
28-
fn multiple1() { } //~ ERROR multiple deprecated attributes
27+
#[deprecated(since = "a", note = "b")] //~ ERROR multiple deprecated attributes
28+
fn multiple1() { }
2929

3030
#[deprecated(since = "a", since = "b", note = "c")] //~ ERROR multiple 'since' items
3131
fn f1() { }
3232

33+
struct X;
34+
35+
#[deprecated = "hello"] //~ ERROR this `#[deprecated]` annotation has no effect
36+
impl Default for X {
37+
fn default() -> Self {
38+
X
39+
}
40+
}
41+
3342
fn main() { }

src/test/ui/deprecation/deprecation-sanity.stderr

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,28 @@ LL | #[deprecated("test")]
4141
| ^^^^^^
4242

4343
error[E0550]: multiple deprecated attributes
44-
--> $DIR/deprecation-sanity.rs:28:1
44+
--> $DIR/deprecation-sanity.rs:27:1
4545
|
46-
LL | fn multiple1() { }
47-
| ^^^^^^^^^^^^^^^^^^
46+
LL | #[deprecated(since = "a", note = "b")]
47+
| -------------------------------------- first deprecation attribute
48+
LL | #[deprecated(since = "a", note = "b")]
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ repeated deprecation attribute
4850

4951
error[E0538]: multiple 'since' items
5052
--> $DIR/deprecation-sanity.rs:30:27
5153
|
5254
LL | #[deprecated(since = "a", since = "b", note = "c")]
5355
| ^^^^^^^^^^^
5456

55-
error: aborting due to 9 previous errors
57+
error: this `#[deprecated]` annotation has no effect
58+
--> $DIR/deprecation-sanity.rs:35:1
59+
|
60+
LL | #[deprecated = "hello"]
61+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: remove the unnecessary deprecation attribute
62+
|
63+
= note: `#[deny(useless_deprecated)]` on by default
64+
65+
error: aborting due to 10 previous errors
5666

5767
Some errors have detailed explanations: E0538, E0541, E0550, E0551, E0565.
5868
For more information about an error, try `rustc --explain E0538`.

src/test/ui/stability-attribute/stability-attribute-sanity.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ fn multiple3() { }
5959

6060
#[stable(feature = "a", since = "b")]
6161
#[rustc_deprecated(since = "b", reason = "text")]
62-
#[rustc_deprecated(since = "b", reason = "text")]
62+
#[rustc_deprecated(since = "b", reason = "text")] //~ ERROR multiple deprecated attributes
6363
#[rustc_const_unstable(feature = "c", issue = "none")]
6464
#[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels
65-
pub const fn multiple4() { } //~ ERROR multiple deprecated attributes
65+
pub const fn multiple4() { }
6666
//~^ ERROR Invalid stability or deprecation version found
6767

6868
#[rustc_deprecated(since = "a", reason = "text")]
6969
fn deprecated_without_unstable_or_stable() { }
70-
//~^ ERROR rustc_deprecated attribute must be paired with either stable or unstable attribute
70+
//~^^ ERROR rustc_deprecated attribute must be paired with either stable or unstable attribute
7171

7272
fn main() { }

src/test/ui/stability-attribute/stability-attribute-sanity.stderr

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ LL | #[stable(feature = "a", since = "b")]
8383
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8484

8585
error[E0550]: multiple deprecated attributes
86-
--> $DIR/stability-attribute-sanity.rs:65:1
86+
--> $DIR/stability-attribute-sanity.rs:62:1
8787
|
88-
LL | pub const fn multiple4() { }
89-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88+
LL | #[rustc_deprecated(since = "b", reason = "text")]
89+
| ------------------------------------------------- first deprecation attribute
90+
LL | #[rustc_deprecated(since = "b", reason = "text")]
91+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ repeated deprecation attribute
9092

9193
error[E0544]: multiple stability levels
9294
--> $DIR/stability-attribute-sanity.rs:64:1
@@ -101,10 +103,10 @@ LL | pub const fn multiple4() { }
101103
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
102104

103105
error[E0549]: rustc_deprecated attribute must be paired with either stable or unstable attribute
104-
--> $DIR/stability-attribute-sanity.rs:69:1
106+
--> $DIR/stability-attribute-sanity.rs:68:1
105107
|
106-
LL | fn deprecated_without_unstable_or_stable() { }
107-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
108+
LL | #[rustc_deprecated(since = "a", reason = "text")]
109+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
108110

109111
error: aborting due to 18 previous errors
110112

0 commit comments

Comments
 (0)