yield type check against yield target
This commit is contained in:
@@ -12266,7 +12266,9 @@ build_value_block :: proc(
|
|||||||
) -> (value: hir.Expr_Id, value_type: types.Type) {
|
) -> (value: hir.Expr_Id, value_type: types.Type) {
|
||||||
checker := ctx.checker
|
checker := ctx.checker
|
||||||
n := len(body_stmts)
|
n := len(body_stmts)
|
||||||
if n == 0 || checker.ast_module.statements[body_stmts[n - 1]].kind != .Yield {
|
if n == 0 ||
|
||||||
|
checker.ast_module.statements[body_stmts[n - 1]].kind != .Yield ||
|
||||||
|
symbol.is_valid(checker.ast_module.statements[body_stmts[n - 1]].label) {
|
||||||
// Build whatever is there so inner errors (and misplaced yields) surface, then
|
// Build whatever is there so inner errors (and misplaced yields) surface, then
|
||||||
// report the missing trailing yield.
|
// report the missing trailing yield.
|
||||||
inner := build_block(ctx, body_stmts)
|
inner := build_block(ctx, body_stmts)
|
||||||
@@ -12657,6 +12659,21 @@ emit_value_branch :: proc(
|
|||||||
emit_slot_assign(checker, out, slot^, value, span)
|
emit_slot_assign(checker, out, slot^, value, span)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if n == 1 {
|
||||||
|
block_stmt := checker.ast_module.statements[branch_stmts[0]]
|
||||||
|
if block_stmt.kind == .Block && symbol.is_valid(block_stmt.label) {
|
||||||
|
expected := slot_type^ if slot^ != hir.INVALID_LOCAL else types.INVALID
|
||||||
|
value, value_type := build_value_labeled_block(
|
||||||
|
ctx, out, block_stmt.body, block_stmt.label, expected, block_stmt.span,
|
||||||
|
)
|
||||||
|
if checker.module.exprs[value].kind == .Invalid {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
value = adopt_value_slot(ctx, slot, slot_type, value, value_type, span)
|
||||||
|
emit_slot_assign(checker, out, slot^, value, span)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
ends_in_yield := n > 0 &&
|
ends_in_yield := n > 0 &&
|
||||||
checker.ast_module.statements[branch_stmts[n - 1]].kind == .Yield &&
|
checker.ast_module.statements[branch_stmts[n - 1]].kind == .Yield &&
|
||||||
!symbol.is_valid(checker.ast_module.statements[branch_stmts[n - 1]].label)
|
!symbol.is_valid(checker.ast_module.statements[branch_stmts[n - 1]].label)
|
||||||
|
|||||||
@@ -6268,6 +6268,40 @@ value_loop_label_does_not_shadow_own_yield_target :: proc(t: ^testing.T) {
|
|||||||
testing.expect_value(t, len(diagnostics.items), 0)
|
testing.expect_value(t, len(diagnostics.items), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
labeled_block_supplies_value_if_branch_through_catch :: proc(t: ^testing.T) {
|
||||||
|
text := `Failure :: enum { bad }
|
||||||
|
ScanResult :: struct { end usize }
|
||||||
|
scan func() ScanResult ! Failure { return .bad }
|
||||||
|
main func() i32 {
|
||||||
|
start usize = 3
|
||||||
|
end :: if (true) done: {
|
||||||
|
result :: scan() catch {
|
||||||
|
yield :done start
|
||||||
|
}
|
||||||
|
yield :done result.end
|
||||||
|
} else {
|
||||||
|
yield start
|
||||||
|
}
|
||||||
|
if (end == start) return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
`
|
||||||
|
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)
|
||||||
native_union_compiles_and_runs :: proc(t: ^testing.T) {
|
native_union_compiles_and_runs :: proc(t: ^testing.T) {
|
||||||
output := "/tmp/brolang-test-unions"
|
output := "/tmp/brolang-test-unions"
|
||||||
|
|||||||
Reference in New Issue
Block a user