]> git.lizzy.rs Git - rust.git/commitdiff
move GateIssue to rustc_feature & simplify emit_feature_err
authorMazdak Farrokhzad <twingoow@gmail.com>
Sat, 30 Nov 2019 06:40:28 +0000 (07:40 +0100)
committerMazdak Farrokhzad <twingoow@gmail.com>
Sat, 30 Nov 2019 06:40:28 +0000 (07:40 +0100)
17 files changed:
src/librustc/lint/levels.rs
src/librustc/middle/stability.rs
src/librustc_feature/lib.rs
src/librustc_metadata/native_libs.rs
src/librustc_mir/transform/check_consts/ops.rs
src/librustc_parse/config.rs
src/librustc_passes/check_const.rs
src/librustc_resolve/macros.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/feature_gate/check.rs
src/libsyntax/lib.rs
src/libsyntax_expand/expand.rs

index 27bf9649324b4730f560049bd814ca2b43bd40b6..619ca724214c87b5d1464d563568e910bcebd60b 100644 (file)
@@ -232,13 +232,13 @@ pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPu
                             // don't have any lint names (`#[level(reason = "foo")]`)
                             if let ast::LitKind::Str(rationale, _) = name_value.kind {
                                 if !self.sess.features_untracked().lint_reasons {
-                                    feature_gate::emit_feature_err(
+                                    feature_gate::feature_err(
                                         &self.sess.parse_sess,
                                         sym::lint_reasons,
                                         item.span,
-                                        feature_gate::GateIssue::Language,
                                         "lint reasons are experimental"
-                                    );
+                                    )
+                                    .emit();
                                 }
                                 reason = Some(rationale);
                             } else {
index 411a47423c5aa7c93f0917e49e0790756f83c63f..54aafe2114dac04cef756414a9a55658d33cb608 100644 (file)
 use crate::middle::privacy::AccessLevels;
 use crate::session::{DiagnosticMessageId, Session};
 use errors::DiagnosticBuilder;
+use rustc_feature::GateIssue;
 use syntax::symbol::{Symbol, sym};
 use syntax_pos::{Span, MultiSpan};
 use syntax::ast::{Attribute, CRATE_NODE_ID};
 use syntax::errors::Applicability;
-use syntax::feature_gate::{GateIssue, emit_feature_err};
+use syntax::feature_gate::{feature_err, feature_err_issue};
 use syntax::attr::{self, Stability, Deprecation, RustcDeprecation};
 use crate::ty::{self, TyCtxt};
 use crate::util::nodemap::{FxHashSet, FxHashMap};
@@ -512,9 +513,8 @@ pub fn report_unstable(
         if is_soft {
             soft_handler(lint::builtin::SOFT_UNSTABLE, span, &msg)
         } else {
-            emit_feature_err(
-                &sess.parse_sess, feature, span, GateIssue::Library(issue), &msg
-            );
+            feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg)
+                .emit();
         }
     }
 }
@@ -842,15 +842,19 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 let ty = self.tcx.type_of(def_id);
 
                 if adt_def.has_dtor(self.tcx) {
-                    emit_feature_err(&self.tcx.sess.parse_sess,
-                                     sym::untagged_unions, item.span, GateIssue::Language,
-                                     "unions with `Drop` implementations are unstable");
+                    feature_err(
+                        &self.tcx.sess.parse_sess, sym::untagged_unions, item.span,
+                        "unions with `Drop` implementations are unstable"
+                    )
+                    .emit();
                 } else {
                     let param_env = self.tcx.param_env(def_id);
                     if !param_env.can_type_implement_copy(self.tcx, ty).is_ok() {
-                        emit_feature_err(&self.tcx.sess.parse_sess,
-                                         sym::untagged_unions, item.span, GateIssue::Language,
-                                         "unions with non-`Copy` fields are unstable");
+                        feature_err(
+                            &self.tcx.sess.parse_sess, sym::untagged_unions, item.span,
+                            "unions with non-`Copy` fields are unstable"
+                        )
+                        .emit();
                     }
                 }
             }
