Skip to content

Commit

Permalink
Rollup merge of #77170 - ecstatic-morse:const-fn-ptr, r=oli-obk
Browse files Browse the repository at this point in the history
Remove `#[rustc_allow_const_fn_ptr]` and add `#![feature(const_fn_fn_ptr_basics)]`

`rustc_allow_const_fn_ptr` was a hack to work around the lack of an escape hatch for the "min `const fn`" checks in const-stable functions. Now that we have co-opted `allow_internal_unstable` for this purpose, we no longer need a bespoke attribute.

Now this functionality is gated under `const_fn_fn_ptr_basics` (how concise!), and `#[allow_internal_unstable(const_fn_fn_ptr_basics)]` replaces `#[rustc_allow_const_fn_ptr]`. `const_fn_fn_ptr_basics` allows function pointer types to appear in the arguments and locals of a `const fn` as well as function pointer casts to be performed inside a `const fn`. Both of these were allowed in constants and statics already. Notably, this does **not** allow users to invoke function pointers in a const context. Presumably, we will use a nicer name for that (`const_fn_ptr`?).

r? @oli-obk
  • Loading branch information
RalfJung authored Sep 28, 2020
2 parents 88ae20d + 807260b commit 85a59d4
Show file tree
Hide file tree
Showing 39 changed files with 146 additions and 135 deletions.
31 changes: 7 additions & 24 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,6 @@ pub struct ConstStability {
pub feature: Symbol,
/// whether the function has a `#[rustc_promotable]` attribute
pub promotable: bool,
/// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute
pub allow_const_fn_ptr: bool,
}

/// The available stability levels.
Expand Down Expand Up @@ -190,7 +188,6 @@ where
let mut stab: Option<Stability> = None;
let mut const_stab: Option<ConstStability> = None;
let mut promotable = false;
let mut allow_const_fn_ptr = false;
let diagnostic = &sess.parse_sess.span_diagnostic;

'outer: for attr in attrs_iter {
Expand All @@ -200,7 +197,6 @@ where
sym::unstable,
sym::stable,
sym::rustc_promotable,
sym::rustc_allow_const_fn_ptr,
]
.iter()
.any(|&s| attr.has_name(s))
Expand All @@ -215,9 +211,6 @@ where
if attr.has_name(sym::rustc_promotable) {
promotable = true;
}
if attr.has_name(sym::rustc_allow_const_fn_ptr) {
allow_const_fn_ptr = true;
}
// attributes with data
else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta {
let meta = meta.as_ref().unwrap();
Expand Down Expand Up @@ -360,12 +353,8 @@ where
if sym::unstable == meta_name {
stab = Some(Stability { level, feature });
} else {
const_stab = Some(ConstStability {
level,
feature,
promotable: false,
allow_const_fn_ptr: false,
});
const_stab =
Some(ConstStability { level, feature, promotable: false });
}
}
(None, _, _) => {
Expand Down Expand Up @@ -440,12 +429,8 @@ where
if sym::stable == meta_name {
stab = Some(Stability { level, feature });
} else {
const_stab = Some(ConstStability {
level,
feature,
promotable: false,
allow_const_fn_ptr: false,
});
const_stab =
Some(ConstStability { level, feature, promotable: false });
}
}
(None, _) => {
Expand All @@ -464,18 +449,16 @@ where
}

// Merge the const-unstable info into the stability info
if promotable || allow_const_fn_ptr {
if promotable {
if let Some(ref mut stab) = const_stab {
stab.promotable = promotable;
stab.allow_const_fn_ptr = allow_const_fn_ptr;
} else {
struct_span_err!(
diagnostic,
item_sp,
E0717,
"rustc_promotable and rustc_allow_const_fn_ptr attributes \
must be paired with either a rustc_const_unstable or a rustc_const_stable \
attribute"
"`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` \
or a `rustc_const_stable` attribute"
)
.emit();
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,9 @@ declare_features! (
/// Allows basic arithmetic on floating point types in a `const fn`.
(active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),

/// Allows using and casting function pointers in a `const fn`.
(active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None),

// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// ==========================================================================

rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL),
rustc_attr!(rustc_allow_const_fn_ptr, AssumedUsed, template!(Word), IMPL_DETAIL),
rustc_attr!(rustc_args_required_const, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE),

// ==========================================================================
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,10 +457,6 @@ rustc_queries! {
desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) }
}

query const_fn_is_allowed_fn_ptr(key: DefId) -> bool {
desc { |tcx| "checking if const fn allows `fn()` types: `{}`", tcx.def_path_str(key) }
}

/// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
query is_foreign_item(key: DefId) -> bool {
desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) }
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_mir/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,11 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
}
}

fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
is_const_fn(tcx, def_id)
&& tcx.lookup_const_stability(def_id).map(|stab| stab.allow_const_fn_ptr).unwrap_or(false)
}

pub fn provide(providers: &mut Providers) {
*providers = Providers {
is_const_fn_raw,
is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()),
is_promotable_const_fn,
const_fn_is_allowed_fn_ptr,
..*providers
};
}
28 changes: 21 additions & 7 deletions compiler/rustc_mir/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,21 @@ impl NonConstOp for FnPtrCast {
const STOPS_CONST_CHECKING: bool = true;

fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
mcf_status_in_item(ccx)
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
Status::Unstable(sym::const_fn_fn_ptr_basics)
}
}

fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "function pointer casts are not allowed in const fn");
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_fn_ptr_basics,
span,
&format!("function pointer casts are not allowed in {}s", ccx.const_kind()),
)
.emit()
}
}

Expand Down Expand Up @@ -596,17 +606,21 @@ pub mod ty {
const STOPS_CONST_CHECKING: bool = true;

fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
// FIXME: This attribute a hack to allow the specialization of the `futures` API. See
// #59739. We should have a proper feature gate for this.
if ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_allow_const_fn_ptr) {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
mcf_status_in_item(ccx)
Status::Unstable(sym::const_fn_fn_ptr_basics)
}
}

fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "function pointers in const fn are unstable");
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_fn_ptr_basics,
span,
&format!("function pointers cannot appear in {}s", ccx.const_kind()),
)
.emit()
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ symbols! {
const_extern_fn,
const_fn,
const_fn_floating_point_arithmetic,
const_fn_fn_ptr_basics,
const_fn_transmute,
const_fn_union,
const_generics,
Expand Down Expand Up @@ -884,7 +885,6 @@ symbols! {
rustc,
rustc_allocator,
rustc_allocator_nounwind,
rustc_allow_const_fn_ptr,
rustc_args_required_const,
rustc_attrs,
rustc_builtin_macro,
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
#![feature(const_fn_union)]
#![feature(const_fn)]
#![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))]
#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))]
#![feature(const_generics)]
#![feature(const_option)]
#![feature(const_precise_live_drops)]
Expand Down
8 changes: 2 additions & 6 deletions library/core/src/task/wake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,9 @@ impl RawWakerVTable {
/// associated task.
#[rustc_promotable]
#[stable(feature = "futures_api", since = "1.36.0")]
// `rustc_allow_const_fn_ptr` is a hack that should not be used anywhere else
// without first consulting with T-Lang.
//
// FIXME: remove whenever we have a stable way to accept fn pointers from const fn
// (see https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062)
#[rustc_allow_const_fn_ptr]
#[rustc_const_stable(feature = "futures_api", since = "1.36.0")]
#[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_fn_ptr_basics))]
#[cfg_attr(bootstrap, rustc_allow_const_fn_ptr)]
pub const fn new(
clone: unsafe fn(*const ()) -> RawWaker,
wake: unsafe fn(*const ()),
Expand Down
1 change: 1 addition & 0 deletions library/proc_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#![feature(nll)]
#![feature(staged_api)]
#![feature(const_fn)]
#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))]
#![feature(allow_internal_unstable)]
#![feature(decl_macro)]
#![feature(extern_types)]
Expand Down
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
#![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))]
#![feature(const_fn_transmute)]
#![feature(const_fn)]
#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))]
#![feature(const_ip)]
#![feature(const_ipv6)]
#![feature(const_raw_ptr_deref)]
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/consts/auxiliary/const_fn_lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Crate that exports a const fn. Used for testing cross-crate.

#![feature(const_fn)]
#![feature(const_fn_fn_ptr_basics)]
#![crate_type="rlib"]

pub const fn foo() -> usize { 22 }
Expand Down
14 changes: 13 additions & 1 deletion src/test/ui/consts/const-eval/const_fn_ptr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,23 @@ help: skipping check that does not even have a feature gate
|
LL | X_CONST(x)
| ^^^^^^^^^^
help: skipping check for `const_fn_fn_ptr_basics` feature
--> $DIR/const_fn_ptr.rs:19:14
|
LL | const fn foo(x: fn(usize) -> usize, y: usize) -> usize {
| ^
help: skipping check for `const_fn_fn_ptr_basics` feature
--> $DIR/const_fn_ptr.rs:20:5
|
LL | x(y)
| ^
help: skipping check that does not even have a feature gate
--> $DIR/const_fn_ptr.rs:20:5
|
LL | x(y)
| ^^^^

warning: 1 warning emitted
error: `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine

error: aborting due to previous error; 1 warning emitted

10 changes: 10 additions & 0 deletions src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ LL | assert_eq!(Z, 4);

warning: skipping const checks
|
help: skipping check for `const_fn_fn_ptr_basics` feature
--> $DIR/const_fn_ptr_fail2.rs:12:14
|
LL | const fn bar(x: fn(usize) -> usize, y: usize) -> usize {
| ^
help: skipping check for `const_fn_fn_ptr_basics` feature
--> $DIR/const_fn_ptr_fail2.rs:13:5
|
LL | x(y)
| ^
help: skipping check that does not even have a feature gate
--> $DIR/const_fn_ptr_fail2.rs:13:5
|
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// check-pass
#![feature(const_fn)]
#![feature(const_fn_fn_ptr_basics)]

const fn nested(x: (for<'a> fn(&'a ()), String)) -> (fn(&'static ()), String) {
x
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const extern fn unsize(x: &[u8; 3]) -> &[u8] { x }
const unsafe extern "C" fn closure() -> fn() { || {} }
//~^ ERROR function pointers in const fn are unstable
//~^ ERROR function pointer
const unsafe extern fn use_float() { 1.0 + 1.0; }
//~^ ERROR floating point arithmetic
const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0723]: function pointers in const fn are unstable
error[E0658]: function pointers cannot appear in constant functions
--> $DIR/const-extern-fn-min-const-fn.rs:4:41
|
LL | const unsafe extern "C" fn closure() -> fn() { || {} }
| ^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable

error[E0658]: floating point arithmetic is not allowed in constant functions
--> $DIR/const-extern-fn-min-const-fn.rs:6:38
Expand All @@ -27,5 +27,4 @@ LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0658, E0723.
For more information about an error, try `rustc --explain E0658`.
For more information about this error, try `rustc --explain E0658`.
2 changes: 1 addition & 1 deletion src/test/ui/consts/issue-37550.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![allow(dead_code)]
#![allow(unused_variables)]

#![feature(const_fn)]
#![feature(const_fn_fn_ptr_basics)]

const fn x() {
let t = true;
Expand Down
7 changes: 3 additions & 4 deletions src/test/ui/consts/issue-56164.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#![feature(const_fn)]
#![feature(const_fn_fn_ptr_basics)]

const fn foo() { (||{})() }
//~^ ERROR calls in constant functions are limited to constant functions, tuple structs and tuple
// variants
//~^ ERROR calls in constant functions

const fn bad(input: fn()) {
input()
//~^ ERROR function pointers are not allowed in const fn
//~^ ERROR function pointer
}

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/consts/issue-56164.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | const fn foo() { (||{})() }
| ^^^^^^^^

error: function pointers are not allowed in const fn
--> $DIR/issue-56164.rs:8:5
--> $DIR/issue-56164.rs:7:5
|
LL | input()
| ^^^^^^^
Expand Down
8 changes: 5 additions & 3 deletions src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#![feature(rustc_attrs, staged_api)]
#![feature(rustc_attrs, staged_api, allow_internal_unstable)]
#![feature(const_fn_fn_ptr_basics)]

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(since="1.0.0", feature = "mep")]
const fn error(_: fn()) {} //~ ERROR function pointers in const fn are unstable
const fn error(_: fn()) {}
//~^ ERROR const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]`

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_allow_const_fn_ptr]
#[rustc_const_stable(since="1.0.0", feature = "mep")]
#[allow_internal_unstable(const_fn_fn_ptr_basics)]
const fn compiles(_: fn()) {}

fn main() {}
12 changes: 7 additions & 5 deletions src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
error[E0723]: function pointers in const fn are unstable
--> $DIR/allow_const_fn_ptr.rs:5:16
error: const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]`
--> $DIR/allow_const_fn_ptr.rs:6:16
|
LL | const fn error(_: fn()) {}
| ^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: otherwise `#[allow_internal_unstable]` can be used to bypass stability checks
help: if it is not part of the public API, make this function unstably const
|
LL | #[rustc_const_unstable(feature = "...", issue = "...")]
|

error: aborting due to previous error

For more information about this error, try `rustc --explain E0723`.
Loading

0 comments on commit 85a59d4

Please sign in to comment.