refine returned match errors
This commit is contained in:
@@ -6349,6 +6349,192 @@ main func() i32 {
|
||||
testing.expect_value(t, state.exit_code, 0)
|
||||
}
|
||||
|
||||
@(test)
|
||||
matched_error_residuals_return_at_runtime_and_comptime :: proc(t: ^testing.T) {
|
||||
text := `KeyError :: enum { key_exists }
|
||||
AllocError :: enum { out_of_memory }
|
||||
AError :: enum { a }
|
||||
BError :: enum { b }
|
||||
CError :: enum { c }
|
||||
DetailError :: union(enum) { out_of_memory i32 }
|
||||
|
||||
key_or_alloc func(code i32) void ! (KeyError | AllocError) {
|
||||
if code == 1 { return .key_exists }
|
||||
if code == 2 { return .out_of_memory }
|
||||
}
|
||||
abc func(code i32) void ! (AError | BError | CError) {
|
||||
if code == 1 { return .a }
|
||||
if code == 2 { return .b }
|
||||
if code == 3 { return .c }
|
||||
}
|
||||
detail func() void ! (KeyError | DetailError) { return .out_of_memory{41} }
|
||||
|
||||
via_else func() i32 ! AllocError {
|
||||
key_or_alloc(2) catch |err| {
|
||||
match err {
|
||||
.key_exists: unreachable
|
||||
else: return err
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
via_group func() i32 ! (AError | BError) {
|
||||
abc(2) catch |err| {
|
||||
match err {
|
||||
.a, .b: return err
|
||||
.c: unreachable
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
via_nested func() i32 ! AError {
|
||||
abc(1) catch |err| {
|
||||
match err {
|
||||
.a, .b: match err {
|
||||
.a: return err
|
||||
else: unreachable
|
||||
}
|
||||
.c: unreachable
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
via_expand func() i32 ! AError {
|
||||
abc(1) catch |err| {
|
||||
match err {
|
||||
expand |tag|: match tag {
|
||||
.a: return err
|
||||
else: unreachable
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
via_payload func() i32 ! DetailError {
|
||||
detail() catch |err| {
|
||||
match err {
|
||||
.key_exists: unreachable
|
||||
else: return err
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
ct_project func() i32 ! AError {
|
||||
abc(1) catch |err| {
|
||||
match err {
|
||||
.a: return err
|
||||
else: unreachable
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
ct_recover func() i32 {
|
||||
return ct_project() catch |_| 5
|
||||
}
|
||||
main func() i32 {
|
||||
a :: via_else() catch |_| 1
|
||||
b :: via_group() catch |err| match err {
|
||||
.a: 1
|
||||
.b: 2
|
||||
}
|
||||
c :: via_nested() catch |_| 3
|
||||
d :: via_expand() catch |_| 4
|
||||
e :: via_payload() catch |err| match err { .out_of_memory |code|: code }
|
||||
f i32 :: $ct_recover()
|
||||
return a + b + c + d + e + f - 56
|
||||
}
|
||||
`
|
||||
directory := "/tmp/brolang-test-matched-error-residuals"
|
||||
main_path := "/tmp/brolang-test-matched-error-residuals/main.bro"
|
||||
output := "/tmp/brolang-test-matched-error-residuals-output"
|
||||
_ = os2.remove_all(directory)
|
||||
defer _ = os2.remove_all(directory)
|
||||
defer _ = os.remove(output)
|
||||
testing.expect(t, os.make_directory(directory) == nil)
|
||||
testing.expect(t, os.write_entire_file(main_path, transmute([]byte)text))
|
||||
testing.expect_value(t, compiler_core.compile_package(directory, output), 0)
|
||||
state := run_executable(output)
|
||||
testing.expect_value(t, state.exit_code, 0)
|
||||
}
|
||||
|
||||
@(test)
|
||||
unproven_error_returns_are_rejected_against_both_channels :: proc(t: ^testing.T) {
|
||||
text := `BadError :: enum { bad }
|
||||
GoodError :: enum { good }
|
||||
Combined :: alias (BadError | GoodError)
|
||||
source func() void ! Combined { return .good }
|
||||
unrefined func() usize ! GoodError {
|
||||
source() catch |err| { return err }
|
||||
return 0
|
||||
}
|
||||
incompatible func() usize ! GoodError {
|
||||
source() catch |err| {
|
||||
match err {
|
||||
.bad: return err
|
||||
else: unreachable
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
aliased func() usize ! GoodError {
|
||||
source() catch |err| {
|
||||
match err {
|
||||
.bad: unreachable
|
||||
else: {
|
||||
copy :: err
|
||||
return copy
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
mutable_subject func() usize ! GoodError {
|
||||
source() catch |err| {
|
||||
value Combined = err
|
||||
match value {
|
||||
.bad: unreachable
|
||||
else: return value
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
main func() void {
|
||||
_ = unrefined() catch 0
|
||||
_ = incompatible() catch 0
|
||||
_ = aliased() catch 0
|
||||
_ = mutable_subject() catch 0
|
||||
}
|
||||
`
|
||||
directory := "/tmp/brolang-test-unproven-error-returns"
|
||||
main_path := "/tmp/brolang-test-unproven-error-returns/main.bro"
|
||||
_ = os2.remove_all(directory)
|
||||
defer _ = os2.remove_all(directory)
|
||||
testing.expect(t, os.make_directory(directory) == nil)
|
||||
testing.expect(t, os.write_entire_file(main_path, transmute([]byte)text))
|
||||
sources := source.init_store()
|
||||
defer source.destroy_store(&sources)
|
||||
diagnostics := source.init_store_diagnostics(&sources)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
ast_module, loaded := loader.load(directory, &sources, &diagnostics, &symbols)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
testing.expect(t, loaded)
|
||||
return_errors := 0
|
||||
for _, diagnostic_index in diagnostics.items {
|
||||
message := source.format(&diagnostics, source.diagnostic_id(diagnostic_index))
|
||||
if strings.contains(message, "cannot return") &&
|
||||
strings.contains(message, "as success type usize or error type GoodError") {
|
||||
return_errors += 1
|
||||
}
|
||||
delete(message)
|
||||
}
|
||||
testing.expect_value(t, return_errors, 4)
|
||||
}
|
||||
|
||||
@(test)
|
||||
conversion_diagnostics_render_source_types :: proc(t: ^testing.T) {
|
||||
text := `Allocator :: struct {
|
||||
|
||||
Reference in New Issue
Block a user