better try/catch fallback

This commit is contained in:
2026-08-05 19:52:40 +02:00
parent aadce94b42
commit 88b94197c9
2 changed files with 36 additions and 3 deletions
-3
View File
@@ -5040,9 +5040,6 @@ infer_compound_expr :: proc(
} }
if expr.right != ast.INVALID_EXPR { if expr.right != ast.INVALID_EXPR {
fallback := infer_nested_expr(checker, expr.right, fallback_locals[:], pkg, file, demanded, local_types) fallback := infer_nested_expr(checker, expr.right, fallback_locals[:], pkg, file, demanded, local_types)
if types.is_valid(success) && types.is_valid(fallback) && !types.equal(success, fallback) {
return types.widest(success, fallback)
}
return success if types.is_valid(success) else fallback return success if types.is_valid(success) else fallback
} }
infer_statements(checker, expr.body, &fallback_locals, local_types, pkg, file, demanded, &success, success) infer_statements(checker, expr.body, &fallback_locals, local_types, pkg, file, demanded, &success, success)
+36
View File
@@ -1307,6 +1307,42 @@ main func() void {
testing.expect_value(t, len(diagnostics.items), 0) testing.expect_value(t, len(diagnostics.items), 0)
} }
@(test)
catch_fallback_preserves_fallible_success_type :: proc(t: ^testing.T) {
text := `Read_Error :: enum {
failed
}
read func(value []u8, fail bool) []u8 ! Read_Error {
if fail {
return .failed
}
return value
}
take_slice func(value []u8) void { _ = value }
main func() void {
expression :: read("ok", false) catch "fallback"
block :: read("ok", true) catch {
yield "fallback"
}
take_slice(expression)
take_slice(block)
}
`
source_file := source.Source{path="test.bro", text=text}
diagnostics := source.init_diagnostics(&source_file)
defer source.destroy_diagnostics(&diagnostics)
symbols := symbol.init_table()
defer symbol.destroy_table(&symbols)
stream := lexer.lex(&source_file, &diagnostics, &symbols)
defer delete(stream.items)
ast_module := parser.parse(&stream, &source_file, &diagnostics)
defer ast.destroy_module(&ast_module)
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
defer hir.destroy_module(&hir_module)
testing.expect_value(t, len(diagnostics.items), 0)
}
@(test) @(test)
pipeline_emits_specialized_calling_conventions_and_checked_add :: proc(t: ^testing.T) { pipeline_emits_specialized_calling_conventions_and_checked_add :: proc(t: ^testing.T) {
text := `sum_c c_func(a, b int) int { text := `sum_c c_func(a, b int) int {