-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Constier maybe uninit #79621
Constier maybe uninit #79621
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @estebank (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
cc @rust-lang/wg-const-eval |
let layout = self.layout_of(ty)?; | ||
|
||
if layout.abi.is_uninhabited() { | ||
throw_ub_format!("attempted to instantiate uninhabited type `{}`", ty); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is wrong. It is not UB to fail an assertion. That is the entire point of this check, to avoid UB and replace it by a well-defined assertion.
Making these intrinsics If we want to share as much code as possible between Miri and CTFE, we should generalize this machine hook to also accept an error message. Then the Miri and CTFE machines can each behave appropriately. |
library/core/src/intrinsics.rs
Outdated
@@ -815,6 +815,7 @@ extern "rust-intrinsic" { | |||
/// This will statically either panic, or do nothing. | |||
/// | |||
/// This intrinsic does not have a stable counterpart. | |||
#[rustc_const_unstable(feature = "const_maybe_assume_init", issue = "none")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the feature gate name... we do not intend to ever stabilize these intrinsics. @oli-obk what is the plan for that case? Usually perma-unstable intrinsics just do not have a feature gate name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't stabilize the intrinsics, but we will "stabilize their constness", thus allowing them to be used in libcore/libstd from stable const fn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, so even if it is const-stable it cannot be used outside libstd? Curious.
Sounds like we want a feature gate collecting the three intrinsics then. Something like const_assert_type
or so?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, does that mean you can have a type that's rustc_const_stable
without being stable
? I think that will break rustdoc's rendering of const fn
. #79551, #79548 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like we want a feature gate collecting the three intrinsics then. Something like const_assert_type or so?
I have removed the constification of the other two intrinsics (see comments). Does the name const_assert_type
still make sense or should i change it to something more specific like const_assert_inhabited
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the name const_assert_type still make sense or should i change it to something more specific like const_assert_inhabited?
Either is fine, I'd say.
@@ -407,6 +407,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |||
sym::transmute => { | |||
self.copy_op_transmute(args[0], dest)?; | |||
} | |||
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@oli-obk how will such aborting intrinsics interact with function memoization?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In particular with #75390 I am wondering if we'll get decent error messages here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that works fine, it will cause the const eval queries to return an error, similar to how the memoization of size_of
can error if the type is not representable on the platform
Thanks a lot for the PR, @usbalbin. :) Yes this is certainly in the right direction.
You are doing many things at once here, that IMO should have different feature gates. Maybe as a start it'd make more sense to restrict the PR to just the
Is there even a way to use A simple smoke test would be something like const TRUE: bool = {
let mut x = MaybeUninit::<bool>::uninit();
x.as_mut_ptr().write(true);
x.assume_init()
};
assert!(TRUE); And also a compile-fail test like const BAD: () = {
MaybeUninit::<!>::uninit().assume_init();
} |
* Undo fn -> const fn for some fns. * Split feature gate. * Made all three intrinsics const
Should I add an fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, !> {
throw_unsup_format!("aborting execution is not supported")
} to something like fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: String) -> InterpResult<'tcx, !> {
Err(ConstEvalErrKind::Abort(msg))
} and then call that if |
@usbalbin yes that sounds like a reasonable plan! |
@@ -126,7 +126,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |||
None => match intrinsic_name { | |||
sym::transmute => throw_ub_format!("transmuting to uninhabited type"), | |||
sym::unreachable => throw_ub!(Unreachable), | |||
sym::abort => M::abort(self)?, | |||
sym::abort => M::abort(self, "aborted execution".to_owned())?, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What message do we want here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd vote for "the program aborted execution".
@@ -110,7 +110,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |||
} | |||
|
|||
Abort => { | |||
M::abort(self)?; | |||
M::abort(self, "aborted execution".to_owned())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What message do we want here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same as in the other place, I'd say.
Still have not figured out how to make it work
e110b1a
to
3282b54
Compare
📌 Commit 0775271 has been approved by |
⌛ Testing commit 0775271 with merge a80568cf2a9375756a461552ee24bef08e362b7d... |
💥 Test timed out |
@bors retry |
☀️ Test successful - checks-actions |
Tested on commit rust-lang/rust@39b841d. Direct link to PR: <rust-lang/rust#79621> 💔 miri on windows: test-pass → build-fail (cc @oli-obk @eddyb @RalfJung). 💔 miri on linux: test-pass → build-fail (cc @oli-obk @eddyb @RalfJung).
@@ -0,0 +1,13 @@ | |||
// error-pattern: any use of this value will cause an error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I only just realized this file is in the wrong folder. It should be in an appropriate subfolder, in this case consts
sounds best. I'll take care of that as part of #79910.
Thank you all for helping me with my first rust PR to get merged! :) |
@usbalbin thanks for contributing to Rust. :-) |
When looking back at this PR while writing the tracking issue for If you want me to keep things as is then should I mention in the tracking issue for |
For these critical low-level unsafe things I think it makes sense tot rack const stability separately from stability. |
Ok :) Tracking issue #86722 created for |
I was playing around trying to make
[T; N]::zip()
in #79451 beconst fn
. One of the things I bumped into wasMaybeUninit::assume_init
. Is there any reason for the intrinsicassert_inhabited<T>()
and thereforeMaybeUninit::assume_init
not beingconst
?I have as best as I could tried to follow the instruction in library/core/src/intrinsics.rs. I have no idea what I am doing but it seems to compile after some slight changes after the copy paste. Is this anywhere near how this should be done?
Also any ideas for name of the feature gate? I guess
const_maybe_assume_init
is quite misleading since I have added some more methods. Should I add test? If so what should be tested?