writeonce/tests/corpus/run/lang-switch-class-arm-leak/fixture.wo
shoney.arickathil 1ba035397d feat(compiler): iteration 5 Tasks 1-4 — modules, language surface, switch, typedef records + enum variants
- Modules: `use`/`pub`, directory-as-module, per-module symbol resolution (a
  flat first-wins merge silently ran the wrong `pub fn` body), six reserved
  stdlib namespaces typed UNKNOWN-BUT-RESERVED.
- Surface: `and`/`or` (own precedence tier, short-circuit, Bool-only), `${}`
  interpolation desugared at parse time, `const`, break/continue with
  drop-correct exits, do-while, inline-fn rejection.
- switch expr/stmt: required `default` over scalars/Text, arm unification,
  EQ/EQS+JZ lowering, per-arm drop scopes with N-way JOIN-DROP; `default`
  sorted last by a shared lowering order (textual order made arms dead).
- typedef records: structural, same shape = one class entry; `?name: T`
  nullable-by-shape; emit_ctor fills omitted defaults; `type` as field name.
- Enum variants: all-bare unions = int ordinals; any-payload = one class
  entry per variant, tag IS the header class_id (no header field, no format
  bump); exhaustive switch without `default`; arity checked both directions.
- Payload escape modeled as move-out (pointer-kind fields only — a scalar
  escape is a copy); caller reaps owned heap temps passed by borrow: two
  unbounded LSan-blind leaks, 10.5 MB -> 1.5 MB flat over 300k iterations.
- Fixed en route, each with a RED repro: dead E209 builtin-arg check and
  `int_to_text` missing from both types.ml builtin tables (both segfaulted
  wovm), multi-file phantom double-report, emit_ctor's field temp clobbering
  dst in tail position (pre-existing), warnings swallowed without an error.
- Two fenced VM builtins: `int_to_text` (13), `variant_tag` (14).
- 14+565 unit (was 14+401), corpus 71 (was 32) plain and under wovm_asan,
  wovm-test + cli_smoke green. Log-watcher 307 -> 93 diagnostics (85 E101 /
  4 E207 / 1 E208 / 3 W202); the 5 non-E101 residuals await Task 7 grammar.
2026-08-12 14:40:07 +02:00

161 lines
4.7 KiB
Text

