Bug converting untyped list #1360

This commit is contained in:
Christoffer Lerno
2024-08-16 18:33:30 +02:00
parent f1efdf3d98
commit 16cb756d3f
5 changed files with 39 additions and 3 deletions

View File

@@ -76,6 +76,7 @@
- Debug info with recursive canonical type usage could cause segfault. - Debug info with recursive canonical type usage could cause segfault.
- Missing check on optional left hand side for `s.x`. - Missing check on optional left hand side for `s.x`.
- Incorrect zero analysis on `foo["test"] = {}` #1360. - Incorrect zero analysis on `foo["test"] = {}` #1360.
- Bug converting untyped list #1360.
### Stdlib changes ### Stdlib changes

View File

@@ -806,6 +806,12 @@ static bool rule_arrptr_to_slice(CastContext *cc, bool is_explicit, bool is_sile
static bool rule_ulist_to_struct(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_ulist_to_struct(CastContext *cc, bool is_explicit, bool is_silent)
{ {
if (expr_is_const_initializer(cc->expr))
{
assert(cc->expr->const_expr.initializer->kind == CONST_INIT_ZERO);
return true;
}
assert(expr_is_const_untyped_list(cc->expr));
Expr **expressions = cc->expr->const_expr.untyped_list; Expr **expressions = cc->expr->const_expr.untyped_list;
unsigned size = vec_size(expressions); unsigned size = vec_size(expressions);
if (!size) return true; if (!size) return true;
@@ -848,6 +854,11 @@ static bool rule_ulist_to_vecarr(CastContext *cc, bool is_explicit, bool is_sile
static bool rule_ulist_to_slice(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_ulist_to_slice(CastContext *cc, bool is_explicit, bool is_silent)
{ {
if (cc->expr->const_expr.const_kind == CONST_INITIALIZER)
{
assert(cc->expr->const_expr.initializer->kind == CONST_INIT_ZERO);
return true;
}
Type *base = cc->to->array.base; Type *base = cc->to->array.base;
FOREACH(Expr *, expr, cc->expr->const_expr.untyped_list) FOREACH(Expr *, expr, cc->expr->const_expr.untyped_list)
{ {
@@ -1790,8 +1801,19 @@ static void cast_vec_to_vec(SemaContext *context, Expr *expr, Type *to_type)
static void cast_untyped_list_to_other(SemaContext *context, Expr *expr, Type *to_type) static void cast_untyped_list_to_other(SemaContext *context, Expr *expr, Type *to_type)
{ {
// Recursively set the type of all ConstInitializer inside. if (expr->const_expr.const_kind == CONST_UNTYPED_LIST)
expr_recursively_rewrite_untyped_list(expr, expr->const_expr.untyped_list); {
// Recursively set the type of all ConstInitializer inside.
expr_recursively_rewrite_untyped_list(expr, expr->const_expr.untyped_list);
}
if (expr_is_const_initializer(expr) && expr->const_expr.initializer->kind == CONST_INIT_ZERO)
{
expr->type = to_type;
expr->inner_expr->type = type_flatten(to_type);
expr->resolve_status = RESOLVE_DONE;
return;
}
expr->resolve_status = RESOLVE_NOT_DONE;
// We can now analyse the list (this is where the actual check happens) // We can now analyse the list (this is where the actual check happens)
bool success = sema_expr_analyse_initializer_list(context, type_flatten(to_type), expr); bool success = sema_expr_analyse_initializer_list(context, type_flatten(to_type), expr);
assert(success); assert(success);

View File

@@ -2958,6 +2958,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
if (eval_type == SUBSCRIPT_EVAL_ASSIGN) if (eval_type == SUBSCRIPT_EVAL_ASSIGN)
{ {
expr->expr_kind = EXPR_SUBSCRIPT_ASSIGN; expr->expr_kind = EXPR_SUBSCRIPT_ASSIGN;
expr->type = index_type;
expr->subscript_assign_expr.expr = exprid(current_expr); expr->subscript_assign_expr.expr = exprid(current_expr);
expr->subscript_assign_expr.index = exprid(index); expr->subscript_assign_expr.index = exprid(index);
expr->subscript_assign_expr.method = declid(overload); expr->subscript_assign_expr.method = declid(overload);

View File

@@ -466,6 +466,7 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ass
// Note at this point this we either have // Note at this point this we either have
// EXPR_DESIGNATED_INITIALIZER_LIST // EXPR_DESIGNATED_INITIALIZER_LIST
// or EXPR_INITIALIZER_LIST // or EXPR_INITIALIZER_LIST
// or EXPR_CONST with a ConstInitializer
// 1. Designated initializer is separately evaluated. // 1. Designated initializer is separately evaluated.
if (expr->expr_kind == EXPR_DESIGNATED_INITIALIZER_LIST) if (expr->expr_kind == EXPR_DESIGNATED_INITIALIZER_LIST)
@@ -475,6 +476,7 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ass
if (expr->expr_kind == EXPR_CONST) if (expr->expr_kind == EXPR_CONST)
{ {
assert(expr->const_expr.const_kind == CONST_INITIALIZER);
return cast_implicit(context, expr, assigned_type, false); return cast_implicit(context, expr, assigned_type, false);
} }
assert(expr->expr_kind == EXPR_INITIALIZER_LIST); assert(expr->expr_kind == EXPR_INITIALIZER_LIST);

View File

@@ -1,10 +1,20 @@
module test; module test;
import std::collections::map; import std::collections::map;
def Foo = HashMap(<String, HashMap(<String, String>)>);
fn void main() fn void main()
{ {
HashMap(<String, String>) map; HashMap(<String, String>) map0;
map0["c3c"] = {};
Foo map;
map["c3c"] = {}; map["c3c"] = {};
map["c3c"] = { {}, null, 1 ,2 ,2 };
HashMap(<String, HashMap(<String, String>)>) map2;
map2["c3c"] = {};
map2["c3c"] = { {}, null, 1 ,2 ,2 };
} }
/* #expect: test.ll /* #expect: test.ll