about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorJoshua Nelson <jyn514@gmail.com>2021-03-31 16:28:32 -0400
committerJoshua Nelson <jyn514@gmail.com>2021-04-02 19:36:44 -0400
commit53a11050742ae1c59ccb33302a2d998cd35aed03 (patch)
tree9ae8afe31ab7a159e03930865d5388be94ac6ea7 /compiler
parentbba40880c0750f880119b4517821ffe0a96f74d1 (diff)
downloadrust-53a11050742ae1c59ccb33302a2d998cd35aed03.tar.gz
rust-53a11050742ae1c59ccb33302a2d998cd35aed03.zip
On stable, suggest removing `#![feature]` for features that have been stabilized
I don't know how to test this. I confirmed locally that this gives the
appropriate help with `channel = "beta"`:

```
error[E0554]: `#![feature]` may not be used on the beta release channel
 --> src/lib.rs:2:1
  |
2 | #![feature(min_const_generics)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the attribute
  |
  = help: the feature `min_const_generics` has been stable since 1.51.0 and no longer requires an attribute to enable

error[E0554]: `#![feature]` may not be used on the beta release channel
 --> src/lib.rs:3:1
  |
3 | #![feature(min_const_generics, min_specialization)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: the feature `min_const_generics` has been stable since 1.51.0 and no longer requires an attribute to enable

error[E0554]: `#![feature]` may not be used on the beta release channel
 --> src/lib.rs:4:1
  |
4 | #![feature(box_patterns)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^
```
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs36
1 files changed, 33 insertions, 3 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 2f73e44faf6..3385b159b5c 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -740,16 +740,46 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
 }
 
 fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
+    use rustc_errors::Applicability;
+
     if !sess.opts.unstable_features.is_nightly_build() {
+        let lang_features = &sess.features_untracked().declared_lang_features;
         for attr in krate.attrs.iter().filter(|attr| sess.check_name(attr, sym::feature)) {
-            struct_span_err!(
+            let mut err = struct_span_err!(
                 sess.parse_sess.span_diagnostic,
                 attr.span,
                 E0554,
                 "`#![feature]` may not be used on the {} release channel",
                 option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)")
-            )
-            .emit();
+            );
+            let mut all_stable = true;
+            for ident in
+                attr.meta_item_list().into_iter().flatten().map(|nested| nested.ident()).flatten()
+            {
+                let name = ident.name;
+                let stable_since = lang_features
+                    .iter()
+                    .flat_map(|&(feature, _, since)| if feature == name { since } else { None })
+                    .next();
+                if let Some(since) = stable_since {
+                    err.help(&format!(
+                        "the feature `{}` has been stable since {} and no longer requires \
+                                  an attribute to enable",
+                        name, since
+                    ));
+                } else {
+                    all_stable = false;
+                }
+            }
+            if all_stable {
+                err.span_suggestion(
+                    attr.span,
+                    "remove the attribute",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
+            }
+            err.emit();
         }
     }
 }