Skip to content

Properly feature gate all unstable ABIs #34904

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/doc/book/closures.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ trait system to overload operators. Calling functions is no different. We have
three separate traits to overload with:

```rust
# #![feature(unboxed_closures)]
# mod foo {
pub trait Fn<Args> : FnMut<Args> {
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
Expand Down
73 changes: 41 additions & 32 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,29 @@ macro_rules! gate_feature_post {
}}
}

impl<'a> PostExpansionVisitor<'a> {
fn check_abi(&self, abi: Abi, span: Span) {
match abi {
Abi::RustIntrinsic =>
gate_feature_post!(&self, intrinsics, span,
"intrinsics are subject to change"),
Abi::PlatformIntrinsic => {
gate_feature_post!(&self, platform_intrinsics, span,
"platform intrinsics are experimental and possibly buggy")
},
Abi::Vectorcall => {
gate_feature_post!(&self, abi_vectorcall, span,
"vectorcall is experimental and subject to change")
}
Abi::RustCall => {
gate_feature_post!(&self, unboxed_closures, span,
"rust-call ABI is subject to change");
}
_ => {}
}
}
}

impl<'a> Visitor for PostExpansionVisitor<'a> {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
if !self.context.cm.span_allows_unstable(attr.span) {
Expand Down Expand Up @@ -831,21 +854,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
across platforms, it is recommended to \
use `#[link(name = \"foo\")]` instead")
}
match foreign_module.abi {
Abi::RustIntrinsic =>
gate_feature_post!(&self, intrinsics, i.span,
"intrinsics are subject to change"),
Abi::PlatformIntrinsic => {
gate_feature_post!(&self, platform_intrinsics, i.span,
"platform intrinsics are experimental \
and possibly buggy")
},
Abi::Vectorcall => {
gate_feature_post!(&self, abi_vectorcall, i.span,
"vectorcall is experimental and subject to change")
}
_ => ()
}
self.check_abi(foreign_module.abi, i.span);
}

ast::ItemKind::Fn(..) => {
Expand Down Expand Up @@ -928,6 +937,16 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
visit::walk_foreign_item(self, i)
}

fn visit_ty(&mut self, ty: &ast::Ty) {
match ty.node {
ast::TyKind::BareFn(ref bare_fn_ty) => {
self.check_abi(bare_fn_ty.abi, ty.span);
}
_ => {}
}
visit::walk_ty(self, ty)
}

fn visit_expr(&mut self, e: &ast::Expr) {
match e.node {
ast::ExprKind::Box(_) => {
Expand Down Expand Up @@ -1015,23 +1034,10 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
}

match fn_kind {
FnKind::ItemFn(_, _, _, _, abi, _) if abi == Abi::RustIntrinsic => {
gate_feature_post!(&self, intrinsics,
span,
"intrinsics are subject to change")
}
FnKind::ItemFn(_, _, _, _, abi, _) |
FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => match abi {
Abi::RustCall => {
gate_feature_post!(&self, unboxed_closures, span,
"rust-call ABI is subject to change");
},
Abi::Vectorcall => {
gate_feature_post!(&self, abi_vectorcall, span,
"vectorcall is experimental and subject to change");
},
_ => {}
},
FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => {
self.check_abi(abi, span);
}
_ => {}
}
visit::walk_fn(self, fn_kind, fn_decl, block, span);
Expand All @@ -1044,7 +1050,10 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
ti.span,
"associated constants are experimental")
}
ast::TraitItemKind::Method(ref sig, _) => {
ast::TraitItemKind::Method(ref sig, ref block) => {
if block.is_none() {
self.check_abi(sig.abi, ti.span);
}
if sig.constness == ast::Constness::Const {
gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/E0045.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern "rust-call" { fn foo(x: u8, ...); } //~ ERROR E0045
extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045

fn main() {
}
19 changes: 0 additions & 19 deletions src/test/compile-fail/feature-gate-abi-vectorcall.rs

This file was deleted.

60 changes: 60 additions & 0 deletions src/test/compile-fail/feature-gate-abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Functions
extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change

// Methods in trait definition
trait Tr {
extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change

extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
}

struct S;

// Methods in trait impl
impl Tr for S {
extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
}

// Methods in inherent impl
impl S {
extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
}

// Function pointer types
type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change

// Foreign modules
extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" {} //~ ERROR rust-call ABI is subject to change

fn main() {}
21 changes: 0 additions & 21 deletions src/test/compile-fail/feature-gate-rust-call.rs

This file was deleted.