index 82e60889316d93be8701895a6b6f1fe016f39711..c38bb3740af3a6e664dc686243b4e745c469d945 100644 (file)
@@ -49,8 +49,7 @@ pub struct Feature {
 }
 
 impl Feature {
-    // FIXME(Centril): privatize again.
-    pub fn issue(&self) -> Option<NonZeroU32> {
+    fn issue(&self) -> Option<NonZeroU32> {
         self.issue.and_then(|i| NonZeroU32::new(i))
     }
 }
@@ -97,6 +96,37 @@ pub fn is_nightly_build(&self) -> bool {
     }
 }
 
+fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
+    if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) {
+        // FIXME (#28244): enforce that active features have issue numbers
+        // assert!(info.issue().is_some())
+        info.issue()
+    } else {
+        // search in Accepted, Removed, or Stable Removed features
+        let found = ACCEPTED_FEATURES
+            .iter()
+            .chain(REMOVED_FEATURES)
+            .chain(STABLE_REMOVED_FEATURES)
+            .find(|t| t.name == feature);
+        match found {
+            Some(found) => found.issue(),
+            None => panic!("feature `{}` is not declared anywhere", feature),
+        }
+    }
+}
+
+pub enum GateIssue {
+    Language,
+    Library(Option<NonZeroU32>)
+}
+
+pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZeroU32> {
+    match issue {
+        GateIssue::Language => find_lang_feature_issue(feature),
+        GateIssue::Library(lib) => lib,
+    }
+}
+
 pub use accepted::ACCEPTED_FEATURES;
 pub use active::{ACTIVE_FEATURES, Features, INCOMPLETE_FEATURES};
 pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
index e577b238c86847e991a9f0a21f35807790f28f4b..425e5d1d821bf971b72de83bb6eff492d943bbba 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_target::spec::abi::Abi;
 use syntax::attr;
 use syntax::source_map::Span;
-use syntax::feature_gate::{self, GateIssue};
+use syntax::feature_gate::feature_err;
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::{span_err, struct_span_err};
 
@@ -158,27 +158,29 @@ fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLibrary) {
             }
         }
         if lib.cfg.is_some() && !self.tcx.features().link_cfg {
-            feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
-                                           sym::link_cfg,
-                                           span.unwrap(),
-                                           GateIssue::Language,
-                                           "is unstable");
+            feature_err(&self.tcx.sess.parse_sess, sym::link_cfg, span.unwrap(), "is unstable")
+                .emit();
         }
         if lib.kind == cstore::NativeStaticNobundle &&
-           !self.tcx.features().static_nobundle {
-            feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
-                                           sym::static_nobundle,
-                                           span.unwrap_or_else(|| syntax_pos::DUMMY_SP),
-                                           GateIssue::Language,
-                                           "kind=\"static-nobundle\" is unstable");
+           !self.tcx.features().static_nobundle
+        {
+            feature_err(
+                &self.tcx.sess.parse_sess,
+                sym::static_nobundle,
+                span.unwrap_or_else(|| syntax_pos::DUMMY_SP),
+                "kind=\"static-nobundle\" is unstable"
+            )
+            .emit();
         }
         if lib.kind == cstore::NativeRawDylib &&
            !self.tcx.features().raw_dylib {
-            feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
-                                           sym::raw_dylib,
-                                           span.unwrap_or_else(|| syntax_pos::DUMMY_SP),
-                                           GateIssue::Language,
-                                           "kind=\"raw-dylib\" is unstable");
+            feature_err(
+                &self.tcx.sess.parse_sess,
+                sym::raw_dylib,
+                span.unwrap_or_else(|| syntax_pos::DUMMY_SP),
+                "kind=\"raw-dylib\" is unstable"
+            )
+            .emit();
         }
         self.libs.push(lib);
     }
index acad56be60403434c35f8ea88228c5fd1be479c8..a4f12a4e54fa73cbdb78736bc3f6f7de817dba49 100644 (file)
@@ -4,7 +4,7 @@
 use rustc::mir::BorrowKind;
 use rustc::session::config::nightly_options;
 use rustc::ty::TyCtxt;
