Skip to content

Commit 0651dd4

Browse files
authoredJul 24, 2020
Rollup merge of #74572 - Mark-Simulacrum:unify-rustc-depr, r=petrochenkov
Internally unify rustc_deprecated and deprecated This PR intentionally tries to be "featureless" in that the behavior is not altered for either attribute, though it more clearly exposes cases where that is the case in the code.
2 parents 52476f5 + 8454ee8 commit 0651dd4

File tree

10 files changed

+195
-244
lines changed

10 files changed

+195
-244
lines changed
 

‎src/librustc_attr/builtin.rs

+55-111
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,11 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
124124
///
125125
/// - `#[stable]`
126126
/// - `#[unstable]`
127-
/// - `#[rustc_deprecated]`
128127
#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
129128
#[derive(HashStable_Generic)]
130129
pub struct Stability {
131130
pub level: StabilityLevel,
132131
pub feature: Symbol,
133-
pub rustc_depr: Option<RustcDeprecation>,
134132
}
135133

136134
/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
@@ -163,15 +161,6 @@ impl StabilityLevel {
163161
}
164162
}
165163

166-
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
167-
#[derive(HashStable_Generic)]
168-
pub struct RustcDeprecation {
169-
pub since: Symbol,
170-
pub reason: Symbol,
171-
/// A text snippet used to completely replace any use of the deprecated item in an expression.
172-
pub suggestion: Option<Symbol>,
173-
}
174-
175164
/// Checks if `attrs` contains an attribute like `#![feature(feature_name)]`.
176165
/// This will not perform any "sanity checks" on the form of the attributes.
177166
pub fn contains_feature_attr(attrs: &[Attribute], feature_name: Symbol) -> bool {
@@ -205,15 +194,13 @@ where
205194
use StabilityLevel::*;
206195

207196
let mut stab: Option<Stability> = None;
208-
let mut rustc_depr: Option<RustcDeprecation> = None;
209197
let mut const_stab: Option<ConstStability> = None;
210198
let mut promotable = false;
211199
let mut allow_const_fn_ptr = false;
212200
let diagnostic = &sess.span_diagnostic;
213201

214202
'outer: for attr in attrs_iter {
215203
if ![
216-
sym::rustc_deprecated,
217204
sym::rustc_const_unstable,
218205
sym::rustc_const_stable,
219206
sym::unstable,
@@ -258,76 +245,8 @@ where
258245
}
259246
};
260247

