codegen: any string-typed return makes a closure a string closure - #2070
Merged
Merged
Conversation
resolve_closure_return_type typed a closure by its FIRST return site. string.from_int(x) is declared `-> ptr` (an AetherString behind a raw pointer), so a closure returning it on one path and a struct's string field on another was emitted `void*`, was not a string closure, and none of its returns got the uniform-heap wrap of #2054 — while its caller, a `-> string` function returning `cb(...)`, took ownership of the result and freed it. The field path returned a literal; the caller free()d it: STATUS_HEAP_CORRUPTION on Windows, SIGABRT on macOS, glibc absorbed it silently. aether-ui's table cell callback has exactly that shape, so every table in that tree aborted at startup from 0.682 on (aether-ui#147, the 0.683 pin). Any string-typed return site now makes the closure `const char*`, so every path is wrapped: the literal is copied out, the AetherString is copied out by its header, and the caller owns both. tests/regression/test_closure_mixed_string_returns.ae drives both sites fifty times; it aborts under the previous compiler.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
aether-lang-dev/aether-ui#147 moved that tree to 0.683.0 and
table_demoaborts at startup on macOS (Abort trap: 6). Reproduced natively on Windows: exit0xC0000374STATUS_HEAP_CORRUPTION. gdb:The table's cell callback is
resolve_closure_return_typetypes a closure by its first return site.string.from_intisextern … -> ptr, so the closure was emittedstatic void* _closure_fn_10(…), was not a "string closure", and neither return got the uniform-heap wrap #2054 introduced. Its caller,_table_invoke_cell(cb: fn, …) -> string { return cb(item, c) }, is classified heap-returning since #2054, so the call site sets_heap_cell_s = 1and frees the result — the literal"zoe". 0.651 (pre-#2054) set_heap_cell_s = 0and merely leaked thefrom_intstring.What
any_return_is_string: if any return site under the closure body isstring-typed, the closure's C return type isconst char*, soin_string_closureis set and every path goes throughaether_uniform_heap_str— the literal is copied out, the AetherString is copied out by its header (the shim already handles that), the caller owns both.Verified
tests/regression/test_closure_mixed_string_returns.ae: both sites, fifty rounds, the field's literal intact afterwards. Aborts under stock 0.683.0 (exit 127 / heap corruption), passes with this build.test_*closure*/test_fn_*regression tests pass with this build (compiled + run natively on Windows against the 0.683.0 runtime).table_demorebuilt with this compiler against the native win32 backend: runs, the driver lists 41 widgets, cells"zoe"and"100"rendered.