fix: lambda inferred return type from a block body's early returns (issue 0187)
A `:=`-bound closure with no explicit `-> T` and a BLOCK body inferred its
return type via inferExprType(lam.body), which yields the last statement's
type. A block whose value comes only from early `return`s ends in a return
statement (void/noreturn), so the closure was built with a void return while
the body returned i64 — the call site then fed `i64 undef` and LLVM
verification failed. (A block whose tail referenced a block-local hit the
sibling failure: inferExprType returned .unresolved → an LLVM panic.)
Infer the return type exactly as a named fn does (resolveReturnType in
lower.zig): an arrow body `(params) => expr` uses the expression type; a block
body `(params) { stmts }` takes the first explicit `return <val>` type via
findReturnValueType, else void (the block tail is a discarded statement unless
an explicit `-> R` makes it the value). Regression test:
examples/closures/0313-closure-inferred-return-early.sx.
This commit is contained in:
28
examples/closures/0313-closure-inferred-return-early.sx
Normal file
28
examples/closures/0313-closure-inferred-return-early.sx
Normal file
@@ -0,0 +1,28 @@
|
||||
// A block-body closure (`closure((params) { ... })`) with an INFERRED return
|
||||
// type whose value is produced via early `return`s must infer the return type
|
||||
// from the `return` operands — not fall through to void.
|
||||
//
|
||||
// Regression (issue 0187): `closure(() { if c { return 11; } return 22; })`
|
||||
// used to infer `void` (the block's last stmt is the `return`, not a value), so
|
||||
// the call site fed an `i64 undef` to `print` and LLVM verification failed. The
|
||||
// closure return-type inference now mirrors the function-decl path, scanning
|
||||
// the body's `return` statements.
|
||||
//
|
||||
// Syntax note: a block body is the `closure((params) -> R? { ... })` form; the
|
||||
// bare `(params) => expr` lambda is arrow + EXPRESSION only (no block).
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
// early returns only — inferred return, no optionals
|
||||
f := closure(() { if 1 > 0 { return 11; } return 22; });
|
||||
print("f: {}\n", f());
|
||||
|
||||
// early return + trailing-expression block value
|
||||
g := closure((n: i64) { if n > 0 { return 100; } 200 });
|
||||
print("g+: {}\n", g(1));
|
||||
print("g-: {}\n", g(-1));
|
||||
|
||||
// inferred float return via early returns
|
||||
h := closure((n: i64) { if n > 0 { return 3.5; } return 1.5; });
|
||||
print("h: {}\n", h(1));
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
f: 11
|
||||
g+: 100
|
||||
g-: 200
|
||||
h: 3.500000
|
||||
Reference in New Issue
Block a user