Skip to content

Commit 1967c1c

Browse files
committed
fix(decoding): decode fieldless signed enum tags for allocs
1 parent 84b53a2 commit 1967c1c

2 files changed

Lines changed: 19 additions & 15 deletions

File tree

kmir/src/kmir/decoding.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,14 @@ def _decode_enum_multiple(
402402
# ---
403403
types: Mapping[Ty, TypeMetadata],
404404
) -> Value:
405-
assert len(offsets) == 1, 'Assumed offsets to only contain the tag offset'
406-
assert tag_field == 0, 'Assumed tag field to be zero accordingly'
407-
tag_offset = offsets[tag_field]
408-
tag_value, width = _extract_tag(data=data, tag_offset=tag_offset, tag=tag)
405+
if offsets:
406+
assert 0 <= tag_field < len(offsets), 'Expected tag_field to point to an existing offset'
407+
tag_offset_in_bytes = offsets[tag_field].in_bytes
408+
else:
409+
# Fieldless enums can omit offsets in Stable MIR; their tag still starts at byte 0.
410+
assert tag_field == 0, 'Expected empty offsets only when tag_field is zero'
411+
tag_offset_in_bytes = 0
412+
tag_value, width = _extract_tag(data=data, tag_offset_in_bytes=tag_offset_in_bytes, tag=tag)
409413
discriminant = tag_encoding.decode(tag_value, width=width)
410414

411415
try:
@@ -440,7 +444,7 @@ def _decode_fields(
440444
return res
441445

442446

443-
def _extract_tag(*, data: bytes, tag_offset: MachineSize, tag: Scalar) -> tuple[int, IntegerLength]:
447+
def _extract_tag(*, data: bytes, tag_offset_in_bytes: int, tag: Scalar) -> tuple[int, IntegerLength]:
444448
match tag:
445449
case Initialized(
446450
value=PrimitiveInt(
@@ -449,9 +453,8 @@ def _extract_tag(*, data: bytes, tag_offset: MachineSize, tag: Scalar) -> tuple[
449453
),
450454
valid_range=_,
451455
):
452-
# Stable MIR enum discriminants are represented against the raw tag bits.
453-
# Use unsigned decoding even when the scalar metadata marks the tag as signed.
454-
tag_data = data[tag_offset.in_bytes : tag_offset.in_bytes + length.value]
456+
tag_data = data[tag_offset_in_bytes : tag_offset_in_bytes + length.value]
457+
# For enum-tag decoding we match Stable MIR discriminants in wrapped form.
455458
tag_value = int.from_bytes(tag_data, byteorder='little', signed=False)
456459
return tag_value, length
457460
# special case: niche-encoded optional pointer, None == 0x00000000

kmir/src/tests/integration/data/prove-rs/show/iter-eq-copied-take-dereftruncate-fail.repro.expected

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
│ span: 0
55
6-
│ (5553 steps)
7-
└─ 3 (stuck, leaf)
8-
#traverseProjection ( toLocal ( 12 ) , thunk ( #decodeConstant ( constantKindAll
9-
span: 282
10-
11-
12-
┌─ 2 (root, leaf, target, terminal)
6+
│ (5601 steps)
7+
├─ 3 (terminal)
138
│ #EndProgram ~> .K
9+
10+
┊ constraint: true
11+
┊ subst: ...
12+
└─ 2 (leaf, target, terminal)
13+
#EndProgram ~> .K
14+
1415

1516

0 commit comments

Comments
 (0)