Skip to content

Commit 7667292

Browse files
authored
Add RFC for no-argument m.Case() semantic change. (amaranth-lang#39)
2 parents 14e0a61 + 252fac8 commit 7667292

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

text/0039-empty-case.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
- Start Date: 2024-01-08
2+
- RFC PR: [amaranth-lang/rfcs#39](https://github.com/amaranth-lang/rfcs/pull/39)
3+
- Amaranth Issue: [amaranth-lang/amaranth#1021](https://github.com/amaranth-lang/amaranth/issues/1021)
4+
5+
# Change semantics of no-argument `m.Case()`
6+
7+
## Summary
8+
[summary]: #summary
9+
10+
Change the semantics of `with m.Case():` (without any arguments) from always-true conditional to always-false conditional. Likewise, change `value.matches()` from returning `C(1)` to returning `C(0)`.
11+
12+
## Motivation
13+
[motivation]: #motivation
14+
15+
Currently, `with m.Case():` results in an always-true conditional, and `value.matches()` likewise returns a const-1 value. However, this is not consistent with what would be expected from extrapolating the non-empty case.
16+
17+
In all non-empty cases, the semantics are equivalent to an OR of equality comparisons with all specified values:
18+
19+
`value.matches(1, 2, 3) =def= (value == 1) | (value == 2) | (value == 3)`
20+
21+
`value.matches(1, 2, 3) =def= Const(0) | (value == 1) | (value == 2) | (value == 3)`
22+
23+
Extrapolating from this, one would expect `value.matches()` to be the empty OR, ie. `Const(0)`.
24+
25+
It is unlikely that any manually written code will rely on this, but this can be a dangerous trap for machine-generated code that doesn't take the empty case into account.
26+
27+
## Guide-level explanation
28+
[guide-level-explanation]: #guide-level-explanation
29+
30+
The semantics of `m.Case()` change from always matching to never matching. Likewise, the semantics of `value.matches()` change from always-1 to always-0. The change is committed to the current `main` branch and will be included in Amaranth 0.5.
31+
32+
Amaranth 0.4.1 is released with the old semantics, but a deprecation warning is emitted whenever `m.Case()` or `value.matches()` is used.
33+
34+
## Reference-level explanation
35+
[reference-level-explanation]: #reference-level-explanation
36+
37+
See above.
38+
39+
## Drawbacks
40+
[drawbacks]: #drawbacks
41+
42+
Obviously backwards-incompatible, changes the semantics of a language construct to the direct opposite.
43+
44+
## Rationale and alternatives
45+
[rationale-and-alternatives]: #rationale-and-alternatives
46+
47+
It is unlikely anyone actually uses `value.matches()` directly, since this is just a constant. For generated code, the current semantics is much more likely to be a bug that intended behavior.
48+
49+
For `m.Case()` the situation is similar: it is redundant with `m.Default()`, which should be used instead. It is somewhat possible that there is code out there written by someone who didn't know about `m.Default()` and ended up using `m.Case()` instead (the official documentation didn't include either for a long time). This code will need to be fixed.
50+
51+
An alternative, if the empty case is deemed too confusing or insufficiently useful, is to make the semantics a hard error instead.
52+
53+
## Prior art
54+
[prior-art]: #prior-art
55+
56+
The current behavior is likely taken directly from RTLIL, which exhibits a similar inconsistency.
57+
58+
## Unresolved questions
59+
[unresolved-questions]: #unresolved-questions
60+
61+
Should we include more warnings about the change? This RFC proposes a warning in the 0.4.1 release, but this will never be seen by someone always using amaranth from git main.
62+
63+
## Future possibilities
64+
[future-possibilities]: #future-possibilities
65+
66+
None.

0 commit comments

Comments
 (0)