use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use log::debug;
+use rustc_error_codes::*;
+
+
use std::env;
use std::num::NonZeroU32;
}
}
+ fn check_extern(&self, ext: ast::Extern) {
+ if let ast::Extern::Explicit(abi) = ext {
+ self.check_abi(abi);
+ }
+ }
+
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,
);
}
}
+
+ /// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
+ fn check_impl_trait(&self, ty: &ast::Ty) {
+ struct ImplTraitVisitor<'a> {
+ vis: &'a PostExpansionVisitor<'a>,
+ }
+ 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"
+ );
+ }
+ visit::walk_ty(self, ty);
+ }
+ }
+ ImplTraitVisitor { vis: self }.visit_ty(ty);
+ }
}
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_item(&mut self, i: &'a ast::Item) {
match i.kind {
ast::ItemKind::ForeignMod(ref foreign_module) => {
- self.check_abi(foreign_module.abi);
+ if let Some(abi) = foreign_module.abi {
+ self.check_abi(abi);
+ }
}
ast::ItemKind::Fn(..) => {
gate_feature_post!(&self, decl_macro, i.span, msg);
}
- ast::ItemKind::OpaqueTy(..) => {
- gate_feature_post!(
- &self,
- type_alias_impl_trait,
- i.span,
- "`impl Trait` in type aliases is unstable"
- );
- }
+ ast::ItemKind::TyAlias(ref ty, ..) => self.check_impl_trait(&ty),
_ => {}
}
fn visit_ty(&mut self, ty: &'a ast::Ty) {
match ty.kind {
ast::TyKind::BareFn(ref bare_fn_ty) => {
- self.check_abi(bare_fn_ty.abi);
+ self.check_extern(bare_fn_ty.ext);
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span,
// Stability of const fn methods are covered in
// `visit_trait_item` and `visit_impl_item` below; this is
// because default methods don't pass through this point.
- self.check_abi(header.abi);
+ self.check_extern(header.ext);
}
if fn_decl.c_variadic() {
match ti.kind {
ast::TraitItemKind::Method(ref sig, ref block) => {
if block.is_none() {
- self.check_abi(sig.header.abi);
+ self.check_extern(sig.header.ext);
}
if sig.decl.c_variadic() {
gate_feature_post!(&self, c_variadic, ti.span,
}
}
ast::TraitItemKind::Type(_, ref default) => {
- // We use three if statements instead of something like match guards so that all
- // of these errors can be emitted if all cases apply.
- if default.is_some() {
+ if let Some(ty) = default {
+ self.check_impl_trait(ty);
gate_feature_post!(&self, associated_type_defaults, ti.span,
"associated type defaults are unstable");
}
"C-variadic functions are unstable");
}
}
- ast::ImplItemKind::OpaqueTy(..) => {
- gate_feature_post!(
- &self,
- type_alias_impl_trait,
- ii.span,
- "`impl Trait` in type aliases is unstable"
- );
- }
- ast::ImplItemKind::TyAlias(_) => {
+ ast::ImplItemKind::TyAlias(ref ty) => {
+ self.check_impl_trait(ty);
self.check_gat(&ii.generics, ii.span);
}
_ => {}