]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_ast_passes/src/feature_gate.rs
Stablize `const_extern_fn` for "Rust" and "C"
[rust.git] / compiler / rustc_ast_passes / src / feature_gate.rs
index 5b6147c72230d53b943586280b3a6d457d103886..5b2716b2dd088d405e9fd1b46356d3d488291968 100644 (file)
@@ -58,9 +58,22 @@ struct PostExpansionVisitor<'a> {
 }
 
 impl<'a> PostExpansionVisitor<'a> {
-    fn check_abi(&self, abi: ast::StrLit) {
+    fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
         let ast::StrLit { symbol_unescaped, span, .. } = abi;
 
+        if let ast::Const::Yes(_) = constness {
+            match symbol_unescaped.as_str() {
+                // Stable
+                "Rust" | "C" => {}
+                abi => gate_feature_post!(
+                    &self,
+                    const_extern_fn,
+                    span,
+                    &format!("`{}` as a `const fn` ABI is unstable", abi)
+                ),
+            }
+        }
+
         match symbol_unescaped.as_str() {
             // Stable
             "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
@@ -261,9 +274,9 @@ fn check_abi(&self, abi: ast::StrLit) {
         }
     }
 
-    fn check_extern(&self, ext: ast::Extern) {
+    fn check_extern(&self, ext: ast::Extern, constness: ast::Const) {
         if let ast::Extern::Explicit(abi) = ext {
-            self.check_abi(abi);
+            self.check_abi(abi, constness);
         }
     }
 
@@ -445,7 +458,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
         match i.kind {
             ast::ItemKind::ForeignMod(ref foreign_module) => {
                 if let Some(abi) = foreign_module.abi {
-                    self.check_abi(abi);
+                    self.check_abi(abi, ast::Const::No);
                 }
             }
 
@@ -568,7 +581,8 @@ 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_extern(bare_fn_ty.ext);
+                // Function pointers cannot be `const`
+                self.check_extern(bare_fn_ty.ext, ast::Const::No);
             }
             ast::TyKind::Never => {
                 gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
@@ -668,18 +682,7 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
     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_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"
-                );
-            }
+            self.check_extern(header.ext, header.constness);
         }
 
         if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {