`const if` to supress instantiation/codegen of unreachable branches
Nobody has claimed this yet.
- Dominant language
- Markdown
- Stars
- 6.6k
- Forks
- 1.7k
- Avg merge
- 16h 14m
- Merged PRs (30d)
- 1
Description
Currently there's a suboptimal interaction between const asserts and const generics.
A more general function that is valid for all N cannot call a function that asserts at compile time that N fulfills some conditions even if the call is on a branch that's dead for the invalid N.
I.e. this does not compile:
#![feature(inline_const)]
// method in std
fn method_with_precondition<const N: usize>() {
const { assert!(N > 0) };
}
// user method, no way to opt out of asserts for N = 0
fn generic_caller_method<const N: usize>() -> fn() {
if N > 0 {
panic_on_zero::<N>
} else {
|| {} // fallback
}
}
fn main() {
let _fun = foo::<0>();
}
error[E0080]: evaluation of `panic_on_zero::<0>::{constant#0}` failed
--> src/main.rs:5:13
|
5 | const { assert!(N > 0) };
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: N > 0', src/main.rs:5:13
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
This blocks / requires unpleasant choices in several T-libs features that want to check for N != 0 or similar constraints:
- https://github.com/rust-lang/rust/issues/100450
- https://github.com/rust-lang/rust/issues/74985
- https://github.com/rust-lang/rust/issues/75027
- https://github.com/rust-lang/rust/issues/90091 - although this one needs generic_const_exprs before we can even worry about callers
- https://github.com/rust-lang/rust/issues/87155
If const-eval in the dead branches is expensive it might also help compile perf.
There are efforts (https://github.com/rust-lang/rust/issues/99682) to move monomorphization-time errors to check time and also apply those checks to dead code (https://github.com/rust-lang/rust/pull/112879), which will make it even more difficult to discharge compile-time obligations imposed by callees.
Currently the language does not seem to have any way to select different code paths in generic contexts without also instantiating those paths. Even generic_const_exprs does not offer this unless it gets extended https://github.com/rust-lang/project-const-generics/issues/26
Therefore it would be useful if we could write the case above as
fn foo<const N: usize>() -> fn() {
const if N > 0 {
panic_on_zero::<N>
} else {
|| {} // fallback
}
}
so that panic_on_zero::<0> will never be instantiated.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the issue's generic-const example and proposed const if syntax, then read the linked issues on const generics, monomorphization-time errors, and dead-code checks. Compare the proposal with the constraints described in those discussions. Done means a settled language design and an accepted RFC or other documented resolution; no implementation files or tests are named.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100