diff --git a/releasenotes.md b/releasenotes.md index f88fed197..9c488865e 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -26,6 +26,7 @@ - Bitstructs no longer overloadable with bitops. #2374 - types::has_equals fails with assert for bitstructs #2377 - Fix `native_cpus` functionality for OpenBSD systems. #2387 +- Assert triggered when trying to slice a struct. ### Stdlib changes - Add `==` to `Pair`, `Triple` and TzDateTime. Add print to `Pair` and `Triple`. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 193469a14..45fe342a1 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -4265,16 +4265,19 @@ static inline bool sema_expr_analyse_range(SemaContext *context, Range *range, A } } -static inline void sema_slice_initializer(Expr *expr, Expr *subscripted, Range *range) +static inline bool sema_slice_initializer(SemaContext *context, Expr *expr, Expr *subscripted, Range *range) { ConstInitializer *initializer = subscripted->const_expr.initializer; - ASSERT(type_is_arraylike(initializer->type)); + if (!type_is_arraylike(initializer->type)) + { + RETURN_SEMA_ERROR(expr, "It's not possible to slice an expression of type %s.", type_quoted_error_string(subscripted->type)); + } Type *new_type = type_get_slice(type_get_indexed_type(subscripted->type)); // Turn zero length into an untyped list. if (range->len_index == 0) { expr_rewrite_const_empty_slice(expr, new_type); - return; + return true; } bool is_vec = initializer->type->type_kind == TYPE_VECTOR; Type *inner_type = is_vec @@ -4319,6 +4322,7 @@ static inline void sema_slice_initializer(Expr *expr, Expr *subscripted, Range * subscripted->const_expr.const_kind = CONST_SLICE; expr_replace(expr, subscripted); expr->type = new_type; + return true; } static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, CheckType check) @@ -4385,8 +4389,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, Che expr_replace(expr, subscripted); return true; case CONST_INITIALIZER: - sema_slice_initializer(expr, subscripted, range); - return true; + return sema_slice_initializer(context, expr, subscripted, range); case CONST_SLICE: if (!subscripted->const_expr.slice_init) { @@ -4394,8 +4397,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, Che expr_replace(expr, subscripted); return true; } - sema_slice_initializer(expr, subscripted, range); - return true; + return sema_slice_initializer(context, expr, subscripted, range); case CONST_POINTER: case CONST_FLOAT: case CONST_INTEGER: diff --git a/test/test_suite/arrays/slice_const_struct.c3 b/test/test_suite/arrays/slice_const_struct.c3 new file mode 100644 index 000000000..55082242f --- /dev/null +++ b/test/test_suite/arrays/slice_const_struct.c3 @@ -0,0 +1,28 @@ +struct Token +{ + char kind; +} + +macro getTokens() @const +{ + Token[64] $tokes; + $for var $i = 0; $i < 64; $i++: + $tokes = ((Token) {$i}); + $endfor + return $tokes[0..32]; // #error: to slice an expression +} + +macro checkTokes() @const +{ + Token[] $tokes = getTokens(); + $for var $i = 0; $i < $tokes.len; $i++: + $echo $tokes[$i]; + $endfor +} + +macro int main2() +{ + checkTokes(); +} + +fn int main() => checkTokes();