unify catch fallback value sources
This commit is contained in:
@@ -4737,23 +4737,21 @@ infer_compound_expr :: proc(
|
||||
value := infer_nested_expr(checker, expr.left, locals, pkg, file, demanded, local_types, left_expected)
|
||||
success := types.fallible_success(value, store)
|
||||
error_type := types.fallible_error(value, store)
|
||||
fallback_locals: [dynamic]Infer_Local
|
||||
fallback_locals.allocator = checker.allocator
|
||||
defer delete(fallback_locals)
|
||||
append(&fallback_locals, ..locals)
|
||||
if symbol.is_valid(expr.name) && expr.name != checker.sink_symbol && types.is_valid(error_type) {
|
||||
append(&fallback_locals, Infer_Local{name=expr.name, type=error_type, declared=error_type, statement=ast.INVALID_STMT})
|
||||
}
|
||||
if expr.right != ast.INVALID_EXPR {
|
||||
fallback := infer_nested_expr(checker, expr.right, 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
|
||||
}
|
||||
block_locals: [dynamic]Infer_Local
|
||||
block_locals.allocator = checker.allocator
|
||||
defer delete(block_locals)
|
||||
append(&block_locals, ..locals)
|
||||
capture_start := len(block_locals)
|
||||
if symbol.is_valid(expr.name) && expr.name != checker.sink_symbol && types.is_valid(error_type) {
|
||||
append(&block_locals, Infer_Local{name=expr.name, type=error_type, declared=error_type, statement=ast.INVALID_STMT})
|
||||
}
|
||||
infer_statements(checker, expr.body, &block_locals, local_types, pkg, file, demanded, &success, success)
|
||||
resize(&block_locals, capture_start)
|
||||
infer_statements(checker, expr.body, &fallback_locals, local_types, pkg, file, demanded, &success, success)
|
||||
return success
|
||||
case .Struct_Literal:
|
||||
value := types.INVALID
|
||||
@@ -8139,26 +8137,37 @@ build_compound_expr :: proc(
|
||||
block_handler := false
|
||||
void_fallthrough := false
|
||||
fallback := hir.INVALID_EXPR
|
||||
ctx := checker.current_build_ctx
|
||||
capture_start := 0
|
||||
if symbol.is_valid(expr.name) && expr.name != checker.sink_symbol {
|
||||
if ctx == nil {
|
||||
id := source.add(checker.diagnostics, expr.span, "a captured catch fallback is only valid in a function body")
|
||||
return invalid_hir_expr(checker, expr.span, id, success)
|
||||
}
|
||||
capture_start = len(ctx.locals^)
|
||||
error_type := types.fallible_error(channel_type, store)
|
||||
capture = append_build_local(ctx, expr.name, error_type, false, expr.span)
|
||||
}
|
||||
if expr.right != ast.INVALID_EXPR {
|
||||
fallback = build_nested_expr(checker, expr.right, locals, global_reads, calls, success, pkg, file)
|
||||
fallback_locals := locals
|
||||
if capture != hir.INVALID_LOCAL {
|
||||
fallback_locals = ctx.locals^[:]
|
||||
}
|
||||
fallback = build_nested_expr(checker, expr.right, fallback_locals, global_reads, calls, success, pkg, file)
|
||||
fallback = coerce_expr(checker, fallback, success, checker.module.exprs[fallback].span)
|
||||
} else {
|
||||
block_handler = true
|
||||
ctx := checker.current_build_ctx
|
||||
if ctx == nil {
|
||||
id := source.add(checker.diagnostics, expr.span, "catch block form is only valid in a function body")
|
||||
return invalid_hir_expr(checker, expr.span, id, success)
|
||||
}
|
||||
capture_start := len(ctx.locals^)
|
||||
error_type := types.fallible_error(channel_type, store)
|
||||
if symbol.is_valid(expr.name) && expr.name != checker.sink_symbol {
|
||||
capture = append_build_local(ctx, expr.name, error_type, false, expr.span)
|
||||
}
|
||||
handler: [dynamic]hir.Stmt_Id
|
||||
handler.allocator = checker.allocator
|
||||
fallback, _ = build_value_source(ctx, &handler, expr.body, success, expr.span, allow_exit=true)
|
||||
fallback, _ = build_value_source(ctx, &handler, expr.body, success, expr.span, value_control_flow=expr.integer != 0, allow_exit=true)
|
||||
void_fallthrough = fallback == hir.INVALID_EXPR && !all_paths_exit(&checker.module, handler[:])
|
||||
body = handler[:]
|
||||
}
|
||||
if capture != hir.INVALID_LOCAL {
|
||||
resize(ctx.locals, capture_start)
|
||||
}
|
||||
catch_mode := hir.CATCH_EXPRESSION
|
||||
|
||||
@@ -3763,14 +3763,16 @@ ct_eval_catch_expr :: proc(state: ^Ct_State, expr: ast.Expr, expected: types.Typ
|
||||
if value.active == 0 {
|
||||
return payload, ct_flow(.Normal), true
|
||||
}
|
||||
if expr.right != ast.INVALID_EXPR {
|
||||
return ct_eval_expr(state, expr.right, success, depth+1)
|
||||
}
|
||||
scope_start := len(state.bindings)
|
||||
if symbol.is_valid(expr.name) && expr.name != checker.sink_symbol && payload != INVALID_CT_VALUE {
|
||||
error_type := types.fallible_error(value.type, &checker.module.types)
|
||||
ct_bind_value(state, expr.name, error_type, payload, false)
|
||||
}
|
||||
if expr.right != ast.INVALID_EXPR {
|
||||
result, result_flow, result_ok := ct_eval_expr(state, expr.right, success, depth+1)
|
||||
ct_pop_bindings(state, scope_start)
|
||||
return result, result_flow, result_ok
|
||||
}
|
||||
handler, handler_ok := ct_exec_statements(state, expr.body, true, depth+1)
|
||||
ct_pop_bindings(state, scope_start)
|
||||
if !handler_ok {
|
||||
|
||||
Reference in New Issue
Block a user