diff options
| author | Jubilee <workingjubilee@gmail.com> | 2025-06-24 19:45:30 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-24 19:45:30 -0700 |
| commit | f542909d1ceae371fe0e236e00276109522fa86d (patch) | |
| tree | 9dc32e189696a4705b9b3f8f6b26fcb6a8a8a4c3 /src | |
| parent | 4f477427b81bba86e8b761a5fb5b52635b82d54e (diff) | |
| parent | ba5556d239c11232dc8d95123ea70a2783019476 (diff) | |
| download | rust-f542909d1ceae371fe0e236e00276109522fa86d.tar.gz rust-f542909d1ceae371fe0e236e00276109522fa86d.zip | |
Rollup merge of #138780 - trifectatechfoundation:loop_match_attr, r=oli-obk,traviscross
Add `#[loop_match]` for improved DFA codegen
tracking issue: https://github.com/rust-lang/rust/issues/132306
project goal: https://github.com/rust-lang/rust-project-goals/issues/258
This PR adds the `#[loop_match]` attribute, which aims to improve code generation for state machines. For some (very exciting) benchmarks, see https://github.com/rust-lang/rust-project-goals/issues/258#issuecomment-2732965199
Currently, a very restricted syntax pattern is accepted. We'd like to get feedback and merge this now before we go too far in a direction that others have concerns with.
## current state
We accept code that looks like this
```rust
#[loop_match]
loop {
state = 'blk: {
match state {
State::A => {
#[const_continue]
break 'blk State::B
}
State::B => { /* ... */ }
/* ... */
}
}
}
```
- a loop should have the same semantics with and without `#[loop_match]`: normal `continue` and `break` continue to work
- `#[const_continue]` is only allowed in loops annotated with `#[loop_match]`
- the loop body needs to have this particular shape (a single assignment to the match scrutinee, with the body a labelled block containing just a match)
## future work
- perform const evaluation on the `break` value
- support more state/scrutinee types
## maybe future work
- allow `continue 'label value` syntax, which `#[const_continue]` could then use.
- allow the match to be on an arbitrary expression (e.g. `State::Initial`)
- attempt to also optimize `break`/`continue` expressions that are not marked with `#[const_continue]`
r? ``@traviscross``
Diffstat (limited to 'src')
| -rw-r--r-- | src/doc/unstable-book/src/language-features/loop-match.md | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/doc/unstable-book/src/language-features/loop-match.md b/src/doc/unstable-book/src/language-features/loop-match.md new file mode 100644 index 00000000000..4cc763d3434 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/loop-match.md @@ -0,0 +1,52 @@ +# `loop_match` + +The tracking issue for this feature is: [#132306] + +[#132306]: https://github.com/rust-lang/rust/issues/132306 + +------ + +The `#[loop_match]` and `#[const_continue]` attributes can be used to improve the code +generation of logic that fits this shape: + +```ignore (pseudo-rust) +loop { + state = 'blk: { + match state { + State::A => { + break 'blk State::B + } + State::B => { /* ... */ } + /* ... */ + } + } +} +``` + +Here the loop itself can be annotated with `#[loop_match]`, and any `break 'blk` with +`#[const_continue]` if the value is know at compile time: + +```ignore (pseudo-rust) +#[loop_match] +loop { + state = 'blk: { + match state { + State::A => { + #[const_continue] + break 'blk State::B + } + State::B => { /* ... */ } + /* ... */ + } + } +} +``` + +The observable behavior of this loop is exactly the same as without the extra attributes. +The difference is in the generated output: normally, when the state is `A`, control flow +moves from the `A` branch, back to the top of the loop, then to the `B` branch. With the +attributes, The `A` branch will immediately jump to the `B` branch. + +Removing the indirection can be beneficial for stack usage and branch prediction, and +enables other optimizations by clearly splitting out the control flow paths that your +program will actually use. |