-use syntax::feature_gate::{emit_feature_err, GateIssue};
+use syntax::feature_gate::feature_err;
 use syntax::symbol::sym;
 use syntax_pos::{Span, Symbol};
 
@@ -222,13 +222,13 @@ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        emit_feature_err(
+        feature_err(
             &item.tcx.sess.parse_sess,
             sym::const_panic,
             span,
-            GateIssue::Language,
             &format!("panicking in {}s is unstable", item.const_kind()),
-        );
+        )
+        .emit();
     }
 }
 
@@ -240,13 +240,13 @@ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        emit_feature_err(
+        feature_err(
             &item.tcx.sess.parse_sess,
             sym::const_compare_raw_pointers,
             span,
-            GateIssue::Language,
             &format!("comparing raw pointers inside {}", item.const_kind()),
-        );
+        )
+        .emit();
     }
 }
 
@@ -258,14 +258,14 @@ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        emit_feature_err(
-            &item.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
-            span, GateIssue::Language,
+        feature_err(
+            &item.tcx.sess.parse_sess, sym::const_raw_ptr_deref, span,
             &format!(
                 "dereferencing raw pointers in {}s is unstable",
                 item.const_kind(),
             ),
-        );
+        )
+        .emit();
     }
 }
 
@@ -277,14 +277,14 @@ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        emit_feature_err(
-            &item.tcx.sess.parse_sess, sym::const_raw_ptr_to_usize_cast,
-            span, GateIssue::Language,
+        feature_err(
+            &item.tcx.sess.parse_sess, sym::const_raw_ptr_to_usize_cast, span,
             &format!(
                 "casting pointers to integers in {}s is unstable",
                 item.const_kind(),
             ),
-        );
+        )
+        .emit();
     }
 }
 
@@ -334,11 +334,11 @@ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        emit_feature_err(
-            &item.tcx.sess.parse_sess, sym::const_transmute,
-            span, GateIssue::Language,
-            &format!("The use of std::mem::transmute() \
-            is gated in {}s", item.const_kind()));
+        feature_err(
+            &item.tcx.sess.parse_sess, sym::const_transmute, span,
+            &format!("The use of std::mem::transmute() is gated in {}s", item.const_kind())
+        )
+        .emit();
     }
 }
 
@@ -355,10 +355,10 @@ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        emit_feature_err(
-            &item.tcx.sess.parse_sess, sym::const_fn_union,
-            span, GateIssue::Language,
+        feature_err(
+            &item.tcx.sess.parse_sess, sym::const_fn_union, span,
             "unions in const fn are unstable",
-        );
+        )
+        .emit();
     }
 }
index dde320aed219f01556a553fcb2985cce0275f6df..6293858ed4ef626c9dcf1e00086b86fdf0818bad 100644 (file)
@@ -11,7 +11,7 @@
 use crate::validate_attr;
 use rustc_feature::Features;
 use syntax::attr::HasAttrs;
-use syntax::feature_gate::{feature_err, get_features, GateIssue};
+use syntax::feature_gate::{feature_err, get_features};
 use syntax::attr;
 use syntax::ast;
 use syntax::edition::Edition;
