diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 27bf9649324b4..619ca724214c8 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -232,13 +232,13 @@ impl<'a> LintLevelsBuilder<'a> { // 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 { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 411a47423c5aa..54aafe2114dac 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -13,11 +13,12 @@ use crate::ty::query::Providers; 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 @@ impl Visitor<'tcx> for Checker<'tcx> { 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(); } } } diff --git a/src/librustc_feature/lib.rs b/src/librustc_feature/lib.rs index 82e60889316d9..c38bb3740af3a 100644 --- a/src/librustc_feature/lib.rs +++ b/src/librustc_feature/lib.rs @@ -49,8 +49,7 @@ pub struct Feature { } impl Feature { - // FIXME(Centril): privatize again. - pub fn issue(&self) -> Option { + fn issue(&self) -> Option { self.issue.and_then(|i| NonZeroU32::new(i)) } } @@ -97,6 +96,37 @@ impl UnstableFeatures { } } +fn find_lang_feature_issue(feature: Symbol) -> Option { + 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) +} + +pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option { + 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}; diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index e577b238c8684..425e5d1d821bf 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -7,7 +7,7 @@ use rustc::util::nodemap::FxHashSet; 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 @@ impl Collector<'tcx> { } } 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); } diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index acad56be60403..a4f12a4e54fa7 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -4,7 +4,7 @@ use rustc::hir::def_id::DefId; 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 @@ impl NonConstOp for Panic { } 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 @@ impl NonConstOp for RawPtrComparison { } 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 @@ impl NonConstOp for RawPtrDeref { } 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 @@ impl NonConstOp for RawPtrToIntCast { } 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 @@ impl NonConstOp for Transmute { } 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 @@ impl NonConstOp for UnionAccess { } 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(); } } diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index dde320aed219f..6293858ed4ef6 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -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 @@ impl<'a> StripUnconfigured<'a> { 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() { diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 697a3ae873cc8..63c6e60de7954 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -15,7 +15,7 @@ use rustc::ty::TyCtxt; 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 @@ impl<'tcx> CheckConstVisitor<'tcx> { | 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), } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index cc5bc2b41dc3b..9e7098da49f32 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -16,7 +16,7 @@ use rustc_feature::is_builtin_attr_name; 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 @@ impl<'a> Resolver<'a> { 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(); } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a33b2e32c8658..dafb89badd753 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -23,7 +23,7 @@ use crate::require_c_abi_if_c_variadic; 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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } 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, diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 593f8e74ba9cb..901a2192e20dd 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -644,13 +644,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } 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) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 930241262b0c1..84607fb6c8116 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -125,7 +125,7 @@ use syntax_pos::{self, BytePos, Span, MultiSpan}; 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(); } } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b491b10331356..20b6b01de57b2 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -10,7 +10,7 @@ use rustc::middle::lang_items; 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`. diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 652f081e1761c..ab9845c89f5b2 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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)) })); diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index bbcb8cc3c62f9..3c10f27b60ae9 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -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() } } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index ea0eff1eed9f8..c90f4c6f19f30 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -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 log::debug; 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 { - 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) -} - #[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, 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>( +pub fn feature_err_issue<'a>( sess: &'a ParseSess, feature: Symbol, - span: S, + span: impl Into, issue: GateIssue, explain: &str, ) -> DiagnosticBuilder<'a> { leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard) } -fn leveled_feature_err<'a, S: Into>( +fn leveled_feature_err<'a>( sess: &'a ParseSess, feature: Symbol, - span: S, + span: impl Into, 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>( 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 @@ impl<'a> PostExpansionVisitor<'a> { 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 { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index c2d887c926781..3d4a5d624c119 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -94,10 +94,7 @@ pub use syntax_pos::source_map; 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; diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index e4c4f4c43e64f..a6ced1439c5d9 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -14,7 +14,7 @@ use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path}; 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 @@ impl<'a, 'b> MacroExpander<'a, 'b> { 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<'a, 'b> MacroExpander<'a, 'b> { 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 @@ impl<'a, 'b> MacroExpander<'a, 'b> { 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 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { 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