Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize transmute in constants and statics but not const fn #64011

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1321,14 +1321,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
// special intrinsic that can be called diretly without an intrinsic
// feature gate needs a language feature gate
"transmute" => {
if self.mode.requires_const_checking() {
// const eval transmute calls only with the feature gate
if let Mode::ConstFn = self.mode {
// permit transmute calls in const fns only with the feature
// gate. Anywhere else they are fine
if !self.tcx.features().const_transmute {
emit_feature_err(
&self.tcx.sess.parse_sess, sym::const_transmute,
self.span, GateIssue::Language,
&format!("The use of std::mem::transmute() \
is gated in {}s", self.mode));
is gated in const fns"));
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/consts/const-eval/double_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ static FOO: (&Foo, &Bar) = unsafe {(
Union { u8: &BAR }.bar,
)};

static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))};

fn main() {}
2 changes: 2 additions & 0 deletions src/test/ui/consts/const-eval/double_check2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ static FOO: (&Foo, &Bar) = unsafe {( //~ undefined behavior
Union { u8: &BAR }.foo,
Union { u8: &BAR }.bar,
)};
static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))};
//~^ undefined behavior

fn main() {}
10 changes: 9 additions & 1 deletion src/test/ui/consts/const-eval/double_check2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ LL | | )};
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

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

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0080`.
21 changes: 21 additions & 0 deletions src/test/ui/consts/const-eval/ub-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,26 @@ union TransmuteEnum {
}

const GOOD_ENUM: Enum = unsafe { TransmuteEnum { in2: 0 }.out1 };
const GOOD_ENUM_TRANSMUTE: Enum = unsafe { std::mem::transmute(0usize) };

const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
//~^ ERROR is undefined behavior

const BAD_ENUM_TRANSMUTE: Enum = unsafe { std::mem::transmute(1usize) };
//~^ ERROR is undefined behavior

const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
//~^ ERROR is undefined behavior

const BAD_ENUM_PTR_TRANSMUTE: Enum = unsafe { std::mem::transmute(&1) };
//~^ ERROR is undefined behavior

const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
//~^ ERROR is undefined behavior

const BAD_ENUM_WRAPPED_TRANSMUTE: Wrap<Enum> = unsafe { std::mem::transmute(&1) };
//~^ ERROR is undefined behavior

// (Potentially) invalid enum discriminant
#[repr(usize)]
#[derive(Copy, Clone)]
Expand All @@ -45,10 +55,16 @@ union TransmuteEnum2 {
}
const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
//~^ ERROR is undefined behavior
const BAD_ENUM2_TRANSMUTE: Enum2 = unsafe { std::mem::transmute(0usize) };
//~^ ERROR is undefined behavior
const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
//~^ ERROR is undefined behavior
const BAD_ENUM2_PTR_TRANSMUTE: Enum2 = unsafe { std::mem::transmute(&0) };
//~^ ERROR is undefined behavior
const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
//~^ ERROR is undefined behavior
const BAD_ENUM2_WRAPPED_TRANSMUTE: Wrap<Enum2> = unsafe { std::mem::transmute(&0) };
//~^ ERROR is undefined behavior

// Undef enum discriminant.
const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
Expand All @@ -57,6 +73,8 @@ const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
// Pointer value in an enum with a niche that is not just 0.
const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
//~^ ERROR is undefined behavior
const BAD_ENUM2_OPTION_PTR_TRANSMUTE: Option<Enum2> = unsafe { std::mem::transmute(&0) };
//~^ ERROR is undefined behavior

// Invalid enum field content (mostly to test printing of paths for enum tuple
// variants and tuples).
Expand All @@ -67,6 +85,9 @@ union TransmuteChar {
// Need to create something which does not clash with enum layout optimizations.
const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
//~^ ERROR is undefined behavior
const BAD_OPTION_CHAR_TRANSMUTE: Option<(char, char)> =
Some(('x', unsafe { std::mem::transmute(!0) }));
//~^^ ERROR is undefined behavior

fn main() {
}
85 changes: 75 additions & 10 deletions src/test/ui/consts/const-eval/ub-enum.stderr
Original file line number Diff line number Diff line change
@@ -1,75 +1,140 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:22:1
--> $DIR/ub-enum.rs:23:1
|
LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:25:1
--> $DIR/ub-enum.rs:26:1
|
LL | const BAD_ENUM_TRANSMUTE: Enum = unsafe { std::mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:29:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:28:1
--> $DIR/ub-enum.rs:32:1
|
LL | const BAD_ENUM_PTR_TRANSMUTE: Enum = unsafe { std::mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:35:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:46:1
--> $DIR/ub-enum.rs:38:1
|
LL | const BAD_ENUM_WRAPPED_TRANSMUTE: Wrap<Enum> = unsafe { std::mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:56:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:48:1
--> $DIR/ub-enum.rs:58:1
|
LL | const BAD_ENUM2_TRANSMUTE: Enum2 = unsafe { std::mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:60:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:50:1
--> $DIR/ub-enum.rs:62:1
|
LL | const BAD_ENUM2_PTR_TRANSMUTE: Enum2 = unsafe { std::mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:64:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:54:1
--> $DIR/ub-enum.rs:66:1
|
LL | const BAD_ENUM2_WRAPPED_TRANSMUTE: Wrap<Enum2> = unsafe { std::mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:70:1
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:58:1
--> $DIR/ub-enum.rs:74:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:68:1
--> $DIR/ub-enum.rs:76:1
|
LL | const BAD_ENUM2_OPTION_PTR_TRANSMUTE: Option<Enum2> = unsafe { std::mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:86:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error: aborting due to 9 previous errors
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:88:1
|
LL | / const BAD_OPTION_CHAR_TRANSMUTE: Option<(char, char)> =
LL | | Some(('x', unsafe { std::mem::transmute(!0) }));
| |____________________________________________________^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior

error: aborting due to 17 previous errors

For more information about this error, try `rustc --explain E0080`.
6 changes: 5 additions & 1 deletion src/test/ui/feature-gates/feature-gate-const_transmute.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#![feature(const_fn)]

use std::mem;

#[repr(transparent)]
struct Foo(u32);

const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
//~^ ERROR The use of std::mem::transmute() is gated in constants

const fn transmute_fn() -> u32 { unsafe { mem::transmute(Foo(3)) } }
//~^ ERROR The use of std::mem::transmute() is gated in const fns

fn main() {}
8 changes: 4 additions & 4 deletions src/test/ui/feature-gates/feature-gate-const_transmute.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0658]: The use of std::mem::transmute() is gated in constants
--> $DIR/feature-gate-const_transmute.rs:6:38
error[E0658]: The use of std::mem::transmute() is gated in const fns
--> $DIR/feature-gate-const_transmute.rs:10:43
|
LL | const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
| ^^^^^^^^^^^^^^^^^^^^^^
LL | const fn transmute_fn() -> u32 { unsafe { mem::transmute(Foo(3)) } }
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see /~https://github.com/rust-lang/rust/issues/53605
= help: add `#![feature(const_transmute)]` to the crate attributes to enable
Expand Down