On x: [?]T = {...}, minimize errors by using the [?]T expression as a kind of hint

This commit is contained in:
gingerBill
2024-03-19 13:32:37 +00:00
parent 5159f30c9c
commit 80ecf5b68a
3 changed files with 46 additions and 14 deletions
+38 -9
View File
@@ -8672,6 +8672,24 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slice<As
} }
} }
gb_internal bool is_expr_inferred_fixed_array(Ast *type_expr) {
type_expr = unparen_expr(type_expr);
if (type_expr == nullptr) {
return false;
}
// [?]Type
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) {
return true;
}
}
return false;
}
gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Expr; ExprKind kind = Expr_Expr;
ast_node(cl, CompoundLit, node); 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_to_be_determined_array_count = false;
bool is_constant = true; 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 = nullptr;
// [?]Type // [?]Type
if (cl->type->kind == Ast_ArrayType && cl->type->ArrayType.count != nullptr) { if (type_expr->kind == Ast_ArrayType && type_expr->ArrayType.count != nullptr) {
Ast *count = cl->type->ArrayType.count; Ast *count = type_expr->ArrayType.count;
if (count->kind == Ast_UnaryExpr && if (count->kind == Ast_UnaryExpr &&
count->UnaryExpr.op.kind == Token_Question) { 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; is_to_be_determined_array_count = true;
} }
if (cl->elems.count > 0) { if (cl->elems.count > 0) {
if (cl->type->ArrayType.tag != nullptr) { if (type_expr->ArrayType.tag != nullptr) {
Ast *tag = cl->type->ArrayType.tag; Ast *tag = type_expr->ArrayType.tag;
GB_ASSERT(tag->kind == Ast_BasicDirective); GB_ASSERT(tag->kind == Ast_BasicDirective);
String name = tag->BasicDirective.name.string; String name = tag->BasicDirective.name.string;
if (name == "soa") { 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) { if (cl->elems.count > 0) {
Ast *tag = cl->type->DynamicArrayType.tag; Ast *tag = type_expr->DynamicArrayType.tag;
GB_ASSERT(tag->kind == Ast_BasicDirective); GB_ASSERT(tag->kind == Ast_BasicDirective);
String name = tag->BasicDirective.name.string; String name = tag->BasicDirective.name.string;
if (name == "soa") { if (name == "soa") {
@@ -8718,7 +8747,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
} }
if (type == nullptr) { if (type == nullptr) {
type = check_type(c, cl->type); type = check_type(c, type_expr);
} }
} }
+7 -5
View File
@@ -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; 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 != "") { if (ac.is_static && ac.thread_local_model != "") {
error(e->token, "The 'static' attribute is not needed if 'thread_local' is applied"); 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")); 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); check_arity_match(ctx, vd, false);
for (isize i = 0; i < entity_count; i++) { for (isize i = 0; i < entity_count; i++) {
+1
View File
@@ -451,6 +451,7 @@ struct CheckerContext {
u32 state_flags; u32 state_flags;
bool in_defer; bool in_defer;
Type * type_hint; Type * type_hint;
Ast * type_hint_expr;
String proc_name; String proc_name;
DeclInfo * curr_proc_decl; DeclInfo * curr_proc_decl;