-- haxe-parity Task 4: drop correctness around payload-binding switch -- arms (lang-switch-arm-drop is the model). Everything here must hold -- under runtime/build/wovm_asan, not just plain wovm: -- 1. the subject (`ev`, an owned variant object) is dropped exactly -- once, at its own scope end -- its per-variant class-table kinds -- free the payload recursively (Log's CONCAT-built Text; Boxed's -- embedded Big -- 130 Int fields, past the arena's 1024-byte -- ceiling, so any miss is a hard ASan failure, not a silent one); -- 2. `line`/`b`, the arms' payload bindings, are BORROWS of the -- subject's fields -- never dropped by their arm, or the subject's -- own drop double-frees; -- 3. `big` (arm-local owned value in `case Log`) still gets its -- ordinary arm-scope drop alongside the binding; -- 4. `mk(2)`'s local Big is MOVED into `Boxed(big)` -- the variant -- construction is a ctor-field escape (owner.ml), so the local -- must NOT also drop at mk's return: that would double-free the -- Big the variant object now owns; -- 5. `w`, a variant object from a DIRECT construction (not through a -- declared-return fn), is classified owned through the -- construction itself and dropped at main's end. type Ev = Tick | Log(line: Text) | Boxed(b: Big) 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 mk_big() -> Big { return Big { f0: 1, f1: 2, f2: 3, 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 } } fn mk(n: Int) -> Ev { if n == 1 { return Log("boot " .. int_to_text(n)) } if n == 2 { let big = mk_big(); return Boxed(big); } return Tick } fn main() -> Int { let i = 0; while i < 4 { let ev = mk(i); switch ev { case Log(line): let big = mk_big(); print_int(big.f0); print(line); case Boxed(b): print_int(b.f1); case Tick: print("tick"); } i = i + 1; } let w = Boxed(mk_big()); switch w { case Boxed(b): print_int(b.f2); case Log(line): print(line); case Tick: print("tick"); } print("done"); return 0; }