ERR/E5.1: lambda-specific raise-not-failable hint

A closure literal whose body raises but is annotated non-failable (or has
no ! in its return) now gets a lambda-specific diagnostic telling the user
to declare the failable return explicitly, instead of the generic "raise
is only valid inside a failable function". Failability is never inferred
for a lambda, so a raising lambda with no ! is a hard error that should
point at the fix.

New in_lambda_body flag (save/restore for nesting) set around the lambda
body lowering in lowerLambda; diagRaiseNotFailable branches on it.
Top-level functions keep the generic message.

Test: 1043-errors-lambda-raise-annotation-hint.sx.
This commit is contained in:
agra
2026-06-01 22:18:47 +03:00
parent 34bdf8b87c
commit a61685772d
5 changed files with 40 additions and 2 deletions

View File

@@ -0,0 +1,20 @@
// A closure literal whose body `raise`s but is annotated non-failable (or has
// no `!` in its return) gets a LAMBDA-SPECIFIC diagnostic telling the user to
// declare the failable return explicitly (ERR E5.1 sub-feature 1). This is the
// closure analog of the top-level "raise is only valid inside a failable
// function" error — failability is never inferred for a lambda, it must be
// declared, so a raising lambda with no `!` is a hard error pointing at the fix.
#import "modules/std.sx";
E :: error { Neg }
take :: (cb: Closure(s32) -> (s32, !E), x: s32) -> s32 { return cb(x) catch e -1; }
main :: () -> s32 {
// `-> s32` (non-failable) but the body raises → lambda-specific hint:
// "lambda body raises; declare its return type explicitly with
// `-> (T, !)` or `-> (T, !Named)`"
print("{}\n", take(closure((x: s32) -> s32 { if x < 0 { raise error.Neg; } return x; }), -1));
return 0;
}