move GateIssue to rustc_feature & simplify emit_feature_err
This commit is contained in:
parent
91fcd40ca2
commit
79077f13ff
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ impl UnstableFeatures {
|
||||
}
|
||||
}
|
||||
|
||||
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};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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))
|
||||
}));
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<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,
|
||||
feature: Symbol,
|
||||
span: Span,
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
) {
|
||||
feature_err(sess, feature, span, issue, explain).emit();
|
||||
}
|
||||
|
||||
pub fn feature_err<'a, S: Into<MultiSpan>>(
|
||||
pub fn feature_err<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: S,
|
||||
span: impl Into<MultiSpan>,
|
||||
explain: &str,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
feature_err_issue(sess, feature, span, GateIssue::Language, explain)
|
||||
}
|
||||
|
||||
pub fn feature_err_issue<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
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 @@ 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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user