[Rust Generator] Packet specialization match arms sorted alphabetically instead of preserving declaration order or specificity
- Dominant language
- Rust
- Stars
- 86
- Forks
- 18
- Avg merge
- 20h 49m
- Merged PRs (30d)
- 1
Description
### Description
In the Rust code generator (`pdlc --output-format rust`), child packet specialization match arms in `specialize()` / `decode()` are generated in alphabetical order of the packet struct names rather than preserving declaration order or ordering by specificity (e.g. evaluating child packets with more discriminant constraints before generic base/intermediate packets).
When a more specific child packet's name alphabetically follows a more generic sibling or parent packet's name, the generic match arm is evaluated first and greedily matches the buffer, masking the specific child packet and dropping child-specific fields.
---
### Minimal Reproducible Example
Consider the following mock PDL definitions:
```pdl
enum MessageType : 8 {
CONTROL = 1,
DATA = 2,
}
enum Subtype : 8 {
DEFAULT = 0,
EXTENDED = 1,
}
packet Message {
msg_type: MessageType,
subtype: Subtype,
_payload_,
}
// 1. Generic base child (matches any CONTROL message)
packet GenericControlMessage : Message (msg_type = CONTROL) {
}
// 2. Specific child with an additional constraint and extra fields
packet SpecificControlMessage : Message (msg_type = CONTROL, subtype = EXTENDED) {
extended_param: 8,
}
```
### Observed Behavior
Because the generated Rust parser orders match arms alphabetically:
1. `GenericControlMessage` ('G') is placed **before** `SpecificControlMessage` ('S').
2. When parsing a buffer for `SpecificControlMessage` (`msg_type = CONTROL`, `subtype = EXTENDED`, `extended_param = 0x42`):
- The parser evaluates `GenericControlMessage` first.
- Because `GenericControlMessage` only checks `msg_type = CONTROL`, the match succeeds.
- `extended_param` is swallowed into unparsed trailing payload rather than decoding into `SpecificControlMessage`.
- `SpecificControlMessage` is never reached.
*Note: If the specific packet were renamed to `ASpecificControlMessage`, it would match correctly simply because `'A' < 'G'`.*
---
### Expected Behavior
The Rust backend should generate specialization match arms either:
1. **Preserving declaration order** as written in the `.pdl` file (allowing authors to declare specific variants before generic fallback variants).
2. **Ordering by constraint specificity** (child packets with more discriminant constraints evaluated before variants with fewer constraints).
---
### Environment
* PDL Compiler: `pdlc --output-format rust`
* Target Language: Rust
Contributor guide
Research direction
Start by running the minimal PDL example with `pdlc --output-format rust` and inspect the generated `specialize()` and `decode()` match arms. Trace where child packet arms are ordered, then determine whether declaration order or discriminant specificity is the intended rule. Done means a specific child is evaluated before a generic matching sibling and its child-specific fields are decoded rather than treated as trailing payload.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100