Skip to content

Commit 4d4e02c

Browse files
authored
Rollup merge of rust-lang#71481 - estebank:inherit-stability, r=nikomatsakis
Inherit `#[stable(..)]` annotations in enum variants and fields from its item Lint changes for rust-lang#65515. The stdlib will have to be updated once this lands in beta and that version is promoted in master.
2 parents 45b3c28 + 49310ce commit 4d4e02c

17 files changed

+290
-188
lines changed

compiler/rustc_attr/src/builtin.rs

+16-11
Original file line numberDiff line numberDiff line change
@@ -176,23 +176,24 @@ pub fn find_stability(
176176
sess: &Session,
177177
attrs: &[Attribute],
178178
item_sp: Span,
179-
) -> (Option<Stability>, Option<ConstStability>) {
179+
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>) {
180180
find_stability_generic(sess, attrs.iter(), item_sp)
181181
}
182182

183183
fn find_stability_generic<'a, I>(
184184
sess: &Session,
185185
attrs_iter: I,
186186
item_sp: Span,
187-
) -> (Option<Stability>, Option<ConstStability>)
187+
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>)
188188
where
189189
I: Iterator<Item = &'a Attribute>,
190190
{
191191
use StabilityLevel::*;
192192

193-
let mut stab: Option<Stability> = None;
194-
let mut const_stab: Option<ConstStability> = None;
193+
let mut stab: Option<(Stability, Span)> = None;
194+
let mut const_stab: Option<(ConstStability, Span)> = None;
195195
let mut promotable = false;
196+
196197
let diagnostic = &sess.parse_sess.span_diagnostic;
197198

198199
'outer: for attr in attrs_iter {
@@ -356,10 +357,12 @@ where
356357
}
357358
let level = Unstable { reason, issue: issue_num, is_soft };
358359
if sym::unstable == meta_name {
359-
stab = Some(Stability { level, feature });
360+
stab = Some((Stability { level, feature }, attr.span));
360361
} else {
361-
const_stab =
362-
Some(ConstStability { level, feature, promotable: false });
362+
const_stab = Some((
363+
ConstStability { level, feature, promotable: false },
364+
attr.span,
365+
));
363366
}
364367
}
365368
(None, _, _) => {
@@ -432,10 +435,12 @@ where
432435
(Some(feature), Some(since)) => {
433436
let level = Stable { since };
434437
if sym::stable == meta_name {
435-
stab = Some(Stability { level, feature });
438+
stab = Some((Stability { level, feature }, attr.span));
436439
} else {
437-
const_stab =
438-
Some(ConstStability { level, feature, promotable: false });
440+
const_stab = Some((
441+
ConstStability { level, feature, promotable: false },
442+
attr.span,
443+
));
439444
}
440445
}
441446
(None, _) => {
@@ -455,7 +460,7 @@ where
455460

456461
// Merge the const-unstable info into the stability info
457462
if promotable {
458-
if let Some(ref mut stab) = const_stab {
463+
if let Some((ref mut stab, _)) = const_stab {
459464
stab.promotable = promotable;
460465
} else {
461466
struct_span_err!(

compiler/rustc_expand/src/base.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -774,10 +774,16 @@ impl SyntaxExtension {
774774
.find_by_name(attrs, sym::rustc_builtin_macro)
775775
.map(|a| a.value_str().unwrap_or(name));
776776
let (stability, const_stability) = attr::find_stability(&sess, attrs, span);
777-
if const_stability.is_some() {
777+
if let Some((_, sp)) = const_stability {
778778
sess.parse_sess
779779
.span_diagnostic
780-
.span_err(span, "macros cannot have const stability attributes");
780+
.struct_span_err(sp, "macros cannot have const stability attributes")
781+
.span_label(sp, "invalid const stability attribute")
782+
.span_label(
783+
sess.source_map().guess_head_span(span),
784+
"const stability attribute affects this macro",
785+
)
786+
.emit();
781787
}
782788

783789
SyntaxExtension {
@@ -786,7 +792,7 @@ impl SyntaxExtension {
786792
allow_internal_unstable,
787793
allow_internal_unsafe: sess.contains_name(attrs, sym::allow_internal_unsafe),
788794
local_inner_macros,
789-
stability,
795+
stability: stability.map(|(s, _)| s),
790796
deprecation: attr::find_deprecation(&sess, attrs).map(|(d, _)| d),
791797
helper_attrs,
792798
edition,

compiler/rustc_passes/src/lib_features.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl LibFeatureCollector<'tcx> {
109109
}
110110

111111
fn span_feature_error(&self, span: Span, msg: &str) {
112-
struct_span_err!(self.tcx.sess, span, E0711, "{}", &msg,).emit();
112+
struct_span_err!(self.tcx.sess, span, E0711, "{}", &msg).emit();
113113
}
114114
}
115115

compiler/rustc_passes/src/stability.rs

+52-24
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ impl InheritConstStability {
7070
}
7171
}
7272

73+
enum InheritStability {
74+
Yes,
75+
No,
76+
}
77+
78+
impl InheritStability {
79+
fn yes(&self) -> bool {
80+
matches!(self, InheritStability::Yes)
81+
}
82+
}
83+
7384
// A private tree-walker for producing an Index.
7485
struct Annotator<'a, 'tcx> {
7586
tcx: TyCtxt<'tcx>,
@@ -91,6 +102,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
91102
kind: AnnotationKind,
92103
inherit_deprecation: InheritDeprecation,
93104
inherit_const_stability: InheritConstStability,
105+
inherit_from_parent: InheritStability,
94106
visit_children: F,
95107
) where
96108
F: FnOnce(&mut Self),
@@ -131,12 +143,13 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
131143
}
132144

133145
if self.tcx.features().staged_api {
134-
if let Some(..) = attrs.iter().find(|a| self.tcx.sess.check_name(a, sym::deprecated)) {
135-
self.tcx.sess.span_err(
136-
item_sp,
137-
"`#[deprecated]` cannot be used in staged API; \
138-
use `#[rustc_deprecated]` instead",
139-
);
146+
if let Some(a) = attrs.iter().find(|a| self.tcx.sess.check_name(a, sym::deprecated)) {
147+
self.tcx
148+
.sess
149+
.struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API")
150+
.span_label(a.span, "use `#[rustc_deprecated]` instead")
151+
.span_label(item_sp, "")
152+
.emit();
140153
}
141154
} else {
142155
self.recurse_with_stability_attrs(
@@ -150,7 +163,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
150163

151164
let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
152165

153-
let const_stab = const_stab.map(|const_stab| {
166+
let const_stab = const_stab.map(|(const_stab, _)| {
154167
let const_stab = self.tcx.intern_const_stability(const_stab);
155168
self.index.const_stab_map.insert(hir_id, const_stab);
156169
const_stab
@@ -180,12 +193,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
180193
}
181194
}
182195

183-
let stab = stab.map(|stab| {
196+
let stab = stab.map(|(stab, span)| {
184197
// Error if prohibited, or can't inherit anything from a container.
185198
if kind == AnnotationKind::Prohibited
186199
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
187200
{
188-
self.tcx.sess.span_err(item_sp, "This stability annotation is useless");
201+
self.tcx.sess.struct_span_err(span,"this stability annotation is useless")
202+
.span_label(span, "useless stability annotation")
203+
.span_label(item_sp, "the stability attribute annotates this item")
204+
.emit();
189205
}
190206

191207
debug!("annotate: found {:?}", stab);
@@ -202,26 +218,30 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
202218
{
203219
match stab_v.parse::<u64>() {
204220
Err(_) => {
205-
self.tcx.sess.span_err(item_sp, "Invalid stability version found");
221+
self.tcx.sess.struct_span_err(span, "invalid stability version found")
222+
.span_label(span, "invalid stability version")
223+
.span_label(item_sp, "the stability attribute annotates this item")
224+
.emit();
206225
break;
207226
}
208227
Ok(stab_vp) => match dep_v.parse::<u64>() {
209228
Ok(dep_vp) => match dep_vp.cmp(&stab_vp) {
210229
Ordering::Less => {
211-
self.tcx.sess.span_err(
212-
item_sp,
213-
"An API can't be stabilized after it is deprecated",
214-
);
230+
self.tcx.sess.struct_span_err(span, "an API can't be stabilized after it is deprecated")
231+
.span_label(span, "invalid version")
232+
.span_label(item_sp, "the stability attribute annotates this item")
233+
.emit();
215234
break;
216235
}
217236
Ordering::Equal => continue,
218237
Ordering::Greater => break,
219238
},
220239
Err(_) => {
221240
if dep_v != "TBD" {
222-
self.tcx
223-
.sess
224-
.span_err(item_sp, "Invalid deprecation version found");
241+
self.tcx.sess.struct_span_err(span, "invalid deprecation version found")
242+
.span_label(span, "invalid deprecation version")
243+
.span_label(item_sp, "the stability attribute annotates this item")
244+
.emit();
225245
}
226246
break;
227247
}
@@ -237,7 +257,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
237257
if stab.is_none() {
238258
debug!("annotate: stab not found, parent = {:?}", self.parent_stab);
239259
if let Some(stab) = self.parent_stab {
240-
if inherit_deprecation.yes() && stab.level.is_unstable() {
260+
if inherit_deprecation.yes() && stab.level.is_unstable()
261+
|| inherit_from_parent.yes()
262+
{
241263
self.index.stab_map.insert(hir_id, stab);
242264
}
243265
}
@@ -368,6 +390,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
368390
AnnotationKind::Required,
369391
InheritDeprecation::Yes,
370392
InheritConstStability::No,
393+
InheritStability::Yes,
371394
|_| {},
372395
)
373396
}
@@ -382,6 +405,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
382405
kind,
383406
InheritDeprecation::Yes,
384407
const_stab_inherit,
408+
InheritStability::No,
385409
|v| intravisit::walk_item(v, i),
386410
);
387411
self.in_trait_impl = orig_in_trait_impl;
@@ -395,6 +419,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
395419
AnnotationKind::Required,
396420
InheritDeprecation::Yes,
397421
InheritConstStability::No,
422+
InheritStability::No,
398423
|v| {
399424
intravisit::walk_trait_item(v, ti);
400425
},
@@ -411,6 +436,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
411436
kind,
412437
InheritDeprecation::Yes,
413438
InheritConstStability::No,
439+
InheritStability::No,
414440
|v| {
415441
intravisit::walk_impl_item(v, ii);
416442
},
@@ -425,6 +451,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
425451
AnnotationKind::Required,
426452
InheritDeprecation::Yes,
427453
InheritConstStability::No,
454+
InheritStability::Yes,
428455
|v| {
429456
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
430457
v.annotate(
@@ -434,6 +461,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
434461
AnnotationKind::Required,
435462
InheritDeprecation::Yes,
436463
InheritConstStability::No,
464+
InheritStability::No,
437465
|_| {},
438466
);
439467
}
@@ -451,6 +479,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
451479
AnnotationKind::Required,
452480
InheritDeprecation::Yes,
453481
InheritConstStability::No,
482+
InheritStability::Yes,
454483
|v| {
455484
intravisit::walk_struct_field(v, s);
456485
},
@@ -465,6 +494,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
465494
AnnotationKind::Required,
466495
InheritDeprecation::Yes,
467496
InheritConstStability::No,
497+
InheritStability::No,
468498
|v| {
469499
intravisit::walk_foreign_item(v, i);
470500
},
@@ -479,6 +509,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
479509
AnnotationKind::Required,
480510
InheritDeprecation::Yes,
481511
InheritConstStability::No,
512+
InheritStability::No,
482513
|_| {},
483514
);
484515
}
@@ -499,6 +530,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
499530
kind,
500531
InheritDeprecation::No,
501532
InheritConstStability::No,
533+
InheritStability::No,
502534
|v| {
503535
intravisit::walk_generic_param(v, p);
504536
},
@@ -669,6 +701,7 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
669701
AnnotationKind::Required,
670702
InheritDeprecation::Yes,
671703
InheritConstStability::No,
704+
InheritStability::No,
672705
|v| intravisit::walk_crate(v, krate),
673706
);
674707
}
@@ -729,18 +762,13 @@ impl Visitor<'tcx> for Checker<'tcx> {
729762
// error if all involved types and traits are stable, because
730763
// it will have no effect.
731764
// See: https://github.com/rust-lang/rust/issues/55436
732-
if let (Some(Stability { level: attr::Unstable { .. }, .. }), _) =
765+
if let (Some((Stability { level: attr::Unstable { .. }, .. }, span)), _) =
733766
attr::find_stability(&self.tcx.sess, &item.attrs, item.span)
734767
{
735768
let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
736769
c.visit_ty(self_ty);
737770
c.visit_trait_ref(t);
738771
if c.fully_stable {
739-
let span = item
740-
.attrs
741-
.iter()
742-
.find(|a| a.has_name(sym::unstable))
743-
.map_or(item.span, |a| a.span);
744772
self.tcx.struct_span_lint_hir(
745773
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
746774
item.hir_id(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#[rustc_const_stable(feature = "foo", since = "0")]
2+
//~^ ERROR macros cannot have const stability attributes
3+
macro_rules! foo {
4+
() => {};
5+
}
6+
7+
#[rustc_const_unstable(feature = "bar", issue="none")]
8+
//~^ ERROR macros cannot have const stability attributes
9+
macro_rules! bar {
10+
() => {};
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: macros cannot have const stability attributes
2+
--> $DIR/const-stability-on-macro.rs:1:1
3+
|
4+
LL | #[rustc_const_stable(feature = "foo", since = "0")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute
6+
LL |
7+
LL | macro_rules! foo {
8+
| ---------------- const stability attribute affects this macro
9+
10+
error: macros cannot have const stability attributes
11+
--> $DIR/const-stability-on-macro.rs:7:1
12+
|
13+
LL | #[rustc_const_unstable(feature = "bar", issue="none")]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute
15+
LL |
16+
LL | macro_rules! bar {
17+
| ---------------- const stability attribute affects this macro
18+
19+
error: aborting due to 2 previous errors
20+
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
// #[deprecated] cannot be used in staged API
2-
31
#![feature(staged_api)]
4-
52
#![stable(feature = "stable_test_feature", since = "1.0.0")]
6-
7-
#[deprecated]
8-
fn main() { } //~ ERROR `#[deprecated]` cannot be used in staged API
3+
#[deprecated] //~ ERROR `#[deprecated]` cannot be used in staged API
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
error: `#[deprecated]` cannot be used in staged API; use `#[rustc_deprecated]` instead
2-
--> $DIR/deprecation-in-staged-api.rs:8:1
1+
error: `#[deprecated]` cannot be used in staged API
2+
--> $DIR/deprecation-in-staged-api.rs:3:1
33
|
4-
LL | fn main() { }
5-
| ^^^^^^^^^^^^^
4+
LL | #[deprecated]
5+
| ^^^^^^^^^^^^^ use `#[rustc_deprecated]` instead
6+
LL | fn main() {}
7+
| ------------
68

79
error: aborting due to previous error
810

0 commit comments

Comments
 (0)