]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_ast_passes/feature_gate.rs
parse extern consts
[rust.git] / src / librustc_ast_passes / feature_gate.rs
index 3b13ab354fdf98e75585d9110357f8db03d42430..d4de2c937583db5ba44005bf7d444a9f76521fae 100644 (file)
@@ -8,7 +8,7 @@
 use syntax::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
 use syntax::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
 use syntax::attr;
-use syntax::visit::{self, FnKind, Visitor};
+use syntax::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 
 use log::debug;
 
@@ -397,10 +397,10 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
                     );
                 }
             }
-            ast::ForeignItemKind::Ty => {
+            ast::ForeignItemKind::TyAlias(..) => {
                 gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
             }
-            ast::ForeignItemKind::Macro(..) => {}
+            ast::ForeignItemKind::Macro(..) | ast::ForeignItemKind::Const(..) => {}
         }
 
         visit::walk_foreign_item(self, i)
@@ -492,25 +492,28 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
         visit::walk_pat(self, pattern)
     }
 
-    fn visit_fn(
-        &mut self,
-        fn_kind: FnKind<'a>,
-        fn_decl: &'a ast::FnDecl,
-        span: Span,
-        _node_id: NodeId,
-    ) {
+    fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
         if let Some(header) = fn_kind.header() {
-            // 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.
+            // Stability of const fn methods are covered in `visit_assoc_item` below.
             self.check_extern(header.ext);
+
+            if let (ast::Const::Yes(_), ast::Extern::Implicit)
+            | (ast::Const::Yes(_), ast::Extern::Explicit(_)) = (header.constness, header.ext)
+            {
+                gate_feature_post!(
+                    &self,
+                    const_extern_fn,
+                    span,
+                    "`const extern fn` definitions are unstable"
+                );
+            }
         }
 
-        if fn_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");
         }
 
-        visit::walk_fn(self, fn_kind, fn_decl, span)
+        visit::walk_fn(self, fn_kind, span)
     }
 
     fn visit_generic_param(&mut self, param: &'a GenericParam) {
@@ -539,56 +542,34 @@ fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
         visit::walk_assoc_ty_constraint(self, constraint)
     }
 
-    fn visit_trait_item(&mut self, ti: &'a ast::AssocItem) {
-        match ti.kind {
-            ast::AssocItemKind::Fn(ref sig, ref block) => {
-                if block.is_none() {
-                    self.check_extern(sig.header.ext);
-                }
-                if sig.header.constness.node == ast::Constness::Const {
-                    gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
+    fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
+        if i.defaultness == ast::Defaultness::Default {
+            gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
+        }
+
+        match i.kind {
+            ast::AssocItemKind::Fn(ref sig, _, _) => {
+                if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) {
+                    gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
                 }
             }
-            ast::AssocItemKind::TyAlias(_, ref default) => {
-                if let Some(_) = default {
+            ast::AssocItemKind::TyAlias(ref generics, _, ref ty) => {
+                if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
                     gate_feature_post!(
                         &self,
                         associated_type_defaults,
-                        ti.span,
+                        i.span,
                         "associated type defaults are unstable"
                     );
                 }
-            }
-            _ => {}
-        }
-        visit::walk_trait_item(self, ti)
-    }
-
-    fn visit_assoc_item(&mut self, ii: &'a ast::AssocItem) {
-        if ii.defaultness == ast::Defaultness::Default {
-            gate_feature_post!(&self, specialization, ii.span, "specialization is unstable");
-        }
-
-        match ii.kind {
-            ast::AssocItemKind::Fn(ref sig, _) => {
-                if sig.decl.c_variadic() {
-                    gate_feature_post!(
-                        &self,
-                        c_variadic,
-                        ii.span,
-                        "C-variadic functions are unstable"
-                    );
-                }
-            }
-            ast::AssocItemKind::TyAlias(_, ref ty) => {
                 if let Some(ty) = ty {
                     self.check_impl_trait(ty);
                 }
-                self.check_gat(&ii.generics, ii.span);
+                self.check_gat(generics, i.span);
             }
             _ => {}
         }
-        visit::walk_assoc_item(self, ii)
+        visit::walk_assoc_item(self, i, ctxt)
     }
 
     fn visit_vis(&mut self, vis: &'a ast::Visibility) {
@@ -625,7 +606,6 @@ macro_rules! gate_all {
     gate_all!(async_closure, "async closures are unstable");
     gate_all!(generators, "yield syntax is experimental");
     gate_all!(or_patterns, "or-patterns syntax is experimental");
-    gate_all!(const_extern_fn, "`const extern fn` definitions are unstable");
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
     gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
     gate_all!(const_trait_impl, "const trait impls are experimental");