@@ -20,17 +20,44 @@ Additionally constant evaluation can be used to reduce the workload or binary
20
20
size at runtime by precomputing complex operations at compiletime and only
21
21
storing the result.
22
22
23
+ All uses of constant evaluation can either be categorized as "influencing the type system"
24
+ (array lengths, enum variant discriminants, const generic parameters), or as solely being
25
+ done to precompute expressions to be used at runtime.
26
+
23
27
Constant evaluation can be done by calling the ` const_eval_* ` functions of ` TyCtxt ` .
24
28
They're the wrappers of the ` const_eval ` query.
25
29
30
+ ` static ` initializers must use the ` eval_static_initializer ` function. All other functions
31
+ do not represent statics correctly and have thus assertions preventing their use on statics.
32
+
26
33
The ` const_eval_* ` functions use a [ ` ParamEnv ` ] ( ./param_env.html ) of environment
27
34
in which the constant is evaluated (e.g. the function within which the constant is used)
28
35
and a [ ` GlobalId ` ] . The ` GlobalId ` is made up of an ` Instance ` referring to a constant
29
36
or static or of an ` Instance ` of a function and an index into the function's ` Promoted ` table.
30
37
31
- Constant evaluation returns a [ ` EvalToConstValueResult ` ] with either the error, or a
32
- representation of the constant. ` static ` initializers are always represented as
33
- [ ` miri ` ] ( ./miri.html ) virtual memory allocations (via [ ` ConstValue::ByRef ` ] ).
38
+ Constant evaluation returns a [ ` EvalToValTreeResult ` ] (for type system constants) or [ ` EvalToConstValueResult ` ] with either the error, or a
39
+ representation of the constant.
40
+
41
+ Constants for the type system are encoded in "valtree representation". The ` ValTree ` datastructure
42
+ allows us to represent arrays, many structs, tuples, enums and most primitives. The basic rule for
43
+ being permitted in the type system is that every value must be uniquely represented. In other words:
44
+ a specific value must only be representable in one specific way. For example: there is only one way
45
+ to represent an array of two integers as a ` ValTree ` : ` ValTree::Branch(&[ValTree::Leaf(first_int), ValTree;:Leaf(second_int)]) ` .
46
+ Even though theoretically a ` [u32; 2] ` could be encoded in a ` u64 ` and thus just be a ` ValTree::Leaf(bits_of_two_u32) ` , that
47
+ is not a legal construction of ` ValTree ` (and is so complex to do, that it is unlikely to tempt anyone to do so).
48
+ These rules also mean that some values are not representable. There can be no ` union ` s in type level
49
+ constants, as it is not clear how they should be represented, because their active variant is unknown.
50
+ Similarly there is no way to represent pointers, as addresses are unknown at compile-time and thus we
51
+ cannot make any assumptions about them. References on the other hand can be represented, as equality
52
+ for references is defined as equality on their value, so we ignore their address and just look at the
53
+ backing value. This means that there is no difference in encoding for ` &42 ` and ` 42 ` .
54
+ As a consequence, all decoding of ` ValTree ` must happen by matching on the type first and making decisions
55
+ depending on that. The value itself gives no useful information without the type that belongs to it.
56
+ One notable oddity is ` &str ` representation. There is no sized equivalent of it, so unlike slices we cannot
57
+ choose to represent them as their sized variant (slices are represented as arrays). ` &str ` thus has
58
+ its own ` ValTree ` variant ` Str ` . The advantage of using a custom variant is that we are able to translate
59
+ parser/AST/HIR string literals without any conversion as we use the same (` Symbol ` ) representation.
60
+
34
61
Other constants get represented as [ ` ConstValue::Scalar ` ]
35
62
or [ ` ConstValue::Slice ` ] if possible. This means that the ` const_eval_* `
36
63
functions cannot be used to create miri-pointers to the evaluated constant.
@@ -42,4 +69,5 @@ If you need the value of a constant inside Miri, you need to directly work with
42
69
[ `ConstValue::Slice` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Slice
43
70
[ `ConstValue::ByRef` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.ByRef
44
71
[ `EvalToConstValueResult` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToConstValueResult.html
72
+ [ `EvalToValTreeResult` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToValTreeResult.html
45
73
[ `eval_const_to_op` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.InterpCx.html#method.eval_const_to_op
0 commit comments