about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-09-01 14:54:57 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-09-07 21:37:51 +0300
commitf7434aef26bc413469fc0dfeadecabf75e18bd38 (patch)
tree3cac9e58eec901a58254d7b842e811d2fa06edac /src
parentef54f57c5b9d894a38179d09b00610c1b337b086 (diff)
downloadrust-f7434aef26bc413469fc0dfeadecabf75e18bd38.tar.gz
rust-f7434aef26bc413469fc0dfeadecabf75e18bd38.zip
Support "soft" feature-gating using a lint
Use it for feature-gating `#[bench]`
Diffstat (limited to 'src')
-rw-r--r--src/libcore/macros.rs6
-rw-r--r--src/librustc/ich/impls_syntax.rs3
-rw-r--r--src/librustc/lint/builtin.rs7
-rw-r--r--src/librustc/middle/stability.rs22
-rw-r--r--src/librustc_resolve/macros.rs4
-rw-r--r--src/libsyntax/attr/builtin.rs28
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/test/ui/feature-gates/bench.rs4
-rw-r--r--src/test/ui/feature-gates/bench.stderr10
9 files changed, 58 insertions, 27 deletions
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index ffaca029a8a..384bc874998 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -1236,8 +1236,10 @@ pub(crate) mod builtin {
     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 */ }
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 646060bc8be..a33181e5925 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -115,9 +115,10 @@ for ::syntax::attr::StabilityLevel {
                                           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);
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 6d9a6bb77dd..dd290572d7b 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -395,6 +395,12 @@ declare_lint! {
     "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 @@ declare_lint_pass! {
         NESTED_IMPL_TRAIT,
         MUTABLE_BORROW_RESERVATION_CONFLICT,
         INDIRECT_STRUCTURAL_MATCH,
+        SOFT_UNSTABLE,
     ]
 }
 
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index d02259bf301..c06a0feb6a9 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -438,6 +438,7 @@ impl<'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 @@ impl<'tcx> TyCtxt<'tcx> {
         }
 
         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 @@ impl<'tcx> TyCtxt<'tcx> {
                     }
                 }
 
-                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 @@ impl<'tcx> TyCtxt<'tcx> {
     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.
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 054b17fec78..87439440463 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -774,10 +774,10 @@ impl<'a> Resolver<'a> {
     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 {
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index 5fb513783fb..b5037b75f79 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -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 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
                     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 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
                                                       "incorrect 'issue'");
                                             continue
                                         }
-                                    }
+                                    },
+                                    is_soft,
                                 },
                                 feature,
                                 rustc_depr: None,
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index ecc31cfeb3d..ab32d4461ef 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -626,6 +626,7 @@ symbols! {
         size,
         slice_patterns,
         slicing_syntax,
+        soft,
         Some,
         specialization,
         speed,
diff --git a/src/test/ui/feature-gates/bench.rs b/src/test/ui/feature-gates/bench.rs
new file mode 100644
index 00000000000..d8a09625e96
--- /dev/null
+++ b/src/test/ui/feature-gates/bench.rs
@@ -0,0 +1,4 @@
+#[bench] //~ ERROR use of unstable library feature 'test'
+fn bench() {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/bench.stderr b/src/test/ui/feature-gates/bench.stderr
new file mode 100644
index 00000000000..25ddcc5e361
--- /dev/null
+++ b/src/test/ui/feature-gates/bench.stderr
@@ -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
+