diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index aca3fbbca13..c701441e9e5 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -176,7 +176,7 @@ pub fn find_stability( sess: &Session, attrs: &[Attribute], item_sp: Span, -) -> (Option, Option) { +) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>) { find_stability_generic(sess, attrs.iter(), item_sp) } @@ -184,15 +184,16 @@ fn find_stability_generic<'a, I>( sess: &Session, attrs_iter: I, item_sp: Span, -) -> (Option, Option) +) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>) where I: Iterator, { use StabilityLevel::*; - let mut stab: Option = None; - let mut const_stab: Option = 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 { @@ -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, _, _) => { @@ -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, _) => { @@ -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!( diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e3dc793a7fa..bd93e34af68 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -770,10 +770,13 @@ 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 stability attribute") + .span_label(span, "in this macro") + .emit(); } SyntaxExtension { @@ -782,7 +785,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, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 0e142665911..d698512a648 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -163,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 @@ -193,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); @@ -215,16 +218,19 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { { match stab_v.parse::() { 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::() { 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, @@ -232,9 +238,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { }, 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; } @@ -756,18 +763,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, diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.rs b/src/test/ui/stability-attribute/stability-attribute-sanity.rs index 1cc31d8ec18..9f8ecc26281 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity.rs +++ b/src/test/ui/stability-attribute/stability-attribute-sanity.rs @@ -57,16 +57,16 @@ fn multiple2() { } #[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544] fn multiple3() { } -#[stable(feature = "a", since = "b")] +#[stable(feature = "a", since = "b")] //~ ERROR invalid stability version found #[rustc_deprecated(since = "b", reason = "text")] #[rustc_deprecated(since = "b", reason = "text")] //~ ERROR multiple deprecated attributes #[rustc_const_unstable(feature = "c", issue = "none")] #[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels -pub const fn multiple4() { } //~ ERROR invalid stability version found +pub const fn multiple4() { } -#[stable(feature = "a", since = "1.0.0")] +#[stable(feature = "a", since = "1.0.0")] //~ ERROR invalid deprecation version found #[rustc_deprecated(since = "invalid", reason = "text")] -fn invalid_deprecation_version() {} //~ ERROR invalid deprecation version found +fn invalid_deprecation_version() {} #[rustc_deprecated(since = "a", reason = "text")] fn deprecated_without_unstable_or_stable() { } diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr index 07e3da73c60..bde35cca4a2 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr +++ b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr @@ -97,16 +97,22 @@ LL | #[rustc_const_unstable(feature = "d", issue = "none")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid stability version found - --> $DIR/stability-attribute-sanity.rs:65:1 + --> $DIR/stability-attribute-sanity.rs:60:1 | +LL | #[stable(feature = "a", since = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid stability version +... LL | pub const fn multiple4() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- the stability attribute annotates this item error: invalid deprecation version found - --> $DIR/stability-attribute-sanity.rs:69:1 + --> $DIR/stability-attribute-sanity.rs:67:1 | +LL | #[stable(feature = "a", since = "1.0.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid deprecation version +LL | #[rustc_deprecated(since = "invalid", reason = "text")] LL | fn invalid_deprecation_version() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------------------- the stability attribute annotates this item error[E0549]: rustc_deprecated attribute must be paired with either stable or unstable attribute --> $DIR/stability-attribute-sanity.rs:71:1