summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ast_passes
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ast_passes')
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs127
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs127
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs291
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
4 files changed, 136 insertions, 410 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index b1d10e07a..036643244 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -14,6 +14,7 @@ use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
+use rustc_macros::Subdiagnostic;
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -38,6 +39,13 @@ enum SelfSemantic {
No,
}
+/// What is the context that prevents using `~const`?
+enum DisallowTildeConstContext<'a> {
+ TraitObject,
+ ImplTrait,
+ Fn(FnKind<'a>),
+}
+
struct AstValidator<'a> {
session: &'a Session,
@@ -56,7 +64,7 @@ struct AstValidator<'a> {
/// e.g., `impl Iterator<Item = impl Debug>`.
outer_impl_trait: Option<Span>,
- is_tilde_const_allowed: bool,
+ disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
/// or `Foo::Bar<impl Trait>`
@@ -93,18 +101,26 @@ impl<'a> AstValidator<'a> {
self.is_impl_trait_banned = old;
}
- fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
- let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
+ fn with_tilde_const(
+ &mut self,
+ disallowed: Option<DisallowTildeConstContext<'a>>,
+ f: impl FnOnce(&mut Self),
+ ) {
+ let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
f(self);
- self.is_tilde_const_allowed = old;
+ self.disallow_tilde_const = old;
}
fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
- self.with_tilde_const(true, f)
+ self.with_tilde_const(None, f)
}
- fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
- self.with_tilde_const(false, f)
+ fn with_banned_tilde_const(
+ &mut self,
+ ctx: DisallowTildeConstContext<'a>,
+ f: impl FnOnce(&mut Self),
+ ) {
+ self.with_tilde_const(Some(ctx), f)
}
fn with_let_management(
@@ -154,7 +170,7 @@ impl<'a> AstValidator<'a> {
DEPRECATED_WHERE_CLAUSE_LOCATION,
id,
where_clauses.0.1,
- fluent::ast_passes::deprecated_where_clause_location,
+ fluent::ast_passes_deprecated_where_clause_location,
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
where_clauses.1.1.shrink_to_hi(),
suggestion,
@@ -172,7 +188,7 @@ impl<'a> AstValidator<'a> {
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.outer_impl_trait, outer);
if outer.is_some() {
- self.with_banned_tilde_const(f);
+ self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
} else {
f(self);
}
@@ -197,7 +213,10 @@ impl<'a> AstValidator<'a> {
TyKind::ImplTrait(..) => {
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
}
- TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)),
+ TyKind::TraitObject(..) => self
+ .with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| {
+ visit::walk_ty(this, t)
+ }),
TyKind::Path(ref qself, ref path) => {
// We allow these:
// - `Option<impl Trait>`
@@ -233,20 +252,6 @@ impl<'a> AstValidator<'a> {
}
}
- fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
- if let Some(ident) = field.ident {
- if ident.name == kw::Underscore {
- self.visit_vis(&field.vis);
- self.visit_ident(ident);
- self.visit_ty_common(&field.ty);
- self.walk_ty(&field.ty);
- walk_list!(self, visit_attribute, &field.attrs);
- return;
- }
- }
- self.visit_field_def(field);
- }
-
fn err_handler(&self) -> &rustc_errors::Handler {
&self.session.diagnostic()
}
@@ -987,8 +992,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_lifetime(self, lifetime);
}
- fn visit_field_def(&mut self, s: &'a FieldDef) {
- visit::walk_field_def(self, s)
+ fn visit_field_def(&mut self, field: &'a FieldDef) {
+ visit::walk_field_def(self, field)
}
fn visit_item(&mut self, item: &'a Item) {
@@ -1176,42 +1181,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_mod_file_item_asciionly(item.ident);
}
}
- ItemKind::Struct(ref vdata, ref generics) => match vdata {
- // Duplicating the `Visitor` logic allows catching all cases
- // of `Anonymous(Struct, Union)` outside of a field struct or union.
- //
- // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
- // encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
- // it uses `visit_ty_common`, which doesn't contain that specific check.
- VariantData::Struct(ref fields, ..) => {
- self.visit_vis(&item.vis);
- self.visit_ident(item.ident);
- self.visit_generics(generics);
- self.with_banned_assoc_ty_bound(|this| {
- walk_list!(this, visit_struct_field_def, fields);
- });
- walk_list!(self, visit_attribute, &item.attrs);
- return;
- }
- _ => {}
- },
- ItemKind::Union(ref vdata, ref generics) => {
+ ItemKind::Union(ref vdata, ..) => {
if vdata.fields().is_empty() {
self.err_handler().span_err(item.span, "unions cannot have zero fields");
}
- match vdata {
- VariantData::Struct(ref fields, ..) => {
- self.visit_vis(&item.vis);
- self.visit_ident(item.ident);
- self.visit_generics(generics);
- self.with_banned_assoc_ty_bound(|this| {
- walk_list!(this, visit_struct_field_def, fields);
- });
- walk_list!(self, visit_attribute, &item.attrs);
- return;
- }
- _ => {}
- }
}
ItemKind::Const(def, .., None) => {
self.check_defaultness(item.span, def);
@@ -1411,13 +1384,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
);
err.emit();
}
- (_, TraitBoundModifier::MaybeConst) => {
- if !self.is_tilde_const_allowed {
- self.err_handler()
- .struct_span_err(bound.span(), "`~const` is not allowed here")
- .note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
- .emit();
- }
+ (_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
+ let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
+ match reason {
+ DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
+ DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
+ DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
+ DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
+ };
+ err.emit();
}
(_, TraitBoundModifier::MaybeConstMaybe) => {
self.err_handler()
@@ -1524,10 +1499,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
let tilde_const_allowed =
- matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. }))
+ matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
- self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk));
+ let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
+
+ self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
}
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
@@ -1557,7 +1534,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
}
}
- AssocItemKind::TyAlias(box TyAlias {
+ AssocItemKind::Type(box TyAlias {
generics,
where_clauses,
where_predicates_split,
@@ -1596,7 +1573,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
match item.kind {
- AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. })
+ AssocItemKind::Type(box TyAlias { ref generics, ref bounds, ref ty, .. })
if ctxt == AssocCtxt::Trait =>
{
self.visit_vis(&item.vis);
@@ -1771,7 +1748,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
in_const_trait_impl: false,
has_proc_macro_decls: false,
outer_impl_trait: None,
- is_tilde_const_allowed: false,
+ disallow_tilde_const: None,
is_impl_trait_banned: false,
is_assoc_ty_bound_banned: false,
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
@@ -1783,15 +1760,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
}
/// Used to forbid `let` expressions in certain syntactic locations.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Subdiagnostic)]
pub(crate) enum ForbiddenLetReason {
/// `let` is not valid and the source environment is not important
GenericForbidden,
/// A let chain with the `||` operator
- NotSupportedOr(Span),
+ #[note(not_supported_or)]
+ NotSupportedOr(#[primary_span] Span),
/// A let chain with invalid parentheses
///
/// For example, `let 1 = 1 && (expr && expr)` is allowed
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
- NotSupportedParentheses(Span),
+ #[note(not_supported_parentheses)]
+ NotSupportedParentheses(#[primary_span] Span),
}
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 4f3b09c58..59f582f10 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1,13 +1,13 @@
//! Errors emitted by ast_passes.
-use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessage};
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
use crate::ast_validation::ForbiddenLetReason;
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_let)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_let)]
#[note]
pub struct ForbiddenLet {
#[primary_span]
@@ -16,130 +16,116 @@ pub struct ForbiddenLet {
pub(crate) reason: ForbiddenLetReason,
}
-impl AddSubdiagnostic for ForbiddenLetReason {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
- match self {
- Self::GenericForbidden => {}
- Self::NotSupportedOr(span) => {
- diag.span_note(span, fluent::ast_passes::not_supported_or);
- }
- Self::NotSupportedParentheses(span) => {
- diag.span_note(span, fluent::ast_passes::not_supported_parentheses);
- }
- }
- }
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_let_stable)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_let_stable)]
#[note]
pub struct ForbiddenLetStable {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_assoc_constraint)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_assoc_constraint)]
pub struct ForbiddenAssocConstraint {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::keyword_lifetime)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_keyword_lifetime)]
pub struct KeywordLifetime {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::invalid_label)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_invalid_label)]
pub struct InvalidLabel {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::invalid_visibility, code = "E0449")]
+#[derive(Diagnostic)]
+#[diag(ast_passes_invalid_visibility, code = "E0449")]
pub struct InvalidVisibility {
#[primary_span]
pub span: Span,
- #[label(ast_passes::implied)]
+ #[label(implied)]
pub implied: Option<Span>,
#[subdiagnostic]
pub note: Option<InvalidVisibilityNote>,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum InvalidVisibilityNote {
- #[note(ast_passes::individual_impl_items)]
+ #[note(individual_impl_items)]
IndividualImplItems,
- #[note(ast_passes::individual_foreign_items)]
+ #[note(individual_foreign_items)]
IndividualForeignItems,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::trait_fn_const, code = "E0379")]
+#[derive(Diagnostic)]
+#[diag(ast_passes_trait_fn_const, code = "E0379")]
pub struct TraitFnConst {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_lifetime_bound)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_lifetime_bound)]
pub struct ForbiddenLifetimeBound {
#[primary_span]
pub spans: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_non_lifetime_param)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_non_lifetime_param)]
pub struct ForbiddenNonLifetimeParam {
#[primary_span]
pub spans: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_too_many)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_too_many)]
pub struct FnParamTooMany {
#[primary_span]
pub span: Span,
pub max_num_args: usize,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_c_var_args_only)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_c_var_args_only)]
pub struct FnParamCVarArgsOnly {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_c_var_args_not_last)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_c_var_args_not_last)]
pub struct FnParamCVarArgsNotLast {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_doc_comment)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_doc_comment)]
pub struct FnParamDocComment {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_forbidden_attr)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_forbidden_attr)]
pub struct FnParamForbiddenAttr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_forbidden_self)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_forbidden_self)]
#[note]
pub struct FnParamForbiddenSelf {
#[primary_span]
@@ -147,8 +133,8 @@ pub struct FnParamForbiddenSelf {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_default)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_default)]
pub struct ForbiddenDefault {
#[primary_span]
pub span: Span,
@@ -156,8 +142,8 @@ pub struct ForbiddenDefault {
pub def_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_const_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_const_without_body)]
pub struct AssocConstWithoutBody {
#[primary_span]
pub span: Span,
@@ -165,8 +151,8 @@ pub struct AssocConstWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_fn_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_fn_without_body)]
pub struct AssocFnWithoutBody {
#[primary_span]
pub span: Span,
@@ -174,8 +160,8 @@ pub struct AssocFnWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_type_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_type_without_body)]
pub struct AssocTypeWithoutBody {
#[primary_span]
pub span: Span,
@@ -183,8 +169,8 @@ pub struct AssocTypeWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::const_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_const_without_body)]
pub struct ConstWithoutBody {
#[primary_span]
pub span: Span,
@@ -192,8 +178,8 @@ pub struct ConstWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::static_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_static_without_body)]
pub struct StaticWithoutBody {
#[primary_span]
pub span: Span,
@@ -201,8 +187,8 @@ pub struct StaticWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::ty_alias_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_ty_alias_without_body)]
pub struct TyAliasWithoutBody {
#[primary_span]
pub span: Span,
@@ -210,8 +196,8 @@ pub struct TyAliasWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_without_body)]
pub struct FnWithoutBody {
#[primary_span]
pub span: Span,
@@ -227,8 +213,11 @@ pub struct ExternBlockSuggestion {
pub abi: Option<Symbol>,
}
-impl AddSubdiagnostic for ExternBlockSuggestion {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+impl AddToDiagnostic for ExternBlockSuggestion {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
let start_suggestion = if let Some(abi) = self.abi {
format!("extern \"{}\" {{", abi)
} else {
@@ -237,7 +226,7 @@ impl AddSubdiagnostic for ExternBlockSuggestion {
let end_suggestion = " }".to_owned();
diag.multipart_suggestion(
- fluent::ast_passes::extern_block_suggestion,
+ fluent::extern_block_suggestion,
vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
Applicability::MaybeIncorrect,
);
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index aeff73c5b..546010135 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,15 +1,15 @@
use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
-use rustc_ast::{PatKind, RangeEnd, VariantData};
+use rustc_ast::{PatKind, RangeEnd};
use rustc_errors::{struct_span_err, Applicability, StashKey};
-use rustc_feature::Features;
-use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
-use rustc_session::parse::{feature_err, feature_warn};
+use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
+use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
use rustc_session::Session;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_target::spec::abi;
macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
@@ -84,210 +84,26 @@ impl<'a> PostExpansionVisitor<'a> {
}
}
- match symbol_unescaped.as_str() {
- // Stable
- "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
- | "system" => {}
- "rust-intrinsic" => {
- gate_feature_post!(&self, intrinsics, span, "intrinsics are subject to change");
- }
- "platform-intrinsic" => {
- gate_feature_post!(
- &self,
- platform_intrinsics,
- span,
- "platform intrinsics are experimental and possibly buggy"
- );
- }
- "vectorcall" => {
- gate_feature_post!(
- &self,
- abi_vectorcall,
- span,
- "vectorcall is experimental and subject to change"
- );
- }
- "thiscall" => {
- gate_feature_post!(
- &self,
- abi_thiscall,
- span,
- "thiscall is experimental and subject to change"
- );
- }
- "rust-call" => {
- gate_feature_post!(
- &self,
- unboxed_closures,
- span,
- "rust-call ABI is subject to change"
- );
- }
- "rust-cold" => {
- gate_feature_post!(
- &self,
- rust_cold_cc,
- span,
- "rust-cold is experimental and subject to change"
- );
- }
- "ptx-kernel" => {
- gate_feature_post!(
- &self,
- abi_ptx,
- span,
- "PTX ABIs are experimental and subject to change"
- );
- }
- "unadjusted" => {
- gate_feature_post!(
- &self,
- abi_unadjusted,
- span,
- "unadjusted ABI is an implementation detail and perma-unstable"
- );
- }
- "msp430-interrupt" => {
- gate_feature_post!(
- &self,
- abi_msp430_interrupt,
- span,
- "msp430-interrupt ABI is experimental and subject to change"
- );
- }
- "x86-interrupt" => {
- gate_feature_post!(
- &self,
- abi_x86_interrupt,
- span,
- "x86-interrupt ABI is experimental and subject to change"
- );
- }
- "amdgpu-kernel" => {
- gate_feature_post!(
- &self,
- abi_amdgpu_kernel,
- span,
- "amdgpu-kernel ABI is experimental and subject to change"
- );
- }
- "avr-interrupt" | "avr-non-blocking-interrupt" => {
- gate_feature_post!(
- &self,
- abi_avr_interrupt,
- span,
- "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"
- );
- }
- "efiapi" => {
- gate_feature_post!(
- &self,
- abi_efiapi,
- span,
- "efiapi ABI is experimental and subject to change"
- );
- }
- "C-cmse-nonsecure-call" => {
- gate_feature_post!(
- &self,
- abi_c_cmse_nonsecure_call,
+ match abi::is_enabled(&self.features, span, symbol_unescaped.as_str()) {
+ Ok(()) => (),
+ Err(abi::AbiDisabled::Unstable { feature, explain }) => {
+ feature_err_issue(
+ &self.sess.parse_sess,
+ feature,
span,
- "C-cmse-nonsecure-call ABI is experimental and subject to change"
- );
- }
- "C-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "C-unwind ABI is experimental and subject to change"
- );
- }
- "stdcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "stdcall-unwind ABI is experimental and subject to change"
- );
- }
- "system-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "system-unwind ABI is experimental and subject to change"
- );
- }
- "thiscall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "thiscall-unwind ABI is experimental and subject to change"
- );
- }
- "cdecl-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "cdecl-unwind ABI is experimental and subject to change"
- );
- }
- "fastcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "fastcall-unwind ABI is experimental and subject to change"
- );
- }
- "vectorcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "vectorcall-unwind ABI is experimental and subject to change"
- );
- }
- "aapcs-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "aapcs-unwind ABI is experimental and subject to change"
- );
- }
- "win64-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "win64-unwind ABI is experimental and subject to change"
- );
- }
- "sysv64-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "sysv64-unwind ABI is experimental and subject to change"
- );
- }
- "wasm" => {
- gate_feature_post!(
- &self,
- wasm_abi,
- span,
- "wasm ABI is experimental and subject to change"
- );
+ GateIssue::Language,
+ explain,
+ )
+ .emit();
}
- abi => {
+ Err(abi::AbiDisabled::Unrecognized) => {
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
self.sess.parse_sess.span_diagnostic.delay_span_bug(
span,
- &format!("unrecognized ABI not caught in lowering: {}", abi),
+ &format!(
+ "unrecognized ABI not caught in lowering: {}",
+ symbol_unescaped.as_str()
+ ),
);
}
}
@@ -300,46 +116,6 @@ impl<'a> PostExpansionVisitor<'a> {
}
}
- fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
- let has_fields = variants.iter().any(|variant| match variant.data {
- VariantData::Tuple(..) | VariantData::Struct(..) => true,
- VariantData::Unit(..) => false,
- });
-
- let discriminant_spans = variants
- .iter()
- .filter(|variant| match variant.data {
- VariantData::Tuple(..) | VariantData::Struct(..) => false,
- VariantData::Unit(..) => true,
- })
- .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
- .collect::<Vec<_>>();
-
- if !discriminant_spans.is_empty() && has_fields {
- let mut err = feature_err(
- &self.sess.parse_sess,
- sym::arbitrary_enum_discriminant,
- discriminant_spans.clone(),
- "custom discriminant values are not allowed in enums with tuple or struct variants",
- );
- for sp in discriminant_spans {
- err.span_label(sp, "disallowed custom discriminant");
- }
- for variant in variants.iter() {
- match &variant.data {
- VariantData::Struct(..) => {
- err.span_label(variant.span, "struct variant defined here");
- }
- VariantData::Tuple(..) => {
- err.span_label(variant.span, "tuple variant defined here");
- }
- VariantData::Unit(..) => {}
- }
- }
- err.emit();
- }
- }
-
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
fn check_impl_trait(&self, ty: &ast::Ty) {
struct ImplTraitVisitor<'a> {
@@ -457,26 +233,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
- ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
- for variant in variants {
- match (&variant.data, &variant.disr_expr) {
- (ast::VariantData::Unit(..), _) => {}
- (_, Some(disr_expr)) => gate_feature_post!(
- &self,
- arbitrary_enum_discriminant,
- disr_expr.value.span,
- "discriminants on non-unit variants are experimental"
- ),
- _ => {}
- }
- }
-
- let has_feature = self.features.arbitrary_enum_discriminant;
- if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
- self.maybe_report_invalid_custom_discriminants(&variants);
- }
- }
-
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
if let ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!(
@@ -645,7 +401,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
gate_feature_post!(
&self,
- half_open_range_patterns,
+ half_open_range_patterns_in_slices,
pat.span,
"`X..` patterns in slices are experimental"
);
@@ -701,7 +457,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
let is_fn = match i.kind {
ast::AssocItemKind::Fn(_) => true,
- ast::AssocItemKind::TyAlias(box ast::TyAlias { ref ty, .. }) => {
+ ast::AssocItemKind::Type(box ast::TyAlias { ref ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!(
&self,
@@ -773,7 +529,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(generators, "yield syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental");
gate_all!(const_trait_impl, "const trait impls are experimental");
- gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
+ gate_all!(
+ half_open_range_patterns_in_slices,
+ "half-open range patterns in slices are unstable"
+ );
gate_all!(inline_const, "inline-const is experimental");
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
gate_all!(associated_const_equality, "associated const equality is incomplete");
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 8aa9d57f0..f58fffc91 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -9,7 +9,6 @@
#![feature(if_let_guard)]
#![feature(iter_is_partitioned)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![recursion_limit = "256"]
#[macro_use]