commit fe4556d224d5b26a65843dcc9fe1cd9ac98785a1
parent 6c11668244aa2a3ce4288c24c626ca2225df0156
Author: Sebastian <sebastian@sebsite.pw>
Date: Wed, 11 Jan 2023 18:25:51 -0500
check: fix type reduction when yielding without value
Previously, using `yield` without a value didn't correctly add a `void`
expression to the list of yields for a scope. So, for instance, code
like this would incorrectly compile:
let x: int = {
if (true) yield 0;
yield;
};
If the above `yield` was changed to a `yield void` this would correctly
not compile. This has been fixed, by adding a `void` value to a yield
without a value during check.
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
2 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -1878,22 +1878,29 @@ check_expr_control(struct context *ctx,
}
expr->control.scope = scope;
+ if (expr->type != EXPR_YIELD) {
+ return;
+ }
+
+ expr->control.value = xcalloc(1, sizeof(struct expression));
if (aexpr->control.value) {
- expr->control.value = xcalloc(1, sizeof(struct expression));
check_expression(ctx, aexpr->control.value,
expr->control.value, scope->hint);
+ } else {
+ expr->control.value->type = EXPR_CONSTANT;
+ expr->control.value->result = &builtin_type_void;
+ }
- struct type_tagged_union *result =
- xcalloc(1, sizeof(struct type_tagged_union));
- result->type = expr->control.value->result;
- result->next = scope->results;
- scope->results = result;
+ struct type_tagged_union *result =
+ xcalloc(1, sizeof(struct type_tagged_union));
+ result->type = expr->control.value->result;
+ result->next = scope->results;
+ scope->results = result;
- struct yield *yield = xcalloc(1, sizeof(struct yield));
- yield->expression = &expr->control.value;
- yield->next = scope->yields;
- scope->yields = yield;
- }
+ struct yield *yield = xcalloc(1, sizeof(struct yield));
+ yield->expression = &expr->control.value;
+ yield->next = scope->yields;
+ scope->yields = yield;
}
static void
diff --git a/tests/30-reduction.c b/tests/30-reduction.c
@@ -128,6 +128,11 @@ int main(void) {
"if (true) null: *int "
"else if (true) null: const nullable *int "
"else null: nullable *int");
+ test(&ctx, "(int | void)",
+ "{ "
+ "if (true) yield; "
+ "yield 0; "
+ "}");
test(&ctx, "",
"if (true) null "