Support "soft" feature-gating using a lint
Use it for feature-gating `#[bench]`
This commit is contained in:
parent
ef54f57c5b
commit
f7434aef26
@ -1236,8 +1236,10 @@ macro_rules! trace_macros {
|
||||
pub macro test($item:item) { /* compiler built-in */ }
|
||||
|
||||
/// Attribute macro applied to a function to turn it into a benchmark test.
|
||||
#[unstable(feature = "test", issue = "50297",
|
||||
reason = "`bench` is a part of custom test frameworks which are unstable")]
|
||||
#[cfg_attr(not(boostrap_stdarch_ignore_this), unstable(soft, feature = "test", issue = "50297",
|
||||
reason = "`bench` is a part of custom test frameworks which are unstable"))]
|
||||
#[cfg_attr(boostrap_stdarch_ignore_this, unstable(feature = "test", issue = "50297",
|
||||
reason = "`bench` is a part of custom test frameworks which are unstable"))]
|
||||
#[allow_internal_unstable(test, rustc_attrs)]
|
||||
#[rustc_builtin_macro]
|
||||
pub macro bench($item:item) { /* compiler built-in */ }
|
||||
|
@ -115,9 +115,10 @@ fn hash_stable<W: StableHasherResult>(&self,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||
match *self {
|
||||
::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
|
||||
::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => {
|
||||
reason.hash_stable(hcx, hasher);
|
||||
issue.hash_stable(hcx, hasher);
|
||||
is_soft.hash_stable(hcx, hasher);
|
||||
}
|
||||
::syntax::attr::StabilityLevel::Stable { ref since } => {
|
||||
since.hash_stable(hcx, hasher);
|
||||
|
@ -395,6 +395,12 @@ pub mod parser {
|
||||
"reservation of a two-phased borrow conflicts with other shared borrows"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub SOFT_UNSTABLE,
|
||||
Deny,
|
||||
"a feature gate that doesn't break dependent crates"
|
||||
}
|
||||
|
||||
declare_lint_pass! {
|
||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||
/// that are used by other parts of the compiler.
|
||||
@ -460,6 +466,7 @@ pub mod parser {
|
||||
NESTED_IMPL_TRAIT,
|
||||
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
||||
INDIRECT_STRUCTURAL_MATCH,
|
||||
SOFT_UNSTABLE,
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -438,6 +438,7 @@ pub fn new(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
|
||||
level: attr::StabilityLevel::Unstable {
|
||||
reason: Some(Symbol::intern(reason)),
|
||||
issue: 27812,
|
||||
is_soft: false,
|
||||
},
|
||||
feature: sym::rustc_private,
|
||||
rustc_depr: None,
|
||||
@ -480,7 +481,7 @@ pub fn provide(providers: &mut Providers<'_>) {
|
||||
}
|
||||
|
||||
pub fn report_unstable(
|
||||
sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, span: Span
|
||||
sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, is_soft: bool, span: Span
|
||||
) {
|
||||
let msg = match reason {
|
||||
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
|
||||
@ -505,7 +506,13 @@ pub fn report_unstable(
|
||||
let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone());
|
||||
let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
|
||||
if fresh {
|
||||
emit_feature_err(&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg);
|
||||
if is_soft {
|
||||
sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg);
|
||||
} else {
|
||||
emit_feature_err(
|
||||
&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -621,6 +628,7 @@ pub enum EvalResult {
|
||||
feature: Symbol,
|
||||
reason: Option<Symbol>,
|
||||
issue: u32,
|
||||
is_soft: bool,
|
||||
},
|
||||
/// The item does not have the `#[stable]` or `#[unstable]` marker assigned.
|
||||
Unmarked,
|
||||
@ -720,7 +728,9 @@ pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> Eva
|
||||
}
|
||||
|
||||
match stability {
|
||||
Some(&Stability { level: attr::Unstable { reason, issue }, feature, .. }) => {
|
||||
Some(&Stability {
|
||||
level: attr::Unstable { reason, issue, is_soft }, feature, ..
|
||||
}) => {
|
||||
if span.allows_unstable(feature) {
|
||||
debug!("stability: skipping span={:?} since it is internal", span);
|
||||
return EvalResult::Allow;
|
||||
@ -744,7 +754,7 @@ pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> Eva
|
||||
}
|
||||
}
|
||||
|
||||
EvalResult::Deny { feature, reason, issue }
|
||||
EvalResult::Deny { feature, reason, issue, is_soft }
|
||||
}
|
||||
Some(_) => {
|
||||
// Stable APIs are always ok to call and deprecated APIs are
|
||||
@ -767,8 +777,8 @@ pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> Eva
|
||||
pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
|
||||
match self.eval_stability(def_id, id, span) {
|
||||
EvalResult::Allow => {}
|
||||
EvalResult::Deny { feature, reason, issue } =>
|
||||
report_unstable(self.sess, feature, reason, issue, span),
|
||||
EvalResult::Deny { feature, reason, issue, is_soft } =>
|
||||
report_unstable(self.sess, feature, reason, issue, is_soft, span),
|
||||
EvalResult::Unmarked => {
|
||||
// The API could be uncallable for other reasons, for example when a private module
|
||||
// was referenced.
|
||||
|
@ -774,10 +774,10 @@ struct Flags: u8 {
|
||||
fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) {
|
||||
let span = path.span;
|
||||
if let Some(stability) = &ext.stability {
|
||||
if let StabilityLevel::Unstable { reason, issue } = stability.level {
|
||||
if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
|
||||
let feature = stability.feature;
|
||||
if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
|
||||
stability::report_unstable(self.session, feature, reason, issue, span);
|
||||
stability::report_unstable(self.session, feature, reason, issue, is_soft, span);
|
||||
}
|
||||
}
|
||||
if let Some(depr) = &stability.rustc_depr {
|
||||
|
@ -154,23 +154,10 @@ pub struct Stability {
|
||||
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
|
||||
pub enum StabilityLevel {
|
||||
// Reason for the current stability level and the relevant rust-lang issue
|
||||
Unstable { reason: Option<Symbol>, issue: u32 },
|
||||
Unstable { reason: Option<Symbol>, issue: u32, is_soft: bool },
|
||||
Stable { since: Symbol },
|
||||
}
|
||||
|
||||
impl Stability {
|
||||
pub fn unstable(feature: Symbol, reason: Option<Symbol>, issue: u32) -> Stability {
|
||||
Stability {
|
||||
level: StabilityLevel::Unstable { reason, issue },
|
||||
feature,
|
||||
rustc_depr: None,
|
||||
const_stability: None,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StabilityLevel {
|
||||
pub fn is_unstable(&self) -> bool {
|
||||
if let StabilityLevel::Unstable {..} = *self {
|
||||
@ -356,19 +343,27 @@ macro_rules! get_meta {
|
||||
let mut feature = None;
|
||||
let mut reason = None;
|
||||
let mut issue = None;
|
||||
let mut is_soft = false;
|
||||
for meta in metas {
|
||||
if let Some(mi) = meta.meta_item() {
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => if !get(mi, &mut feature) { continue 'outer },
|
||||
sym::reason => if !get(mi, &mut reason) { continue 'outer },
|
||||
sym::issue => if !get(mi, &mut issue) { continue 'outer },
|
||||
sym::soft => {
|
||||
if !mi.is_word() {
|
||||
let msg = "`soft` should not have any arguments";
|
||||
sess.span_diagnostic.span_err(mi.span, msg);
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
mi.path.to_string(),
|
||||
&["feature", "reason", "issue"]
|
||||
&["feature", "reason", "issue", "soft"]
|
||||
),
|
||||
);
|
||||
continue 'outer
|
||||
@ -400,7 +395,8 @@ macro_rules! get_meta {
|
||||
"incorrect 'issue'");
|
||||
continue
|
||||
}
|
||||
}
|
||||
},
|
||||
is_soft,
|
||||
},
|
||||
feature,
|
||||
rustc_depr: None,
|
||||
|
@ -626,6 +626,7 @@
|
||||
size,
|
||||
slice_patterns,
|
||||
slicing_syntax,
|
||||
soft,
|
||||
Some,
|
||||
specialization,
|
||||
speed,
|
||||
|
4
src/test/ui/feature-gates/bench.rs
Normal file
4
src/test/ui/feature-gates/bench.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#[bench] //~ ERROR use of unstable library feature 'test'
|
||||
fn bench() {}
|
||||
|
||||
fn main() {}
|
10
src/test/ui/feature-gates/bench.stderr
Normal file
10
src/test/ui/feature-gates/bench.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
|
||||
--> $DIR/bench.rs:1:3
|
||||
|
|
||||
LL | #[bench]
|
||||
| ^^^^^
|
||||
|
|
||||
= note: `#[deny(soft_unstable)]` on by default
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user