Skip to content

Commit 62c3d99

Browse files
authored
Rollup merge of rust-lang#72920 - oli-obk:const_transmute, r=RalfJung
Stabilize `transmute` in constants and statics but not const fn cc rust-lang#53605 (leaving issue open so we can add `transmute` to `const fn` later) Previous attempt: rust-lang#64011 r? @RalfJung cc @rust-lang/wg-const-eval
2 parents 346aec9 + dd872be commit 62c3d99

39 files changed

+238
-106
lines changed

src/libcore/intrinsics.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1285,7 +1285,9 @@ extern "rust-intrinsic" {
12851285
/// }
12861286
/// ```
12871287
#[stable(feature = "rust1", since = "1.0.0")]
1288-
#[rustc_const_unstable(feature = "const_transmute", issue = "53605")]
1288+
// NOTE: While this makes the intrinsic const stable, we have some custom code in const fn
1289+
// checks that prevent its use within `const fn`.
1290+
#[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
12891291
pub fn transmute<T, U>(e: T) -> U;
12901292

12911293
/// Returns `true` if the actual type given as `T` requires drop

src/libcore/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@
140140
#![feature(rtm_target_feature)]
141141
#![feature(f16c_target_feature)]
142142
#![feature(hexagon_target_feature)]
143-
#![feature(const_transmute)]
143+
#![cfg_attr(not(bootstrap), feature(const_fn_transmute))]
144144
#![feature(abi_unadjusted)]
145145
#![feature(adx_target_feature)]
146146
#![feature(maybe_uninit_slice)]

src/librustc_ast/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#![cfg_attr(bootstrap, feature(const_if_match))]
1111
#![feature(const_fn)] // For the `transmute` in `P::new`
1212
#![feature(const_panic)]
13-
#![feature(const_transmute)]
13+
#![cfg_attr(not(bootstrap), feature(const_fn_transmute))]
1414
#![feature(crate_visibility_modifier)]
1515
#![feature(label_break_value)]
1616
#![feature(nll)]

src/librustc_feature/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ declare_features! (
573573
/// Lazily evaluate constants. This allows constants to depend on type parameters.
574574
(active, lazy_normalization_consts, "1.46.0", Some(72219), None),
575575

576+
/// Alloc calling `transmute` in const fn
577+
(active, const_fn_transmute, "1.46.0", Some(53605), None),
578+
576579
// -------------------------------------------------------------------------
577580
// feature-group-end: actual feature gates
578581
// -------------------------------------------------------------------------

src/librustc_middle/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#![cfg_attr(bootstrap, feature(const_if_match))]
3131
#![feature(const_fn)]
3232
#![feature(const_panic)]
33-
#![feature(const_transmute)]
33+
#![cfg_attr(not(bootstrap), feature(const_fn_transmute))]
3434
#![feature(core_intrinsics)]
3535
#![feature(discriminant_kind)]
3636
#![feature(drain_filter)]

src/librustc_mir/transform/qualify_min_const_fn.rs

+15
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_middle::ty::subst::GenericArgKind;
66
use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
77
use rustc_span::symbol::{sym, Symbol};
88
use rustc_span::Span;
9+
use rustc_target::spec::abi::Abi::RustIntrinsic;
910
use std::borrow::Cow;
1011

1112
type McfResult = Result<(), (Span, Cow<'static, str>)>;
@@ -418,6 +419,20 @@ fn check_terminator(
418419
));
419420
}
420421

422+
// HACK: This is to "unstabilize" the `transmute` intrinsic
423+
// within const fns. `transmute` is allowed in all other const contexts.
424+
// This won't really scale to more intrinsics or functions. Let's allow const
425+
// transmutes in const fn before we add more hacks to this.
426+
if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic
427+
&& tcx.item_name(fn_def_id) == sym::transmute
428+
&& !feature_allowed(tcx, def_id, sym::const_fn_transmute)
429+
{
430+
return Err((
431+
span,
432+
"can only call `transmute` from const items, not `const fn`".into(),
433+
));
434+
}
435+
421436
check_operand(tcx, func, span, fn_def_id, body)?;
422437

423438
for arg in args {

src/librustc_span/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,7 @@ symbols! {
848848
track_caller,
849849
trait_alias,
850850
transmute,
851+
const_fn_transmute,
851852
transparent,
852853
transparent_enums,
853854
transparent_unions,

src/test/ui/consts/const-eval/dangling.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(const_transmute, const_raw_ptr_deref)]
1+
#![feature(const_raw_ptr_deref)]
22

33
use std::{mem, usize};
44

src/test/ui/consts/const-eval/double_check.rs

+2
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ static FOO: (&Foo, &Bar) = unsafe {(
2020
Union { u8: &BAR }.bar,
2121
)};
2222

23+
static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))};
24+
2325
fn main() {}

