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

Constier maybe uninit #79621

Merged
merged 16 commits into from
Dec 10, 2020
Merged

Constier maybe uninit #79621

merged 16 commits into from
Dec 10, 2020

Conversation

usbalbin
Copy link
Contributor

@usbalbin usbalbin commented Dec 2, 2020

I was playing around trying to make [T; N]::zip() in #79451 be const fn. One of the things I bumped into was MaybeUninit::assume_init. Is there any reason for the intrinsic assert_inhabited<T>() and therefore MaybeUninit::assume_init not being const?


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?

@rust-highfive
Copy link
Collaborator

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.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 2, 2020
@oli-obk oli-obk added the A-const-eval Area: Constant evaluation (MIR interpretation) label Dec 2, 2020
@oli-obk
Copy link
Contributor

oli-obk commented Dec 2, 2020

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);
Copy link
Member

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.

@RalfJung
Copy link
Member

RalfJung commented Dec 2, 2020

Making these intrinsics const fn is fine, but we have to decide what we actually want them to do. For reference, this is what Miri does. TerminationInfo::Abort is a Miri-specific mechanism; the CTFE equivalent would involve this enum.

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.

@@ -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")]
Copy link
Member

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.

Copy link
Contributor

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

Copy link
Member

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?

Copy link
Member

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)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@RalfJung

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?

Copy link
Member

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 => {
Copy link
Member

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?

Copy link
Member

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.

Copy link
Contributor

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

@RalfJung
Copy link
Member

RalfJung commented Dec 2, 2020

Thanks a lot for the PR, @usbalbin. :) Yes this is certainly in the right direction.

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.

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 assume_init method(s).

Should I add test? If so what should be tested?

Is there even a way to use assume_init correctly given the current CTFE limitations? I think that will require mutable references; I am not sure what the status of this is.

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
@usbalbin
Copy link
Contributor Author

usbalbin commented Dec 2, 2020

@RalfJung

Making these intrinsics const fn is fine, but we have to decide what we actually want them to do. For reference, this is what Miri does. TerminationInfo::Abort is a Miri-specific mechanism; the CTFE equivalent would involve this enum.

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.

Should I add an Abort variant to ConstEvalErrKind and change

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 if layout.abi.is_uninhabited() { in compiler/rustc_mir/src/interpret/intrinsics.rs?

@RalfJung
Copy link
Member

RalfJung commented Dec 5, 2020

@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())?,
Copy link
Contributor Author

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?

Copy link
Member

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())?;
Copy link
Contributor Author

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?

Copy link
Member

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.

library/core/tests/mem.rs Outdated Show resolved Hide resolved
Still have not figured out how to make it work
@bors
Copy link
Contributor

bors commented Dec 9, 2020

📌 Commit 0775271 has been approved by RalfJung

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 9, 2020
@bors
Copy link
Contributor

bors commented Dec 10, 2020

⌛ Testing commit 0775271 with merge a80568cf2a9375756a461552ee24bef08e362b7d...

@bors
Copy link
Contributor

bors commented Dec 10, 2020

💥 Test timed out

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Dec 10, 2020
@RalfJung
Copy link
Member

@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 10, 2020
@bors
Copy link
Contributor

bors commented Dec 10, 2020

⌛ Testing commit 0775271 with merge 39b841d...

@bors
Copy link
Contributor

bors commented Dec 10, 2020

☀️ Test successful - checks-actions
Approved by: RalfJung
Pushing 39b841d to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Dec 10, 2020
@bors bors merged commit 39b841d into rust-lang:master Dec 10, 2020
@rustbot rustbot added this to the 1.50.0 milestone Dec 10, 2020
@rust-highfive
Copy link
Collaborator

📣 Toolstate changed by #79621!

Tested on commit 39b841d.
Direct link to PR: #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).

rust-highfive added a commit to rust-lang-nursery/rust-toolstate that referenced this pull request Dec 10, 2020
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
Copy link
Member

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.

@usbalbin
Copy link
Contributor Author

Thank you all for helping me with my first rust PR to get merged! :)

@RalfJung
Copy link
Member

@usbalbin thanks for contributing to Rust. :-)

@usbalbin
Copy link
Contributor Author

When looking back at this PR while writing the tracking issue for const_maybe_uninit_assume_init I noticed that both of the slice assume init methods are unstable behind the feature gate maybe_uninit_slice, with tracking issue #63569. Should the constness of those methods be under the const_maybe_uninit_assume_init as now or changed to the same as the methods feature gate maybe_uninit_slice.

If you want me to keep things as is then should I mention in the tracking issue for const_maybe_uninit_assume_init that the slice methods are also blocked on that other feature gate?

@usbalbin usbalbin deleted the constier_maybe_uninit branch June 29, 2021 13:35
@RalfJung
Copy link
Member

For these critical low-level unsafe things I think it makes sense tot rack const stability separately from stability.

@usbalbin
Copy link
Contributor Author

Ok :)

Tracking issue #86722 created for const_maybe_uninit_assume_init

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: Constant evaluation (MIR interpretation) merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants