Store version of deprecated
attribute in structured form
This commit is contained in:
parent
5c7cf83739
commit
2fe7d17bd9
7 changed files with 85 additions and 105 deletions
|
@ -13,6 +13,7 @@ use rustc_session::parse::{feature_err, ParseSess};
|
||||||
use rustc_session::{RustcVersion, Session};
|
use rustc_session::{RustcVersion, Session};
|
||||||
use rustc_span::hygiene::Transparency;
|
use rustc_span::hygiene::Transparency;
|
||||||
use rustc_span::{symbol::sym, symbol::Symbol, Span};
|
use rustc_span::{symbol::sym, symbol::Symbol, Span};
|
||||||
|
use std::fmt::{self, Display};
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||||
|
@ -720,17 +721,37 @@ pub fn eval_condition(
|
||||||
|
|
||||||
#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
|
#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
|
||||||
pub struct Deprecation {
|
pub struct Deprecation {
|
||||||
pub since: Option<Symbol>,
|
pub since: Option<DeprecatedSince>,
|
||||||
/// The note to issue a reason.
|
/// The note to issue a reason.
|
||||||
pub note: Option<Symbol>,
|
pub note: Option<Symbol>,
|
||||||
/// A text snippet used to completely replace any use of the deprecated item in an expression.
|
/// A text snippet used to completely replace any use of the deprecated item in an expression.
|
||||||
///
|
///
|
||||||
/// This is currently unstable.
|
/// This is currently unstable.
|
||||||
pub suggestion: Option<Symbol>,
|
pub suggestion: Option<Symbol>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether to treat the since attribute as being a Rust version identifier
|
/// Release in which an API is deprecated.
|
||||||
/// (rather than an opaque string).
|
#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
|
||||||
pub is_since_rustc_version: bool,
|
pub enum DeprecatedSince {
|
||||||
|
RustcVersion(RustcVersion),
|
||||||
|
/// Deprecated in the future ("to be determined").
|
||||||
|
Future,
|
||||||
|
/// `feature(staged_api)` is off, or it's on but the deprecation version
|
||||||
|
/// cannot be parsed as a RustcVersion. In the latter case, an error has
|
||||||
|
/// already been emitted. In the former case, deprecation versions outside
|
||||||
|
/// the standard library are allowed to be arbitrary strings, for better or
|
||||||
|
/// worse.
|
||||||
|
Symbol(Symbol),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for DeprecatedSince {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
DeprecatedSince::RustcVersion(since) => Display::fmt(since, formatter),
|
||||||
|
DeprecatedSince::Future => formatter.write_str("TBD"),
|
||||||
|
DeprecatedSince::Symbol(since) => Display::fmt(since, formatter),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the deprecation attribute. `None` if none exists.
|
/// Finds the deprecation attribute. `None` if none exists.
|
||||||
|
@ -839,22 +860,30 @@ pub fn find_deprecation(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_rustc {
|
let since = if let Some(since) = since {
|
||||||
if since.is_none() {
|
if since.as_str() == "TBD" {
|
||||||
sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
|
Some(DeprecatedSince::Future)
|
||||||
continue;
|
} else if !is_rustc {
|
||||||
|
Some(DeprecatedSince::Symbol(since))
|
||||||
|
} else if let Some(version) = parse_version(since) {
|
||||||
|
Some(DeprecatedSince::RustcVersion(version))
|
||||||
|
} else {
|
||||||
|
sess.emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
||||||
|
Some(DeprecatedSince::Symbol(since))
|
||||||
}
|
}
|
||||||
|
} else if is_rustc {
|
||||||
|
sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if note.is_none() {
|
if is_rustc && note.is_none() {
|
||||||
sess.emit_err(session_diagnostics::MissingNote { span: attr.span });
|
sess.emit_err(session_diagnostics::MissingNote { span: attr.span });
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
depr = Some((
|
depr = Some((Deprecation { since, note, suggestion }, attr.span));
|
||||||
Deprecation { since, note, suggestion, is_since_rustc_version: is_rustc },
|
|
||||||
attr.span,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
depr
|
depr
|
||||||
|
|
|
@ -5,7 +5,9 @@ pub use self::StabilityLevel::*;
|
||||||
|
|
||||||
use crate::ty::{self, TyCtxt};
|
use crate::ty::{self, TyCtxt};
|
||||||
use rustc_ast::NodeId;
|
use rustc_ast::NodeId;
|
||||||
use rustc_attr::{self as attr, ConstStability, DefaultBodyStability, Deprecation, Stability};
|
use rustc_attr::{
|
||||||
|
self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
|
||||||
|
};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{Applicability, Diagnostic};
|
use rustc_errors::{Applicability, Diagnostic};
|
||||||
use rustc_feature::GateIssue;
|
use rustc_feature::GateIssue;
|
||||||
|
@ -126,36 +128,14 @@ pub fn report_unstable(
|
||||||
/// Checks whether an item marked with `deprecated(since="X")` is currently
|
/// Checks whether an item marked with `deprecated(since="X")` is currently
|
||||||
/// deprecated (i.e., whether X is not greater than the current rustc version).
|
/// deprecated (i.e., whether X is not greater than the current rustc version).
|
||||||
pub fn deprecation_in_effect(depr: &Deprecation) -> bool {
|
pub fn deprecation_in_effect(depr: &Deprecation) -> bool {
|
||||||
let is_since_rustc_version = depr.is_since_rustc_version;
|
match depr.since {
|
||||||
let since = depr.since.as_ref().map(Symbol::as_str);
|
Some(DeprecatedSince::RustcVersion(since)) => since <= RustcVersion::CURRENT,
|
||||||
|
Some(DeprecatedSince::Future) => false,
|
||||||
if !is_since_rustc_version {
|
|
||||||
// The `since` field doesn't have semantic purpose without `#![staged_api]`.
|
// The `since` field doesn't have semantic purpose without `#![staged_api]`.
|
||||||
return true;
|
Some(DeprecatedSince::Symbol(_)) => true,
|
||||||
|
// Assume deprecation is in effect if "since" field is missing.
|
||||||
|
None => true,
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(since) = since {
|
|
||||||
if since == "TBD" {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We ignore non-integer components of the version (e.g., "nightly").
|
|
||||||
let since: Vec<u16> =
|
|
||||||
since.split(|c| c == '.' || c == '-').flat_map(|s| s.parse()).collect();
|
|
||||||
|
|
||||||
// We simply treat invalid `since` attributes as relating to a previous
|
|
||||||
// Rust version, thus always displaying the warning.
|
|
||||||
if since.len() != 3 {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let rustc = RustcVersion::CURRENT;
|
|
||||||
return since.as_slice() <= &[rustc.major, rustc.minor, rustc.patch];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Assume deprecation is in effect if "since" field is missing
|
|
||||||
// or if we can't determine the current Rust version.
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deprecation_suggestion(
|
pub fn deprecation_suggestion(
|
||||||
|
@ -180,7 +160,7 @@ fn deprecation_lint(is_in_effect: bool) -> &'static Lint {
|
||||||
|
|
||||||
fn deprecation_message(
|
fn deprecation_message(
|
||||||
is_in_effect: bool,
|
is_in_effect: bool,
|
||||||
since: Option<Symbol>,
|
since: Option<DeprecatedSince>,
|
||||||
note: Option<Symbol>,
|
note: Option<Symbol>,
|
||||||
kind: &str,
|
kind: &str,
|
||||||
path: &str,
|
path: &str,
|
||||||
|
@ -188,9 +168,7 @@ fn deprecation_message(
|
||||||
let message = if is_in_effect {
|
let message = if is_in_effect {
|
||||||
format!("use of deprecated {kind} `{path}`")
|
format!("use of deprecated {kind} `{path}`")
|
||||||
} else {
|
} else {
|
||||||
let since = since.as_ref().map(Symbol::as_str);
|
if let Some(DeprecatedSince::Future) = since {
|
||||||
|
|
||||||
if since == Some("TBD") {
|
|
||||||
format!("use of {kind} `{path}` that will be deprecated in a future Rust version")
|
format!("use of {kind} `{path}` that will be deprecated in a future Rust version")
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
|
@ -381,7 +359,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
// With #![staged_api], we want to emit down the whole
|
// With #![staged_api], we want to emit down the whole
|
||||||
// hierarchy.
|
// hierarchy.
|
||||||
let depr_attr = &depr_entry.attr;
|
let depr_attr = &depr_entry.attr;
|
||||||
if !skip || depr_attr.is_since_rustc_version {
|
if !skip || matches!(depr_attr.since, Some(DeprecatedSince::RustcVersion(_))) {
|
||||||
// Calculating message for lint involves calling `self.def_path_str`.
|
// Calculating message for lint involves calling `self.def_path_str`.
|
||||||
// Which by default to calculate visible path will invoke expensive `visible_parent_map` query.
|
// Which by default to calculate visible path will invoke expensive `visible_parent_map` query.
|
||||||
// So we skip message calculation altogether, if lint is allowed.
|
// So we skip message calculation altogether, if lint is allowed.
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use rustc_attr::{
|
use rustc_attr::{
|
||||||
self as attr, ConstStability, Stability, StabilityLevel, StableSince, Unstable, UnstableReason,
|
self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince,
|
||||||
VERSION_PLACEHOLDER,
|
Unstable, UnstableReason, VERSION_PLACEHOLDER,
|
||||||
};
|
};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -24,8 +24,6 @@ use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::iter;
|
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
|
@ -198,7 +196,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr {
|
if let Some((
|
||||||
|
rustc_attr::Deprecation { since: Some(DeprecatedSince::RustcVersion(_)), .. },
|
||||||
|
span,
|
||||||
|
)) = &depr
|
||||||
|
{
|
||||||
if stab.is_none() {
|
if stab.is_none() {
|
||||||
self.tcx.sess.emit_err(errors::DeprecatedAttribute { span: *span });
|
self.tcx.sess.emit_err(errors::DeprecatedAttribute { span: *span });
|
||||||
}
|
}
|
||||||
|
@ -223,41 +225,20 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
|
|
||||||
// Check if deprecated_since < stable_since. If it is,
|
// Check if deprecated_since < stable_since. If it is,
|
||||||
// this is *almost surely* an accident.
|
// this is *almost surely* an accident.
|
||||||
if let (&Some(dep_since), &attr::Stable { since: stab_since, .. }) =
|
if let (
|
||||||
(&depr.as_ref().and_then(|(d, _)| d.since), &stab.level)
|
&Some(DeprecatedSince::RustcVersion(dep_since)),
|
||||||
|
&attr::Stable { since: stab_since, .. },
|
||||||
|
) = (&depr.as_ref().and_then(|(d, _)| d.since), &stab.level)
|
||||||
{
|
{
|
||||||
match stab_since {
|
match stab_since {
|
||||||
StableSince::Current => {
|
StableSince::Current => {
|
||||||
self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated { span, item_sp });
|
self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated { span, item_sp });
|
||||||
}
|
}
|
||||||
StableSince::Version(stab_since) => {
|
StableSince::Version(stab_since) => {
|
||||||
// Explicit version of iter::order::lt to handle parse errors properly
|
if dep_since < stab_since {
|
||||||
for (dep_v, stab_v) in iter::zip(
|
self.tcx
|
||||||
dep_since.as_str().split('.'),
|
.sess
|
||||||
[stab_since.major, stab_since.minor, stab_since.patch],
|
.emit_err(errors::CannotStabilizeDeprecated { span, item_sp });
|
||||||
) {
|
|
||||||
match dep_v.parse::<u64>() {
|
|
||||||
Ok(dep_vp) => match dep_vp.cmp(&u64::from(stab_v)) {
|
|
||||||
Ordering::Less => {
|
|
||||||
self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated {
|
|
||||||
span,
|
|
||||||
item_sp,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Ordering::Equal => continue,
|
|
||||||
Ordering::Greater => break,
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
if dep_v != "TBD" {
|
|
||||||
self.tcx.sess.emit_err(errors::InvalidDeprecationVersion {
|
|
||||||
span,
|
|
||||||
item_sp,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StableSince::Err => {
|
StableSince::Err => {
|
||||||
|
|
|
@ -48,7 +48,7 @@ use std::str;
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use rustc_attr::{ConstStability, Deprecation, StabilityLevel, StableSince};
|
use rustc_attr::{ConstStability, DeprecatedSince, Deprecation, StabilityLevel, StableSince};
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_hir::def_id::{DefId, DefIdSet};
|
use rustc_hir::def_id::{DefId, DefIdSet};
|
||||||
|
@ -617,21 +617,18 @@ fn short_item_info(
|
||||||
) -> Vec<ShortItemInfo> {
|
) -> Vec<ShortItemInfo> {
|
||||||
let mut extra_info = vec![];
|
let mut extra_info = vec![];
|
||||||
|
|
||||||
if let Some(depr @ Deprecation { note, since, is_since_rustc_version: _, suggestion: _ }) =
|
if let Some(depr @ Deprecation { note, since, suggestion: _ }) = item.deprecation(cx.tcx()) {
|
||||||
item.deprecation(cx.tcx())
|
|
||||||
{
|
|
||||||
// We display deprecation messages for #[deprecated], but only display
|
// We display deprecation messages for #[deprecated], but only display
|
||||||
// the future-deprecation messages for rustc versions.
|
// the future-deprecation messages for rustc versions.
|
||||||
let mut message = if let Some(since) = since {
|
let mut message = if let Some(since) = since {
|
||||||
let since = since.as_str();
|
|
||||||
if !stability::deprecation_in_effect(&depr) {
|
if !stability::deprecation_in_effect(&depr) {
|
||||||
if since == "TBD" {
|
if let DeprecatedSince::Future = since {
|
||||||
String::from("Deprecating in a future Rust version")
|
String::from("Deprecating in a future Rust version")
|
||||||
} else {
|
} else {
|
||||||
format!("Deprecating in {}", Escape(since))
|
format!("Deprecating in {}", Escape(&since.to_string()))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
format!("Deprecated since {}", Escape(since))
|
format!("Deprecated since {}", Escape(&since.to_string()))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String::from("Deprecated")
|
String::from("Deprecated")
|
||||||
|
|
|
@ -138,8 +138,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
|
pub(crate) fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
|
||||||
#[rustfmt::skip]
|
let rustc_attr::Deprecation { since, note, suggestion: _ } = deprecation;
|
||||||
let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
|
|
||||||
Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
|
Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,9 +64,8 @@ fn multiple3() { }
|
||||||
#[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels
|
#[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels
|
||||||
pub const fn multiple4() { }
|
pub const fn multiple4() { }
|
||||||
|
|
||||||
#[stable(feature = "a", since = "1.0.0")] //~ ERROR invalid deprecation version found
|
#[stable(feature = "a", since = "1.0.0")] //~ ERROR feature `a` is declared stable since 1.0.0
|
||||||
//~^ ERROR feature `a` is declared stable since 1.0.0
|
#[deprecated(since = "invalid", note = "text")] //~ ERROR 'since' must be a Rust version number, such as "1.31.0"
|
||||||
#[deprecated(since = "invalid", note = "text")]
|
|
||||||
fn invalid_deprecation_version() {}
|
fn invalid_deprecation_version() {}
|
||||||
|
|
||||||
#[deprecated(since = "5.5.5", note = "text")]
|
#[deprecated(since = "5.5.5", note = "text")]
|
||||||
|
|
|
@ -106,17 +106,14 @@ error[E0544]: multiple stability levels
|
||||||
LL | #[rustc_const_unstable(feature = "d", issue = "none")]
|
LL | #[rustc_const_unstable(feature = "d", issue = "none")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: invalid deprecation version found
|
error: 'since' must be a Rust version number, such as "1.31.0"
|
||||||
--> $DIR/stability-attribute-sanity.rs:67:1
|
--> $DIR/stability-attribute-sanity.rs:68:1
|
||||||
|
|
|
|
||||||
LL | #[stable(feature = "a", since = "1.0.0")]
|
LL | #[deprecated(since = "invalid", note = "text")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid deprecation version
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
...
|
|
||||||
LL | fn invalid_deprecation_version() {}
|
|
||||||
| ----------------------------------- the stability attribute annotates this item
|
|
||||||
|
|
||||||
error[E0549]: deprecated attribute must be paired with either stable or unstable attribute
|
error[E0549]: deprecated attribute must be paired with either stable or unstable attribute
|
||||||
--> $DIR/stability-attribute-sanity.rs:72:1
|
--> $DIR/stability-attribute-sanity.rs:71:1
|
||||||
|
|
|
|
||||||
LL | #[deprecated(since = "5.5.5", note = "text")]
|
LL | #[deprecated(since = "5.5.5", note = "text")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue