Skip to content

Commit 6535a4a

Browse files
committed
Merge remote-tracking branch 'oli-obk/master'
2 parents 0881d7b + 61d1436 commit 6535a4a

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

text/0000-compile-time-asserts.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
- Feature Name: compile_time_asserts
2+
- Start Date: 2015-07-30
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
8+
If the constant evaluator encounters erronous code during the evaluation of
9+
an expression that is not part of a true constant evaluation context a warning
10+
must be emitted and the expression needs to be translated normally.
11+
12+
# Definition of constant evaluation context
13+
14+
There are exactly five places where an expression needs to be constant.
15+
16+
- the initializer of a constant `const foo: ty = EXPR` or `static foo: ty = EXPR`
17+
- the size of an array `[T; EXPR]`
18+
- the length of a repeat expression `[VAL; LEN_EXPR]`
19+
- C-Like enum variant discriminant values
20+
- patterns
21+
22+
In the future the body of `const fn` might also be interpreted as a constant
23+
evaluation context.
24+
25+
Any other expression might still be constant evaluated, but it could just
26+
as well be compiled normally and executed at runtime.
27+
28+
# Motivation
29+
30+
Expressions are const-evaluated even when they are not in a const environment.
31+
32+
For example
33+
34+
```rust
35+
fn blub<T>(t: T) -> T { t }
36+
let x = 5 << blub(42);
37+
```
38+
39+
will not cause a compiler error currently, while `5 << 42` will.
40+
If the constant evaluator gets smart enough, it will be able to const evaluate
41+
the `blub` function. This would be a breaking change, since the code would not
42+
compile anymore. (this occurred in https://github.com/rust-lang/rust/pull/26848).
43+
44+
# Detailed design
45+
46+
The PRs https://github.com/rust-lang/rust/pull/26848 and https://github.com/rust-lang/rust/pull/25570 will be setting a precedent
47+
for warning about such situations (WIP, not pushed yet).
48+
49+
When the constant evaluator fails while evaluating a normal expression,
50+
a warning will be emitted and normal translation needs to be resumed.
51+
52+
# Drawbacks
53+
54+
None, if we don't do anything, the const evaluator cannot get much smarter.
55+
56+
# Alternatives
57+
58+
## allow breaking changes
59+
60+
Let the compiler error on things that will unconditionally panic at runtime.
61+
62+
## insert an unconditional panic instead of generating regular code
63+
64+
GNAT (an Ada compiler) does this already:
65+
66+
```ada
67+
procedure Hello is
68+
Var: Integer range 15 .. 20 := 21;
69+
begin
70+
null;
71+
end Hello;
72+
```
73+
74+
The anonymous subtype `Integer range 15 .. 20` only accepts values in `[15, 20]`.
75+
This knowledge is used by GNAT to emit the following warning during compilation:
76+
77+
```
78+
warning: value not in range of subtype of "Standard.Integer" defined at line 2
79+
warning: "Constraint_Error" will be raised at run time
80+
```
81+
82+
I don't have a GNAT with `-emit-llvm` handy, but here's the asm with `-O0`:
83+
84+
```asm
85+
.cfi_startproc
86+
pushq %rbp
87+
.cfi_def_cfa_offset 16
88+
.cfi_offset 6, -16
89+
movq %rsp, %rbp
90+
.cfi_def_cfa_register 6
91+
movl $2, %esi
92+
movl $.LC0, %edi
93+
movl $0, %eax
94+
call __gnat_rcheck_CE_Range_Check
95+
```
96+
97+
98+
# Unresolved questions
99+
100+
## Const-eval the body of `const fn` that are never used in a constant environment
101+
102+
Currently a `const fn` that is called in non-const code is treated just like a normal function.
103+
104+
In case there is a statically known erroneous situation in the body of the function,
105+
the compiler should raise an error, even if the function is never called.
106+
107+
The same applies to unused associated constants.

0 commit comments

Comments
 (0)