-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
We currently have two separate MIR passes that are responsible for const-checking. One lives in the check_consts
directory, and is responsible for the checks that run in all const contexts. The other is qualify_min_const_fn
, which performs additional checks within const fn
when #![feature(const_fn)]
is not enabled. The split was necessary to push const fn
feature over the finish line due to technical debt in the const-qualification code, but it resulted in some checks being duplicated between the two modules. Const-qualification has since been rewritten entirely, and it should be possible to unify the two to reduce the maintenance burden and improve diagnostics.
I half-heartedly attempted this in #68940, but eventually abandoned it due to the volume of error message changes and reticence from a former lang-team member. However, I think we should give this another try, since the split has caused some confusion about #![feature(const_fn)]
(see #76602) and there was a request from the libs-team to change how stability attributes affect whether the qualify_min_const_fn
runs (see #75794).
I did not fully understand when writing #68940 that qualify_min_const_fn
is responsible for ensuring that publicly exported, stable const fn
in staged_api
crates do not rely on unstable features as part of their implementation. check_consts
makes no such effort. So far, we've relied on the review process to enforce this, but I think one of the first steps will be to add this functionality to check_consts
, enabling it only within const fn
at first. After that, we can define new structured errors for each of the checks in qualify_min_const_fn
in the check_consts
framework and disable the former entirely. At first, all of these checks will be controlled by the #![feature(const_fn)]
feature gate, but I think we should assign a new gate to each (floating point arithmetic within const fn
, impl Trait
, etc.).
@oli-obk, would you be willing to review this work? Is there anything I missed?
TODO:
- ... (list needs completing)To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
cc @rust-lang/wg-const-eval
Activity
RalfJung commentedon Sep 12, 2020
I am confused, haven't we relied on
qualify_min_const_fn
to enforce this?ecstatic-morse commentedon Sep 12, 2020
For checks that exist in both
qualify_min_const_fn
andcheck_consts
, yes. However, not everything incheck_consts
has an analogue inqualify_min_const_fn
.const_precise_live_drops
for sure does not, and I believe there are others (MutDeref
?).Pin
methods #76654RalfJung commentedon Sep 13, 2020
Ah, so basically when
check_consts
was extended to accept more things, we sometimes forgot to extendqualify_min_const_fn
to make sure it rejects them? That is surprising as I thoughtqualify_min_const_fn
was a tight whitelist and thus wouldn't accept any of these new features.josephlr commentedon Sep 13, 2020
So it looks like stable library functions can't use
MutDeref
, asqualify_min_const_fn
has a specific type-level check that bans any mutable references. However, this only applies in functions not constants, leading to a strange outcome where:is allowed on stable, but
is not, playground link.
The corresponding check in
check_consts
bans the operation of taking mutable references, rather than the type itself. These checks not being exactly the same mostly just seem to cause weird compiler errors (with incorrect recommendations).This seems mostly true, an example of where it's not is the type-level check, which checks for some banned types, and then lets all other types pass through, which means if a new const-incompatible type/operation was added, this check would need to be updated.
RalfJung commentedon Sep 13, 2020
Note that we have a few cases where things are allowed in constants but not
const fn
. Union field access andmem:.transmute
are further examples.oli-obk commentedon Sep 17, 2020
yes definively!
8 remaining items
ecstatic-morse commentedon Sep 25, 2020
I tried to remove
qualify_min_const_fn
in #76850, but ended up merely disabling it inrustc
because it would have brokenclippy
, which would have caused CI to fail. I tried again in #77128, butclippy
can only run lints onoptimized_mir
, which is a) wrong and b) causes some assertions in const-checking to fail.To fully resolve the first half of this issue, one of a few things needs to happen:
qualify_min_const_fn.rs
can be moved intoclippy
. Themissing_const_for_fn
lint will be wrong in some cases but no worse than before. I'm not going to continue to maintain it, however.missing_const_for_fn
can be disabled entirely. This lint is only in the "nursery", so this should be fine.clippy
can add support for linting on the stolen MIR queries (Linting shouldn't be run on optimized MIR rust-clippy#6080) (e.g.mir_const
). This is the correct solution long-term, and it means we can reopen Add speculative const-checking and removequalify_min_const_fn.rs
#77128.RalfJung commentedon Sep 26, 2020
That would be my preferred solution for now, TBH -- but I am not a Clippy maintainer so obviously I am picking what would be easiest for rustc itself.
I added resolving this as a checkbox to the OP. I am not sure if there are still parts of
const_fn
left to be moved out so I couldn't add those to the list.RalfJung commentedon Sep 26, 2020
Cc @rust-lang/clippy for the clippy problem
ebroto commentedon Sep 26, 2020
RalfJung commentedon Sep 26, 2020
Clippy is the only client of
qualify_min_const_fn
right now. So it should be either moved to Clippy or removed, as rustc itself does not use it.The new const analysis that rustc is using does not have a "speculative mode" -- if it detects a const-error, it raises a hard error. That is how such analysis usually work in rustc AFAIK, min_const_fn was the odd one out. Clippy exploited this special status to be able to detect if a function could be const without raising hard errors when it is not. A new mechanism to achieve this will have to be introduced, ideally with minimal maintenance overhead on the rustc side.
Rollup merge of rust-lang#77122 - ecstatic-morse:const-fn-arithmetic,…
Rollup merge of rust-lang#77122 - ecstatic-morse:const-fn-arithmetic,…
oli-obk commentedon Sep 26, 2020
Clippy frequently has custom algorithms to detect whether to lint on something. It's totally fine not to reuse the compiler logic and keep the compiler logic simple and just have a bunch of false negatives in the lint. False negatives in a non-bug-detecting lint are absolutely no problem. So yes, I think we should just move the function to clippy and call it a day. We can then look into improving things on the clippy side without requiring any maintaining on the compiler side
RalfJung commentedon Sep 26, 2020
@oli-obk sounds like a good plan to me.
oli-obk commentedon Sep 26, 2020
I'll do that now
missing_const_for_fn
out of rustc to clippy #77231RalfJung commentedon Jan 24, 2021
@oli-obk @ecstatic-morse what is left to be done here? The checklist in the original issue only has one unchecked item, which says "list needs completing"... ;)