-
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
Implement the min_const_fn
feature gate
#53604
Conversation
This comment has been minimized.
This comment has been minimized.
src/libsyntax/feature_gate.rs
Outdated
@@ -206,9 +213,12 @@ declare_features! ( | |||
// #23121. Array patterns have some hazards yet. | |||
(active, slice_patterns, "1.0.0", Some(23121), None), | |||
|
|||
// Allows the definition of `const fn` functions. | |||
// Allows the definition of `const fn` functions with some advanced features | |||
(active, const_fn, "1.2.0", Some(24111), 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.
We will need to ensure that the standard library has not enabled #![feature(const_fn)]
; this includes libstd, liballoc, libcore.
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.
Well, we will want it for NonZero::new_unchecked
, right?
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... I was hoping on using the stabilization of min_const_fn
but exclusion of const_fn
from libstd so that standard library functions could be const
-ified en masse instead of piecemeal. This kinda relies on not having #![feature(const_fn)]
enabled so that accidental things don't happen.
Could we handle new_unchecked
through some other internal means instead temporarily?
EDIT: like rustc_const_stable
or something...
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 say:
const fn
without#[rustc_const_unstable]
is stable if it passesmin_const_fn
const fn
not passingmin_const_fn
can be forced stable with#[rustc_const_fn_force_stable]
This way the active feature gates have no influence on stability, but we're checking the right thing and can't accidentally do anything wrong.
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 this sounds good to me :)
Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())), | ||
Place::Projection(proj) => { | ||
match proj.elem { | ||
// raw ptr derefs prevented by `const_raw_ptr_deref` |
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 is const_raw_ptr_deref
?
Can't we somehow check unsafety, instead of trying to get an exhaustive list of unsafe behavior?
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.
If it aint possible to detect this in MIR perhaps do it in HIR instead?
EDIT: Add a test with an empty unsafe { ... }
block in it
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.
AFAIK MIR has some unsafety information; we do some unsafety checks in MIR.
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.
done
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.
Done as in, the reference to const_raw_ptr_deref
is gone? If not, please mention the filename where that function is defined...^^
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.
As in there's a test. And const_raw_ptr_deref
is a feature gate.
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 see. That's not clear.^^
But the feature is ruled out independent of whether that gate is set...?
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.
well... it's additionally prevented in min_const_fn
due to its unsafety. The same doesn't hold for casting *const T
to usize
. I'll add some more sanity checks. This will annoy the heck out of nightly users since they are now getting a lot of messages twice in different wording (already happening with a bunch of things in this PR)
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's a consequence of doing multiple analyses, right?
I do not think that is the right approach... even if we have separate analyses, we should only call one.
Is it really better to have all that code duplicated into a second analysis, than changing the existing analysis to qualify every |
The existing analysis is supposed to be split up into three separate analyses. Me adding a fourth one to be split out in the future would not help the process. |
Three?!? I can see that promotion is separate, but other than that everything else should be just "const checking", which should (eventually) be the same for |
The checks for |
@@ -477,6 +491,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { | |||
.note(&details.as_str()[..]) | |||
.emit(); | |||
} | |||
UnsafetyViolationKind::MinConstFn => { |
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.
fun side effect: the two cases below which are future compat lints are hard errors inside const fns
This comment has been minimized.
This comment has been minimized.
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.
Some more tests... :)
const fn no_inner_dyn_trait2(x: Hide) { | ||
x.0.field; | ||
//~^ ERROR function pointers in const fn | ||
} | ||
const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) } | ||
//~^ ERROR function pointers in 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.
I specifically do want a test here that ensures that even without access, const fn no_inner_fn_ptr2(x: Hide) { }
is banned.
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 requires a lot of code... I'll impl it, but I don't think it's a good addition to rustc
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.
So you already have the erroring tests:
const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
const fn no_fn_ptrs(_x: fn()) {}
This is good, because it leaves open the possibility that this means &dyn const std::fmt::Debug
or const fn()
; If we didn't reject this, then users could pass in values where you don't have a const
implementation of std::fmt::Debug
, and so we wouldn't be able to change this in the future. However, as for situations where you have:
struct Hide<'a>(&'a dyn Debug);
const fn foo(_x: Hide) {}
... this would only prevent a situation in the future where we decided to split up our nominal type universe into one for the const
restriction and one for impure
... This seems like a very unlikely future... as such... I think the tests you have currently are sufficient.
So you don't need to implement it.
This comment has been minimized.
This comment has been minimized.
Should be fine to merge once the tests pass. :) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@Centril this is ready now I think |
So... while I could actually implement a check that validates the MIR of constants in Can we just decide to treat Alternatively I can rewrite the entire |
I am perfectly fine with treating |
@oli-obk I'm fine with this; I guess T-libs will just be a bit more careful with respect to |
@bors r=Centril,varkor |
📌 Commit 2839f4f has been approved by |
Implement the `min_const_fn` feature gate cc @RalfJung @eddyb r? @Centril implements the feature gate for #53555 I added a hack so the `const_fn` feature gate also enables the `min_const_fn` feature gate. This ensures that nightly users of `const_fn` don't have to touch their code at all. The `min_const_fn` checks are run first, and if they succeeded, the `const_fn` checks are run additionally to ensure we didn't miss anything.
☀️ Test successful - status-appveyor, status-travis |
I had this code in a PR I was working on, how should I write this now? impl<T> UnsafeList<T> {
pub const fn new() -> Self {
unsafe {
UnsafeList {
head_tail: NonNull::new_unchecked(1 as _),
head_tail_entry: None
}
}
}
} |
Minimal repro on playground: #![feature(staged_api, const_fn)]
use std::ptr::NonNull;
pub struct UnsafeList<T>(NonNull<T>);
impl<T> UnsafeList<T> {
pub const fn new() -> Self {
unsafe {
UnsafeList(NonNull::new_unchecked(1 as _))
}
}
} The only way to get around this is to add an |
@jethrogb Is this for a PR to the standard library or the compiler, or is this for code outside of that? |
PR for |
@jethrogb if |
@Centril that is not sufficient. You also need to add an |
@jethrogb |
cc @RalfJung @eddyb
r? @Centril
implements the feature gate for #53555
I added a hack so the
const_fn
feature gate also enables themin_const_fn
feature gate. This ensures that nightly users ofconst_fn
don't have to touch their code at all.The
min_const_fn
checks are run first, and if they succeeded, theconst_fn
checks are run additionally to ensure we didn't miss anything.