From 3948b054dc8e598b83a194056dc4d3a0852dc79e Mon Sep 17 00:00:00 2001 From: Florian Warzecha Date: Wed, 21 Oct 2020 12:36:07 +0200 Subject: [PATCH 1/7] add rustc_allow_const_fn_unstable attribute allow_internal_unstable is currently used to side-step feature gate and stability checks. While it was originally only meant to be used only on macros, its use was expanded to const functions. This commit prepares stricter checks for the usage of allow_internal_unstable (only on macros) and introduces the rustc_allow_const_fn_unstable attribute for usage on functions. See rust-lang/rust#69399 --- compiler/rustc_feature/src/active.rs | 5 +++++ compiler/rustc_feature/src/builtin_attrs.rs | 4 ++++ compiler/rustc_span/src/symbol.rs | 1 + .../feature-gate-rustc-allow-const-fn-unstable.rs | 6 ++++++ ...feature-gate-rustc-allow-const-fn-unstable.stderr | 12 ++++++++++++ 5 files changed, 28 insertions(+) create mode 100644 src/test/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.rs create mode 100644 src/test/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index c13fe2ae2806b..90fed862b9993 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -210,6 +210,11 @@ declare_features! ( /// it is not on path for eventual stabilization). (active, no_niche, "1.42.0", None, None), + /// Allows using `#[rustc_allow_const_fn_unstable]`. + /// This is an attribute on `const fn` for the same + /// purpose as `#[allow_internal_unstable]`. + (active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None), + // no-tracking-issue-end // ------------------------------------------------------------------------- diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 83aa1f62106cb..f73363cbccc25 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -379,6 +379,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ allow_internal_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."), "allow_internal_unstable side-steps feature gating and stability checks", ), + gated!( + rustc_allow_const_fn_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."), + "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" + ), gated!( allow_internal_unsafe, Normal, template!(Word), "allow_internal_unsafe side-steps the unsafe_code lint", diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9cf530d57c0b1..13864f6d0ea8d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -893,6 +893,7 @@ symbols! { rustc, rustc_allocator, rustc_allocator_nounwind, + rustc_allow_const_fn_unstable, rustc_args_required_const, rustc_attrs, rustc_builtin_macro, diff --git a/src/test/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.rs b/src/test/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.rs new file mode 100644 index 0000000000000..19d8fa87f5536 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.rs @@ -0,0 +1,6 @@ +#![allow(unused_macros)] + +#[rustc_allow_const_fn_unstable()] //~ ERROR rustc_allow_const_fn_unstable side-steps +const fn foo() { } + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr b/src/test/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr new file mode 100644 index 0000000000000..a549cb64e0cb6 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: rustc_allow_const_fn_unstable side-steps feature gating and stability checks + --> $DIR/feature-gate-rustc-allow-const-fn-unstable.rs:3:1 + | +LL | #[rustc_allow_const_fn_unstable()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69399 for more information + = help: add `#![feature(rustc_allow_const_fn_unstable)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 05f4a9a42abbbdb64d3ec4ed0ae6883c10c66e3f Mon Sep 17 00:00:00 2001 From: Florian Warzecha Date: Wed, 21 Oct 2020 20:54:20 +0200 Subject: [PATCH 2/7] switch allow_internal_unstable const fns to rustc_allow_const_fn_unstable --- compiler/rustc_attr/src/builtin.rs | 25 ++++++++++++++++--- compiler/rustc_expand/src/base.rs | 9 +++++-- .../src/transform/check_consts/mod.rs | 2 +- .../src/transform/check_consts/validation.rs | 6 ++--- compiler/rustc_passes/src/check_const.rs | 6 ++--- library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec.rs | 3 ++- library/core/src/lib.rs | 1 + library/core/src/num/int_macros.rs | 6 +++-- library/core/src/num/uint_macros.rs | 6 +++-- library/core/src/slice/mod.rs | 3 ++- library/core/src/str/converts.rs | 3 ++- library/core/src/str/mod.rs | 3 ++- library/core/src/task/wake.rs | 3 ++- library/proc_macro/src/bridge/client.rs | 15 +++++++---- library/proc_macro/src/bridge/scoped_cell.rs | 3 ++- library/proc_macro/src/lib.rs | 1 + library/std/src/lib.rs | 1 + library/std/src/net/ip.rs | 3 ++- .../consts/min_const_fn/allow_const_fn_ptr.rs | 4 +-- .../min_const_fn/allow_const_fn_ptr.stderr | 4 +-- .../allow_const_fn_ptr_run_pass.rs | 4 +-- .../min_const_fn_libstd_stability.stderr | 4 +-- ...in_const_unsafe_fn_libstd_stability.stderr | 4 +-- 24 files changed, 81 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 9c309345000bb..218a9b229e0df 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -1013,13 +1013,28 @@ pub fn allow_internal_unstable<'a>( sess: &'a Session, attrs: &'a [Attribute], ) -> Option + 'a> { - let attrs = sess.filter_by_name(attrs, sym::allow_internal_unstable); + allow_unstable(sess, attrs, sym::allow_internal_unstable) +} + +pub fn rustc_allow_const_fn_unstable<'a>( + sess: &'a Session, + attrs: &'a [Attribute], +) -> Option + 'a> { + allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable) +} + +fn allow_unstable<'a>( + sess: &'a Session, + attrs: &'a [Attribute], + symbol: Symbol, +) -> Option + 'a> { + let attrs = sess.filter_by_name(attrs, symbol); let list = attrs .filter_map(move |attr| { attr.meta_item_list().or_else(|| { sess.diagnostic().span_err( attr.span, - "`allow_internal_unstable` expects a list of feature names", + &format!("`{}` expects a list of feature names", symbol.to_ident_string()), ); None }) @@ -1029,8 +1044,10 @@ pub fn allow_internal_unstable<'a>( Some(list.into_iter().filter_map(move |it| { let name = it.ident().map(|ident| ident.name); if name.is_none() { - sess.diagnostic() - .span_err(it.span(), "`allow_internal_unstable` expects feature names"); + sess.diagnostic().span_err( + it.span(), + &format!("`{}` expects feature names", symbol.to_ident_string()), + ); } name })) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b0e43a260e91d..e5bb213b51412 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -768,8 +768,13 @@ impl SyntaxExtension { name: Symbol, attrs: &[ast::Attribute], ) -> SyntaxExtension { - let allow_internal_unstable = attr::allow_internal_unstable(sess, &attrs) - .map(|features| features.collect::>().into()); + let allow_internal_unstable = { + let mut feat_list = Vec::new(); + attr::allow_internal_unstable(sess, &attrs).map(|features| feat_list.extend(features)); + attr::rustc_allow_const_fn_unstable(sess, &attrs) + .map(|features| feat_list.extend(features)); + Some(feat_list.into()) + }; let mut local_inner_macros = false; if let Some(macro_export) = sess.find_by_name(attrs, sym::macro_export) { diff --git a/compiler/rustc_mir/src/transform/check_consts/mod.rs b/compiler/rustc_mir/src/transform/check_consts/mod.rs index 33815ceba620b..11e389cbe4464 100644 --- a/compiler/rustc_mir/src/transform/check_consts/mod.rs +++ b/compiler/rustc_mir/src/transform/check_consts/mod.rs @@ -79,7 +79,7 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { pub fn allow_internal_unstable(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool { let attrs = tcx.get_attrs(def_id); - attr::allow_internal_unstable(&tcx.sess, attrs) + attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs) .map_or(false, |mut features| features.any(|name| name == feature_gate)) } diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 587b5b381288a..e23fb453c5ae0 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -805,7 +805,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { } // Calling an unstable function *always* requires that the corresponding gate - // be enabled, even if the function has `#[allow_internal_unstable(the_gate)]`. + // be enabled, even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`. if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) { self.check_op(ops::FnCallUnstable(callee, Some(gate))); return; @@ -965,8 +965,8 @@ fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol ) .span_suggestion( attr_span, - "otherwise `#[allow_internal_unstable]` can be used to bypass stability checks", - format!("#[allow_internal_unstable({})]\n", gate), + "otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks", + format!("#[rustc_allow_const_fn_unstable({})]\n", gate), Applicability::MaybeIncorrect, ) .emit(); diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index dd0bcbf208d7c..b24c62b971a46 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -87,7 +87,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { let is_feature_allowed = |feature_gate| { // All features require that the corresponding gate be enabled, - // even if the function has `#[allow_internal_unstable(the_gate)]`. + // even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`. if !tcx.features().enabled(feature_gate) { return false; } @@ -105,8 +105,8 @@ impl<'tcx> CheckConstVisitor<'tcx> { } // However, we cannot allow stable `const fn`s to use unstable features without an explicit - // opt-in via `allow_internal_unstable`. - attr::allow_internal_unstable(&tcx.sess, &tcx.get_attrs(def_id)) + // opt-in via `rustc_allow_const_fn_unstable`. + attr::rustc_allow_const_fn_unstable(&tcx.sess, &tcx.get_attrs(def_id)) .map_or(false, |mut features| features.any(|name| name == feature_gate)) }; diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index b69e19072af44..ccabc336acc16 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -72,6 +72,7 @@ #![allow(explicit_outlives_requirements)] #![allow(incomplete_features)] #![deny(unsafe_op_in_unsafe_fn)] +#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(new_uninit))] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 1844d3ae004f4..43628259ba32a 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -150,7 +150,8 @@ impl RawVec { impl RawVec { /// Like `new`, but parameterized over the choice of allocator for /// the returned `RawVec`. - #[allow_internal_unstable(const_fn)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))] pub const fn new_in(alloc: A) -> Self { // `cap: 0` means "unallocated". zero-sized types are ignored. Self { ptr: Unique::dangling(), cap: 0, alloc } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index af4b7199397b3..6cb240d1730ed 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -63,6 +63,7 @@ #![warn(missing_debug_implementations)] #![allow(explicit_outlives_requirements)] #![allow(incomplete_features)] +#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))] #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] #![feature(asm)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 33fa26675f610..295a876773c48 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2045,7 +2045,8 @@ assert_eq!( #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute them to arrays of bytes - #[allow_internal_unstable(const_fn_transmute)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { // SAFETY: integers are plain old datatypes so we can always transmute them to @@ -2193,7 +2194,8 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute to them - #[allow_internal_unstable(const_fn_transmute)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { // SAFETY: integers are plain old datatypes so we can always transmute to them diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0de1cc6b1654a..bdea0ea3b08c0 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1803,7 +1803,8 @@ assert_eq!( #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute them to arrays of bytes - #[allow_internal_unstable(const_fn_transmute)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { // SAFETY: integers are plain old datatypes so we can always transmute them to @@ -1951,7 +1952,8 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute to them - #[allow_internal_unstable(const_fn_transmute)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { // SAFETY: integers are plain old datatypes so we can always transmute to them diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d32e7d4355161..007c75dd07647 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -88,7 +88,8 @@ impl [T] { #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) - #[allow_internal_unstable(const_fn_union)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_union))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_union))] pub const fn len(&self) -> usize { // SAFETY: this is safe because `&[T]` and `FatPtr` have the same layout. // Only `std` can make this guarantee. diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index de2a93f735032..952d0598a7c5b 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -157,7 +157,8 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")] -#[allow_internal_unstable(const_fn_transmute)] +#[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))] +#[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))] pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8. // Also relies on `&str` and `&[u8]` having the same layout. diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 3e18a4e70627d..ee9c09fe186c7 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -219,7 +219,8 @@ impl str { #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")] #[inline(always)] #[allow(unused_attributes)] - #[allow_internal_unstable(const_fn_transmute)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))] pub const fn as_bytes(&self) -> &[u8] { // SAFETY: const sound because we transmute two types with the same layout unsafe { mem::transmute(self) } diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 8cca9dc904293..d3c0d9b784139 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -130,7 +130,8 @@ impl RawWakerVTable { #[rustc_promotable] #[stable(feature = "futures_api", since = "1.36.0")] #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] - #[allow_internal_unstable(const_fn_fn_ptr_basics)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_fn_ptr_basics))] pub const fn new( clone: unsafe fn(*const ()) -> RawWaker, wake: unsafe fn(*const ()), diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index ba3d4c075e11f..dfe5df965cfac 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -401,7 +401,8 @@ fn run_client DecodeMut<'a, 's, ()>, R: Encode<()>>( } impl Client crate::TokenStream> { - #[allow_internal_unstable(const_fn)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))] pub const fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self { extern "C" fn run( bridge: Bridge<'_>, @@ -414,7 +415,8 @@ impl Client crate::TokenStream> { } impl Client crate::TokenStream> { - #[allow_internal_unstable(const_fn)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))] pub const fn expand2( f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream, ) -> Self { @@ -459,7 +461,8 @@ impl ProcMacro { } } - #[allow_internal_unstable(const_fn)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))] pub const fn custom_derive( trait_name: &'static str, attributes: &'static [&'static str], @@ -468,7 +471,8 @@ impl ProcMacro { ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) } } - #[allow_internal_unstable(const_fn)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))] pub const fn attr( name: &'static str, expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream, @@ -476,7 +480,8 @@ impl ProcMacro { ProcMacro::Attr { name, client: Client::expand2(expand) } } - #[allow_internal_unstable(const_fn)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))] pub const fn bang( name: &'static str, expand: fn(crate::TokenStream) -> crate::TokenStream, diff --git a/library/proc_macro/src/bridge/scoped_cell.rs b/library/proc_macro/src/bridge/scoped_cell.rs index daa577f74bac3..e7c32b10384d4 100644 --- a/library/proc_macro/src/bridge/scoped_cell.rs +++ b/library/proc_macro/src/bridge/scoped_cell.rs @@ -35,7 +35,8 @@ impl<'a, 'b, T: LambdaL> DerefMut for RefMutL<'a, 'b, T> { pub struct ScopedCell(Cell<>::Out>); impl ScopedCell { - #[allow_internal_unstable(const_fn)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))] pub const fn new(value: >::Out) -> Self { ScopedCell(Cell::new(value)) } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 139b3591206e7..5a4b69cf6fc1b 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -18,6 +18,7 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] +#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))] #![feature(nll)] #![feature(staged_api)] #![feature(const_fn)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 30e7a7f3c3b10..7aac411b63307 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -206,6 +206,7 @@ #![needs_panic_runtime] // std may use features in a platform-specific way #![allow(unused_features)] +#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))] #![cfg_attr(test, feature(print_internals, set_stdio, update_panic_count))] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 8089d7a8ba6f1..bb3ece4c2739f 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1043,7 +1043,8 @@ impl Ipv6Addr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")] - #[allow_internal_unstable(const_fn_transmute)] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))] + #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))] pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { let addr16 = [ a.to_be(), diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs index dc10db177ed69..53ade85bfd2e7 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, staged_api, allow_internal_unstable)] +#![feature(rustc_attrs, staged_api, rustc_allow_const_fn_unstable)] #![feature(const_fn_fn_ptr_basics)] #[stable(feature = "rust1", since = "1.0.0")] @@ -8,7 +8,7 @@ const fn error(_: fn()) {} #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(since="1.0.0", feature = "mep")] -#[allow_internal_unstable(const_fn_fn_ptr_basics)] +#[rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics)] const fn compiles(_: fn()) {} fn main() {} diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr index a08d57b6043d7..6f89225719f84 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr @@ -8,9 +8,9 @@ help: if it is not part of the public API, make this function unstably const | LL | #[rustc_const_unstable(feature = "...", issue = "...")] | -help: otherwise `#[allow_internal_unstable]` can be used to bypass stability checks +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks | -LL | #[allow_internal_unstable(const_fn_fn_ptr_basics)] +LL | #[rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics)] | error: aborting due to previous error diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs index b4e836bbc9540..430e911aacdee 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(allow_internal_unstable)] +#![feature(rustc_allow_const_fn_unstable)] #![feature(const_fn_fn_ptr_basics)] #![feature(rustc_attrs, staged_api)] @@ -7,7 +7,7 @@ #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(since="1.0.0", feature = "mep")] -#[allow_internal_unstable(const_fn_fn_ptr_basics)] +#[rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics)] const fn takes_fn_ptr(_: fn()) {} const FN: fn() = || (); diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index de6a9a19269b1..d3017c5602a8c 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -24,9 +24,9 @@ help: if it is not part of the public API, make this function unstably const | LL | #[rustc_const_unstable(feature = "...", issue = "...")] | -help: otherwise `#[allow_internal_unstable]` can be used to bypass stability checks +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks | -LL | #[allow_internal_unstable(const_fn_floating_point_arithmetic)] +LL | #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] | error: `foo2_gated` is not yet stable as a const fn diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr index f258deb12a9d9..53a59467e3d20 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -24,9 +24,9 @@ help: if it is not part of the public API, make this function unstably const | LL | #[rustc_const_unstable(feature = "...", issue = "...")] | -help: otherwise `#[allow_internal_unstable]` can be used to bypass stability checks +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks | -LL | #[allow_internal_unstable(const_fn_floating_point_arithmetic)] +LL | #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] | error: `foo2_gated` is not yet stable as a const fn From 7258740509877ff97c32c52cea7ac236ba80c51a Mon Sep 17 00:00:00 2001 From: Florian Warzecha Date: Wed, 21 Oct 2020 22:49:08 +0200 Subject: [PATCH 3/7] validate allow_internal_unstable target Adds a check to make sure `#[allow_internal_unstable]` can be applied only to macro definitions. --- compiler/rustc_passes/src/check_attr.rs | 29 +++++++++++++++++++ ...ure-gate-allow-internal-unstable-struct.rs | 1 + ...gate-allow-internal-unstable-struct.stderr | 11 ++++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1acaa4c6eff5d..95e6cc3b863c4 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -85,6 +85,8 @@ impl CheckAttrVisitor<'tcx> { self.check_export_name(&attr, span, target) } else if self.tcx.sess.check_name(attr, sym::rustc_args_required_const) { self.check_rustc_args_required_const(&attr, span, target, item) + } else if self.tcx.sess.check_name(attr, sym::allow_internal_unstable) { + self.check_allow_internal_unstable(&attr, span, target, &attrs) } else { // lint-only checks if self.tcx.sess.check_name(attr, sym::cold) { @@ -762,6 +764,33 @@ impl CheckAttrVisitor<'tcx> { } } } + + /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. + /// (Allows proc_macro functions) + fn check_allow_internal_unstable( + &self, + attr: &Attribute, + span: &Span, + target: Target, + attrs: &[Attribute], + ) -> bool { + debug!("Checking target: {:?}", target); + if target == Target::Fn { + for attr in attrs { + if self.tcx.sess.is_proc_macro_attr(attr) { + debug!("Is proc macro attr"); + return true; + } + } + debug!("Is not proc macro attr"); + } + self.tcx + .sess + .struct_span_err(attr.span, "attribute should be applied to a macro") + .span_label(*span, "not a macro") + .emit(); + false + } } impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs index ede969097d5ae..8b13f1bf2788e 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs @@ -2,6 +2,7 @@ // this needs a different test since this is done after expansion #[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps +//~| ERROR attribute should struct S; fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr index a1acfd553738f..df7773ba4fb65 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr @@ -6,6 +6,15 @@ LL | #[allow_internal_unstable()] | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable -error: aborting due to previous error +error: attribute should be applied to a macro + --> $DIR/feature-gate-allow-internal-unstable-struct.rs:4:1 + | +LL | #[allow_internal_unstable()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct S; + | --------- not a macro + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. From 3a63bf02998f7b5e040a4b87e049d03ddd144f74 Mon Sep 17 00:00:00 2001 From: Florian Warzecha Date: Thu, 22 Oct 2020 00:02:26 +0200 Subject: [PATCH 4/7] validate rustc_allow_const_fn_unstable targets Adds a check to make sure `#[rustc_allow_const_fn_unstable]` can be applied only to functions. --- compiler/rustc_passes/src/check_attr.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 95e6cc3b863c4..d6936ae942cdd 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -87,6 +87,8 @@ impl CheckAttrVisitor<'tcx> { self.check_rustc_args_required_const(&attr, span, target, item) } else if self.tcx.sess.check_name(attr, sym::allow_internal_unstable) { self.check_allow_internal_unstable(&attr, span, target, &attrs) + } else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) { + self.check_rustc_allow_const_fn_unstable(&attr, span, target) } else { // lint-only checks if self.tcx.sess.check_name(attr, sym::cold) { @@ -791,6 +793,26 @@ impl CheckAttrVisitor<'tcx> { .emit(); false } + + /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. + /// (Allows proc_macro functions) + fn check_rustc_allow_const_fn_unstable( + &self, + attr: &Attribute, + span: &Span, + target: Target, + ) -> bool { + if let Target::Fn | Target::Method(_) = target { + // FIXME Check that this isn't just a function, but a const fn + return true; + } + self.tcx + .sess + .struct_span_err(attr.span, "attribute should be applied to `const fn`") + .span_label(*span, "not a `const fn`") + .emit(); + false + } } impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { From 83fbdddc99f5fc4f76e144c6d86184dd09169287 Mon Sep 17 00:00:00 2001 From: Florian Warzecha Date: Fri, 23 Oct 2020 16:54:25 +0200 Subject: [PATCH 5/7] ignore #[rustc_allow_const_fn_unstable] for macro expansion Recognition for `rustc_allow_const_fn_unstable` attribute was errorneously added in 05f4a9a42abbbdb64d3ec4ed0ae6883c10c66e3f. --- compiler/rustc_expand/src/base.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e5bb213b51412..b0e43a260e91d 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -768,13 +768,8 @@ impl SyntaxExtension { name: Symbol, attrs: &[ast::Attribute], ) -> SyntaxExtension { - let allow_internal_unstable = { - let mut feat_list = Vec::new(); - attr::allow_internal_unstable(sess, &attrs).map(|features| feat_list.extend(features)); - attr::rustc_allow_const_fn_unstable(sess, &attrs) - .map(|features| feat_list.extend(features)); - Some(feat_list.into()) - }; + let allow_internal_unstable = attr::allow_internal_unstable(sess, &attrs) + .map(|features| features.collect::>().into()); let mut local_inner_macros = false; if let Some(macro_export) = sess.find_by_name(attrs, sym::macro_export) { From 13b481b247fe472ccf75b4fb13f3a46ac8f9ecaf Mon Sep 17 00:00:00 2001 From: Florian Warzecha Date: Fri, 23 Oct 2020 17:11:08 +0200 Subject: [PATCH 6/7] rename allow_internal_unstable() to rustc_allow_const_fn_unstable() in rustc_mir Followup rename from 05f4a9a42abbbdb64d3ec4ed0ae6883c10c66e3f, which introduced `#[rustc_allow_const_fn_unstable]` for `const fn`s. --- compiler/rustc_mir/src/transform/check_consts/mod.rs | 6 +++++- .../rustc_mir/src/transform/check_consts/validation.rs | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/mod.rs b/compiler/rustc_mir/src/transform/check_consts/mod.rs index 11e389cbe4464..1eb06c0ef65e2 100644 --- a/compiler/rustc_mir/src/transform/check_consts/mod.rs +++ b/compiler/rustc_mir/src/transform/check_consts/mod.rs @@ -77,7 +77,11 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { Some(def_id) == tcx.lang_items().panic_fn() || Some(def_id) == tcx.lang_items().begin_panic_fn() } -pub fn allow_internal_unstable(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool { +pub fn rustc_allow_const_fn_unstable( + tcx: TyCtxt<'tcx>, + def_id: DefId, + feature_gate: Symbol, +) -> bool { let attrs = tcx.get_attrs(def_id); attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs) .map_or(false, |mut features| features.any(|name| name == feature_gate)) diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index e23fb453c5ae0..30e1d0d8adc04 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -292,7 +292,11 @@ impl Validator<'mir, 'tcx> { Status::Unstable(gate) if self.tcx.features().enabled(gate) => { let unstable_in_stable = self.ccx.is_const_stable_const_fn() - && !super::allow_internal_unstable(self.tcx, self.def_id().to_def_id(), gate); + && !super::rustc_allow_const_fn_unstable( + self.tcx, + self.def_id().to_def_id(), + gate, + ); if unstable_in_stable { emit_unstable_in_stable_error(self.ccx, span, gate); } @@ -819,7 +823,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { // Otherwise, we are something const-stable calling a const-unstable fn. - if super::allow_internal_unstable(tcx, caller, gate) { + if super::rustc_allow_const_fn_unstable(tcx, caller, gate) { return; } From ac2c599f23d6c8b5d3413febde4c6febff68062e Mon Sep 17 00:00:00 2001 From: Florian Warzecha Date: Fri, 23 Oct 2020 17:54:48 +0200 Subject: [PATCH 7/7] fix validation for rustc_allow_const_fn_unstable targets The validation was introduced in 3a63bf02998f7b5e040a4b87e049d03ddd144f74 without strict validation of functions, e. g. all function types were allowed. Now the validation only allows `const fn`s. --- compiler/rustc_passes/src/check_attr.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d6936ae942cdd..920c69cb619b5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -88,7 +88,7 @@ impl CheckAttrVisitor<'tcx> { } else if self.tcx.sess.check_name(attr, sym::allow_internal_unstable) { self.check_allow_internal_unstable(&attr, span, target, &attrs) } else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) { - self.check_rustc_allow_const_fn_unstable(&attr, span, target) + self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) } else { // lint-only checks if self.tcx.sess.check_name(attr, sym::cold) { @@ -798,13 +798,15 @@ impl CheckAttrVisitor<'tcx> { /// (Allows proc_macro functions) fn check_rustc_allow_const_fn_unstable( &self, + hir_id: HirId, attr: &Attribute, span: &Span, target: Target, ) -> bool { if let Target::Fn | Target::Method(_) = target { - // FIXME Check that this isn't just a function, but a const fn - return true; + if self.tcx.is_const_fn_raw(self.tcx.hir().local_def_id(hir_id)) { + return true; + } } self.tcx .sess