Skip to content

Commit a4573fb

Browse files
authored
Merge pull request #40 from RalfJung/const_checks
describe static vs dynamic const checks
2 parents 8873865 + 9c2a0c8 commit a4573fb

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ which sort of is a virtual machine using `MIR` as "bytecode".
2121
## Table of Contents
2222

2323
* [Const Safety](const_safety.md)
24+
* [Static and dynamic checks](const_checks.md)
2425
* The three "kinds" of compile-time evaluated data:
2526
* [Statics](static.md) (`static`, `static mut`)
2627
* [Constants](const.md) (`const`, array sizes, non-`Copy` array initializers)

const_checks.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Static and dynamic checks
2+
3+
This repository describes a set of rules that various forms of compile-time evaluated code needs to satisfy.
4+
The compiler contains two kinds of checks that guard against violations of these rules: static checks and dynamic checks.
5+
6+
## Dynamic checks
7+
8+
Dynamic checks are conceptually very simple: when evaluating the compile-time code, we look at what it does, and if what it does violates the rules, we halt evaluation.
9+
Thus, a dynamic check generally makes it very clear what is being protected against.
10+
11+
The main disadvantage of dynamic checks is that they can only run when the compile-time code is being evaluated, which is after monomorphization.
12+
We generally try to avoid post-monomorphization errors as they inherently make for a bad user experience.
13+
While there are technical aspects that could be improved here, the main problem is that the site where the error is reported is disconnected from the site where the root cause is.
14+
Such problems can be observed when creating an associated constant that uses associated constants from generic parameters.
15+
These generic parameters are unknown, so the usage of these associated constants may cause errors depending on the *value* of the generic parameter's associated constants.
16+
17+
[Promotion analysis](promotion.md) also makes little sense dynamically as it is about code transformation.
18+
All we can do is check after the transformation if the generated code makes sense.
19+
20+
## Static checks
21+
22+
Static checks work by "looking" at the code.
23+
(This is "static" as in [static analysis](https://en.wikipedia.org/wiki/Static_analysis), not to be confused with Rust's `static` keyword.)
24+
The idea is to predict what the code will do without actually executing it.
25+
That means we can even analyze code that we cannot run pre-monomorphization.
26+
However, static checks are necessarily less precise than dynamic checks (this is the famous halting problem), which means they will reject code that the dynamic checks would accept.
27+
28+
The key property is that the static check is *sound*, which means that everything accepted by the static checks will also be accepted by the dynamic checks.
29+
It might seem like this makes the dynamic checks unnecessary, but they are still tremendously useful.
30+
On the one hand, the dynamic checks serve as a safety net for when we have bugs in the static checks (dynamic checks are much easier to get right, typically).
31+
On the other hand, having the dynamic checks forces us through the helpful exercise of figuring out what the dynamic property we are enforcing actually *is*, which is crucial when we want to adjust the static check to be more precise.
32+
The dynamic check serves as the "ground truth" that the static check approximates, and we can improve that approximation over time.

static.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ Statics (`static`, `static mut`) are the simplest kind of compile-time evaluated
1414
## `Drop`
1515

1616
The compiler rejects intermediate values (created and discarded during the computation of a static initializer) that implement `Drop`.
17-
The reason for this is simply that the `Drop` implementation might be non-`const fn`.
17+
The reason for this is simply that the `Drop` implementation might be non-`const fn`
18+
(so really, this is just a special case of static initializers not being able to call non-`const` functions).
1819
This restriction can be lifted once `const impl Drop for Type` (or something similar) is supported.
1920

2021
```rust

0 commit comments

Comments
 (0)