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

Make unreachable_unchecked a const fn #74459

Merged
merged 4 commits into from
Jul 19, 2020
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
3 changes: 2 additions & 1 deletion src/libcore/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ use crate::intrinsics;
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
pub unsafe fn unreachable_unchecked() -> ! {
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
pub const unsafe fn unreachable_unchecked() -> ! {
// SAFETY: the safety contract for `intrinsics::unreachable` must
// be upheld by the caller.
unsafe { intrinsics::unreachable() }
Expand Down
1 change: 1 addition & 0 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is
/// [`std::hint::unreachable_unchecked`](../../std/hint/fn.unreachable_unchecked.html).
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
pub fn unreachable() -> !;

/// Informs the optimizer that a condition is always true.
Expand Down
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
#![feature(const_slice_ptr_len)]
#![feature(const_type_name)]
#![feature(const_likely)]
#![feature(const_unreachable_unchecked)]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let (dest, ret) = match ret {
None => match intrinsic_name {
sym::transmute => throw_ub_format!("transmuting to uninhabited type"),
sym::unreachable => throw_ub!(Unreachable),
sym::abort => M::abort(self)?,
// Unsupported diverging intrinsic.
_ => return Ok(false),
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/consts/const_unsafe_unreachable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// run-pass

#![feature(const_fn)]
#![feature(const_unreachable_unchecked)]

const unsafe fn foo(x: bool) -> bool {
match x {
true => true,
false => std::hint::unreachable_unchecked(),
}
}

const BAR: bool = unsafe { foo(true) };

fn main() {
assert_eq!(BAR, true);
}
20 changes: 20 additions & 0 deletions src/test/ui/consts/const_unsafe_unreachable_ub.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// build-fail

#![feature(const_fn)]
Copy link
Contributor

Choose a reason for hiding this comment

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

If you make this test #[warn(const_err)] you'll get an additional error on the BAR use site, which you can then mark with //~ ERROR erroneous constant

Copy link
Contributor Author

@canova canova Jul 17, 2020

Choose a reason for hiding this comment

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

I tried to add #[warn(const_err)] on top of the BAR constant but I still don't get an error in the use site.

Edit: Okay, I figured out. I was missing the build-fail annotation actually. Updating the code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@oli-obk Thanks for the recommendation! I figured out and updated the code. Could you take a look again?
(Added it as a new commit to make it easier to see new changes, but I can squash with the previous commit later if you prefer it that way.)

Copy link
Contributor

Choose a reason for hiding this comment

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

yea, that build-fail thing is really problematic around const prop and similar. I gotta figure something out for that.

The PR lgtm now, thanks!

#![feature(const_unreachable_unchecked)]

const unsafe fn foo(x: bool) -> bool {
match x {
true => true,
false => std::hint::unreachable_unchecked(),
}
}

#[warn(const_err)]
const BAR: bool = unsafe { foo(false) };

fn main() {
assert_eq!(BAR, true);
//~^ ERROR E0080
//~| ERROR erroneous constant
}
44 changes: 44 additions & 0 deletions src/test/ui/consts/const_unsafe_unreachable_ub.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
warning: any use of this value will cause an error
--> $SRC_DIR/libcore/hint.rs:LL:COL
|
LL | unsafe { intrinsics::unreachable() }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The error is showing the internal code instead of the const_unsafe_unreachable_ub.rs source code, but I'm not sure how to make it show the source code instead. We still have the source code mentioned in the stack below though. Do you think this is a blocker?

| ^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| entering unreachable code
| inside `std::hint::unreachable_unchecked` at $SRC_DIR/libcore/hint.rs:LL:COL
| inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:9:18
| inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:14:28
|
::: $DIR/const_unsafe_unreachable_ub.rs:14:1
|
LL | const BAR: bool = unsafe { foo(false) };
| ----------------------------------------
|
note: the lint level is defined here
--> $DIR/const_unsafe_unreachable_ub.rs:13:8
|
LL | #[warn(const_err)]
| ^^^^^^^^^

error[E0080]: evaluation of constant expression failed
--> $DIR/const_unsafe_unreachable_ub.rs:17:3
|
LL | assert_eq!(BAR, true);
| ^^^^^^^^^^^---^^^^^^^^
| |
| referenced constant has errors
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: erroneous constant used
--> $DIR/const_unsafe_unreachable_ub.rs:17:3
|
LL | assert_eq!(BAR, true);
| ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
= note: `#[deny(const_err)]` on by default
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors; 1 warning emitted

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