@@ -212,7 +212,6 @@ pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) {
             let mut err = feature_err(self.sess,
                                       sym::stmt_expr_attributes,
                                       attr.span,
-                                      GateIssue::Language,
                                       "attributes on expressions are experimental");
 
             if attr.is_doc_comment() {
index 697a3ae873cc83d951c91e13238ee160bd517380..63c6e60de795436133760662e7b6768184417274 100644 (file)
@@ -15,7 +15,7 @@
 use rustc::ty::query::Providers;
 use rustc_feature::Features;
 use syntax::ast::Mutability;
-use syntax::feature_gate::{emit_feature_err, GateIssue};
+use syntax::feature_gate::feature_err;
 use syntax::span_err;
 use syntax_pos::{sym, Span};
 use rustc_error_codes::*;
@@ -141,13 +141,7 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
             | NonConstExpr::Match(hir::MatchSource::Normal)
             | NonConstExpr::Match(hir::MatchSource::IfDesugar { .. })
             | NonConstExpr::Match(hir::MatchSource::IfLetDesugar { .. })
-            => emit_feature_err(
-                &self.tcx.sess.parse_sess,
-                sym::const_if_match,
-                span,
-                GateIssue::Language,
-                &msg
-            ),
+            => feature_err(&self.tcx.sess.parse_sess, sym::const_if_match, span, &msg).emit(),
 
             _ => span_err!(self.tcx.sess, span, E0744, "{}", msg),
         }
index cc5bc2b41dc3bbdafc73d93cb0ca329917419733..9e7098da49f32b111ec027252583458df462f7f6 100644 (file)
@@ -16,7 +16,7 @@
 use syntax::ast::{self, NodeId, Ident};
 use syntax::attr::{self, StabilityLevel};
 use syntax::edition::Edition;
-use syntax::feature_gate::{emit_feature_err, GateIssue};
+use syntax::feature_gate::feature_err;
 use syntax::print::pprust;
 use syntax_expand::base::{self, InvocationRes, Indeterminate};
 use syntax_expand::base::SyntaxExtension;
@@ -346,13 +346,8 @@ fn smart_resolve_macro_path(
                segment.ident.as_str().starts_with("rustc") {
                 let msg =
                     "attributes starting with `rustc` are reserved for use by the `rustc` compiler";
-                emit_feature_err(
-                    &self.session.parse_sess,
-                    sym::rustc_attrs,
-                    segment.ident.span,
-                    GateIssue::Language,
-                    msg,
-                );
+                feature_err(&self.session.parse_sess, sym::rustc_attrs, segment.ident.span, msg)
+                    .emit();
             }
         }
 
index a33b2e32c86585d6d499052fbc32152a60a00a33..dafb89badd75356a08c4f18543bb5cccc9f71cbb 100644 (file)
@@ -23,7 +23,7 @@
 use smallvec::SmallVec;
 use syntax::ast;
 use syntax::errors::pluralize;
-use syntax::feature_gate::{GateIssue, emit_feature_err};
+use syntax::feature_gate::feature_err;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::symbol::sym;
 use syntax_pos::{DUMMY_SP, Span, MultiSpan};
@@ -914,8 +914,7 @@ fn create_substs_for_ast_trait_ref<'a>(
             } else {
                 "parenthetical notation is only stable when used with `Fn`-family traits"
             };
-            emit_feature_err(&self.tcx().sess.parse_sess, sym::unboxed_closures,
-                             span, GateIssue::Language, msg);
+            feature_err(&self.tcx().sess.parse_sess, sym::unboxed_closures, span, msg).emit();
         }
 
         self.create_substs_for_ast_path(span,
index 593f8e74ba9cba0daaca69ec643445ef3c6344d3..901a2192e20dd91c92fa1d3510281b38a60b2615 100644 (file)
@@ -644,13 +644,13 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc
         }
 
         if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
-            feature_gate::emit_feature_err(
+            feature_gate::feature_err(
                 &self.tcx.sess.parse_sess,
                 sym::unsized_tuple_coercion,
                 self.cause.span,
-                feature_gate::GateIssue::Language,
                 "unsized tuple coercion is not stable enough for use and is subject to change",
-            );
+            )
+            .emit();
         }
 
         Ok(coercion)
index 930241262b0c17845347d48cc6c0fe46917f0c16..84607fb6c8116f27bbc50db43fa1ea359819a0cb 100644 (file)
 use syntax_pos::hygiene::DesugaringKind;
 use syntax::ast;
 use syntax::attr;
-use syntax::feature_gate::{GateIssue, emit_feature_err};
+use syntax::feature_gate::feature_err;
 use syntax::source_map::{DUMMY_SP, original_sp};
 use syntax::symbol::{kw, sym, Ident};
 use syntax::util::parser::ExprPrecedence;
