From 1ace1e4c30046c40b23bb1743854081a0f951d6a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 30 Jul 2015 16:26:03 +0200 Subject: [PATCH 1/6] turn statically known erroneous code into a warning and an unconditional panic --- text/0000-compile-time-asserts.md | 88 +++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 text/0000-compile-time-asserts.md diff --git a/text/0000-compile-time-asserts.md b/text/0000-compile-time-asserts.md new file mode 100644 index 00000000000..7aefb2548b7 --- /dev/null +++ b/text/0000-compile-time-asserts.md @@ -0,0 +1,88 @@ +- Feature Name: compile_time_asserts +- Start Date: 2015-07-30 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary + +If the compiler can detect at compile-time that something will always +cause a `debug_assert` or an `assert` it should instead +insert an unconditional runtime-panic and issue a warning. + +# Motivation + +Expressions are const-evaluated even when they are not in a const environment. + +For example + +```rust +fn blub(t: T) -> T { t } +let x = 5 << blub(42); +``` + +will not cause a compiler error currently, while `5 << 42` will. +If the constant evaluator gets smart enough, it will be able to const evaluate +the `blub` function. This would be a breaking change, since the code would not +compile anymore. (this occurred in https://github.com/rust-lang/rust/pull/26848). + +GNAT (an Ada compiler) does this already: + +```ada +procedure Hello is + Var: Integer range 15 .. 20 := 21; +begin + null; +end Hello; +``` + +The anonymous subtype `Integer range 15 .. 20` only accepts values in `[15, 20]`. +This knowledge is used by GNAT to emit the following warning during compilation: + +``` +warning: value not in range of subtype of "Standard.Integer" defined at line 2 +warning: "Constraint_Error" will be raised at run time +``` + +I don't have a GNAT with `-emit-llvm` handy, but here's the asm with `-O0`: + +```asm +.cfi_startproc +pushq %rbp +.cfi_def_cfa_offset 16 +.cfi_offset 6, -16 +movq %rsp, %rbp +.cfi_def_cfa_register 6 +movl $2, %esi +movl $.LC0, %edi +movl $0, %eax +call __gnat_rcheck_CE_Range_Check +``` + + +# Detailed design + +The PRs https://github.com/rust-lang/rust/pull/26848 and https://github.com/rust-lang/rust/pull/25570 will be setting a precedent +for warning about such situations (WIP, not pushed yet). +All future additions to the const-evaluator need to notify the const evaluator +that when it encounters a statically known erroneous situation, the +entire expression must be replaced by a panic and a warning must be emitted. + +# Drawbacks + +None, if we don't do anything, the const evaluator cannot get much smarter. + +# Alternatives + +## allow breaking changes + +Let the compiler error on things that will unconditionally panic at runtime. + +## only warn, don't influence code generation + +This has the disadvantage, that in release-mode statically known issues like +overflow or shifting more than the number of bits available will not be +caught even at runtime. + +# Unresolved questions + +How to implement this? From 1a7110bd8b6ca96b579604e626d76909ef5853c2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 31 Jul 2015 10:35:24 +0200 Subject: [PATCH 2/6] add a definition of constant evaluation context --- text/0000-compile-time-asserts.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/text/0000-compile-time-asserts.md b/text/0000-compile-time-asserts.md index 7aefb2548b7..b37380fd0c4 100644 --- a/text/0000-compile-time-asserts.md +++ b/text/0000-compile-time-asserts.md @@ -9,6 +9,20 @@ If the compiler can detect at compile-time that something will always cause a `debug_assert` or an `assert` it should instead insert an unconditional runtime-panic and issue a warning. +# Definition of constant evaluation context + +There are exactly three places where an expression needs to be constant. + +- the initializer of a constant `const foo: ty = EXPR` or `static foo: ty = EXPR` +- the size of an array `[T; EXPR]` +- the length of a repeat expression `[VAL; LEN_EXPR]` + +In the future the body of `const fn` might also be interpreted as a constant +evaluation context. + +Any other expression might still be constant evaluated, but it could just +as well be compiled normally and executed at runtime. + # Motivation Expressions are const-evaluated even when they are not in a const environment. From 3855520c722f606934e6a19502e31f490eea71ab Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 31 Jul 2015 10:35:34 +0200 Subject: [PATCH 3/6] minor clarifications --- text/0000-compile-time-asserts.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/text/0000-compile-time-asserts.md b/text/0000-compile-time-asserts.md index b37380fd0c4..d3f8e424cf1 100644 --- a/text/0000-compile-time-asserts.md +++ b/text/0000-compile-time-asserts.md @@ -78,7 +78,8 @@ call __gnat_rcheck_CE_Range_Check The PRs https://github.com/rust-lang/rust/pull/26848 and https://github.com/rust-lang/rust/pull/25570 will be setting a precedent for warning about such situations (WIP, not pushed yet). All future additions to the const-evaluator need to notify the const evaluator -that when it encounters a statically known erroneous situation, the +that when it encounters a statically known erroneous situation while evaluating +an expression outside of a constant evaluation environment, the entire expression must be replaced by a panic and a warning must be emitted. # Drawbacks @@ -93,10 +94,13 @@ Let the compiler error on things that will unconditionally panic at runtime. ## only warn, don't influence code generation +The const evaluator should simply issue a warning and notify it's caller that the expression cannot be evaluated and should be translated. This has the disadvantage, that in release-mode statically known issues like overflow or shifting more than the number of bits available will not be caught even at runtime. +On the other hand, this alternative does not change the behavior of existing code. + # Unresolved questions How to implement this? From 81079080ca8087b9a5ebf118c437c13090aa3f42 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 31 Jul 2015 10:49:51 +0200 Subject: [PATCH 4/6] add const fn unresolved question --- text/0000-compile-time-asserts.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/text/0000-compile-time-asserts.md b/text/0000-compile-time-asserts.md index d3f8e424cf1..796e60a75e8 100644 --- a/text/0000-compile-time-asserts.md +++ b/text/0000-compile-time-asserts.md @@ -103,4 +103,13 @@ On the other hand, this alternative does not change the behavior of existing cod # Unresolved questions -How to implement this? +## How to implement this? + +## Const-eval the body of `const fn` that are never used in a constant environment + +Currently a `const fn` that is called in non-const code is treated just like a normal function. + +In case there is a statically known erroneous situation in the body of the function, +the compiler should raise an error, even if the function is never called. + +The same applies to unused associated constants. From 1354de7b180575bc31560bd26b3f6f93bc264252 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 31 Jul 2015 21:06:45 +0200 Subject: [PATCH 5/6] added c-like enums and patterns to const context list --- text/0000-compile-time-asserts.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/0000-compile-time-asserts.md b/text/0000-compile-time-asserts.md index 796e60a75e8..e6423478b19 100644 --- a/text/0000-compile-time-asserts.md +++ b/text/0000-compile-time-asserts.md @@ -11,11 +11,13 @@ insert an unconditional runtime-panic and issue a warning. # Definition of constant evaluation context -There are exactly three places where an expression needs to be constant. +There are exactly five places where an expression needs to be constant. - the initializer of a constant `const foo: ty = EXPR` or `static foo: ty = EXPR` - the size of an array `[T; EXPR]` - the length of a repeat expression `[VAL; LEN_EXPR]` +- C-Like enum variant discriminant values +- patterns In the future the body of `const fn` might also be interpreted as a constant evaluation context. From 61d1436d9d9f41f4741add6c201d6284661e1453 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 7 Aug 2015 15:08:26 +0200 Subject: [PATCH 6/6] use alternative "warn + normal codegen" instead --- text/0000-compile-time-asserts.md | 56 +++++++++++++------------------ 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/text/0000-compile-time-asserts.md b/text/0000-compile-time-asserts.md index e6423478b19..72cbcfcc7d6 100644 --- a/text/0000-compile-time-asserts.md +++ b/text/0000-compile-time-asserts.md @@ -5,9 +5,9 @@ # Summary -If the compiler can detect at compile-time that something will always -cause a `debug_assert` or an `assert` it should instead -insert an unconditional runtime-panic and issue a warning. +If the constant evaluator encounters erronous code during the evaluation of +an expression that is not part of a true constant evaluation context a warning +must be emitted and the expression needs to be translated normally. # Definition of constant evaluation context @@ -41,6 +41,26 @@ If the constant evaluator gets smart enough, it will be able to const evaluate the `blub` function. This would be a breaking change, since the code would not compile anymore. (this occurred in https://github.com/rust-lang/rust/pull/26848). +# Detailed design + +The PRs https://github.com/rust-lang/rust/pull/26848 and https://github.com/rust-lang/rust/pull/25570 will be setting a precedent +for warning about such situations (WIP, not pushed yet). + +When the constant evaluator fails while evaluating a normal expression, +a warning will be emitted and normal translation needs to be resumed. + +# Drawbacks + +None, if we don't do anything, the const evaluator cannot get much smarter. + +# Alternatives + +## allow breaking changes + +Let the compiler error on things that will unconditionally panic at runtime. + +## insert an unconditional panic instead of generating regular code + GNAT (an Ada compiler) does this already: ```ada @@ -75,38 +95,8 @@ call __gnat_rcheck_CE_Range_Check ``` -# Detailed design - -The PRs https://github.com/rust-lang/rust/pull/26848 and https://github.com/rust-lang/rust/pull/25570 will be setting a precedent -for warning about such situations (WIP, not pushed yet). -All future additions to the const-evaluator need to notify the const evaluator -that when it encounters a statically known erroneous situation while evaluating -an expression outside of a constant evaluation environment, the -entire expression must be replaced by a panic and a warning must be emitted. - -# Drawbacks - -None, if we don't do anything, the const evaluator cannot get much smarter. - -# Alternatives - -## allow breaking changes - -Let the compiler error on things that will unconditionally panic at runtime. - -## only warn, don't influence code generation - -The const evaluator should simply issue a warning and notify it's caller that the expression cannot be evaluated and should be translated. -This has the disadvantage, that in release-mode statically known issues like -overflow or shifting more than the number of bits available will not be -caught even at runtime. - -On the other hand, this alternative does not change the behavior of existing code. - # Unresolved questions -## How to implement this? - ## Const-eval the body of `const fn` that are never used in a constant environment Currently a `const fn` that is called in non-const code is treated just like a normal function.