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

Made std::intrinsics::transmute() const fn. #53535

Merged
merged 1 commit into from
Aug 30, 2018
Merged
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: 7 additions & 0 deletions src/librustc_mir/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
};
self.write_scalar(out_val, dest)?;
}
"transmute" => {
// Go through an allocation, to make sure the completely different layouts
// do not pose a problem. (When the user transmutes through a union,
// there will not be a layout mismatch.)
let dest = self.force_allocation(dest)?;
self.copy_op(args[0], dest.into())?;
}

_ => return Ok(false),
}
Expand Down
12 changes: 12 additions & 0 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
| "cttz_nonzero"
| "ctlz"
| "ctlz_nonzero" => is_const_fn = Some(def_id),
"transmute" => {
if self.mode != Mode::Fn {
is_const_fn = Some(def_id);
if !self.tcx.sess.features_untracked().const_transmute {
emit_feature_err(
&self.tcx.sess.parse_sess, "const_transmute",
self.span, GateIssue::Language,
&format!("The use of std::mem::transmute() \
is gated in {}s", self.mode));
}
}
}

name if name.starts_with("simd_shuffle") => {
is_shuffle = true;
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ declare_features! (
// Allows dereferencing raw pointers during const eval
(active, const_raw_ptr_deref, "1.27.0", Some(51911), None),

// Allows reinterpretation of the bits of a value of one type as another type during const eval
(active, const_transmute, "1.29.0", Some(53605), None),

// Allows comparing raw pointers during const eval
(active, const_compare_raw_pointers, "1.27.0", Some(53020), None),

Expand Down
22 changes: 22 additions & 0 deletions src/test/run-pass/ctfe/transmute-const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(const_transmute)]

use std::mem;

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

const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };

fn main() {
assert_eq!(TRANSMUTED_U32, 3);
}
18 changes: 18 additions & 0 deletions src/test/ui/consts/const-eval/transmute-const-promotion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(const_transmute)]

use std::mem;

fn main() {
let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
//~^ ERROR value does not live long enough
}
14 changes: 14 additions & 0 deletions src/test/ui/consts/const-eval/transmute-const-promotion.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0597]: borrowed value does not live long enough
--> $DIR/transmute-const-promotion.rs:16:37
|
LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
LL | //~^ ERROR value does not live long enough
LL | }
| - temporary value only lives until here
|
= note: borrowed value must be valid for the static lifetime...

error: aborting due to previous error

For more information about this error, try `rustc --explain E0597`.
19 changes: 19 additions & 0 deletions src/test/ui/consts/const-eval/transmute-const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(const_transmute)]

use std::mem;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you also add a test that checks that static FOO: bool = unsafe { mem::transmute(3) }; is an error?

Copy link
Member

@RalfJung RalfJung Aug 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test exists now but it fails saying the sizes are wrong.

Likely you meant mem::transmute(3u8)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm slightly confused, because I built it on my box and it passes, as does the travis build.


static FOO: bool = unsafe { mem::transmute(3u8) };
//~^ ERROR this static likely exhibits undefined behavior
//~^^ type validation failed: encountered 3, but expected something in the range 0..=1

fn main() {}
11 changes: 11 additions & 0 deletions src/test/ui/consts/const-eval/transmute-const.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0080]: this static likely exhibits undefined behavior
--> $DIR/transmute-const.rs:15:1
|
LL | static FOO: bool = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected something in the range 0..=1
|
= 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

For more information about this error, try `rustc --explain E0080`.
4 changes: 2 additions & 2 deletions src/test/ui/consts/const-fn-not-safe-for-const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@

// Test that we can't call random fns in a const fn or do other bad things.

#![feature(const_fn)]
#![feature(const_fn, const_transmute)]

use std::mem::transmute;

fn random() -> u32 { 0 }

const fn sub(x: &u32) -> usize {
unsafe { transmute(x) } //~ ERROR E0015
unsafe { transmute(x) }
}

const fn sub1() -> u32 {
Expand Down
8 changes: 1 addition & 7 deletions src/test/ui/consts/const-fn-not-safe-for-const.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/const-fn-not-safe-for-const.rs:20:14
|
LL | unsafe { transmute(x) } //~ ERROR E0015
| ^^^^^^^^^^^^

error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/const-fn-not-safe-for-const.rs:24:5
|
Expand Down Expand Up @@ -70,7 +64,7 @@ LL | x + y
|
= help: add #![feature(const_let)] to the crate attributes to enable

error: aborting due to 10 previous errors
error: aborting due to 9 previous errors

Some errors occurred: E0013, E0015, E0658.
For more information about an error, try `rustc --explain E0013`.
19 changes: 19 additions & 0 deletions src/test/ui/feature-gates/feature-gate-const_transmute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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 (see issue #53605)

fn main() {}
11 changes: 11 additions & 0 deletions src/test/ui/feature-gates/feature-gate-const_transmute.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0658]: The use of std::mem::transmute() is gated in constants (see issue #53605)
--> $DIR/feature-gate-const_transmute.rs:16:38
|
LL | const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(const_transmute)] to the crate attributes to enable

error: aborting due to previous error

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