summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ast_passes/src/feature_gate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ast_passes/src/feature_gate.rs')
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs92
1 files changed, 50 insertions, 42 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 96042ea30..17bcd24ee 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,6 +1,6 @@
use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
-use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
+use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId};
use rustc_ast::{PatKind, RangeEnd};
use rustc_errors::{Applicability, StashKey};
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
@@ -121,24 +121,34 @@ impl<'a> PostExpansionVisitor<'a> {
}
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
- fn check_impl_trait(&self, ty: &ast::Ty) {
+ fn check_impl_trait(&self, ty: &ast::Ty, in_associated_ty: bool) {
struct ImplTraitVisitor<'a> {
vis: &'a PostExpansionVisitor<'a>,
+ in_associated_ty: bool,
}
impl Visitor<'_> for ImplTraitVisitor<'_> {
fn visit_ty(&mut self, ty: &ast::Ty) {
if let ast::TyKind::ImplTrait(..) = ty.kind {
- gate_feature_post!(
- &self.vis,
- type_alias_impl_trait,
- ty.span,
- "`impl Trait` in type aliases is unstable"
- );
+ if self.in_associated_ty {
+ gate_feature_post!(
+ &self.vis,
+ impl_trait_in_assoc_type,
+ ty.span,
+ "`impl Trait` in associated types is unstable"
+ );
+ } else {
+ gate_feature_post!(
+ &self.vis,
+ type_alias_impl_trait,
+ ty.span,
+ "`impl Trait` in type aliases is unstable"
+ );
+ }
}
visit::walk_ty(self, ty);
}
}
- ImplTraitVisitor { vis: self }.visit_ty(ty);
+ ImplTraitVisitor { vis: self, in_associated_ty }.visit_ty(ty);
}
fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
@@ -232,7 +242,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
ast::ItemKind::Fn(..) => {
- if self.sess.contains_name(&i.attrs, sym::start) {
+ if attr::contains_name(&i.attrs, sym::start) {
gate_feature_post!(
&self,
start,
@@ -245,7 +255,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
ast::ItemKind::Struct(..) => {
- for attr in self.sess.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) {
if item.has_name(sym::simd) {
gate_feature_post!(
@@ -294,7 +304,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
- self.check_impl_trait(&ty)
+ self.check_impl_trait(&ty, false)
}
_ => {}
@@ -306,7 +316,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
match i.kind {
ast::ForeignItemKind::Fn(..) | ast::ForeignItemKind::Static(..) => {
- let link_name = self.sess.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.map_or(false, |val| val.as_str().starts_with("llvm."));
if links_to_llvm {
@@ -337,9 +347,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
}
- ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::DynStar, ..) => {
- gate_feature_post!(&self, dyn_star, ty.span, "dyn* trait objects are unstable");
- }
_ => {}
}
visit::walk_ty(self, ty)
@@ -395,14 +402,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_expr(&mut self, e: &'a ast::Expr) {
match e.kind {
- ast::ExprKind::Box(_) => {
- gate_feature_post!(
- &self,
- box_syntax,
- e.span,
- "box expression syntax is experimental; you can call `Box::new` instead"
- );
- }
ast::ExprKind::Type(..) => {
if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
// To avoid noise about type ascription in common syntax errors,
@@ -415,24 +414,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
);
} else {
// And if it isn't, cancel the early-pass warning.
- self.sess
+ if let Some(err) = self
+ .sess
.parse_sess
.span_diagnostic
.steal_diagnostic(e.span, StashKey::EarlySyntaxWarning)
- .map(|err| err.cancel());
+ {
+ err.cancel()
+ }
}
}
ast::ExprKind::TryBlock(_) => {
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
}
- ast::ExprKind::Closure(box ast::Closure { constness: ast::Const::Yes(_), .. }) => {
- gate_feature_post!(
- &self,
- const_closures,
- e.span,
- "const closures are experimental"
- );
- }
_ => {}
}
visit::walk_expr(self, e)
@@ -501,12 +495,24 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) {
if let AssocConstraintKind::Bound { .. } = constraint.kind {
- gate_feature_post!(
- &self,
- associated_type_bounds,
- constraint.span,
- "associated type bounds are unstable"
- )
+ if let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref()
+ && args.inputs.is_empty()
+ && matches!(args.output, ast::FnRetTy::Default(..))
+ {
+ gate_feature_post!(
+ &self,
+ return_type_notation,
+ constraint.span,
+ "return type notation is experimental"
+ );
+ } else {
+ gate_feature_post!(
+ &self,
+ associated_type_bounds,
+ constraint.span,
+ "associated type bounds are unstable"
+ );
+ }
}
visit::walk_assoc_constraint(self, constraint)
}
@@ -524,7 +530,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
);
}
if let Some(ty) = ty {
- self.check_impl_trait(ty);
+ self.check_impl_trait(ty, true);
}
false
}
@@ -594,6 +600,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
gate_all!(associated_const_equality, "associated const equality is incomplete");
gate_all!(yeet_expr, "`do yeet` expression is experimental");
+ gate_all!(dyn_star, "`dyn*` trait objects are experimental");
+ gate_all!(const_closures, "const closures are experimental");
// All uses of `gate_all!` below this point were added in #65742,
// and subsequently disabled (with the non-early gating readded).
@@ -609,11 +617,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(trait_alias, "trait aliases are experimental");
gate_all!(associated_type_bounds, "associated type bounds are unstable");
+ gate_all!(return_type_notation, "return type notation is experimental");
gate_all!(decl_macro, "`macro` is experimental");
gate_all!(box_patterns, "box pattern syntax is experimental");
gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
gate_all!(try_blocks, "`try` blocks are unstable");
- gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
gate_all!(type_ascription, "type ascription is experimental");
visit::walk_crate(&mut visitor, krate);