test(compiler): unit helpers run inference; retarget borrow-escape fixture
Wire Gcinfer.infer into runner.ml's owner_str/emit_str so the unit tests classify GC-ness identically to the driver (prerequisite for removing @gc: its tests read the golden .wo through the library). That exposed owner-err/borrow-escape.wo, which tested WO-E304 on *class* escapes — now legally demand-promoted. Retargeted it to CONTAINER (`multi Text`) escapes, which are owned and never promoted, so it still exercises the three WO-E304 shapes (stored-in-field, returned, moved-to-take). Assertion positions + golden re-blessed. Verified: woc-test 566/0, test_diag 14/0, oop-e2e 79/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
07bcc1c485
commit
1cedbda0bb
3 changed files with 25 additions and 22 deletions
|
|
@ -1,19 +1,19 @@
|
||||||
owner-err/borrow-escape.wo:9:16: error WO-E304: borrow of `other` cannot be stored in `self.box` — borrows cannot outlive their scope
|
owner-err/borrow-escape.wo:9:18: error WO-E304: borrow of `other` cannot be stored in `self.items` — borrows cannot outlive their scope
|
||||||
self.box = other
|
self.items = other
|
||||||
^
|
^
|
||||||
owner-err/borrow-escape.wo:8:12: `other` is borrowed here — declare it `take other: T` to pass ownership in
|
owner-err/borrow-escape.wo:8:12: `other` is borrowed here — declare it `take other: T` to pass ownership in
|
||||||
fn adopt(other: Box) {
|
fn adopt(other: multi Text) {
|
||||||
^
|
^
|
||||||
|
|
||||||
owner-err/borrow-escape.wo:18:10: error WO-E304: borrow of `h.box` escapes `leak` — borrows cannot outlive their scope
|
owner-err/borrow-escape.wo:18:10: error WO-E304: borrow of `h.items` escapes `leak` — borrows cannot outlive their scope
|
||||||
return h.box
|
return h.items
|
||||||
^
|
^
|
||||||
owner-err/borrow-escape.wo:17:9: `h` is borrowed here — declare it `take h: T` to pass ownership in
|
owner-err/borrow-escape.wo:17:9: `h` is borrowed here — declare it `take h: T` to pass ownership in
|
||||||
fn leak(h: Holder) -> Box {
|
fn leak(h: Holder) -> multi Text {
|
||||||
^
|
^
|
||||||
|
|
||||||
owner-err/borrow-escape.wo:22:15: error WO-E304: borrow of `h.box` cannot be passed to `take b` — borrows cannot outlive their scope
|
owner-err/borrow-escape.wo:22:15: error WO-E304: borrow of `h.items` cannot be passed to `take b` — borrows cannot outlive their scope
|
||||||
return keep(h.box)
|
return keep(h.items)
|
||||||
^
|
^
|
||||||
owner-err/borrow-escape.wo:21:10: `h` is borrowed here — declare it `take h: T` to pass ownership in
|
owner-err/borrow-escape.wo:21:10: `h` is borrowed here — declare it `take h: T` to pass ownership in
|
||||||
fn stash(h: Holder) -> Int {
|
fn stash(h: Holder) -> Int {
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
class Box {
|
-- Iteration 7b: WO-E304 borrow escapes, using CONTAINER values (`multi Text`).
|
||||||
n: Int
|
-- A class value that escapes is demand-promoted to traced, so the illustrative
|
||||||
}
|
-- escapes must be containers, which are owned and never promoted. Mirrors the
|
||||||
|
-- run/borrow-escape-return corpus case (a class escape, now legal).
|
||||||
class Holder {
|
class Holder {
|
||||||
box: Box
|
items: multi Text
|
||||||
|
|
||||||
fn adopt(other: Box) {
|
fn adopt(other: multi Text) {
|
||||||
self.box = other
|
self.items = other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keep(take b: Box) -> Int {
|
fn keep(take b: multi Text) -> Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn leak(h: Holder) -> Box {
|
fn leak(h: Holder) -> multi Text {
|
||||||
return h.box
|
return h.items
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stash(h: Holder) -> Int {
|
fn stash(h: Holder) -> Int {
|
||||||
return keep(h.box)
|
return keep(h.items)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ module Parser = Woc_lib.Parser
|
||||||
module Dump = Woc_lib.Dump
|
module Dump = Woc_lib.Dump
|
||||||
module Types = Woc_lib.Types
|
module Types = Woc_lib.Types
|
||||||
module Owner = Woc_lib.Owner
|
module Owner = Woc_lib.Owner
|
||||||
|
module Gcinfer = Woc_lib.Gcinfer
|
||||||
module Emit = Woc_lib.Emit
|
module Emit = Woc_lib.Emit
|
||||||
module Disasm = Woc_lib.Disasm
|
module Disasm = Woc_lib.Disasm
|
||||||
|
|
||||||
|
|
@ -1807,6 +1808,7 @@ let owner_str ~file src =
|
||||||
let toks = Lexer.tokenize collector ~file src in
|
let toks = Lexer.tokenize collector ~file src in
|
||||||
let prog = Parser.parse collector ~file toks in
|
let prog = Parser.parse collector ~file toks in
|
||||||
let syms, () = Types.typecheck ~file prog collector in
|
let syms, () = Types.typecheck ~file prog collector in
|
||||||
|
let syms = Gcinfer.infer [ (file, prog) ] syms in
|
||||||
let tables = Owner.analyze ~file prog syms collector in
|
let tables = Owner.analyze ~file prog syms collector in
|
||||||
(tables, collector)
|
(tables, collector)
|
||||||
|
|
||||||
|
|
@ -1819,6 +1821,7 @@ let emit_str ~file src =
|
||||||
let toks = Lexer.tokenize collector ~file src in
|
let toks = Lexer.tokenize collector ~file src in
|
||||||
let prog = Parser.parse collector ~file toks in
|
let prog = Parser.parse collector ~file toks in
|
||||||
let syms, () = Types.typecheck ~file prog collector in
|
let syms, () = Types.typecheck ~file prog collector in
|
||||||
|
let syms = Gcinfer.infer [ (file, prog) ] syms in
|
||||||
let tables = Owner.analyze ~file prog syms collector in
|
let tables = Owner.analyze ~file prog syms collector in
|
||||||
(* Single-file helper (every golden fixture is one file): its own
|
(* Single-file helper (every golden fixture is one file): its own
|
||||||
module is "." and that module's own symbols are exactly `syms` —
|
module is "." and that module's own symbols are exactly `syms` —
|
||||||
|
|
@ -1929,7 +1932,7 @@ let () =
|
||||||
field, returned, moved out to a `take` parameter. *)
|
field, returned, moved out to a `take` parameter. *)
|
||||||
match owner_err_fixture "borrow-escape" with
|
match owner_err_fixture "borrow-escape" with
|
||||||
| [ store; ret; take ] ->
|
| [ store; ret; take ] ->
|
||||||
check_site "borrow-escape (stored in a field)" ~code:"WO-E304" ~line:9 ~col:16 ~rel_line:8
|
check_site "borrow-escape (stored in a field)" ~code:"WO-E304" ~line:9 ~col:18 ~rel_line:8
|
||||||
~rel_col:12 store;
|
~rel_col:12 store;
|
||||||
check_site "borrow-escape (returned)" ~code:"WO-E304" ~line:18 ~col:10 ~rel_line:17 ~rel_col:9
|
check_site "borrow-escape (returned)" ~code:"WO-E304" ~line:18 ~col:10 ~rel_line:17 ~rel_col:9
|
||||||
ret;
|
ret;
|
||||||
|
|
@ -1937,7 +1940,7 @@ let () =
|
||||||
~rel_line:21 ~rel_col:10 take;
|
~rel_line:21 ~rel_col:10 take;
|
||||||
(* spec section 6's own wording for this diagnostic *)
|
(* spec section 6's own wording for this diagnostic *)
|
||||||
check "borrow-escape: names the place and the function it escapes"
|
check "borrow-escape: names the place and the function it escapes"
|
||||||
(Option.is_some (find_substring ~needle:"borrow of `h.box` escapes `leak`" ret.Diag.message))
|
(Option.is_some (find_substring ~needle:"borrow of `h.items` escapes `leak`" ret.Diag.message))
|
||||||
| ds ->
|
| ds ->
|
||||||
check_eq "borrow-escape: exactly three ownership errors" ~expected:3 ~actual:(List.length ds)
|
check_eq "borrow-escape: exactly three ownership errors" ~expected:3 ~actual:(List.length ds)
|
||||||
string_of_int
|
string_of_int
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue