-
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
Tracking issue for a minimal subset of RFC 911, const fn #53555
Comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Some concerns noted over at #24111:
|
does not apply here, because we neither stabilize
The 2018 edition takes precedence over this feature. Since it has been minimized to a very small surface area which will be enforced by a feature whitelist, it seems plausible that we can get everyone on board to at least stabilize it shortly after the 2018 edition has been released.
Since we are punting on (almost) all design issues by using a minimal scheme, the only design question left is whether we want to start attaching the Alternate designs:
Wrt the "everything function is getting |
We do not? I see you sneakily added that to the first post.^^ These are already stable for |
@oli-obk added that part, but I think about it like this: given union field accesses, you can perform
All in all, I think that if we are more conservative here and punt on this, we can ship a more minimal |
I see. I don't like these inconsistencies but oh well. Looks like In terms of teaching, again we have the same problem for union Trans { x: &'static i32, y: usize }
const BAR : usize = unsafe { Trans { x: &0 }.y }; |
First, a nit:
Presumably something like But, more generally, I think that this proposal does a good job of outlining the surface area of the language to be stabilized, but I'd like to see a better outline of what the implications are regarding the "const system in general". One key question here is the interaction of I think by now I am mostly bought into the general framing from Ralf's blog post, but I'd like to also know if there are alternative approaches that we are ruling out by stabilizing const fn. It seems like one of the key bits that I could imagine being controversial was the idea that a |
To expand a bit on something:
I had initially considered suggesting that we allow auto traits as well, but I do not think this is a good idea. For one thing, unlike unsafe impl<T: Display> Send for Foo<T> { } Now, if you have a Since |
Hehe; I don't like them either, but I fully intend for many of the restrictions to be temporary ^.^
Right; so I think lifetimes in bounds + |
I'm curious about the UX side of things. Some of the limitations might be surprising to people. For example, being able to write a generic but not bounds. I can imagine it being frustrating to start implementing my program and then all of a sudden something doesn't work because it requires nightly. I either have to change to nightly or change my implementation approach. Of course, it could be one of those things that just needs experimentation on nightly for a while. For example, we could implement the proposed min_const_fn feature and see how many uses of the const_fn feature on crates.io can be changed to it. If that proportion is low, I think we should think twice before stabilizing. |
My long-term plan (which I still did not get around to submit to the const RFC repo...) was that a call to a safe I originally thought we could not look into the body for promoting uses of const FOO : Option<Cell<i32>> = None;
&FOO but not const FOO : Option<Cell<i32>> = Some(Cell::new(0));
&FOO So it seems like, even if it's just for backwards compatibility, looking "into" a Now @oli-obk can fix all my misconceptions. :D |
A const fn call is "always" promoted right now. If the creation of its arguments involves unions, raw pointer to
This means we are fully forward compatible with any scheme that we choose wrt promotion failures (or lack thereof).
We don't allow even mentioning cells, even if they don't end up in the final result. I think it would be very confusing for users if they can use const FOO : Option<Cell<i32>> = (None, Some(Cell::new(0))).0;
let _: &'static _ = &FOO; // ERROR: does not live long enough If we want to make this properly (meaning not surprising to users) we need to do these checks on final values, not on constant/const fn bodies. I have implemented a prototype for checking whether a value needs user-written
We have so many const features that users are surprised about not being stable although very similar features are. I don't think extending the group of stable features will make ppl unhappy. |
So we check the type to be frozen recursively?
Oh so currently we do not do any value-based analysis, and could go entirely off of the type of the No that's not true, the following works const FOO : Option<Vec<i32>> = None;
let _: &'static _ = &FOO; |
No, I implemented a prototype for checking the constant's final value for promotability. So the body is ignored, but we check the value similarly how the const sanity checks work. |
Well that's still looking "into" the constant, breaking the abstraction. OTOH it enables reasonable code, so we likely want it. You said you "implemented a prototype", but something seems to already have landed? |
No, we've had body-revealing checks since forever. This is nothing new. |
Why can we not allow control flow in const fns? |
Also, has there been an audit of which const fns in std/crates.io can be implemented according to these restrictions? |
@durka I've skimmed the const fns in libstd and I think it should all work with these restrictions. Wrt. control flow and destructuring, see:
|
@durka this is not the issue for discussing what to add to the minimal const fn (control flow isn't even in full const fns yet), but for discussing what to remove to make it forward compatible to every possible scheme. So. @RalfJung has noted that |
Instead of banning random subsets of unsafe operations, I'd prefer -- if we want to keep the space open for how we resolve "const safety" -- to just not allow unsafe blocks in I think the only safe operation we are worried about is raw ptr to |
Update:
|
Is there any plan or timeframe for stabilisation of this feature? This is blocking a major embedded use case to safely pass data and peripherals in and out of interrupt handlers as far as I can see (cf. rust-embedded/bare-metal#11). The use of |
@therealprof Stabilization is blocked on merging #53851. |
We discussed this on IRC a while ago, but I don't see it mentioned here, so it might be worth it to update the OP. We are sure about this: it is, in general, impossible to achieve the same results at compile-time and run-time (on all targets). What |
As uncovered in #54696, raw pointer comparison is not the only concern -- we also have ti disallow function pointer comparison as CTFE does not support that operation. Does |
Well... we do have "function pointers in const fn are unstable" even for casting functions to function pointers. |
But we could still write a function that takes two fn ptrs and compares them? It couldn't be called (currently), but we should rule out the binop as well. |
@RalfJung Attempting to define const fn cmp(x: fn(), y: fn()) -> bool {
x == y
} with |
If we have that in a test, I am happy :) |
@RalfJung , it would appear that post-#54835 nightly still accepts this code without warning. Did you intend for this code not to work? |
Nightly on the playground gives me
|
And there's tests as well: https://github.com/rust-lang/rust/blob/master/src/test/ui/consts/const-eval/ub-nonnull.rs This can been fixed with #54762 |
Any change we can get this into beta? I'd really love to do some 2018 edition proving and cleanup of some embedded crates but without |
It will be in the next beta. Until then you could just use nightly without any feature gates |
@oli-obk That's what I'm doing at the moment but I thought the point of the beta was to test Edition features and nightly might behave differently. I guess I'm looking forward then to trying the next beta and everything working fine just like on nighty. ;) |
Documentation was done in rust-lang/reference#440. Since everything is done, I'll close this out. |
@oli-obk > It will be in the next beta. Until then you could just use nightly without any feature gates
|
@therealprof "the next beta" means the 1.31 one, which will arrive some time around the time 1.30 stable ships(Oct 25). |
This is a tracking issue for the RFC "Const functions and inherent methods" (rust-lang/rfcs#911).
This issue only tracks a minimal subset of the proposal in 911 that we are (hopefully) comfortable with stabilizing. To opt into the minimal subset, use
#![feature(min_const_fn)]
. To use the more expansive feature set, you can continue using#![feature(const_fn)]
and other associated feature gates.The minimal set will not include items from the following (incomplete) list:
const fn
s with type parameters with bounds (includingwhere
clauses) in scope (including from the parent e.g.impl
) other than: lifetimes,Sized
, or (the "un"-bound)?Sized
This restriction exists because we are not sure about our story around what bounds mean in a
const fn
context. See RFC: const bounds and methods rfcs#2237,const fn
and generics const-eval#1, and https://github.com/Centril/rfc-effects/ for a discussion on this.const fn
s with argument types or return types that containfn
pointers,dyn Trait
, orimpl Trait
.This is checked recursively.
The restriction ensures that you may not reach a value of these types by any means.
This restriction exists for the same reasons as in 1.
const fn
s with any operations on floating-point numbers. This is achieved by making any floating-point operation not beconst
insideconst fn
.This restriction exists because we are not sure about the story wrt. determinism, achieving the same results on compile-time / run-time (including other machines) and floating points.
using a
const fn
call in a pattern, e.g.;anything else that is not currently in
const_fn
or constantsusize
cast (e.g.*const/mut T -> usize
).if
/if let
/match
.loop
/while
.let
and destructuring.union field access.
code requiring
unsafe
blocks.Exhaustive list of features supported in
const fn
with#![feature(min_const_fn)]
:type parameters where the parameters have any of the following as part of their bounds (either on
where
or directly on the parameters):Sized
This means that
<T: 'a + ?Sized>
and<T: 'b + Sized>
+<T>
are all permitted.Note that
?Sized
is the absence of a constraint when bounds have been fully elaboratedwhich includes adding implicit
Sized
bounds.This entails that permitting
Sized
+ lifetimes allows the above examples.This rule also applies to type parameters of items that contain
const fn
s.arithmetic operators on integers
boolean operators (except for
&&
and||
which are banned since they are short-circuiting).any kind of aggregate constructor (array,
struct
,enum
, tuple, ...)calls to other
const fn
s (methods and functions)index operations on arrays and slices
field accesses on structs and tuples
reading from constants (but not statics, not even taking a reference to a static)
&
and*
(only dereferencing of references, not raw pointers)casts except for raw pointer to
usize
castsconst unsafe fn
is allowed, but the body must consist of safe operations onlyThe bar for stabilizing
const fn
s in libcore/liballoc/libstd will be that they are writable in stable user code (unless they are wrappers for intrinsics, i.e.size_of
andalign_of
). This means that they must work withmin_const_fn
.Things to be done before stabilizing:
min_const_fn
feature gate. (Implement themin_const_fn
feature gate #53604)Unresolved questions:
None.
Vocabulary:
The text was updated successfully, but these errors were encountered: