fix catch handlers / match statements yielding past scope
This commit is contained in:
@@ -4417,7 +4417,7 @@ build_block :: proc(
|
||||
if typed {
|
||||
expected = type_from_syntax(statement.type)
|
||||
}
|
||||
value, value_type := build_value_source(ctx, &body, statement.body, expected, statement.span, statement.label)
|
||||
value, value_type := build_value_source(ctx, &body, statement.body, expected, statement.span, statement.label, statement.value_control_flow)
|
||||
if _, found := find_build_local(ctx.locals^[duplicate_start:], statement.name); found {
|
||||
id := source.addf(
|
||||
checker.diagnostics, statement.span,
|
||||
@@ -4628,7 +4628,7 @@ build_block :: proc(
|
||||
} else if statement.expr == ast.INVALID_EXPR {
|
||||
// `target = { ... yield v }`: build the value block against the
|
||||
// target's type (build_value_block coerces internally).
|
||||
value, _ = build_value_source(ctx, &body, statement.body, target_type, statement.span, statement.label)
|
||||
value, _ = build_value_source(ctx, &body, statement.body, target_type, statement.span, statement.label, statement.value_control_flow)
|
||||
} else {
|
||||
value = build_expr(
|
||||
checker, statement.expr, ctx.locals^[:], ctx.global_reads, ctx.calls,
|
||||
@@ -4648,7 +4648,7 @@ build_block :: proc(
|
||||
if statement.name == checker.sink_symbol {
|
||||
value: hir.Expr_Id
|
||||
if statement.expr == ast.INVALID_EXPR {
|
||||
value, _ = build_value_source(ctx, &body, statement.body, types.INVALID, statement.span, statement.label)
|
||||
value, _ = build_value_source(ctx, &body, statement.body, types.INVALID, statement.span, statement.label, statement.value_control_flow)
|
||||
} else {
|
||||
value = build_expr(checker, statement.expr, ctx.locals^[:], ctx.global_reads, ctx.calls, types.INVALID, ctx.pkg, ctx.file)
|
||||
}
|
||||
@@ -4692,7 +4692,7 @@ build_block :: proc(
|
||||
}
|
||||
value: hir.Expr_Id
|
||||
if statement.expr == ast.INVALID_EXPR {
|
||||
value, _ = build_value_source(ctx, &body, statement.body, local.type, statement.span, statement.label)
|
||||
value, _ = build_value_source(ctx, &body, statement.body, local.type, statement.span, statement.label, statement.value_control_flow)
|
||||
} else {
|
||||
value = build_expr(
|
||||
checker, statement.expr, ctx.locals^[:], ctx.global_reads, ctx.calls,
|
||||
@@ -5430,10 +5430,10 @@ build_value_block :: proc(
|
||||
return value, value_type
|
||||
}
|
||||
|
||||
// build_value_source feeds a declaration/assignment RHS into the right value builder:
|
||||
// a labeled `blk: { ... }` block, a plain `{ ... }` block, an `if` whose branches yield,
|
||||
// or a `for`/`while` whose iterations yield. All return the produced value and its type
|
||||
// for the enclosing binding. `label` is the labeled-block label (INVALID otherwise).
|
||||
// build_value_source feeds a declaration/assignment RHS into the right value builder.
|
||||
// Braced blocks are plain value blocks and must end in their own `yield`; bare RHS
|
||||
// control flow (`x :: match ...`) sets `value_control_flow` and can produce directly.
|
||||
// `label` is the labeled-block label (INVALID otherwise).
|
||||
build_value_source :: proc(
|
||||
ctx: ^Build_Ctx,
|
||||
body: ^[dynamic]hir.Stmt_Id,
|
||||
@@ -5441,12 +5441,13 @@ build_value_source :: proc(
|
||||
expected: types.Type,
|
||||
span: source.Span,
|
||||
label := symbol.INVALID,
|
||||
value_control_flow := false,
|
||||
) -> (value: hir.Expr_Id, value_type: types.Type) {
|
||||
checker := ctx.checker
|
||||
if symbol.is_valid(label) {
|
||||
return build_value_labeled_block(ctx, body, body_stmts, label, expected, span)
|
||||
}
|
||||
if len(body_stmts) == 1 {
|
||||
if value_control_flow && len(body_stmts) == 1 {
|
||||
#partial switch checker.ast_module.statements[body_stmts[0]].kind {
|
||||
case .If:
|
||||
return build_value_if(ctx, body, body_stmts[0], expected, span)
|
||||
|
||||
Reference in New Issue
Block a user