Rollup merge of #73862 - oli-obk:const_array_to_slice, r=RalfJung

Stabilize casts and coercions to `&[T]` in const fn

Part of #64992

There was never a reason to not stabilize this, we just accidentally prevented them when we implemented the `min_const_fn` feature that gave us `const fn` on stable. This PR stabilizes these casts (which are already stable in `const` outside `const fn`), while keeping all other unsizing casts (so `T` -> `dyn Trait`) unstable within const fn.
These casts have no forward compatibility concerns with any future features for const eval and users were able to use them under the `const_fn` feature gate already since at least the miri merger, possibly longer.

r? @rust-lang/lang
This commit is contained in:
Manish Goregaokar 2020-07-10 23:26:26 -07:00 committed by GitHub
commit f4f969027c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 34 additions and 32 deletions

View File

@ -527,7 +527,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
size: Size::ZERO,
}),
// Potentially-fat pointers.
// Potentially-wide pointers.
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
let mut data_ptr = scalar_unit(Pointer);
if !ty.is_unsafe_ptr() {

View File

@ -191,8 +191,17 @@ fn check_rvalue(
_,
_,
) => Err((span, "function pointer casts are not allowed in const fn".into())),
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
Err((span, "unsizing casts are not allowed in const fn".into()))
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), op, cast_ty) => {
let pointee_ty = cast_ty.builtin_deref(true).unwrap().ty;
let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
if let ty::Slice(_) | ty::Str = unsized_ty.kind {
check_operand(tcx, op, span, def_id, body)?;
// Casting/coercing things to slices is fine.
Ok(())
} else {
// We just can't allow trait objects until we have figured out trait method calls.
Err((span, "unsizing casts are not allowed in const fn".into()))
}
}
// binops are fine on integers
Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {

View File

@ -0,0 +1,13 @@
// check-pass
fn main() {}
const fn foo() {
let x = [1, 2, 3, 4, 5];
let y: &[_] = &x;
struct Foo<T: ?Sized>(bool, T);
let x: Foo<[u8; 3]> = Foo(true, [1, 2, 3]);
let y: &Foo<[u8]> = &x;
}

View File

@ -1,7 +1,6 @@
#![feature(const_extern_fn)]
const extern fn unsize(x: &[u8; 3]) -> &[u8] { x }
//~^ ERROR unsizing casts are not allowed in const fn
const unsafe extern "C" fn closure() -> fn() { || {} }
//~^ ERROR function pointers in const fn are unstable
const unsafe extern fn use_float() { 1.0 + 1.0; }

View File

@ -1,14 +1,5 @@
error[E0723]: unsizing casts are not allowed in const fn
--> $DIR/const-extern-fn-min-const-fn.rs:3:48
|
LL | const extern fn unsize(x: &[u8; 3]) -> &[u8] { x }
| ^
|
= 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
error[E0723]: function pointers in const fn are unstable
--> $DIR/const-extern-fn-min-const-fn.rs:5:41
--> $DIR/const-extern-fn-min-const-fn.rs:4:41
|
LL | const unsafe extern "C" fn closure() -> fn() { || {} }
| ^^^^
@ -17,7 +8,7 @@ LL | const unsafe extern "C" fn closure() -> fn() { || {} }
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: only int, `bool` and `char` operations are stable in const fn
--> $DIR/const-extern-fn-min-const-fn.rs:7:38
--> $DIR/const-extern-fn-min-const-fn.rs:6:38
|
LL | const unsafe extern fn use_float() { 1.0 + 1.0; }
| ^^^^^^^^^
@ -26,7 +17,7 @@ LL | const unsafe extern fn use_float() { 1.0 + 1.0; }
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: casting pointers to ints is unstable in const fn
--> $DIR/const-extern-fn-min-const-fn.rs:9:48
--> $DIR/const-extern-fn-min-const-fn.rs:8:48
|
LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
| ^^^^^^^^^^^^
@ -34,6 +25,6 @@ LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
= 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
error: aborting due to 4 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0723`.

View File

@ -1,7 +1,6 @@
fn main() {}
const fn unsize(x: &[u8; 3]) -> &[u8] { x }
//~^ ERROR unsizing casts are not allowed in const fn
const fn closure() -> fn() { || {} }
//~^ ERROR function pointers in const fn are unstable
const fn closure2() {

View File

@ -1,14 +1,5 @@
error[E0723]: unsizing casts are not allowed in const fn
--> $DIR/cast_errors.rs:3:41
|
LL | const fn unsize(x: &[u8; 3]) -> &[u8] { x }
| ^
|
= 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
error[E0723]: function pointers in const fn are unstable
--> $DIR/cast_errors.rs:5:23
--> $DIR/cast_errors.rs:4:23
|
LL | const fn closure() -> fn() { || {} }
| ^^^^
@ -17,7 +8,7 @@ LL | const fn closure() -> fn() { || {} }
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: function pointers in const fn are unstable
--> $DIR/cast_errors.rs:8:5
--> $DIR/cast_errors.rs:7:5
|
LL | (|| {}) as fn();
| ^^^^^^^^^^^^^^^
@ -26,7 +17,7 @@ LL | (|| {}) as fn();
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: function pointers in const fn are unstable
--> $DIR/cast_errors.rs:11:28
--> $DIR/cast_errors.rs:10:28
|
LL | const fn reify(f: fn()) -> unsafe fn() { f }
| ^^^^^^^^^^^
@ -35,7 +26,7 @@ LL | const fn reify(f: fn()) -> unsafe fn() { f }
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: function pointers in const fn are unstable
--> $DIR/cast_errors.rs:13:21
--> $DIR/cast_errors.rs:12:21
|
LL | const fn reify2() { main as unsafe fn(); }
| ^^^^^^^^^^^^^^^^^^^
@ -43,6 +34,6 @@ LL | const fn reify2() { main as unsafe 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
error: aborting due to 5 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0723`.