@@ -2373,13 +2373,13 @@ fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
 
     if adt.is_enum() {
         if !tcx.features().transparent_enums {
-            emit_feature_err(
+            feature_err(
                 &tcx.sess.parse_sess,
                 sym::transparent_enums,
                 sp,
-                GateIssue::Language,
                 "transparent enums are unstable",
-            );
+            )
+            .emit();
         }
         if adt.variants.len() != 1 {
             bad_variant_count(tcx, adt, sp, def_id);
@@ -2391,11 +2391,13 @@ fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
     }
 
     if adt.is_union() && !tcx.features().transparent_unions {
-        emit_feature_err(&tcx.sess.parse_sess,
-                         sym::transparent_unions,
-                         sp,
-                         GateIssue::Language,
-                         "transparent unions are unstable");
+        feature_err(
+            &tcx.sess.parse_sess,
+            sym::transparent_unions,
+            sp,
+            "transparent unions are unstable",
+        )
+        .emit();
     }
 
     // For each field, figure out if it's known to be a ZST and align(1)
@@ -2452,11 +2454,13 @@ pub fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, vs: &'tcx [hir::Variant], i
     let repr_type_ty = def.repr.discr_type().to_ty(tcx);
     if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
         if !tcx.features().repr128 {
-            emit_feature_err(&tcx.sess.parse_sess,
-                             sym::repr128,
-                             sp,
-                             GateIssue::Language,
-                             "repr with 128-bit type is unstable");
+            feature_err(
+                &tcx.sess.parse_sess,
+                sym::repr128,
+                sp,
+                "repr with 128-bit type is unstable",
+            )
+            .emit();
         }
     }
 
index b491b103313561ef7b8cdd57a7196a87880ad92c..20b6b01de57b2555ee26a7da116c826b11b9d1b3 100644 (file)
@@ -10,7 +10,7 @@
 use rustc::infer::opaque_types::may_define_opaque_type;
 
 use syntax::ast;
-use syntax::feature_gate::{self, GateIssue};
+use syntax::feature_gate;
 use syntax_pos::Span;
 use syntax::symbol::sym;
 use errors::DiagnosticBuilder;
@@ -830,13 +830,13 @@ fn check_method_receiver<'fcx, 'tcx>(
                     &fcx.tcx.sess.parse_sess,
                     sym::arbitrary_self_types,
                     span,
-                    GateIssue::Language,
                     &format!(
                         "`{}` cannot be used as the type of `self` without \
                             the `arbitrary_self_types` feature",
                         receiver_ty,
                     ),
-                ).help(HELP_FOR_SELF_TYPE)
+                )
+                .help(HELP_FOR_SELF_TYPE)
                 .emit();
             } else {
                 // Report error; would not have worked with `arbitrary_self_types`.
index 652f081e1761ca5f237c14615739325503f501f5..ab9845c89f5b28fb1c9f5d871c7b899d19317917 100644 (file)
@@ -1494,16 +1494,16 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         _ => None,
                     };
                     if let Some(unsupported_type) = err {
-                        feature_gate::emit_feature_err(
+                        feature_gate::feature_err(
                             &tcx.sess.parse_sess,
                             sym::const_compare_raw_pointers,
                             hir_ty.span,
-                            feature_gate::GateIssue::Language,
                             &format!(
                                 "using {} as const generic parameters is unstable",
                                 unsupported_type
                             ),
-                        );
+                        )
+                        .emit();
                     };
                 }
                 if ty::search_for_structural_match_violation(
@@ -2522,13 +2522,13 @@ fn from_target_feature(
                 None => true,
             };
             if !allowed && id.is_local() {
-                feature_gate::emit_feature_err(
+                feature_gate::feature_err(
                     &tcx.sess.parse_sess,
                     feature_gate.unwrap(),
                     item.span(),
-                    feature_gate::GateIssue::Language,
                     &format!("the target feature `{}` is currently unstable", feature),
-                );
+                )
+                .emit();
             }
             Some(Symbol::intern(feature))
         }));
