Rearrange the gate_feature_* macros.

This commit is contained in:
Nicholas Nethercote 2023-10-30 10:21:43 +11:00
parent c88954e9c1
commit de17ec9dae

View File

@ -13,34 +13,38 @@ use thin_vec::ThinVec;
use crate::errors; use crate::errors;
macro_rules! gate_feature_fn { /// The common case.
($visitor:expr, $has_feature:expr, $span:expr, $name:expr, $explain:expr, $help:expr) => {{ macro_rules! gate {
if !$has_feature($visitor.features) && !$span.allows_unstable($name) { ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).help($help).emit(); if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain).emit();
} }
}}; }};
($visitor:expr, $has_feature:expr, $span:expr, $name:expr, $explain:expr) => {{ ($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
if !$has_feature($visitor.features) && !$span.allows_unstable($name) { if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit(); feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
} .help($help)
}}; .emit();
(future_incompatible; $visitor:expr, $has_feature:expr, $span:expr, $name:expr, $explain:expr) => {{
if !$has_feature($visitor.features) && !$span.allows_unstable($name) {
feature_warn(&$visitor.sess.parse_sess, $name, $span, $explain);
} }
}}; }};
} }
macro_rules! gate_feature_post { /// The unusual case, where the `has_feature` condition is non-standard.
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => { macro_rules! gate_alt {
gate_feature_fn!($visitor, |x:&Features| x.$feature, $span, sym::$feature, $explain, $help) ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
}; if !$has_feature && !$span.allows_unstable($name) {
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => { feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit();
gate_feature_fn!($visitor, |x:&Features| x.$feature, $span, sym::$feature, $explain) }
}; }};
(future_incompatible; $visitor:expr, $feature:ident, $span:expr, $explain:expr) => { }
gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
}; /// The legacy case.
macro_rules! gate_legacy {
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
feature_warn(&$visitor.sess.parse_sess, sym::$feature, $span, $explain);
}
}};
} }
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) { pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
@ -62,7 +66,7 @@ impl<'a> PostExpansionVisitor<'a> {
match symbol_unescaped { match symbol_unescaped {
// Stable // Stable
sym::Rust | sym::C => {} sym::Rust | sym::C => {}
abi => gate_feature_post!( abi => gate!(
&self, &self,
const_extern_fn, const_extern_fn,
span, span,
@ -113,14 +117,14 @@ impl<'a> PostExpansionVisitor<'a> {
fn visit_ty(&mut self, ty: &ast::Ty) { fn visit_ty(&mut self, ty: &ast::Ty) {
if let ast::TyKind::ImplTrait(..) = ty.kind { if let ast::TyKind::ImplTrait(..) = ty.kind {
if self.in_associated_ty { if self.in_associated_ty {
gate_feature_post!( gate!(
&self.vis, &self.vis,
impl_trait_in_assoc_type, impl_trait_in_assoc_type,
ty.span, ty.span,
"`impl Trait` in associated types is unstable" "`impl Trait` in associated types is unstable"
); );
} else { } else {
gate_feature_post!( gate!(
&self.vis, &self.vis,
type_alias_impl_trait, type_alias_impl_trait,
ty.span, ty.span,
@ -172,7 +176,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
.. ..
}) = attr_info }) = attr_info
{ {
gate_feature_fn!(self, has_feature, attr.span, *name, *descr); gate_alt!(self, has_feature(&self.features), *name, attr.span, *descr);
} }
// Check unstable flavors of the `#[doc]` attribute. // Check unstable flavors of the `#[doc]` attribute.
if attr.has_name(sym::doc) { if attr.has_name(sym::doc) {
@ -180,7 +184,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) => { macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) => {
$($(if nested_meta.has_name(sym::$name) { $($(if nested_meta.has_name(sym::$name) {
let msg = concat!("`#[doc(", stringify!($name), ")]` is ", $s); let msg = concat!("`#[doc(", stringify!($name), ")]` is ", $s);
gate_feature_post!(self, $feature, attr.span, msg); gate!(self, $feature, attr.span, msg);
})*)* })*)*
}} }}
@ -204,7 +208,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
&& !self.features.diagnostic_namespace && !self.features.diagnostic_namespace
{ {
let msg = "`#[diagnostic]` attribute name space is experimental"; let msg = "`#[diagnostic]` attribute name space is experimental";
gate_feature_post!(self, diagnostic_namespace, seg.ident.span, msg); gate!(self, diagnostic_namespace, seg.ident.span, msg);
} }
// Emit errors for non-staged-api crates. // Emit errors for non-staged-api crates.
@ -230,12 +234,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::ItemKind::Fn(..) => { ast::ItemKind::Fn(..) => {
if attr::contains_name(&i.attrs, sym::start) { if attr::contains_name(&i.attrs, sym::start) {
gate_feature_post!( gate!(
&self, &self,
start, start,
i.span, i.span,
"`#[start]` functions are experimental \ "`#[start]` functions are experimental and their signature may change \
and their signature may change \
over time" over time"
); );
} }
@ -245,7 +248,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
for attr in attr::filter_by_name(&i.attrs, sym::repr) { for attr in attr::filter_by_name(&i.attrs, sym::repr) {
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(sym::simd) { if item.has_name(sym::simd) {
gate_feature_post!( gate!(
&self, &self,
repr_simd, repr_simd,
attr.span, attr.span,
@ -258,7 +261,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => { ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => {
if let &ast::ImplPolarity::Negative(span) = polarity { if let &ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!( gate!(
&self, &self,
negative_impls, negative_impls,
span.to(of_trait.as_ref().map_or(span, |t| t.path.span)), span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
@ -268,12 +271,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
} }
if let ast::Defaultness::Default(_) = defaultness { if let ast::Defaultness::Default(_) = defaultness {
gate_feature_post!(&self, specialization, i.span, "specialization is unstable"); gate!(&self, specialization, i.span, "specialization is unstable");
} }
} }
ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => { ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
gate_feature_post!( gate!(
&self, &self,
auto_traits, auto_traits,
i.span, i.span,
@ -282,12 +285,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
} }
ast::ItemKind::TraitAlias(..) => { ast::ItemKind::TraitAlias(..) => {
gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental"); gate!(&self, trait_alias, i.span, "trait aliases are experimental");
} }
ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => { ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
let msg = "`macro` is experimental"; let msg = "`macro` is experimental";
gate_feature_post!(&self, decl_macro, i.span, msg); gate!(&self, decl_macro, i.span, msg);
} }
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => { ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
@ -306,7 +309,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name); let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name);
let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm.")); let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
if links_to_llvm { if links_to_llvm {
gate_feature_post!( gate!(
&self, &self,
link_llvm_intrinsics, link_llvm_intrinsics,
i.span, i.span,
@ -315,7 +318,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
} }
} }
ast::ForeignItemKind::TyAlias(..) => { ast::ForeignItemKind::TyAlias(..) => {
gate_feature_post!(&self, extern_types, i.span, "extern types are experimental"); gate!(&self, extern_types, i.span, "extern types are experimental");
} }
ast::ForeignItemKind::MacCall(..) => {} ast::ForeignItemKind::MacCall(..) => {}
} }
@ -331,7 +334,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params); self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
} }
ast::TyKind::Never => { ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental"); gate!(&self, never_type, ty.span, "the `!` type is experimental");
} }
_ => {} _ => {}
} }
@ -364,7 +367,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_expr(&mut self, e: &'a ast::Expr) { fn visit_expr(&mut self, e: &'a ast::Expr) {
match e.kind { match e.kind {
ast::ExprKind::TryBlock(_) => { ast::ExprKind::TryBlock(_) => {
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); gate!(&self, try_blocks, e.span, "`try` expression is experimental");
} }
_ => {} _ => {}
} }
@ -380,7 +383,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
_ => pat, _ => pat,
}; };
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind { if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
gate_feature_post!( gate!(
&self, &self,
half_open_range_patterns_in_slices, half_open_range_patterns_in_slices,
pat.span, pat.span,
@ -390,15 +393,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
} }
} }
PatKind::Box(..) => { PatKind::Box(..) => {
gate_feature_post!( gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
&self,
box_patterns,
pattern.span,
"box pattern syntax is experimental"
);
} }
PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => { PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
gate_feature_post!( gate!(
&self, &self,
exclusive_range_pattern, exclusive_range_pattern,
pattern.span, pattern.span,
@ -426,7 +424,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
} }
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() { if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); gate!(&self, c_variadic, span, "C-variadic functions are unstable");
} }
visit::walk_fn(self, fn_kind) visit::walk_fn(self, fn_kind)
@ -438,14 +436,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
&& args.inputs.is_empty() && args.inputs.is_empty()
&& matches!(args.output, ast::FnRetTy::Default(..)) && matches!(args.output, ast::FnRetTy::Default(..))
{ {
gate_feature_post!( gate!(
&self, &self,
return_type_notation, return_type_notation,
constraint.span, constraint.span,
"return type notation is experimental" "return type notation is experimental"
); );
} else { } else {
gate_feature_post!( gate!(
&self, &self,
associated_type_bounds, associated_type_bounds,
constraint.span, constraint.span,
@ -461,7 +459,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::AssocItemKind::Fn(_) => true, ast::AssocItemKind::Fn(_) => true,
ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => { ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!( gate!(
&self, &self,
associated_type_defaults, associated_type_defaults,
i.span, i.span,
@ -477,11 +475,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}; };
if let ast::Defaultness::Default(_) = i.kind.defaultness() { if let ast::Defaultness::Default(_) = i.kind.defaultness() {
// Limit `min_specialization` to only specializing functions. // Limit `min_specialization` to only specializing functions.
gate_feature_fn!( gate_alt!(
&self, &self,
|x: &Features| x.specialization || (is_fn && x.min_specialization), self.features.specialization || (is_fn && self.features.min_specialization),
i.span,
sym::specialization, sym::specialization,
i.span,
"specialization is unstable" "specialization is unstable"
); );
} }
@ -496,17 +494,17 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
let spans = sess.parse_sess.gated_spans.spans.borrow(); let spans = sess.parse_sess.gated_spans.spans.borrow();
macro_rules! gate_all { macro_rules! gate_all {
($gate:ident, $msg:literal, $help:literal) => {
if let Some(spans) = spans.get(&sym::$gate) {
for span in spans {
gate_feature_post!(&visitor, $gate, *span, $msg, $help);
}
}
};
($gate:ident, $msg:literal) => { ($gate:ident, $msg:literal) => {
if let Some(spans) = spans.get(&sym::$gate) { if let Some(spans) = spans.get(&sym::$gate) {
for span in spans { for span in spans {
gate_feature_post!(&visitor, $gate, *span, $msg); gate!(&visitor, $gate, *span, $msg);
}
}
};
($gate:ident, $msg:literal, $help:literal) => {
if let Some(spans) = spans.get(&sym::$gate) {
for span in spans {
gate!(&visitor, $gate, *span, $msg, $help);
} }
} }
}; };
@ -531,7 +529,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
for &span in spans.get(&sym::yield_expr).iter().copied().flatten() { for &span in spans.get(&sym::yield_expr).iter().copied().flatten() {
if !span.at_least_rust_2024() { if !span.at_least_rust_2024() {
gate_feature_post!(&visitor, coroutines, span, "yield syntax is experimental"); gate!(&visitor, coroutines, span, "yield syntax is experimental");
} }
} }
gate_all!(gen_blocks, "gen blocks are experimental"); gate_all!(gen_blocks, "gen blocks are experimental");
@ -565,7 +563,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
macro_rules! gate_all_legacy_dont_use { macro_rules! gate_all_legacy_dont_use {
($gate:ident, $msg:literal) => { ($gate:ident, $msg:literal) => {
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg); gate_legacy!(&visitor, $gate, *span, $msg);
} }
}; };
} }