fix(compiler): skip auto-Drop after field/let/return moves

Track locals moved by value into struct fields, let bindings, or return
values so Array/Drop types are not freed while still owned by the target.

- hir_lower: movedOutLocals + markMovedOutFromAst + shouldSkipDrop
- Nexus: drop zeroing workaround; free headers after each request
- examples/move_field.bux regression for Box { items: arr }
This commit is contained in:
2026-07-19 23:03:05 +03:00
parent adc5c743a6
commit cfb89dd72f
7 changed files with 106 additions and 23 deletions
+3 -8
View File
@@ -100,8 +100,8 @@ module Parser {
// Find header/body boundary
let boundary: String = bux_strstr(raw, "\r\n\r\n");
// Only one allocation path — avoid Array_New then overwrite (leak) and
// suppress auto-drop after moving into HttpRequest (use-after-free).
// Single assignment path (no Array_New then overwrite). Field-move of
// `headers` into HttpRequest skips auto-Drop (compiler movedOutLocals).
var headers: Array<HeaderEntry>;
var body: String = "";
if String_Len(boundary) > 0 {
@@ -116,7 +116,7 @@ module Parser {
}
if String_Eq(path, "") {
// auto-drop of `headers` runs on return
// auto-drop of `headers` runs on error return
return ParseResult_NewErr(HttpError { tag: HttpError_BadRequest });
}
@@ -127,11 +127,6 @@ module Parser {
body: body,
headers: headers,
};
// Ownership transferred into req — zero local shell so auto-drop is a no-op.
// (Compiler does not yet treat field-move as a move-out of the local.)
headers.data = null as *HeaderEntry;
headers.len = 0;
headers.cap = 0;
return ParseResult_NewOk(req);
}