From 759bc1d9093ed4970f27cbd54bab31eb45126d8d Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 3 Jul 2025 23:32:02 +0200 Subject: [PATCH] Const slice lengths were not always detected as constant. --- releasenotes.md | 1 + src/compiler/sema_casts.c | 2 +- src/compiler/sema_const.c | 12 +++++++++- src/compiler/sema_expr.c | 24 ++++++------------- test/test_suite/slices/const_slice_len.c3 | 6 +++++ .../struct/inline_slice_access_2088.c3t | 3 --- 6 files changed, 26 insertions(+), 22 deletions(-) create mode 100644 test/test_suite/slices/const_slice_len.c3 diff --git a/releasenotes.md b/releasenotes.md index b7c289025..b9650a0bc 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -21,6 +21,7 @@ - Non-const macros may not return untyped lists. - `$for` ct-state not properly popped. - Inline `r / complex` for complex numbers fixed. +- Const slice lengths were not always detected as constant. ### Stdlib changes diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 02302b68b..daf342713 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -2214,7 +2214,7 @@ static void cast_slice_to_bool(Expr *expr, Type *type) } if (expr_is_const_slice(expr)) { - expr_rewrite_const_bool(expr, type, expr->const_expr.slice_init != NULL); + expr_rewrite_const_bool(expr, type, expr->const_expr.slice_init != NULL && expr->const_expr.slice_init->kind != CONST_INIT_ZERO); return; } Expr *inner = expr_copy(expr); diff --git a/src/compiler/sema_const.c b/src/compiler/sema_const.c index 3ed085605..d7e0186bf 100644 --- a/src/compiler/sema_const.c +++ b/src/compiler/sema_const.c @@ -12,7 +12,17 @@ ArrayIndex sema_len_from_const(Expr *expr) // We also handle the case where we have a cast from a const array. if (!sema_cast_const(expr)) { - if (type_flatten(expr->type)->type_kind != TYPE_SLICE) return -1; + Type *flat = type_flatten(expr->type); + switch (flat->type_kind) + { + case TYPE_ARRAY: + case TYPE_VECTOR: + return flat->array.len; + case TYPE_SLICE: + break; + default: + return -1; + } if (expr->expr_kind == EXPR_SLICE) { return range_const_len(&expr->slice_expr.range); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 5874aba56..f06f93a24 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -5889,28 +5889,18 @@ CHECK_DEEPER: // 9. Fix hard coded function `len` on slices and arrays if (kw == kw_len) { + ArrayIndex index = sema_len_from_const(current_parent); + if (index > -1) + { + expr_rewrite_const_int(expr, type_isz, index); + return true; + } if (flat_type->type_kind == TYPE_SLICE) { - // Handle literal "foo".len which is now a slice. - sema_expr_flatten_const_ident(current_parent); - if (expr_is_const_string(current_parent)) - { - expr_rewrite_const_int(expr, type_isz, current_parent->const_expr.bytes.len); - return true; - } expr_rewrite_slice_len(expr, current_parent, type_usz); return true; } - if (flat_type->type_kind == TYPE_ARRAY || flat_type->type_kind == TYPE_VECTOR) - { - expr_rewrite_const_int(expr, type_isz, flat_type->array.len); - return true; - } - if (flat_type->type_kind == TYPE_UNTYPED_LIST) - { - expr_rewrite_const_int(expr, type_isz, vec_size(current_parent->const_expr.untyped_list)); - return true; - } + assert(flat_type->type_kind != TYPE_ARRAY && flat_type->type_kind != TYPE_VECTOR); } if (flat_type->type_kind == TYPE_TYPEID) { diff --git a/test/test_suite/slices/const_slice_len.c3 b/test/test_suite/slices/const_slice_len.c3 new file mode 100644 index 000000000..79871a513 --- /dev/null +++ b/test/test_suite/slices/const_slice_len.c3 @@ -0,0 +1,6 @@ +fn int main() +{ + const char[][] SEQUENCE = { { 1 }}; + var $i = SEQUENCE.len; + return 0; +} \ No newline at end of file diff --git a/test/test_suite/struct/inline_slice_access_2088.c3t b/test/test_suite/struct/inline_slice_access_2088.c3t index e97954ec7..4b1985dad 100644 --- a/test/test_suite/struct/inline_slice_access_2088.c3t +++ b/test/test_suite/struct/inline_slice_access_2088.c3t @@ -15,8 +15,5 @@ fn int main() /* #expect: test.ll entry: - %literal = alloca %Foo, align 8 - call void @llvm.memset.p0.i64(ptr align 8 %literal, i8 0, i64 16, i1 false) - %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 ret i32 0 }