Description
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.;const fn twice<T: Copy>(x: T) -> (T, T) { (x, x) } match x { twice(21) => { ... } _ => { ... } }
-
anything else that is not currently in
const_fn
or constants- raw ptr to
usize
cast (e.g.*const/mut T -> usize
). - raw ptr deref.
if
/if let
/match
.loop
/while
.let
and destructuring.
- raw ptr to
-
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):- lifetimes
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 elaborated
which includes adding implicitSized
bounds.
This entails that permittingSized
+ 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
casts -
const unsafe fn
is allowed, but the body must consist of safe operations only
The 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
and align_of
). This means that they must work with min_const_fn
.
Things to be done before stabilizing:
- Implement the
min_const_fn
feature gate. (Implement themin_const_fn
feature gate #53604) - Ensure that the above restrictions apply.
- Adjust documentation (see instructions on forge)
- Stabilization PR (see instructions on forge)
Unresolved questions:
None.
Vocabulary: