Skip to content

Commit

Permalink
Rollup merge of rust-lang#71481 - estebank:inherit-stability, r=nikom…
Browse files Browse the repository at this point in the history
…atsakis

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.
  • Loading branch information
Dylan-DPC authored Mar 4, 2021
2 parents 1c77a1f + 49310ce commit 229ffc3
Show file tree
Hide file tree
Showing 17 changed files with 290 additions and 188 deletions.
27 changes: 16 additions & 11 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,23 +176,24 @@ pub fn find_stability(
sess: &Session,
attrs: &[Attribute],
item_sp: Span,
) -> (Option<Stability>, Option<ConstStability>) {
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>) {
find_stability_generic(sess, attrs.iter(), item_sp)
}

fn find_stability_generic<'a, I>(
sess: &Session,
attrs_iter: I,
item_sp: Span,
) -> (Option<Stability>, Option<ConstStability>)
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>)
where
I: Iterator<Item = &'a Attribute>,
{
use StabilityLevel::*;

let mut stab: Option<Stability> = None;
let mut const_stab: Option<ConstStability> = None;
let mut stab: Option<(Stability, Span)> = None;
let mut const_stab: Option<(ConstStability, Span)> = None;
let mut promotable = false;

let diagnostic = &sess.parse_sess.span_diagnostic;

'outer: for attr in attrs_iter {
Expand Down Expand Up @@ -356,10 +357,12 @@ where
}
let level = Unstable { reason, issue: issue_num, is_soft };
if sym::unstable == meta_name {
stab = Some(Stability { level, feature });
stab = Some((Stability { level, feature }, attr.span));
} else {
const_stab =
Some(ConstStability { level, feature, promotable: false });
const_stab = Some((
ConstStability { level, feature, promotable: false },
attr.span,
));
}
}
(None, _, _) => {
Expand Down Expand Up @@ -432,10 +435,12 @@ where
(Some(feature), Some(since)) => {
let level = Stable { since };
if sym::stable == meta_name {
stab = Some(Stability { level, feature });
stab = Some((Stability { level, feature }, attr.span));
} else {
const_stab =
Some(ConstStability { level, feature, promotable: false });
const_stab = Some((
ConstStability { level, feature, promotable: false },
attr.span,
));
}
}
(None, _) => {
Expand All @@ -455,7 +460,7 @@ where

// Merge the const-unstable info into the stability info
if promotable {
if let Some(ref mut stab) = const_stab {
if let Some((ref mut stab, _)) = const_stab {
stab.promotable = promotable;
} else {
struct_span_err!(
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -774,10 +774,16 @@ impl SyntaxExtension {
.find_by_name(attrs, sym::rustc_builtin_macro)
.map(|a| a.value_str().unwrap_or(name));
let (stability, const_stability) = attr::find_stability(&sess, attrs, span);
if const_stability.is_some() {
if let Some((_, sp)) = const_stability {
sess.parse_sess
.span_diagnostic
.span_err(span, "macros cannot have const stability attributes");
.struct_span_err(sp, "macros cannot have const stability attributes")
.span_label(sp, "invalid const stability attribute")
.span_label(
sess.source_map().guess_head_span(span),
"const stability attribute affects this macro",
)
.emit();
}

SyntaxExtension {
Expand All @@ -786,7 +792,7 @@ impl SyntaxExtension {
allow_internal_unstable,
allow_internal_unsafe: sess.contains_name(attrs, sym::allow_internal_unsafe),
local_inner_macros,
stability,
stability: stability.map(|(s, _)| s),
deprecation: attr::find_deprecation(&sess, attrs).map(|(d, _)| d),
helper_attrs,
edition,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/lib_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl LibFeatureCollector<'tcx> {
}

fn span_feature_error(&self, span: Span, msg: &str) {
struct_span_err!(self.tcx.sess, span, E0711, "{}", &msg,).emit();
struct_span_err!(self.tcx.sess, span, E0711, "{}", &msg).emit();
}
}

Expand Down
76 changes: 52 additions & 24 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ impl InheritConstStability {
}
}

enum InheritStability {
Yes,
No,
}

impl InheritStability {
fn yes(&self) -> bool {
matches!(self, InheritStability::Yes)
}
}

// A private tree-walker for producing an Index.
struct Annotator<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
Expand All @@ -91,6 +102,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
kind: AnnotationKind,
inherit_deprecation: InheritDeprecation,
inherit_const_stability: InheritConstStability,
inherit_from_parent: InheritStability,
visit_children: F,
) where
F: FnOnce(&mut Self),
Expand Down Expand Up @@ -131,12 +143,13 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}

if self.tcx.features().staged_api {
if let Some(..) = attrs.iter().find(|a| self.tcx.sess.check_name(a, sym::deprecated)) {
self.tcx.sess.span_err(
item_sp,
"`#[deprecated]` cannot be used in staged API; \
use `#[rustc_deprecated]` instead",
);
if let Some(a) = attrs.iter().find(|a| self.tcx.sess.check_name(a, sym::deprecated)) {
self.tcx
.sess
.struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API")
.span_label(a.span, "use `#[rustc_deprecated]` instead")
.span_label(item_sp, "")
.emit();
}
} else {
self.recurse_with_stability_attrs(
Expand All @@ -150,7 +163,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {

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

let const_stab = const_stab.map(|const_stab| {
let const_stab = const_stab.map(|(const_stab, _)| {
let const_stab = self.tcx.intern_const_stability(const_stab);
self.index.const_stab_map.insert(hir_id, const_stab);
const_stab
Expand Down Expand Up @@ -180,12 +193,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}
}

let stab = stab.map(|stab| {
let stab = stab.map(|(stab, span)| {
// Error if prohibited, or can't inherit anything from a container.
if kind == AnnotationKind::Prohibited
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
{
self.tcx.sess.span_err(item_sp, "This stability annotation is useless");
self.tcx.sess.struct_span_err(span,"this stability annotation is useless")
.span_label(span, "useless stability annotation")
.span_label(item_sp, "the stability attribute annotates this item")
.emit();
}

debug!("annotate: found {:?}", stab);
Expand All @@ -202,26 +218,30 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
{
match stab_v.parse::<u64>() {
Err(_) => {
self.tcx.sess.span_err(item_sp, "Invalid stability version found");
self.tcx.sess.struct_span_err(span, "invalid stability version found")
.span_label(span, "invalid stability version")
.span_label(item_sp, "the stability attribute annotates this item")
.emit();
break;
}
Ok(stab_vp) => match dep_v.parse::<u64>() {
Ok(dep_vp) => match dep_vp.cmp(&stab_vp) {
Ordering::Less => {
self.tcx.sess.span_err(
item_sp,
"An API can't be stabilized after it is deprecated",
);
self.tcx.sess.struct_span_err(span, "an API can't be stabilized after it is deprecated")
.span_label(span, "invalid version")
.span_label(item_sp, "the stability attribute annotates this item")
.emit();
break;
}
Ordering::Equal => continue,
Ordering::Greater => break,
},
Err(_) => {
if dep_v != "TBD" {
self.tcx
.sess
.span_err(item_sp, "Invalid deprecation version found");
self.tcx.sess.struct_span_err(span, "invalid deprecation version found")
.span_label(span, "invalid deprecation version")
.span_label(item_sp, "the stability attribute annotates this item")
.emit();
}
break;
}
Expand All @@ -237,7 +257,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if stab.is_none() {
debug!("annotate: stab not found, parent = {:?}", self.parent_stab);
if let Some(stab) = self.parent_stab {
if inherit_deprecation.yes() && stab.level.is_unstable() {
if inherit_deprecation.yes() && stab.level.is_unstable()
|| inherit_from_parent.yes()
{
self.index.stab_map.insert(hir_id, stab);
}
}
Expand Down Expand Up @@ -368,6 +390,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::Yes,
|_| {},
)
}
Expand All @@ -382,6 +405,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
kind,
InheritDeprecation::Yes,
const_stab_inherit,
InheritStability::No,
|v| intravisit::walk_item(v, i),
);
self.in_trait_impl = orig_in_trait_impl;
Expand All @@ -395,6 +419,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::No,
|v| {
intravisit::walk_trait_item(v, ti);
},
Expand All @@ -411,6 +436,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
kind,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::No,
|v| {
intravisit::walk_impl_item(v, ii);
},
Expand All @@ -425,6 +451,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::Yes,
|v| {
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
v.annotate(
Expand All @@ -434,6 +461,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::No,
|_| {},
);
}
Expand All @@ -451,6 +479,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::Yes,
|v| {
intravisit::walk_struct_field(v, s);
},
Expand All @@ -465,6 +494,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::No,
|v| {
intravisit::walk_foreign_item(v, i);
},
Expand All @@ -479,6 +509,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::No,
|_| {},
);
}
Expand All @@ -499,6 +530,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
kind,
InheritDeprecation::No,
InheritConstStability::No,
InheritStability::No,
|v| {
intravisit::walk_generic_param(v, p);
},
Expand Down Expand Up @@ -669,6 +701,7 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::No,
|v| intravisit::walk_crate(v, krate),
);
}
Expand Down Expand Up @@ -729,18 +762,13 @@ impl Visitor<'tcx> for Checker<'tcx> {
// error if all involved types and traits are stable, because
// it will have no effect.
// See: https://github.com/rust-lang/rust/issues/55436
if let (Some(Stability { level: attr::Unstable { .. }, .. }), _) =
if let (Some((Stability { level: attr::Unstable { .. }, .. }, span)), _) =
attr::find_stability(&self.tcx.sess, &item.attrs, item.span)
{
let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
c.visit_ty(self_ty);
c.visit_trait_ref(t);
if c.fully_stable {
let span = item
.attrs
.iter()
.find(|a| a.has_name(sym::unstable))
.map_or(item.span, |a| a.span);
self.tcx.struct_span_lint_hir(
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
item.hir_id(),
Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/attributes/const-stability-on-macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[rustc_const_stable(feature = "foo", since = "0")]
//~^ ERROR macros cannot have const stability attributes
macro_rules! foo {
() => {};
}

#[rustc_const_unstable(feature = "bar", issue="none")]
//~^ ERROR macros cannot have const stability attributes
macro_rules! bar {
() => {};
}

fn main() {}
20 changes: 20 additions & 0 deletions src/test/ui/attributes/const-stability-on-macro.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: macros cannot have const stability attributes
--> $DIR/const-stability-on-macro.rs:1:1
|
LL | #[rustc_const_stable(feature = "foo", since = "0")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute
LL |
LL | macro_rules! foo {
| ---------------- const stability attribute affects this macro

error: macros cannot have const stability attributes
--> $DIR/const-stability-on-macro.rs:7:1
|
LL | #[rustc_const_unstable(feature = "bar", issue="none")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute
LL |
LL | macro_rules! bar {
| ---------------- const stability attribute affects this macro

error: aborting due to 2 previous errors

8 changes: 2 additions & 6 deletions src/test/ui/deprecation/deprecation-in-staged-api.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
// #[deprecated] cannot be used in staged API

#![feature(staged_api)]

#![stable(feature = "stable_test_feature", since = "1.0.0")]

#[deprecated]
fn main() { } //~ ERROR `#[deprecated]` cannot be used in staged API
#[deprecated] //~ ERROR `#[deprecated]` cannot be used in staged API
fn main() {}
10 changes: 6 additions & 4 deletions src/test/ui/deprecation/deprecation-in-staged-api.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error: `#[deprecated]` cannot be used in staged API; use `#[rustc_deprecated]` instead
--> $DIR/deprecation-in-staged-api.rs:8:1
error: `#[deprecated]` cannot be used in staged API
--> $DIR/deprecation-in-staged-api.rs:3:1
|
LL | fn main() { }
| ^^^^^^^^^^^^^
LL | #[deprecated]
| ^^^^^^^^^^^^^ use `#[rustc_deprecated]` instead
LL | fn main() {}
| ------------

error: aborting due to previous error

Loading

0 comments on commit 229ffc3

Please sign in to comment.