aboutsummaryrefslogtreecommitdiff
path: root/typecheck.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-11 15:20:33 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-11 15:20:33 -0400
commitf7ff82913fccde369fcbc666100570e7cad066db (patch)
treed06c222b44a541547089a22447f43e77f1981a2b /typecheck.c
parent7bd4c6a5b331197df33941ab83656f3e0a720f6c (diff)
Fix recursive structs with optionals
Diffstat (limited to 'typecheck.c')
-rw-r--r--typecheck.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/typecheck.c b/typecheck.c
index c459b733..49ed7577 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -298,9 +298,10 @@ void bind_statement(env_t *env, ast_t *statement)
arg_t *fields = NULL;
for (arg_ast_t *field_ast = def->fields; field_ast; field_ast = field_ast->next) {
type_t *field_t = get_arg_ast_type(env, field_ast);
- if ((field_t->tag == StructType && Match(field_t, StructType)->opaque)
- || (field_t->tag == EnumType && Match(field_t, EnumType)->opaque)) {
- if (field_t == type)
+ type_t *non_opt_field_t = field_t->tag == OptionalType ? Match(field_t, OptionalType)->type : field_t;
+ if ((non_opt_field_t->tag == StructType && Match(non_opt_field_t, StructType)->opaque)
+ || (non_opt_field_t->tag == EnumType && Match(non_opt_field_t, EnumType)->opaque)) {
+ if (non_opt_field_t == type)
code_err(field_ast->type, "This is a recursive struct that would be infinitely large. Maybe you meant to use an optional '@%T?' pointer instead?", type);
else
code_err(field_ast->type, "I'm still in the process of defining the fields of %T, so I don't know how to use it as a member."
@@ -329,9 +330,10 @@ void bind_statement(env_t *env, ast_t *statement)
arg_t *fields = NULL;
for (arg_ast_t *field_ast = tag_ast->fields; field_ast; field_ast = field_ast->next) {
type_t *field_t = get_arg_ast_type(env, field_ast);
- if ((field_t->tag == StructType && Match(field_t, StructType)->opaque)
- || (field_t->tag == EnumType && Match(field_t, EnumType)->opaque)) {
- if (field_t == type)
+ type_t *non_opt_field_t = field_t->tag == OptionalType ? Match(field_t, OptionalType)->type : field_t;
+ if ((non_opt_field_t->tag == StructType && Match(non_opt_field_t, StructType)->opaque)
+ || (non_opt_field_t->tag == EnumType && Match(non_opt_field_t, EnumType)->opaque)) {
+ if (non_opt_field_t == type)
code_err(field_ast->type, "This is a recursive enum that would be infinitely large. Maybe you meant to use an optional '@%T?' pointer instead?", type);
else
code_err(field_ast->type, "I'm still in the process of defining the fields of %T, so I don't know how to use it as a member."