]> git.lizzy.rs Git - rust.git/blobdiff - src/libsyntax/feature_gate/check.rs
ast: Keep `extern` qualifiers in functions more precisely
[rust.git] / src / libsyntax / feature_gate / check.rs
index 3bf1e24bf12796d8734d183a537fd7963f231cf8..d90fa9addf7f6f28154484c28e913a7ce606eda0 100644 (file)
@@ -17,6 +17,9 @@
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use log::debug;
 
+use rustc_error_codes::*;
+
+
 use std::env;
 use std::num::NonZeroU32;
 
@@ -255,6 +258,12 @@ fn check_abi(&self, abi: ast::Abi) {
         }
     }
 
+    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,
@@ -318,6 +327,27 @@ fn check_gat(&self, generics: &ast::Generics, span: Span) {
             );
         }
     }
+
+    /// 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> {
@@ -364,7 +394,9 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) {
     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(..) => {
@@ -452,14 +484,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 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),
 
             _ => {}
         }
@@ -494,7 +519,7 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
     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,
@@ -588,7 +613,7 @@ fn visit_fn(&mut self,
             // 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() {
@@ -622,7 +647,7 @@ fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
         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,
@@ -633,9 +658,8 @@ fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
                 }
             }
             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");
                 }
@@ -660,15 +684,8 @@ fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
                                        "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);
             }
             _ => {}