Skip to content

Commit c2561c4

Browse files
JohnTitorRalfJung
andauthored
Update docs related to const-eval/Miri (#676)
* Update docs related to const-eval Co-authored-by: Ralf Jung <[email protected]>
1 parent d10f70b commit c2561c4

File tree

2 files changed

+39
-32
lines changed

2 files changed

+39
-32
lines changed

src/const-eval.md

+24-17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ specific item (constant/static/array length) this happens after the MIR for the
55
item is borrow-checked and optimized. In many cases trying to const evaluate an
66
item will trigger the computation of its MIR for the first time.
77

8-
Prominent examples are
8+
Prominent examples are:
99

1010
* The initializer of a `static`
1111
* Array length
@@ -20,19 +20,26 @@ Additionally constant evaluation can be used to reduce the workload or binary
2020
size at runtime by precomputing complex operations at compiletime and only
2121
storing the result.
2222

23-
Constant evaluation can be done by calling the `const_eval` query of `TyCtxt`.
24-
25-
The `const_eval` query takes a [`ParamEnv`](./param_env.html) of environment in
26-
which the constant is evaluated (e.g. the function within which the constant is
27-
used) and a `GlobalId`. The `GlobalId` is made up of an
28-
`Instance` referring to a constant or static or of an
29-
`Instance` of a function and an index into the function's `Promoted` table.
30-
31-
Constant evaluation returns a `Result` with either the error, or the simplest
32-
representation of the constant. "simplest" meaning if it is representable as an
33-
integer or fat pointer, it will directly yield the value (via `ConstValue::Scalar` or
34-
`ConstValue::ScalarPair`), instead of referring to the [`miri`](./miri.html) virtual
35-
memory allocation (via `ConstValue::ByRef`). This means that the `const_eval`
36-
function cannot be used to create miri-pointers to the evaluated constant or
37-
static. If you need that, you need to directly work with the functions in
38-
[src/librustc_mir/const_eval.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/const_eval/index.html).
23+
Constant evaluation can be done by calling the `const_eval_*` functions of `TyCtxt`.
24+
They're the wrappers of the `const_eval` query.
25+
26+
The `const_eval_*` functions use a [`ParamEnv`](./param_env.html) of environment
27+
in which the constant is evaluated (e.g. the function within which the constant is used)
28+
and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant
29+
or static or of an `Instance` of a function and an index into the function's `Promoted` table.
30+
31+
Constant evaluation returns a [`ConstEvalResult`] with either the error, or the a
32+
representation of the constant. `static` initializers are always represented as
33+
[`miri`](./miri.html) virtual memory allocations (via [`ConstValue::ByRef`]).
34+
Other constants get represented as [`ConstValue::Scalar`]
35+
or [`ConstValue::Slice`] if possible. This means that the `const_eval_*`
36+
functions cannot be used to create miri-pointers to the evaluated constant.
37+
If you need the value of a constant inside Miri, you need to directly work with
38+
[`eval_const_to_op`].
39+
40+
[`GlobalId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/struct.GlobalId.html
41+
[`ConstValue::Scalar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Scalar
42+
[`ConstValue::Slice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Slice
43+
[`ConstValue::ByRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.ByRef
44+
[`ConstEvalResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.ConstEvalResult.html
45+
[`eval_const_to_op`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.InterpCx.html#method.eval_const_to_op

src/miri.md

+15-15
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Miri
22

33
Miri (**MIR** **I**nterpreter) is a virtual machine for executing MIR without
4-
compiling to machine code. It is usually invoked via `tcx.const_eval`.
4+
compiling to machine code. It is usually invoked via `tcx.const_eval_*` functions.
55

6-
If you start out with a constant
6+
If you start out with a constant:
77

88
```rust
99
const FOO: usize = 1 << 12;
@@ -12,7 +12,7 @@ const FOO: usize = 1 << 12;
1212
rustc doesn't actually invoke anything until the constant is either used or
1313
placed into metadata.
1414

15-
Once you have a use-site like
15+
Once you have a use-site like:
1616

1717
```rust,ignore
1818
type Foo = [u8; FOO - 42];
@@ -35,17 +35,17 @@ Invoking `tcx.const_eval(param_env.and(gid))` will now trigger the creation of
3535
the MIR of the array length expression. The MIR will look something like this:
3636

3737
```mir
38-
const Foo::{{initializer}}: usize = {
39-
let mut _0: usize; // return pointer
38+
Foo::{{constant}}#0: usize = {
39+
let mut _0: usize;
4040
let mut _1: (usize, bool);
4141

4242
bb0: {
43-
_1 = CheckedSub(const Unevaluated(FOO, Slice([])), const 42usize);
44-
assert(!(_1.1: bool), "attempt to subtract with overflow") -> bb1;
43+
_1 = CheckedSub(const FOO, const 42usize);
44+
assert(!move (_1.1: bool), "attempt to subtract with overflow") -> bb1;
4545
}
4646

4747
bb1: {
48-
_0 = (_1.0: usize);
48+
_0 = move (_1.0: usize);
4949
return;
5050
}
5151
}
@@ -55,16 +55,16 @@ Before the evaluation, a virtual memory location (in this case essentially a
5555
`vec![u8; 4]` or `vec![u8; 8]`) is created for storing the evaluation result.
5656

5757
At the start of the evaluation, `_0` and `_1` are
58-
`Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef))`. This is quite
58+
`Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef))`. This is quite
5959
a mouthful: [`Operand`] can represent either data stored somewhere in the
6060
[interpreter memory](#memory) (`Operand::Indirect`), or (as an optimization)
6161
immediate data stored in-line. And [`Immediate`] can either be a single
6262
(potentially uninitialized) [scalar value][`Scalar`] (integer or thin pointer),
63-
or a pair of two of them. In our case, the single scalar value is *not* (yet)
63+
or a pair of two of them. In our case, the single scalar value is *not* (yet)
6464
initialized.
6565

6666
When the initialization of `_1` is invoked, the value of the `FOO` constant is
67-
required, and triggers another call to `tcx.const_eval`, which will not be shown
67+
required, and triggers another call to `tcx.const_eval_*`, which will not be shown
6868
here. If the evaluation of FOO is successful, `42` will be subtracted from its
6969
value `4096` and the result stored in `_1` as
7070
`Operand::Immediate(Immediate::ScalarPair(Scalar::Raw { data: 4054, .. },
@@ -200,8 +200,8 @@ division on pointer values.
200200

201201
## Interpretation
202202

203-
Although the main entry point to constant evaluation is the `tcx.const_eval`
204-
query, there are additional functions in
203+
Although the main entry point to constant evaluation is the `tcx.const_eval_*`
204+
functions, there are additional functions in
205205
[librustc_mir/const_eval.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/const_eval/index.html)
206206
that allow accessing the fields of a `ConstValue` (`ByRef` or otherwise). You should
207207
never have to access an `Allocation` directly except for translating it to the
@@ -217,7 +217,7 @@ A stack frame is defined by the `Frame` type in
217217
and contains all the local
218218
variables memory (`None` at the start of evaluation). Each frame refers to the
219219
evaluation of either the root constant or subsequent calls to `const fn`. The
220-
evaluation of another constant simply calls `tcx.const_eval`, which produces an
220+
evaluation of another constant simply calls `tcx.const_eval_*`, which produce an
221221
entirely new and independent stack frame.
222222

223223
The frames are just a `Vec<Frame>`, there's no way to actually refer to a
@@ -229,4 +229,4 @@ Miri now calls the `step` method (in
229229
) until it either returns an error or has no further statements to execute. Each
230230
statement will now initialize or modify the locals or the virtual memory
231231
referred to by a local. This might require evaluating other constants or
232-
statics, which just recursively invokes `tcx.const_eval`.
232+
statics, which just recursively invokes `tcx.const_eval_*`.

0 commit comments

Comments
 (0)