@@ -20,17 +20,63 @@ 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+ * ` const_eval_global_id_for_typeck ` evaluates a constant to a valtree,
31+ so the result value can be further inspected by the compiler.
32+ * ` const_eval_global_id ` evaluate a constant to an "opaque blob" containing its final value;
33+ this is only useful for codegen backends and the CTFE evaluator engine itself.
34+ * ` eval_static_initializer ` specifically computes the initial values of a static.
35+ Statics are special; all other functions do not represent statics correctly
36+ and have thus assertions preventing their use on statics.
37+
2638The ` const_eval_* ` functions use a [ ` ParamEnv ` ] ( ./param_env.html ) of environment
2739in which the constant is evaluated (e.g. the function within which the constant is used)
2840and a [ ` GlobalId ` ] . The ` GlobalId ` is made up of an ` Instance ` referring to a constant
2941or static or of an ` Instance ` of a function and an index into the function's ` Promoted ` table.
3042
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 ` ] ).
43+ Constant evaluation returns an [ ` EvalToValTreeResult ` ] for type system constants or
44+ [ ` EvalToConstValueResult ` ] with either the error, or a representation of the constant.
45+
46+ Constants for the type system are encoded in "valtree representation". The ` ValTree ` datastructure
47+ allows us to represent
48+
49+ * arrays,
50+ * many structs,
51+ * tuples,
52+ * enums and,
53+ * most primitives.
54+
55+ The basic rule for
56+ being permitted in the type system is that every value must be uniquely represented. In other
57+ words: a specific value must only be representable in one specific way. For example: there is only
58+ one way to represent an array of two integers as a ` ValTree ` :
59+ ` ValTree::Branch(&[ValTree::Leaf(first_int), ValTree;:Leaf(second_int)]) ` .
60+ Even though theoretically a ` [u32; 2] ` could be encoded in a ` u64 ` and thus just be a
61+ ` ValTree::Leaf(bits_of_two_u32) ` , that is not a legal construction of ` ValTree `
62+ (and is very complex to do, so it is unlikely anyone is tempted to do so).
63+
64+ These rules also mean that some values are not representable. There can be no ` union ` s in type
65+ level constants, as it is not clear how they should be represented, because their active variant
66+ is unknown. Similarly there is no way to represent raw pointers, as addresses are unknown at
67+ compile-time and thus we cannot make any assumptions about them. References on the other hand
68+ * can* be represented, as equality for references is defined as equality on their value, so we
69+ ignore their address and just look at the backing value. We must make sure that the pointer values
70+ of the references are not observable at compile time. We thus encode ` &42 ` exactly like ` 42 ` .
71+ Any conversion from
72+ valtree back to codegen constants must reintroduce an actual indirection. At codegen time the
73+ addresses may be deduplicated between multiple uses or not, entirely depending on arbitrary
74+ optimization choices.
75+
76+ As a consequence, all decoding of ` ValTree ` must happen by matching on the type first and making
77+ decisions depending on that. The value itself gives no useful information without the type that
78+ belongs to it.
79+
3480Other constants get represented as [ ` ConstValue::Scalar ` ]
3581or [ ` ConstValue::Slice ` ] if possible. This means that the ` const_eval_* `
3682functions cannot be used to create miri-pointers to the evaluated constant.
@@ -42,4 +88,5 @@ If you need the value of a constant inside Miri, you need to directly work with
4288[ `ConstValue::Slice` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Slice
4389[ `ConstValue::ByRef` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.ByRef
4490[ `EvalToConstValueResult` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToConstValueResult.html
91+ [ `EvalToValTreeResult` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToValTreeResult.html
4592[ `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