src/test/ui/consts/const-eval/double_check2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ static FOO: (&Foo, &Bar) = unsafe {( //~ undefined behavior
1717
Union { u8: &BAR }.foo,
1818
Union { u8: &BAR }.bar,
1919
)};
20+
static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))};
21+
//~^ undefined behavior
2022

2123
fn main() {}

src/test/ui/consts/const-eval/double_check2.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ LL | | )};
99
|
1010
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
1111

12-
error: aborting due to previous error
12+
error[E0080]: it is undefined behavior to use this value
13+
--> $DIR/double_check2.rs:20:1
14+
|
15+
LL | static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))};
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x05 at .1.<deref>.<enum-tag>, but expected a valid enum tag
17+
|
18+
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
19+
20+
error: aborting due to 2 previous errors
1321

1422
For more information about this error, try `rustc --explain E0080`.

src/test/ui/consts/const-eval/issue-55541.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
// Test that we can handle newtypes wrapping extern types
44

5-
#![feature(extern_types, const_transmute)]
5+
#![feature(extern_types)]
66

77
use std::marker::PhantomData;
88

src/test/ui/consts/const-eval/transmute-const.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![feature(const_transmute)]
2-
31
use std::mem;
42

53
static FOO: bool = unsafe { mem::transmute(3u8) };

src/test/ui/consts/const-eval/transmute-const.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/transmute-const.rs:5:1
2+
--> $DIR/transmute-const.rs:3:1
33
|
44
LL | static FOO: bool = unsafe { mem::transmute(3u8) };
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03, but expected a boolean

src/test/ui/consts/const-eval/ub-enum.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// normalize-stderr-64bit "0x0000000000" -> "0x00"
2-
#![feature(const_transmute, never_type)]
2+
#![feature(never_type)]
33
#![allow(const_err)] // make sure we cannot allow away the errors tested here
44

55
use std::mem;

src/test/ui/consts/const-eval/ub-int-array.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![feature(const_transmute)]
21
#![allow(const_err)] // make sure we cannot allow away the errors tested here
32

43
//! Test the "array of int" fast path in validity checking, and in particular whether it

src/test/ui/consts/const-eval/ub-int-array.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/ub-int-array.rs:15:1
2+
--> $DIR/ub-int-array.rs:14:1
33
|
44
LL | / const UNINIT_INT_0: [u32; 3] = unsafe {
55
LL | |
@@ -13,7 +13,7 @@ LL | | };
1313
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
1414

1515
error[E0080]: it is undefined behavior to use this value
16-
--> $DIR/ub-int-array.rs:24:1
16+
--> $DIR/ub-int-array.rs:23:1
1717
|
1818
LL | / const UNINIT_INT_1: [u32; 3] = unsafe {
1919
LL | |
@@ -27,7 +27,7 @@ LL | | };
2727
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
2828

2929
error[E0080]: it is undefined behavior to use this value
30-
--> $DIR/ub-int-array.rs:44:1
30+
--> $DIR/ub-int-array.rs:43:1
3131
|
3232
LL | / const UNINIT_INT_2: [u32; 3] = unsafe {
3333
LL | |

src/test/ui/consts/const-eval/ub-nonnull.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(rustc_attrs, const_transmute)]
1+
#![feature(rustc_attrs)]
22
#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here
33