-- haxe-parity Task 3, review fix (Critical 3): `let w = switch ...`
-- with NO `: Type` annotation used to leak every single iteration --
-- owner.ml's `expr_ty` returned `None` for a `Switch` (a deliberate,
-- but wrong, "not chased" call from the original task), and
-- `analyze_let`'s own fallback for `expr_ty = None` is `Scalar "Int"`
-- (Copy-classified, never dropped) -- so an unannotated switch-valued
-- `let` binding a plain class (no union involved) was silently never
-- freed. `Big` has 130 Int fields (the same arena-ceiling trick
-- lang-break-owned-drop/lang-switch-arm-drop already use: 1040 bytes
-- crosses the 1024-byte size-class ceiling, so a missed DROP is a
-- hard, observable ASan leak, not a silent miss lost in the arena's
-- own small-object reuse). RED (fix disabled): 3168 bytes leaked
-- across the 3 loop iterations, one object each, confirmed under
-- `runtime/build/wovm_asan` (task-3-report.md has the transcript).
-- GREEN (fix restored, this fixture): clean under both plain `wovm`
-- and `wovm_asan`.
class Big {
f0: Int
f1: Int
f2: Int
f3: Int
f4: Int
f5: Int
f6: Int
f7: Int
f8: Int
f9: Int
f10: Int
f11: Int
f12: Int
f13: Int
f14: Int
f15: Int
f16: Int
f17: Int
f18: Int
f19: Int
f20: Int
f21: Int
f22: Int
f23: Int
f24: Int
f25: Int
f26: Int
f27: Int
f28: Int
f29: Int
f30: Int
f31: Int
f32: Int
f33: Int
f34: Int
f35: Int
f36: Int
f37: Int
f38: Int
f39: Int
f40: Int
f41: Int
f42: Int
f43: Int
f44: Int
f45: Int
f46: Int
f47: Int
f48: Int
f49: Int
f50: Int
f51: Int
f52: Int
f53: Int
f54: Int
f55: Int
f56: Int
f57: Int
f58: Int
f59: Int
f60: Int
f61: Int
f62: Int
f63: Int
f64: Int
f65: Int
f66: Int
f67: Int
f68: Int
f69: Int
f70: Int
f71: Int
f72: Int
f73: Int
f74: Int
f75: Int
f76: Int
f77: Int
f78: Int
f79: Int
f80: Int
f81: Int
f82: Int
f83: Int
f84: Int
f85: Int
f86: Int
f87: Int
f88: Int
f89: Int
f90: Int
f91: Int
f92: Int
f93: Int
f94: Int
f95: Int
f96: Int
f97: Int
f98: Int
f99: Int
f100: Int
f101: Int
f102: Int
f103: Int
f104: Int
f105: Int
f106: Int
f107: Int
f108: Int
f109: Int
f110: Int
f111: Int
f112: Int
f113: Int
f114: Int
f115: Int
f116: Int
f117: Int
f118: Int
f119: Int
f120: Int
f121: Int
f122: Int
f123: Int
f124: Int
f125: Int
f126: Int
f127: Int
f128: Int
f129: Int
}
fn main() -> Int {
let i = 0;
while i < 3 {
let w = switch i {
case 0: Big { f0: 1, f1: 1, f2: 1, f3: 1, f4: 1, f5: 1, f6: 1, f7: 1, f8: 1, f9: 1, f10: 1, f11: 1, f12: 1, f13: 1, f14: 1, f15: 1, f16: 1, f17: 1, f18: 1, f19: 1, f20: 1, f21: 1, f22: 1, f23: 1, f24: 1, f25: 1, f26: 1, f27: 1, f28: 1, f29: 1, f30: 1, f31: 1, f32: 1, f33: 1, f34: 1, f35: 1, f36: 1, f37: 1, f38: 1, f39: 1, f40: 1, f41: 1, f42: 1, f43: 1, f44: 1, f45: 1, f46: 1, f47: 1, f48: 1, f49: 1, f50: 1, f51: 1, f52: 1, f53: 1, f54: 1, f55: 1, f56: 1, f57: 1, f58: 1, f59: 1, f60: 1, f61: 1, f62: 1, f63: 1, f64: 1, f65: 1, f66: 1, f67: 1, f68: 1, f69: 1, f70: 1, f71: 1, f72: 1, f73: 1, f74: 1, f75: 1, f76: 1, f77: 1, f78: 1, f79: 1, f80: 1, f81: 1, f82: 1, f83: 1, f84: 1, f85: 1, f86: 1, f87: 1, f88: 1, f89: 1, f90: 1, f91: 1, f92: 1, f93: 1, f94: 1, f95: 1, f96: 1, f97: 1, f98: 1, f99: 1, f100: 1, f101: 1, f102: 1, f103: 1, f104: 1, f105: 1, f106: 1, f107: 1, f108: 1, f109: 1, f110: 1, f111: 1, f112: 1, f113: 1, f114: 1, f115: 1, f116: 1, f117: 1, f118: 1, f119: 1, f120: 1, f121: 1, f122: 1, f123: 1, f124: 1, f125: 1, f126: 1, f127: 1, f128: 1, f129: 1 };
default: Big { f0: 1, f1: 1, f2: 1, f3: 1, f4: 1, f5: 1, f6: 1, f7: 1, f8: 1, f9: 1, f10: 1, f11: 1, f12: 1, f13: 1, f14: 1, f15: 1, f16: 1, f17: 1, f18: 1, f19: 1, f20: 1, f21: 1, f22: 1, f23: 1, f24: 1, f25: 1, f26: 1, f27: 1, f28: 1, f29: 1, f30: 1, f31: 1, f32: 1, f33: 1, f34: 1, f35: 1, f36: 1, f37: 1, f38: 1, f39: 1, f40: 1, f41: 1, f42: 1, f43: 1, f44: 1, f45: 1, f46: 1, f47: 1, f48: 1, f49: 1, f50: 1, f51: 1, f52: 1, f53: 1, f54: 1, f55: 1, f56: 1, f57: 1, f58: 1, f59: 1, f60: 1, f61: 1, f62: 1, f63: 1, f64: 1, f65: 1, f66: 1, f67: 1, f68: 1, f69: 1, f70: 1, f71: 1, f72: 1, f73: 1, f74: 1, f75: 1, f76: 1, f77: 1, f78: 1, f79: 1, f80: 1, f81: 1, f82: 1, f83: 1, f84: 1, f85: 1, f86: 1, f87: 1, f88: 1, f89: 1, f90: 1, f91: 1, f92: 1, f93: 1, f94: 1, f95: 1, f96: 1, f97: 1, f98: 1, f99: 1, f100: 1, f101: 1, f102: 1, f103: 1, f104: 1, f105: 1, f106: 1, f107: 1, f108: 1, f109: 1, f110: 1, f111: 1, f112: 1, f113: 1, f114: 1, f115: 1, f116: 1, f117: 1, f118: 1, f119: 1, f120: 1, f121: 1, f122: 1, f123: 1, f124: 1, f125: 1, f126: 1, f127: 1, f128: 1, f129: 1 };
};
print_int(w.f0);
i = i + 1;
}
return 0;
}