index bbcb8cc3c62f9fbdd7d0aae7390700111ae57c87..3c10f27b60ae94532eba9919aa6de84de0ba7c8b 100644 (file)
@@ -2,7 +2,7 @@
 
 use super::{mark_used, MetaItemKind};
 use crate::ast::{self, Attribute, MetaItem, NestedMetaItem};
-use crate::feature_gate::{emit_feature_err, GateIssue};
+use crate::feature_gate::feature_err;
 use crate::print::pprust;
 use crate::sess::ParseSess;
 
@@ -569,7 +569,7 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
     let (cfg, feature, has_feature) = gated_cfg;
     if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
         let explain = format!("`cfg({})` is experimental and subject to change", cfg);
-        emit_feature_err(sess, *feature, cfg_span, GateIssue::Language, &explain);
+        feature_err(sess, *feature, cfg_span, &explain).emit()
     }
 }
 
index ea0eff1eed9f86fe441df3bede0ade7b42091173..c90f4c6f19f30ef3298418a63eb2c0ec81984359 100644 (file)
@@ -1,6 +1,7 @@
 use rustc_feature::{ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
 use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
 use rustc_feature::{Features, Feature, State as FeatureState, UnstableFeatures};
+use rustc_feature::{find_feature_issue, GateIssue};
 
 use crate::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
 use crate::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
@@ -18,8 +19,6 @@
 
 use rustc_error_codes::*;
 
-use std::num::NonZeroU32;
-
 macro_rules! gate_feature_fn {
     ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
         let (cx, has_feature, span,
@@ -48,30 +47,6 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features:
     PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
 }
 
-fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
-    if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) {
-        // FIXME (#28244): enforce that active features have issue numbers
-        // assert!(info.issue().is_some())
-        info.issue()
-    } else {
-        // search in Accepted, Removed, or Stable Removed features
-        let found = ACCEPTED_FEATURES
-            .iter()
-            .chain(REMOVED_FEATURES)
-            .chain(STABLE_REMOVED_FEATURES)
-            .find(|t| t.name == feature);
-        match found {
-            Some(found) => found.issue(),
-            None => panic!("feature `{}` is not declared anywhere", feature),
-        }
-    }
-}
-
-pub enum GateIssue {
-    Language,
-    Library(Option<NonZeroU32>)
-}
-
 #[derive(Debug, Copy, Clone, PartialEq)]
 pub enum GateStrength {
     /// A hard error. (Most feature gates should use this.)
@@ -80,41 +55,35 @@ pub enum GateStrength {
     Soft,
 }
 
-pub fn emit_feature_err(
-    sess: &ParseSess,
+pub fn feature_err<'a>(
+    sess: &'a ParseSess,
     feature: Symbol,
-    span: Span,
-    issue: GateIssue,
+    span: impl Into<MultiSpan>,
     explain: &str,
-) {
-    feature_err(sess, feature, span, issue, explain).emit();
+) -> DiagnosticBuilder<'a> {
+    feature_err_issue(sess, feature, span, GateIssue::Language, explain)
 }
 
-pub fn feature_err<'a, S: Into<MultiSpan>>(
+pub fn feature_err_issue<'a>(
     sess: &'a ParseSess,
     feature: Symbol,
-    span: S,
+    span: impl Into<MultiSpan>,
     issue: GateIssue,
     explain: &str,
 ) -> DiagnosticBuilder<'a> {
     leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
 }
 
-fn leveled_feature_err<'a, S: Into<MultiSpan>>(
+fn leveled_feature_err<'a>(
     sess: &'a ParseSess,
     feature: Symbol,
-    span: S,
+    span: impl Into<MultiSpan>,
     issue: GateIssue,
     explain: &str,
     level: GateStrength,
 ) -> DiagnosticBuilder<'a> {
     let diag = &sess.span_diagnostic;
 
-    let issue = match issue {
-        GateIssue::Language => find_lang_feature_issue(feature),
-        GateIssue::Library(lib) => lib,
-    };
-
     let mut err = match level {
         GateStrength::Hard => {
             diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658))
