diff --git a/releasenotes.md b/releasenotes.md index ddd6ceb63..79c74eb54 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -76,6 +76,7 @@ - Debug info with recursive canonical type usage could cause segfault. - Missing check on optional left hand side for `s.x`. - Incorrect zero analysis on `foo["test"] = {}` #1360. +- Bug converting untyped list #1360. ### Stdlib changes diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 4e8aa359e..47f11d795 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -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) { + 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; unsigned size = vec_size(expressions); 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) { + 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; 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) { - // Recursively set the type of all ConstInitializer inside. - expr_recursively_rewrite_untyped_list(expr, expr->const_expr.untyped_list); + if (expr->const_expr.const_kind == CONST_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) bool success = sema_expr_analyse_initializer_list(context, type_flatten(to_type), expr); assert(success); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 45256c415..212fbe007 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -2958,6 +2958,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, if (eval_type == SUBSCRIPT_EVAL_ASSIGN) { expr->expr_kind = EXPR_SUBSCRIPT_ASSIGN; + expr->type = index_type; expr->subscript_assign_expr.expr = exprid(current_expr); expr->subscript_assign_expr.index = exprid(index); expr->subscript_assign_expr.method = declid(overload); diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index a3ce92d5c..3b794742a 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -466,6 +466,7 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ass // Note at this point this we either have // EXPR_DESIGNATED_INITIALIZER_LIST // or EXPR_INITIALIZER_LIST + // or EXPR_CONST with a ConstInitializer // 1. Designated initializer is separately evaluated. 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) { + assert(expr->const_expr.const_kind == CONST_INITIALIZER); return cast_implicit(context, expr, assigned_type, false); } assert(expr->expr_kind == EXPR_INITIALIZER_LIST); diff --git a/test/test_suite/struct/const_zero_init_1360.c3t b/test/test_suite/struct/const_zero_init_1360.c3t index eefb8b01d..84ac850d5 100644 --- a/test/test_suite/struct/const_zero_init_1360.c3t +++ b/test/test_suite/struct/const_zero_init_1360.c3t @@ -1,10 +1,20 @@ module test; import std::collections::map; +def Foo = HashMap()>); fn void main() { - HashMap() map; + HashMap() map0; + map0["c3c"] = {}; + + Foo map; map["c3c"] = {}; + map["c3c"] = { {}, null, 1 ,2 ,2 }; + + HashMap()>) map2; + map2["c3c"] = {}; + map2["c3c"] = { {}, null, 1 ,2 ,2 }; + } /* #expect: test.ll