From 80ecf5b68aa02a2445aa4cbf3d1d46ed5a007d75 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Mar 2024 13:32:37 +0000 Subject: [PATCH] On `x: [?]T = {...}`, minimize errors by using the `[?]T` expression as a kind of hint --- src/check_expr.cpp | 47 +++++++++++++++++++++++++++++++++++++--------- src/check_stmt.cpp | 12 +++++++----- src/checker.hpp | 1 + 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index bb31a1646..ed6182928 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8672,6 +8672,24 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slicekind == Ast_ArrayType && type_expr->ArrayType.count != nullptr) { + Ast *count = type_expr->ArrayType.count; + if (count->kind == Ast_UnaryExpr && + count->UnaryExpr.op.kind == Token_Question) { + return true; + } + } + return false; +} + gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { ExprKind kind = Expr_Expr; ast_node(cl, CompoundLit, node); @@ -8682,20 +8700,31 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } bool is_to_be_determined_array_count = false; bool is_constant = true; - if (cl->type != nullptr) { + + Ast *type_expr = cl->type; + + bool used_type_hint_expr = false; + if (type_expr == nullptr && c->type_hint_expr != nullptr) { + if (is_expr_inferred_fixed_array(c->type_hint_expr)) { + type_expr = clone_ast(c->type_hint_expr); + used_type_hint_expr = true; + } + } + + if (type_expr != nullptr) { type = nullptr; // [?]Type - if (cl->type->kind == Ast_ArrayType && cl->type->ArrayType.count != nullptr) { - Ast *count = cl->type->ArrayType.count; + if (type_expr->kind == Ast_ArrayType && type_expr->ArrayType.count != nullptr) { + Ast *count = type_expr->ArrayType.count; if (count->kind == Ast_UnaryExpr && count->UnaryExpr.op.kind == Token_Question) { - type = alloc_type_array(check_type(c, cl->type->ArrayType.elem), -1); + type = alloc_type_array(check_type(c, type_expr->ArrayType.elem), -1); is_to_be_determined_array_count = true; } if (cl->elems.count > 0) { - if (cl->type->ArrayType.tag != nullptr) { - Ast *tag = cl->type->ArrayType.tag; + if (type_expr->ArrayType.tag != nullptr) { + Ast *tag = type_expr->ArrayType.tag; GB_ASSERT(tag->kind == Ast_BasicDirective); String name = tag->BasicDirective.name.string; if (name == "soa") { @@ -8705,9 +8734,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } } } - if (cl->type->kind == Ast_DynamicArrayType && cl->type->DynamicArrayType.tag != nullptr) { + if (type_expr->kind == Ast_DynamicArrayType && type_expr->DynamicArrayType.tag != nullptr) { if (cl->elems.count > 0) { - Ast *tag = cl->type->DynamicArrayType.tag; + Ast *tag = type_expr->DynamicArrayType.tag; GB_ASSERT(tag->kind == Ast_BasicDirective); String name = tag->BasicDirective.name.string; if (name == "soa") { @@ -8718,7 +8747,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } if (type == nullptr) { - type = check_type(c, cl->type); + type = check_type(c, type_expr); } } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index a6ca4b9dd..4280e7578 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1919,17 +1919,19 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f e->Variable.thread_local_model = ac.thread_local_model; } - if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) { - // error(e->token, "@(thread_local) is not supported for this target platform"); - } - - if (ac.is_static && ac.thread_local_model != "") { error(e->token, "The 'static' attribute is not needed if 'thread_local' is applied"); } } + // NOTE(bill): This is to improve error handling for things like `x: [?]T = {...}` + Ast *prev_type_hint_expr = ctx->type_hint_expr; + ctx->type_hint_expr = vd->type; + check_init_variables(ctx, entities, entity_count, vd->values, str_lit("variable declaration")); + + ctx->type_hint_expr = prev_type_hint_expr; + check_arity_match(ctx, vd, false); for (isize i = 0; i < entity_count; i++) { diff --git a/src/checker.hpp b/src/checker.hpp index 066d6bb4a..eea99578e 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -451,6 +451,7 @@ struct CheckerContext { u32 state_flags; bool in_defer; Type * type_hint; + Ast * type_hint_expr; String proc_name; DeclInfo * curr_proc_decl;