From 6360ddbc7798e875414015e65df57d4e42963b06 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 11 Nov 2025 12:36:02 +0100 Subject: [PATCH] - When encountering a foreach over a `ZString*` it would not properly emit a compilation error, but hit an assert #2573. --- releasenotes.md | 1 + src/compiler/sema_stmts.c | 4 +++- test/test_suite/statements/foreach_zstring.c3 | 9 +++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/test_suite/statements/foreach_zstring.c3 diff --git a/releasenotes.md b/releasenotes.md index 677634f3d..ac8e3cda9 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -20,6 +20,7 @@ - Compiler assert with const enum based on vector #2566 - Fix to `Path` handling `c:\foo` and `\home` parent. #2569 - Fix appending to `c:\` or `\` #2569. +- When encountering a foreach over a `ZString*` it would not properly emit a compilation error, but hit an assert #2573. ### Stdlib changes diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 263738814..573da66f4 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1546,6 +1546,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen RETURN_SEMA_ERROR(var, "Add an explicit type to the variable if you want to iterate over an initializer list."); } + Type *original_type = enumerator->type; // In the case of a single `*`, then we will implicitly dereference that pointer. if (canonical->type_kind == TYPE_POINTER) { @@ -1555,6 +1556,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen RETURN_SEMA_ERROR(enumerator, "It is not possible to enumerate an expression of type %s.", type_quoted_error_string(enumerator->type)); } if (!sema_expr_rewrite_insert_deref(context, enumerator)) return false; + canonical = enumerator->type->canonical; } // At this point we should have dereferenced any pointer or bailed. @@ -1600,7 +1602,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen if (value_type) goto SKIP_OVERLOAD; // Otherwise this is an error. - RETURN_SEMA_ERROR(enumerator, "It's not possible to enumerate an expression of type %s.", type_quoted_error_string(enumerator->type)); + RETURN_SEMA_ERROR(enumerator, "It's not possible to enumerate an expression of type %s.", type_quoted_error_string(original_type)); } // If we want the value "by ref" and there isn't a &[], then this is an error. if (!by_ref && value_by_ref) diff --git a/test/test_suite/statements/foreach_zstring.c3 b/test/test_suite/statements/foreach_zstring.c3 new file mode 100644 index 000000000..e96baba0e --- /dev/null +++ b/test/test_suite/statements/foreach_zstring.c3 @@ -0,0 +1,9 @@ +module get_environ; +import std; + +fn void main(String[] args) +{ + ZString* environ_arr = std::os::posix::environ; + foreach (idx, ZString &envvar : environ_arr) // #error: It's not possible to enumerate an expression of type 'ZString*' + {} +} \ No newline at end of file