All other ABIs are left unstable for now.
cc #64926
}
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"
}
}
- 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);
}
}
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);
}
}
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");
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() {
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
let whole_span = lo.to(self.prev_token.span);
if let ast::Const::Yes(span) = constness {
+ // If we ever start to allow `const fn()`, then update
+ // feature gating for `#![feature(const_extern_fn)]` to
+ // cover it.
self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
}
if let ast::Async::Yes { span, .. } = asyncness {
-// Check that `const extern fn` and `const unsafe extern fn` are feature-gated.
+// Check that `const extern fn` and `const unsafe extern fn` are feature-gated
+// for certain ABIs.
-const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable
-const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable
-const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern "C" fn bar2() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern "Rust" fn bar3() {} //~ ERROR `const extern fn` definitions are unstable
+const extern fn foo1() {}
+const extern "C" fn foo2() {}
+const extern "Rust" fn foo3() {}
+const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
+const unsafe extern fn bar1() {}
+const unsafe extern "C" fn bar2() {}
+const unsafe extern "Rust" fn bar3() {}
+const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
fn main() {}
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:3:1
+error[E0658]: `cdecl` as a `const fn` ABI is unstable
+ --> $DIR/feature-gate-const_extern_fn.rs:7:14
|
-LL | const extern fn foo1() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const extern "cdecl" fn foo4() {}
+ | ^^^^^^^
|
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:4:1
+error[E0658]: `cdecl` as a `const fn` ABI is unstable
+ --> $DIR/feature-gate-const_extern_fn.rs:11:21
|
-LL | const extern "C" fn foo2() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const unsafe extern "cdecl" fn bar4() {}
+ | ^^^^^^^
|
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:5:1
- |
-LL | const extern "Rust" fn foo3() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
- = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:6:1
- |
-LL | const unsafe extern fn bar1() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
- = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:7:1
- |
-LL | const unsafe extern "C" fn bar2() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
- = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:8:1
- |
-LL | const unsafe extern "Rust" fn bar3() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
- = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.