44
use std::mem;

src/test/ui/consts/const-eval/ub-ref.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// ignore-tidy-linelength
2-
#![feature(const_transmute)]
32
#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here
43

54
use std::mem;

src/test/ui/consts/const-eval/ub-ref.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,69 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/ub-ref.rs:7:1
2+
--> $DIR/ub-ref.rs:6:1
33
|
44
LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
88

99
error[E0080]: it is undefined behavior to use this value
10-
--> $DIR/ub-ref.rs:11:1
10+
--> $DIR/ub-ref.rs:10:1
1111
|
1212
LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1)
1414
|
1515
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
1616

1717
error[E0080]: it is undefined behavior to use this value
18-
--> $DIR/ub-ref.rs:15:1
18+
--> $DIR/ub-ref.rs:14:1
1919
|
2020
LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
2121
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference
2222
|
2323
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
2424

2525
error[E0080]: it is undefined behavior to use this value
26-
--> $DIR/ub-ref.rs:18:1
26+
--> $DIR/ub-ref.rs:17:1
2727
|
2828
LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
2929
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL box
3030
|
3131
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
3232

3333
error[E0080]: it is undefined behavior to use this value
34-
--> $DIR/ub-ref.rs:24:1
34+
--> $DIR/ub-ref.rs:23:1
3535
|
3636
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
3737
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc16, but expected initialized plain (non-pointer) bytes
3838
|
3939
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
4040

4141
error[E0080]: it is undefined behavior to use this value
42-
--> $DIR/ub-ref.rs:27:1
42+
--> $DIR/ub-ref.rs:26:1
4343
|
4444
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
4545
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
4646
|
4747
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
4848

4949
error[E0080]: it is undefined behavior to use this value
50-
--> $DIR/ub-ref.rs:30:1
50+
--> $DIR/ub-ref.rs:29:1
5151
|
5252
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
5353
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
5454
|
5555
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
5656

5757
error[E0080]: it is undefined behavior to use this value
58-
--> $DIR/ub-ref.rs:33:1
58+
--> $DIR/ub-ref.rs:32:1
5959
|
6060
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
6161
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer)
6262
|
6363
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
6464

6565
error[E0080]: it is undefined behavior to use this value
66-
--> $DIR/ub-ref.rs:36:1
66+
--> $DIR/ub-ref.rs:35:1
6767
|
6868
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
6969
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer)

src/test/ui/consts/const-eval/ub-uninhabit.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![feature(const_transmute)]
21
#![allow(const_err)] // make sure we cannot allow away the errors tested here
32

43
use std::mem;

src/test/ui/consts/const-eval/ub-uninhabit.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/ub-uninhabit.rs:15:1
2+
--> $DIR/ub-uninhabit.rs:14:1
33
|
44
LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
88

99
error[E0080]: it is undefined behavior to use this value
10-
--> $DIR/ub-uninhabit.rs:18:1
10+
--> $DIR/ub-uninhabit.rs:17:1
1111
|
1212
LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at .<deref>
1414
|
1515
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
1616

1717
error[E0080]: it is undefined behavior to use this value
18-
--> $DIR/ub-uninhabit.rs:21:1
18+
--> $DIR/ub-uninhabit.rs:20:1
1919
|
2020
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
2121
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0]

src/test/ui/consts/const-eval/ub-upvars.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![feature(const_transmute)]
21
#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here
32

43
use std::mem;

src/test/ui/consts/const-eval/ub-upvars.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/ub-upvars.rs:6:1
2+
--> $DIR/ub-upvars.rs:5:1
33
|
44
LL | / const BAD_UPVAR: &dyn FnOnce() = &{
55
LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) };

src/test/ui/consts/const-eval/ub-wide-ptr.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// ignore-tidy-linelength
2-
#![feature(const_transmute)]
32
#![allow(unused)]
43
#![allow(const_err)] // make sure we cannot allow away the errors tested here
54

0 commit comments

Comments
 (0)