An Option has no fields to take the address of, and two rows now say so
FIX.org carried Addr(Pfield ...) on an Option as a hole in both backends. It is not reachable from the language: a field access goes through struct_target, which admits a struct or a pointer to one and refuses everything else by name with a location, so (addr (.x o)) is refused at the field and never reaches a place. The node that failed was one the compiler built for itself. The refusal is pinned on the bare field and on the address of one, and FIX.org now records the finding, including the asymmetry that stays: the x86 backend lays out an Option's tag and value as fields and the LLVM backend does not. Neither path is reachable, so matching them would be untestable code written to balance a road nobody drives on.
This commit is contained in:
parent
81b807f544
commit
9f85139f1f
16
FIX.org
16
FIX.org
@ -156,9 +156,19 @@ against 985ms on LLVM.
|
||||
arena does not make safe — and that a Map has no operation answering *where*
|
||||
a value lives, which is what reading an arena-parsed EDN document back would
|
||||
need. Both were relayed to the arena agent.
|
||||
- [Tast.Addr (Tast.Pfield ...)] on an Option fails in both backends. The
|
||||
working route is [Prim (AddrOf, [Field ...])]. Found by the drop lane, not
|
||||
fixed.
|
||||
- [Tast.Addr (Tast.Pfield ...)] on an Option: closed, and closed as
|
||||
unreachable rather than fixed. Nothing in the source language builds it.
|
||||
[.field] goes through [struct_target], which admits a struct and a pointer
|
||||
to one and refuses everything else by name with a location — "(Option Point)
|
||||
is not a struct, so it has no fields" — so [(addr (.x o))] never reaches a
|
||||
place for [addr] to take. The node the drop lane hit was one the compiler
|
||||
built for itself. Two rows in test_flan.ml pin the refusal, on the bare field
|
||||
and on the address of one.
|
||||
What is still asymmetric, and is a note rather than a bug: [x86.ml]'s
|
||||
[field_loc] does lay out an Option's tag and value, and [emit.ml]'s [place]
|
||||
admits only a named struct. Neither is reachable, so neither is tested, and
|
||||
growing the LLVM side to match would be untestable code written to balance a
|
||||
path nothing takes.
|
||||
- Re-run still does not work under --two-process: a finished child is
|
||||
genuinely gone. It now works under --x86 because --x86 runs merged.
|
||||
- sand.flan still holds an uncommitted experiment line that is refused with a
|
||||
|
||||
@ -912,6 +912,22 @@ let () =
|
||||
(defn f [s [u8]] i32 (let [c (Cursor {.src s})] (g (addr c))))");
|
||||
rejects_check "addr of a non-place"
|
||||
"(defn f [] () (addr (+ 1 2)))" ~needle:"addr takes the address of a place";
|
||||
(* An Option's two fields exist in both backends' layouts — the tag and the
|
||||
value — and the structural printer reads the tag through them. What has no
|
||||
spelling in the source language is reaching one: [match] and [some] are
|
||||
how an Option is opened, and a (.field o) that read the value of a None
|
||||
would be reading storage the tag says is not there. FIX.org recorded
|
||||
[Addr (Pfield ...)] on an Option as a hole in both backends; this is the
|
||||
pair of rows that says the hole has no door — the refusal is the field
|
||||
access itself, so (addr ...) never gets a place to take the address of. *)
|
||||
rejects_check "a field of an Option"
|
||||
"(defstruct Point [x i32 y i32])\n\
|
||||
(defn f [o (Option Point)] i32 (.x o))"
|
||||
~needle:"(Option Point) is not a struct, so it has no fields";
|
||||
rejects_check "the address of a field of an Option"
|
||||
"(defstruct Point [x i32 y i32])\n\
|
||||
(defn f [o (Option Point)] (Ptr i32) (addr (.x o)))"
|
||||
~needle:"(Option Point) is not a struct, so it has no fields";
|
||||
|
||||
(* ── Option, some, match ───────────────────────────────────────── *)
|
||||
accepts "some unwraps in an Option-returning function"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user