261-
macro_rules! get_meta {
262-
($($name:ident),+) => {
263-
$(
264-
let mut $name = None;
265-
)+
266-
for meta in metas {
267-
if let Some(mi) = meta.meta_item() {
268-
match mi.name_or_empty() {
269-
$(
270-
sym::$name => if !get(mi, &mut $name) { continue 'outer },
271-
)+
272-
_ => {
273-
let expected = &[ $( stringify!($name) ),+ ];
274-
handle_errors(
275-
sess,
276-
mi.span,
277-
AttrError::UnknownMetaItem(
278-
pprust::path_to_string(&mi.path),
279-
expected,
280-
),
281-
);
282-
continue 'outer
283-
}
284-
}
285-
} else {
286-
handle_errors(
287-
sess,
288-
meta.span(),
289-
AttrError::UnsupportedLiteral(
290-
"unsupported literal",
291-
false,
292-
),
293-
);
294-
continue 'outer
295-
}
296-
}
297-
}
298-
}
299-
300248
let meta_name = meta.name_or_empty();
301249
match meta_name {
302-
sym::rustc_deprecated => {
303-
if rustc_depr.is_some() {
304-
struct_span_err!(
305-
diagnostic,
306-
item_sp,
307-
E0540,
308-
"multiple rustc_deprecated attributes"
309-
)
310-
.emit();
311-
continue 'outer;
312-
}
313-
314-
get_meta!(since, reason, suggestion);
315-
316-
match (since, reason) {
317-
(Some(since), Some(reason)) => {
318-
rustc_depr = Some(RustcDeprecation { since, reason, suggestion })
319-
}
320-
(None, _) => {
321-
handle_errors(sess, attr.span, AttrError::MissingSince);
322-
continue;
323-
}
324-
_ => {
325-
struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'")
326-
.emit();
327-
continue;
328-
}
329-
}
330-
}
331250
sym::rustc_const_unstable | sym::unstable => {
332251
if meta_name == sym::unstable && stab.is_some() {
333252
handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels);
@@ -429,7 +348,7 @@ where
429348
(Some(feature), reason, Some(_)) => {
430349
let level = Unstable { reason, issue: issue_num, is_soft };
431350
if sym::unstable == meta_name {
432-
stab = Some(Stability { level, feature, rustc_depr: None });
351+
stab = Some(Stability { level, feature });
433352
} else {
434353
const_stab = Some(ConstStability {
435354
level,
@@ -501,7 +420,7 @@ where
501420
(Some(feature), Some(since)) => {
502421
let level = Stable { since };
503422
if sym::stable == meta_name {
504-
stab = Some(Stability { level, feature, rustc_depr: None });
423+
stab = Some(Stability { level, feature });
505424
} else {
506425
const_stab = Some(ConstStability {
507426
level,
@@ -526,22 +445,6 @@ where
526445
}
527446
}
528447

529-
// Merge the deprecation info into the stability info
530-
if let Some(rustc_depr) = rustc_depr {
531-
if let Some(ref mut stab) = stab {
532-
stab.rustc_depr = Some(rustc_depr);
533-
} else {
534-
struct_span_err!(
535-
diagnostic,
536-
item_sp,
537-
E0549,
538-
"rustc_deprecated attribute must be paired with \
539-
either stable or unstable attribute"
540-
)
541-
.emit();
542-
}
543-
}
544-
545448
// Merge the const-unstable info into the stability info
546449
if promotable || allow_const_fn_ptr {
547450
if let Some(ref mut stab) = const_stab {
@@ -714,7 +617,16 @@ pub fn eval_condition(
714617
#[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)]
715618
pub struct Deprecation {
716619
pub since: Option<Symbol>,
620+
/// The note to issue a reason.
717621
pub note: Option<Symbol>,
622+
/// A text snippet used to completely replace any use of the deprecated item in an expression.
623+
///
624+
/// This is currently unstable.
625+
pub suggestion: Option<Symbol>,
626+
627+
/// Whether to treat the since attribute as being a Rust version identifier
628+
/// (rather than an opaque string).
629+
pub is_since_rustc_version: bool,
718630
}
719631

720632
/// Finds the deprecation attribute. `None` if none exists.
@@ -738,7 +650,7 @@ where
738650
let diagnostic = &sess.span_diagnostic;
739651

740652
'outer: for attr in attrs_iter {
741-
if !attr.check_name(sym::deprecated) {
653+
if !(attr.check_name(sym::deprecated) || attr.check_name(sym::rustc_deprecated)) {
742654
continue;
743655
}
744656

@@ -751,11 +663,12 @@ where
751663
Some(meta) => meta,
752664
None => continue,
753665
};
754-
depr = match &meta.kind {
755-
MetaItemKind::Word => Some(Deprecation { since: None, note: None }),
756-
MetaItemKind::NameValue(..) => {
757-
meta.value_str().map(|note| Deprecation { since: None, note: Some(note) })
758-
}
666+
let mut since = None;
667+
let mut note = None;
668+
let mut suggestion = None;
669+
match &meta.kind {
670+
MetaItemKind::Word => {}
671+
MetaItemKind::NameValue(..) => note = meta.value_str(),
759672
MetaItemKind::List(list) => {
760673
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
761674
if item.is_some() {
@@ -789,8 +702,6 @@ where
789702
}
790703
};
791704

792-
let mut since = None;
793-
let mut note = None;
794705
for meta in list {
795706
match meta {
796707
NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() {
@@ -799,18 +710,32 @@ where
799710
continue 'outer;
800711
}
801712
}
802-
sym::note => {
713+
sym::note if attr.check_name(sym::deprecated) => {
714+
if !get(mi, &mut note) {
715+
continue 'outer;
716+
}
717+
}
718+
sym::reason if attr.check_name(sym::rustc_deprecated) => {
803719
if !get(mi, &mut note) {
804720
continue 'outer;
805721
}
806722
}
723+
sym::suggestion if attr.check_name(sym::rustc_deprecated) => {
724+
if !get(mi, &mut suggestion) {
725+
continue 'outer;
726+
}
727+
}
807728
_ => {
808729
handle_errors(
809730
sess,
810731
meta.span(),
811732
AttrError::UnknownMetaItem(
812733
pprust::path_to_string(&mi.path),
813-
&["since", "note"],
734+
if attr.check_name(sym::deprecated) {
735+
&["since", "note"]
736+
} else {
737+
&["since", "reason", "suggestion"]
738+
},
814739
),
815740
);
816741
continue 'outer;
@@ -829,10 +754,29 @@ where
829754
}
830755
}
831756
}
757+
}
758+
}
759+
760+
if suggestion.is_some() && attr.check_name(sym::deprecated) {
761+
unreachable!("only allowed on rustc_deprecated")
762+
}
832763

833-
Some(Deprecation { since, note })
764+
if attr.check_name(sym::rustc_deprecated) {
765+
if since.is_none() {
766+
handle_errors(sess, attr.span, AttrError::MissingSince);
767+
continue;
834768
}
835-
};
769+
770+
if note.is_none() {
771+
struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'").emit();
772+
continue;
773+
}
774+
}
775+
776+
mark_used(&attr);
777+
778+
let is_since_rustc_version = attr.check_name(sym::rustc_deprecated);
779+
depr = Some(Deprecation { since, note, suggestion, is_since_rustc_version });
836780
}
837781

838782
depr

‎src/librustc_error_codes/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ E0771: include_str!("./error_codes/E0771.md"),
589589
E0521, // borrowed data escapes outside of closure
590590
E0523,
591591
// E0526, // shuffle indices are not constant
592-
E0540, // multiple rustc_deprecated attributes
592+
// E0540, // multiple rustc_deprecated attributes
593593
E0542, // missing 'since'
594594
E0543, // missing 'reason'
595595
E0544, // multiple stability levels

‎src/librustc_middle/middle/stability.rs

+41-30
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub use self::StabilityLevel::*;
55

66
use crate::ty::{self, TyCtxt};
77
use rustc_ast::ast::CRATE_NODE_ID;
8-
use rustc_attr::{self as attr, ConstStability, Deprecation, RustcDeprecation, Stability};
8+
use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
99
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1010
use rustc_errors::{Applicability, DiagnosticBuilder};
1111
use rustc_feature::GateIssue;
@@ -130,14 +130,26 @@ pub fn report_unstable(
130130

131131
/// Checks whether an item marked with `deprecated(since="X")` is currently
132132
/// deprecated (i.e., whether X is not greater than the current rustc version).
133-
pub fn deprecation_in_effect(since: &str) -> bool {
133+
pub fn deprecation_in_effect(is_since_rustc_version: bool, since: Option<&str>) -> bool {
134+
let since = if let Some(since) = since {
135+
if is_since_rustc_version {
136+
since
137+
} else {
138+
// We assume that the deprecation is in effect if it's not a
139+
// rustc version.
140+
return true;
141+
}
142+
} else {
143+
// If since attribute is not set, then we're definitely in effect.
144+
return true;
145+
};
134146
fn parse_version(ver: &str) -> Vec<u32> {
135147
// We ignore non-integer components of the version (e.g., "nightly").
136148
ver.split(|c| c == '.' || c == '-').flat_map(|s| s.parse()).collect()
137149
}
138150

139151
if let Some(rustc) = option_env!("CFG_RELEASE") {
140-
let since: Vec<u32> = parse_version(since);
152+
let since: Vec<u32> = parse_version(&since);
141153
let rustc: Vec<u32> = parse_version(rustc);
142154
// We simply treat invalid `since` attributes as relating to a previous
143155
// Rust version, thus always displaying the warning.
@@ -167,31 +179,27 @@ pub fn deprecation_suggestion(
167179
}
168180
}
169181

170-
fn deprecation_message_common(message: String, reason: Option<Symbol>) -> String {
171-
match reason {
172-
Some(reason) => format!("{}: {}", message, reason),
173-
None => message,
174-
}
175-
}
176-
177182
pub fn deprecation_message(depr: &Deprecation, path: &str) -> (String, &'static Lint) {
178-
let message = format!("use of deprecated item '{}'", path);
179-
(deprecation_message_common(message, depr.note), DEPRECATED)
180-
}
181-
182-
pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String, &'static Lint) {
183-
let (message, lint) = if deprecation_in_effect(&depr.since.as_str()) {
183+
let (message, lint) = if deprecation_in_effect(
184+
depr.is_since_rustc_version,
185+
depr.since.map(Symbol::as_str).as_deref(),
186+
) {
184187
(format!("use of deprecated item '{}'", path), DEPRECATED)
185188
} else {
186189
(
187190
format!(
188191
"use of item '{}' that will be deprecated in future version {}",
189-
path, depr.since
192+
path,
193+
depr.since.unwrap()
190194
),
191195
DEPRECATED_IN_FUTURE,
192196
)
193197
};
194-
(deprecation_message_common(message, Some(depr.reason)), lint)
198+
let message = match depr.note {
199+
Some(reason) => format!("{}: {}", message, reason),
200+
None => message,
201+
};
202+
(message, lint)
195203
}
196204

197205
pub fn early_report_deprecation(
@@ -289,10 +297,23 @@ impl<'tcx> TyCtxt<'tcx> {
289297
.lookup_deprecation_entry(parent_def_id.to_def_id())
290298
.map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
291299

292-
if !skip {
300+
// #[deprecated] doesn't emit a notice if we're not on the
301+
// topmost deprecation. For example, if a struct is deprecated,
302+
// the use of a field won't be linted.
303+
//
304+
// #[rustc_deprecated] however wants to emit down the whole
305+
// hierarchy.
306+
if !skip || depr_entry.attr.is_since_rustc_version {
293307
let (message, lint) =
294308
deprecation_message(&depr_entry.attr, &self.def_path_str(def_id));
295-
late_report_deprecation(self, &message, None, lint, span, id);
309+
late_report_deprecation(
310+
self,
311+
&message,
312+
depr_entry.attr.suggestion,
313+
lint,
314+
span,
315+
id,
316+
);
296317
}
297318
};
298319
}
@@ -310,16 +331,6 @@ impl<'tcx> TyCtxt<'tcx> {
310331
def_id, span, stability
311332
);
312333

313-
if let Some(id) = id {
314-
if let Some(stability) = stability {
315-
if let Some(depr) = &stability.rustc_depr {
316-
let (message, lint) =
317-
rustc_deprecation_message(depr, &self.def_path_str(def_id));
318-
late_report_deprecation(self, &message, depr.suggestion, lint, span, id);
319-
}
320-
}
321-
}
322-
323334
// Only the cross-crate scenario matters when checking unstable APIs
324335
let cross_crate = !def_id.is_local();
325336
if !cross_crate {

‎src/librustc_passes/stability.rs

+75-53
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,50 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
5959
) where
6060
F: FnOnce(&mut Self),
6161
{
62+
debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs);
63+
let mut did_error = false;
6264
if !self.tcx.features().staged_api {
63-
self.forbid_staged_api_attrs(hir_id, attrs, item_sp, kind, visit_children);
64-
return;
65+
did_error = self.forbid_staged_api_attrs(hir_id, attrs);
6566
}
6667

67-
// This crate explicitly wants staged API.
68+
let depr = if did_error {
69+
None
70+
} else {
71+
attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp)
72+
};
73+
let mut is_deprecated = false;
74+
if let Some(depr) = &depr {
75+
is_deprecated = true;
6876

69-
debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs);
70-
if let Some(..) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) {
71-
self.tcx.sess.span_err(
72-
item_sp,
73-
"`#[deprecated]` cannot be used in staged API; \
74-
use `#[rustc_deprecated]` instead",
77+
if kind == AnnotationKind::Prohibited {
78+
self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless");
79+
}
80+
81+
// `Deprecation` is just two pointers, no need to intern it
82+
let depr_entry = DeprecationEntry::local(depr.clone(), hir_id);
83+
self.index.depr_map.insert(hir_id, depr_entry);
84+
} else if let Some(parent_depr) = self.parent_depr.clone() {
85+
is_deprecated = true;
86+
info!("tagging child {:?} as deprecated from parent", hir_id);
87+
self.index.depr_map.insert(hir_id, parent_depr);
88+
}
89+
90+
if self.tcx.features().staged_api {
91+
if let Some(..) = attrs.iter().find(|a| a.check_name(sym::deprecated)) {
92+
self.tcx.sess.span_err(
93+
item_sp,
94+
"`#[deprecated]` cannot be used in staged API; \
95+
use `#[rustc_deprecated]` instead",
96+
);
97+
}
98+
} else {
99+
self.recurse_with_stability_attrs(
100+
depr.map(|d| DeprecationEntry::local(d, hir_id)),
101+
None,
102+
None,
103+
visit_children,
75104
);
105+
return;
76106
}
77107

78108
let (stab, const_stab) = attr::find_stability(&self.tcx.sess.parse_sess, attrs, item_sp);
@@ -92,33 +122,34 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
92122
}
93123
}
94124

95-
let stab = stab.map(|mut stab| {
125+
if depr.as_ref().map_or(false, |d| d.is_since_rustc_version) {
126+
if stab.is_none() {
127+
struct_span_err!(
128+
self.tcx.sess,
129+
item_sp,
130+
E0549,
131+
"rustc_deprecated attribute must be paired with \
132+
either stable or unstable attribute"
133+
)
134+
.emit();
135+
}
136+
}
137+
138+
let stab = stab.map(|stab| {
96139
// Error if prohibited, or can't inherit anything from a container.
97140
if kind == AnnotationKind::Prohibited
98-
|| (kind == AnnotationKind::Container
99-
&& stab.level.is_stable()
100-
&& stab.rustc_depr.is_none())
141+
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
101142
{
102143
self.tcx.sess.span_err(item_sp, "This stability annotation is useless");
103144
}
104145

105146
debug!("annotate: found {:?}", stab);
106-
// If parent is deprecated and we're not, inherit this by merging
107-
// deprecated_since and its reason.
108-
if let Some(parent_stab) = self.parent_stab {
109-
if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() {
110-
stab.rustc_depr = parent_stab.rustc_depr
111-
}
112-
}
113-
114147
let stab = self.tcx.intern_stability(stab);
115148

116149
// Check if deprecated_since < stable_since. If it is,
117150
// this is *almost surely* an accident.
118-
if let (
119-
&Some(attr::RustcDeprecation { since: dep_since, .. }),
120-
&attr::Stable { since: stab_since },
121-
) = (&stab.rustc_depr, &stab.level)
151+
if let (&Some(dep_since), &attr::Stable { since: stab_since }) =
152+
(&depr.as_ref().and_then(|d| d.since), &stab.level)
122153
{
123154
// Explicit version of iter::order::lt to handle parse errors properly
124155
for (dep_v, stab_v) in
@@ -163,19 +194,29 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
163194
}
164195
}
165196

166-
self.recurse_with_stability_attrs(stab, const_stab, visit_children);
197+
self.recurse_with_stability_attrs(
198+
depr.map(|d| DeprecationEntry::local(d, hir_id)),
199+
stab,
200+
const_stab,
201+
visit_children,
202+
);
167203
}
168204

169205
fn recurse_with_stability_attrs(
170206
&mut self,
207+
depr: Option<DeprecationEntry>,
171208
stab: Option<&'tcx Stability>,
172209
const_stab: Option<&'tcx ConstStability>,
173210
f: impl FnOnce(&mut Self),
174211
) {
175212
// These will be `Some` if this item changes the corresponding stability attribute.
213+
let mut replaced_parent_depr = None;
176214
let mut replaced_parent_stab = None;
177215
let mut replaced_parent_const_stab = None;
178216

217+
if let Some(depr) = depr {
218+
replaced_parent_depr = Some(replace(&mut self.parent_depr, Some(depr)));
219+
}
179220
if let Some(stab) = stab {
180221
replaced_parent_stab = Some(replace(&mut self.parent_stab, Some(stab)));
181222
}
@@ -186,6 +227,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
186227

187228
f(self);
188229

230+
if let Some(orig_parent_depr) = replaced_parent_depr {
231+
self.parent_depr = orig_parent_depr;
232+
}
189233
if let Some(orig_parent_stab) = replaced_parent_stab {
190234
self.parent_stab = orig_parent_stab;
191235
}
@@ -194,14 +238,8 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
194238
}
195239
}
196240

197-
fn forbid_staged_api_attrs(
198-
&mut self,
199-
hir_id: HirId,
200-
attrs: &[Attribute],
201-
item_sp: Span,
202-
kind: AnnotationKind,
203-
visit_children: impl FnOnce(&mut Self),
204-
) {
241+
// returns true if an error occurred, used to suppress some spurious errors
242+
fn forbid_staged_api_attrs(&mut self, hir_id: HirId, attrs: &[Attribute]) -> bool {
205243
// Emit errors for non-staged-api crates.
206244
let unstable_attrs = [
207245
sym::unstable,
@@ -210,6 +248,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
210248
sym::rustc_const_unstable,
211249
sym::rustc_const_stable,
212250
];
251+
let mut has_error = false;
213252
for attr in attrs {
214253
let name = attr.name_or_empty();
215254
if unstable_attrs.contains(&name) {
@@ -221,6 +260,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
221260
"stability attributes may not be used outside of the standard library",
222261
)
223262
.emit();
263+
has_error = true;
224264
}
225265
}
226266

@@ -232,24 +272,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
232272
}
233273
}
234274

235-
if let Some(depr) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) {
236-
if kind == AnnotationKind::Prohibited {
237-
self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless");
238-
}
239-
240-
// `Deprecation` is just two pointers, no need to intern it
241-
let depr_entry = DeprecationEntry::local(depr, hir_id);
242-
self.index.depr_map.insert(hir_id, depr_entry.clone());
243-
244-
let orig_parent_depr = replace(&mut self.parent_depr, Some(depr_entry));
245-
visit_children(self);
246-
self.parent_depr = orig_parent_depr;
247-
} else if let Some(parent_depr) = self.parent_depr.clone() {
248-
self.index.depr_map.insert(hir_id, parent_depr);
249-
visit_children(self);
250-
} else {
251-
visit_children(self);
252-
}
275+
has_error
253276
}
254277
}
255278

@@ -454,7 +477,6 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
454477
is_soft: false,
455478
},
456479
feature: sym::rustc_private,
457-
rustc_depr: None,
458480
});
459481
annotator.parent_stab = Some(stability);
460482
}

‎src/librustc_resolve/macros.rs

+7-12
Original file line numberDiff line numberDiff line change
@@ -1017,22 +1017,17 @@ impl<'a> Resolver<'a> {
10171017
);
10181018
}
10191019
}
1020-
if let Some(depr) = &stability.rustc_depr {
1021-
let path = pprust::path_to_string(path);
1022-
let (message, lint) = stability::rustc_deprecation_message(depr, &path);
1023-
stability::early_report_deprecation(
1024-
&mut self.lint_buffer,
1025-
&message,
1026-
depr.suggestion,
1027-
lint,
1028-
span,
1029-
);
1030-
}
10311020
}
10321021
if let Some(depr) = &ext.deprecation {
10331022
let path = pprust::path_to_string(&path);
10341023
let (message, lint) = stability::deprecation_message(depr, &path);
1035-
stability::early_report_deprecation(&mut self.lint_buffer, &message, None, lint, span);
1024+
stability::early_report_deprecation(
1025+
&mut self.lint_buffer,
1026+
&message,
1027+
depr.suggestion,
1028+
lint,
1029+
span,
1030+
);
10361031
}
10371032
}
10381033