@@ -122,7 +91,7 @@ fn leveled_feature_err<'a, S: Into<MultiSpan>>(
         GateStrength::Soft => diag.struct_span_warn(span, explain),
     };
 
-    if let Some(n) = issue {
+    if let Some(n) = find_feature_issue(feature, issue) {
         err.note(&format!(
             "for more information, see https://github.com/rust-lang/rust/issues/{}",
             n,
@@ -257,7 +226,6 @@ fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
                 self.parse_sess,
                 sym::arbitrary_enum_discriminant,
                 discriminant_spans.clone(),
-                crate::feature_gate::GateIssue::Language,
                 "custom discriminant values are not allowed in enums with tuple or struct variants",
             );
             for sp in discriminant_spans {
index c2d887c9267818356ed50e3b9f7fbf986bb7c868..3d4a5d624c1190eccf025a807b2779387d3de59d 100644 (file)
@@ -94,10 +94,7 @@ pub mod util {
 pub mod entry;
 pub mod feature_gate {
     mod check;
-    pub use check::{
-        check_crate, check_attribute, get_features, feature_err, emit_feature_err,
-        GateIssue,
-    };
+    pub use check::{check_crate, check_attribute, get_features, feature_err, feature_err_issue};
 }
 pub mod mut_visit;
 pub mod ptr;
index e4c4f4c43e64fe19123f604fbd4edaea8500b69a..a6ced1439c5d95c5e07800899cd4f8980872fa9c 100644 (file)
@@ -14,7 +14,7 @@
 use syntax::ast::{MacStmtStyle, StmtKind, ItemKind};
 use syntax::attr::{self, HasAttrs, is_builtin_attr};
 use syntax::source_map::respan;
-use syntax::feature_gate::{self, GateIssue, emit_feature_err};
+use syntax::feature_gate::{self, feature_err};
 use syntax::mut_visit::*;
 use syntax::print::pprust;
 use syntax::ptr::P;
@@ -727,13 +727,13 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
         if self.cx.ecfg.proc_macro_hygiene() {
             return
         }
-        emit_feature_err(
+        feature_err(
             self.cx.parse_sess,
             sym::proc_macro_hygiene,
             span,
-            GateIssue::Language,
             &format!("custom attributes cannot be applied to {}", kind),
-        );
+        )
+        .emit();
     }
 
     fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
@@ -745,13 +745,13 @@ impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
             fn visit_item(&mut self, item: &'ast ast::Item) {
                 match &item.kind {
                     ast::ItemKind::Mod(module) if !module.inline => {
-                        emit_feature_err(
+                        feature_err(
                             self.parse_sess,
                             sym::proc_macro_hygiene,
                             item.span,
-                            GateIssue::Language,
                             "non-inline modules in proc macro input are unstable",
-                        );
+                        )
+                        .emit();
                     }
                     _ => {}
                 }
@@ -790,13 +790,13 @@ fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
         if self.cx.ecfg.proc_macro_hygiene() {
             return
         }
-        emit_feature_err(
+        feature_err(
             self.cx.parse_sess,
             sym::proc_macro_hygiene,
             span,
-            GateIssue::Language,
             &format!("procedural macros cannot be expanded to {}", kind),
-        );
+        )
+        .emit();
     }
 
     fn parse_ast_fragment(
@@ -992,9 +992,11 @@ fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, after_derive: &mut bo
         if let Some(attr) = &attr {
             if !self.cx.ecfg.custom_inner_attributes() &&
                attr.style == ast::AttrStyle::Inner && !attr.has_name(sym::test) {
-                emit_feature_err(&self.cx.parse_sess, sym::custom_inner_attributes,
-                                 attr.span, GateIssue::Language,
-                                 "non-builtin inner attributes are unstable");
+                feature_err(
+                    &self.cx.parse_sess, sym::custom_inner_attributes, attr.span,
+                    "non-builtin inner attributes are unstable"
+                )
+                .emit();
             }
         }
         attr