bug fixes
This commit is contained in:
@@ -5913,6 +5913,7 @@ build_compound_expr :: proc(
|
||||
body: []hir.Stmt_Id
|
||||
capture := hir.INVALID_LOCAL
|
||||
block_handler := false
|
||||
void_fallthrough := false
|
||||
fallback := hir.INVALID_EXPR
|
||||
if expr.right != ast.INVALID_EXPR {
|
||||
fallback = build_nested_expr(checker, expr.right, locals, global_reads, calls, success, pkg, file)
|
||||
@@ -5932,14 +5933,19 @@ build_compound_expr :: proc(
|
||||
handler: [dynamic]hir.Stmt_Id
|
||||
handler.allocator = checker.allocator
|
||||
fallback, _ = build_value_source(ctx, &handler, expr.body, success, expr.span, allow_exit=true)
|
||||
void_fallthrough = fallback == hir.INVALID_EXPR && !all_paths_exit(&checker.module, handler[:])
|
||||
body = handler[:]
|
||||
resize(ctx.locals, capture_start)
|
||||
}
|
||||
catch_mode := hir.CATCH_EXPRESSION
|
||||
if block_handler {
|
||||
catch_mode = hir.CATCH_VOID_FALLTHROUGH if void_fallthrough else hir.CATCH_BLOCK
|
||||
}
|
||||
return add_hir_expr(checker, hir.Expr{
|
||||
kind=.Catch,
|
||||
span=expr.span,
|
||||
type=success,
|
||||
integer=1 if block_handler else 0,
|
||||
integer=catch_mode,
|
||||
left=channel,
|
||||
right=fallback,
|
||||
body=body,
|
||||
@@ -8236,10 +8242,11 @@ build_block :: proc(
|
||||
}
|
||||
|
||||
// build_value_block builds a `{ ... yield v }` value block whose final statement
|
||||
// must be a `yield`. Catch handlers may instead exit on every path, in which case
|
||||
// `allow_exit` leaves the fallback expression invalid. Otherwise it builds the leading
|
||||
// statements inline, evaluates the yield in their scope, then captures the value before
|
||||
// running defers. `expected` is the binding's type (INVALID for an untyped `::`).
|
||||
// must be a `yield`. Catch handlers may instead exit on every path or complete with
|
||||
// void, in which case `allow_exit` leaves the fallback expression invalid. Otherwise
|
||||
// it builds the leading statements inline, evaluates the yield in their scope, then
|
||||
// captures the value before running defers. `expected` is the binding's type (INVALID
|
||||
// for an untyped `::`).
|
||||
build_value_block :: proc(
|
||||
ctx: ^Build_Ctx,
|
||||
body: ^[dynamic]hir.Stmt_Id,
|
||||
@@ -8257,7 +8264,7 @@ build_value_block :: proc(
|
||||
for s in inner {
|
||||
append(body, s)
|
||||
}
|
||||
if allow_exit && all_paths_exit(&checker.module, inner) {
|
||||
if allow_exit && (types.is_void(expected) || all_paths_exit(&checker.module, inner)) {
|
||||
delete(inner, checker.allocator)
|
||||
return hir.INVALID_EXPR, expected
|
||||
}
|
||||
@@ -9785,7 +9792,16 @@ build_function :: proc(checker: ^Checker, id: Spec_Id) {
|
||||
}
|
||||
delete(block, checker.allocator)
|
||||
|
||||
if !types.is_void(spec.result) && !returns {
|
||||
fallible_void := types.kind(spec.result, &checker.module.types) == .Fallible &&
|
||||
types.is_void(types.fallible_success(spec.result, &checker.module.types))
|
||||
if !returns && fallible_void {
|
||||
value := fallible_aggregate(checker, function.span, spec.result, hir.INVALID_EXPR, false)
|
||||
append(&body, hir.stmt_id(len(checker.module.statements)))
|
||||
append(&checker.module.statements, hir.Stmt{
|
||||
kind=.Return, span=function.span, expr=value, local=hir.INVALID_LOCAL,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else if !types.is_void(spec.result) && !returns {
|
||||
id := source.addf(
|
||||
checker.diagnostics,
|
||||
function.span,
|
||||
@@ -9944,8 +9960,8 @@ build_globals :: proc(checker: ^Checker) {
|
||||
}
|
||||
expr := build_expr(checker, global.expr, nil, &dependencies, &calls, expected, global.pkg, global.file)
|
||||
global_type := checker.global_types[global_index]
|
||||
if is_runtime_type(checker, declared) {
|
||||
expr = coerce_expr(checker, expr, declared, global.span)
|
||||
if is_runtime_type(checker, checker.global_types[global_index]) {
|
||||
expr = coerce_expr(checker, expr, checker.global_types[global_index], global.span)
|
||||
global_type = checker.module.exprs[expr].type
|
||||
} else if is_runtime_type(checker, checker.module.exprs[expr].type) {
|
||||
global_type = checker.module.exprs[expr].type
|
||||
|
||||
Reference in New Issue
Block a user