@@ -20,17 +20,49 @@ Additionally constant evaluation can be used to reduce the workload or binary
2020size at runtime by precomputing complex operations at compiletime and only
2121storing the result.
2222
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+
2327Constant evaluation can be done by calling the ` const_eval_* ` functions of ` TyCtxt ` .
2428They're the wrappers of the ` const_eval ` query.
2529
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+
2633The ` const_eval_* ` functions use a [ ` ParamEnv ` ] ( ./param_env.html ) of environment
2734in which the constant is evaluated (e.g. the function within which the constant is used)
2835and a [ ` GlobalId ` ] . The ` GlobalId ` is made up of an ` Instance ` referring to a constant
2936or static or of an ` Instance ` of a function and an index into the function's ` Promoted ` table.
3037
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
39+ [ ` EvalToConstValueResult ` ] with either the error, or a 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
44+ words: a specific value must only be representable in one specific way. For example: there is only
45+ one way to represent an array of two integers as a ` ValTree ` :
46+ ` ValTree::Branch(&[ValTree::Leaf(first_int), ValTree;:Leaf(second_int)]) ` .
47+ Even though theoretically a ` [u32; 2] ` could be encoded in a ` u64 ` and thus just be a
48+ ` ValTree::Leaf(bits_of_two_u32) ` , that is not a legal construction of ` ValTree `
49+ (and is so complex to do, so it is unlikely anyone is tempted to do so).
50+
51+ These rules also mean that some values are not representable. There can be no ` union ` s in type
52+ level constants, as it is not clear how they should be represented, because their active variant
53+ is unknown. Similarly there is no way to represent pointers, as addresses are unknown at
54+ compile-time and thus we cannot make any assumptions about them. References on the other hand
55+ can be represented, as equality for references is defined as equality on their value, so we
56+ ignore their address and just look at the backing value. We must make sure that the pointer value
57+ of the references are not observable. We thus encode ` &42 ` exactly like ` 42 ` . Any conversion from
58+ valtree back to codegen constants must reintroduce an actual indirection. At codegen time the
59+ addresses may be deduplicated between multiple uses or not, entirely depending on arbitrary
60+ optimization choices.
61+
62+ As a consequence, all decoding of ` ValTree ` must happen by matching on the type first and making
63+ decisions depending on that. The value itself gives no useful information without the type that
64+ belongs to it.
65+
3466Other constants get represented as [ ` ConstValue::Scalar ` ]
3567or [ ` ConstValue::Slice ` ] if possible. This means that the ` const_eval_* `
3668functions cannot be used to create miri-pointers to the evaluated constant.
@@ -42,4 +74,5 @@ If you need the value of a constant inside Miri, you need to directly work with
4274[ `ConstValue::Slice` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Slice
4375[ `ConstValue::ByRef` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.ByRef
4476[ `EvalToConstValueResult` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToConstValueResult.html
77+ [ `EvalToValTreeResult` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToValTreeResult.html
4578[ `const_to_op` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.InterpCx.html#method.const_to_op
0 commit comments