From 7e682d3f6f5761471e05fefc21e5de6ce4a52444 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 29 Jun 2020 17:01:44 +0200 Subject: [PATCH] Stabilize casts and coercions to `&[T]` in const fn --- src/librustc_middle/ty/layout.rs | 2 +- .../transform/qualify_min_const_fn.rs | 13 +++++++++++-- src/test/ui/consts/array-to-slice-cast.rs | 13 +++++++++++++ .../const-extern-fn-min-const-fn.rs | 1 - .../const-extern-fn-min-const-fn.stderr | 17 ++++------------- .../ui/consts/min_const_fn/cast_errors.rs | 1 - .../ui/consts/min_const_fn/cast_errors.stderr | 19 +++++-------------- 7 files changed, 34 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/consts/array-to-slice-cast.rs diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index e4cc96dd83b..f6788e317ae 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -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() { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 5a3663384fb..28d9a3ad63c 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -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) => { diff --git a/src/test/ui/consts/array-to-slice-cast.rs b/src/test/ui/consts/array-to-slice-cast.rs new file mode 100644 index 00000000000..796f9d1b71f --- /dev/null +++ b/src/test/ui/consts/array-to-slice-cast.rs @@ -0,0 +1,13 @@ +// check-pass + +fn main() {} + +const fn foo() { + let x = [1, 2, 3, 4, 5]; + let y: &[_] = &x; + + struct Foo(bool, T); + + let x: Foo<[u8; 3]> = Foo(true, [1, 2, 3]); + let y: &Foo<[u8]> = &x; +} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs index 56198117688..2854c086657 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs @@ -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; } diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr index f520bd35847..146d119fc8f 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -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 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 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`. diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs index 8648cd35387..8d730df16b0 100644 --- a/src/test/ui/consts/min_const_fn/cast_errors.rs +++ b/src/test/ui/consts/min_const_fn/cast_errors.rs @@ -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() { diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr index a6a05b522a5..583cb4e9720 100644 --- a/src/test/ui/consts/min_const_fn/cast_errors.stderr +++ b/src/test/ui/consts/min_const_fn/cast_errors.stderr @@ -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 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 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`.