-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Description
Consider the following code (Playground):
const _: i32 = match 1 {
2 => 3,
4 => 5,
_ => 0,
};
const _: i32 = if true {
4
} else {
5
};This is not valid today, since if and match are forbidden in constants. That restriction can be lifted soon on nightly, so we would like to emit good errors that point the user to the offending code and suggest a feature gate if it would help.
However, the errors emitted by the nightly compiler are not great:
error[E0019]: constant contains unimplemented expression type
--> src/lib.rs:1:22
|
1 | const _: i32 = match 1 {
| ^
error[E0019]: constant contains unimplemented expression type
--> src/lib.rs:2:5
|
2 | 2 => 3,
| ^
error[E0019]: constant contains unimplemented expression type
--> src/lib.rs:7:19
|
7 | const _: i32 = if true {
| ^^^^
error[E0019]: constant contains unimplemented expression type
--> src/lib.rs:7:16
|
7 | const _: i32 = if true {
| ________________^
8 | | 4
9 | | } else {
10 | | 5
11 | | };
| |_^
error: aborting due to 4 previous errors
At present, each const has two errors associated with it. One is triggered by the FakeRead emitted for the borrow checker and points to the value being branched on (1 and true) respectively. The other is triggered by the SwitchInt terminator itself. While the span of this error is good for the if (it points to the whole if-else construct), it is very confusing for the match, where it points to the pattern in the first match arm despite the SwitchInt handling all arms simultaneously.
I've thought a bit about how to improve this, but I don't have a great solution. I'm hoping someone can help. I don't think we want to rely only on the presence of FakeRead to reject branchy code in a const; SwitchInt seems like the natural candidate (maybe with a fallback to FakeRead to detect single-arm match statements). However, I don't know how to improve the span for the SwitchInt for the match, or if doing so would cause other diagnostics to regress.
I think the ideal approach would be to check for this at the HIR or AST level. This would give us very precise spans, and we could continue checking for SwitchInt in the MIR to make sure the high-level check didn't miss anything. Is this feasible?