From 53a11050742ae1c59ccb33302a2d998cd35aed03 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 31 Mar 2021 16:28:32 -0400 Subject: [PATCH] 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)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ ``` --- compiler/rustc_ast_passes/src/feature_gate.rs | 36 +++++++++++++++++-- 1 file 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 @@ macro_rules! gate_all { } 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(); } } }