‎src/librustdoc/clean/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -2353,10 +2353,6 @@ impl Clean<Stability> for attr::Stability {
23532353
attr::Stable { ref since } => since.to_string(),
23542354
_ => String::new(),
23552355
},
2356-
deprecation: self.rustc_depr.as_ref().map(|d| Deprecation {
2357-
note: Some(d.reason.to_string()).filter(|r| !r.is_empty()),
2358-
since: Some(d.since.to_string()).filter(|d| !d.is_empty()),
2359-
}),
23602356
unstable_reason: match self.level {
23612357
attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
23622358
_ => None,
@@ -2374,6 +2370,7 @@ impl Clean<Deprecation> for attr::Deprecation {
23742370
Deprecation {
23752371
since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()),
23762372
note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()),
2373+
is_since_rustc_version: self.is_since_rustc_version,
23772374
}
23782375
}
23792376
}

‎src/librustdoc/clean/types.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ impl Item {
195195
classes.push("unstable");
196196
}
197197

198-
if s.deprecation.is_some() {
198+
// FIXME: what about non-staged API items that are deprecated?
199+
if self.deprecation.is_some() {
199200
classes.push("deprecated");
200201
}
201202

@@ -216,14 +217,6 @@ impl Item {
216217
ItemType::from(self)
217218
}
218219

219-
/// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
220-
///
221-
/// If the item is not deprecated, returns `None`.
222-
pub fn deprecation(&self) -> Option<&Deprecation> {
223-
self.deprecation
224-
.as_ref()
225-
.or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref()))
226-
}
227220
pub fn is_default(&self) -> bool {
228221
match self.inner {
229222
ItemEnum::MethodItem(ref meth) => {
@@ -1528,7 +1521,6 @@ pub struct Stability {
15281521
pub level: stability::StabilityLevel,
15291522
pub feature: Option<String>,
15301523
pub since: String,
1531-
pub deprecation: Option<Deprecation>,
15321524
pub unstable_reason: Option<String>,
15331525
pub issue: Option<NonZeroU32>,
15341526
}
@@ -1537,6 +1529,7 @@ pub struct Stability {
15371529
pub struct Deprecation {
15381530
pub since: Option<String>,
15391531
pub note: Option<String>,
1532+
pub is_since_rustc_version: bool,
15401533
}
15411534

15421535
/// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or

‎src/librustdoc/html/render.rs

+9-20
Original file line numberDiff line numberDiff line change
@@ -2216,16 +2216,10 @@ fn stability_tags(item: &clean::Item) -> String {
22162216
}
22172217

22182218
// The trailing space after each tag is to space it properly against the rest of the docs.
2219-
if item.deprecation().is_some() {
2219+
if let Some(depr) = &item.deprecation {
22202220
let mut message = "Deprecated";
2221-
if let Some(ref stab) = item.stability {
2222-
if let Some(ref depr) = stab.deprecation {
2223-
if let Some(ref since) = depr.since {
2224-
if !stability::deprecation_in_effect(&since) {
2225-
message = "Deprecation planned";
2226-
}
2227-
}
2228-
}
2221+
if !stability::deprecation_in_effect(depr.is_since_rustc_version, depr.since.as_deref()) {
2222+
message = "Deprecation planned";
22292223
}
22302224
tags += &tag_html("deprecated", message);
22312225
}
@@ -2254,23 +2248,18 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
22542248
let mut stability = vec![];
22552249
let error_codes = cx.shared.codes;
22562250

2257-
if let Some(Deprecation { note, since }) = &item.deprecation() {
2251+
if let Some(Deprecation { ref note, ref since, is_since_rustc_version }) = item.deprecation {
22582252
// We display deprecation messages for #[deprecated] and #[rustc_deprecated]
22592253
// but only display the future-deprecation messages for #[rustc_deprecated].
22602254
let mut message = if let Some(since) = since {
2261-
format!("Deprecated since {}", Escape(since))
2255+
if !stability::deprecation_in_effect(is_since_rustc_version, Some(since)) {
2256+
format!("Deprecating in {}", Escape(&since))
2257+
} else {
2258+
format!("Deprecated since {}", Escape(&since))
2259+
}
22622260
} else {
22632261
String::from("Deprecated")
22642262
};
2265-
if let Some(ref stab) = item.stability {
2266-
if let Some(ref depr) = stab.deprecation {
2267-
if let Some(ref since) = depr.since {
2268-
if !stability::deprecation_in_effect(&since) {
2269-
message = format!("Deprecating in {}", Escape(&since));
2270-
}
2271-
}
2272-
}
2273-
}
22742263

22752264
if let Some(note) = note {
22762265
let mut ids = cx.id_map.borrow_mut();

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fn multiple3() { }
6262
#[rustc_deprecated(since = "b", reason = "text")]
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 rustc_deprecated attributes [E0540]
65+
pub const fn multiple4() { } //~ ERROR multiple deprecated attributes
6666
//~^ ERROR Invalid stability or deprecation version found
6767

6868
#[rustc_deprecated(since = "a", reason = "text")]

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ error[E0544]: multiple stability levels
8282
LL | #[stable(feature = "a", since = "b")]
8383
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8484

85-
error[E0540]: multiple rustc_deprecated attributes
85+
error[E0550]: multiple deprecated attributes
8686
--> $DIR/stability-attribute-sanity.rs:65:1
8787
|
8888
LL | pub const fn multiple4() { }
@@ -108,5 +108,5 @@ LL | fn deprecated_without_unstable_or_stable() { }
108108

109109
error: aborting due to 18 previous errors
110110

111-
Some errors have detailed explanations: E0539, E0541.
111+
Some errors have detailed explanations: E0539, E0541, E0550.
112112
For more information about an error, try `rustc --explain E0539`.

0 commit comments

Comments
 (0)
Please sign in to comment.