From 9292c0bc91a9165a2dc7baa4d154079ad0a5f5c9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 17 Jul 2016 00:15:15 +0300 Subject: [PATCH] Properly feature gate all unstable ABIs --- src/doc/book/closures.md | 1 + src/libsyntax/feature_gate.rs | 73 +++++++++++-------- src/test/compile-fail/E0045.rs | 2 +- .../feature-gate-abi-vectorcall.rs | 19 ----- src/test/compile-fail/feature-gate-abi.rs | 60 +++++++++++++++ .../compile-fail/feature-gate-rust-call.rs | 21 ------ 6 files changed, 103 insertions(+), 73 deletions(-) delete mode 100644 src/test/compile-fail/feature-gate-abi-vectorcall.rs create mode 100644 src/test/compile-fail/feature-gate-abi.rs delete mode 100644 src/test/compile-fail/feature-gate-rust-call.rs diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index 666d0946ecc80..defa63b916928 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -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 : FnMut { extern "rust-call" fn call(&self, args: Args) -> Self::Output; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 27485ee65fcc0..2b79a7012e31f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -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) { @@ -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(..) => { @@ -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(_) => { @@ -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); @@ -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"); } diff --git a/src/test/compile-fail/E0045.rs b/src/test/compile-fail/E0045.rs index edec911d3c070..2a731596b4be8 100644 --- a/src/test/compile-fail/E0045.rs +++ b/src/test/compile-fail/E0045.rs @@ -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() { } diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/compile-fail/feature-gate-abi-vectorcall.rs deleted file mode 100644 index 79f3c8dc77625..0000000000000 --- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern "vectorcall" { //~ ERROR vectorcall is experimental and subject to change - fn bar(); -} - -extern "vectorcall" fn baz() { //~ ERROR vectorcall is experimental and subject to change -} - -fn main() { -} diff --git a/src/test/compile-fail/feature-gate-abi.rs b/src/test/compile-fail/feature-gate-abi.rs new file mode 100644 index 0000000000000..0c01f955c063b --- /dev/null +++ b/src/test/compile-fail/feature-gate-abi.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/compile-fail/feature-gate-rust-call.rs b/src/test/compile-fail/feature-gate-rust-call.rs deleted file mode 100644 index 029a9cad65fcf..0000000000000 --- a/src/test/compile-fail/feature-gate-rust-call.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2014 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change - -trait Foo { - extern "rust-call" fn foo(); -} - -impl Foo for i32 { - extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change -} - -fn main() { }