From 1028f85daaa6820fddd8ffe5ab957ced40092d6b Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 25 Dec 2025 22:01:15 +0100 Subject: [PATCH] - Better error messages when slicing a pointer to a slice or vector. #2681 --- releasenotes.md | 1 + src/compiler/sema_expr.c | 20 ++++++++--- .../slices/slice_error_improvement.c3 | 34 +++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 test/test_suite/slices/slice_error_improvement.c3 diff --git a/releasenotes.md b/releasenotes.md index 0dadd6933..b7d18e543 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -10,6 +10,7 @@ - Support for NetBSD. - Testing for the presence of methods at the top level is prohibited previous to method registration. - `$$MASK_TO_INT` and `$$INT_TO_MASK` to create bool masks from integers and back. +- Better error messages when slicing a pointer to a slice or vector. #2681 ### Fixes - Regression with npot vector in struct triggering an assert #2219. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 03cfafa3c..b4d7d8ce7 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -4450,7 +4450,7 @@ typedef enum RangeEnv RANGE_FLEXIBLE, } RangeEnv; -INLINE bool sema_expr_analyse_range_internal(SemaContext *context, Range *range, ArrayIndex len, RangeEnv env) +INLINE bool sema_expr_analyse_range_internal(SemaContext *context, Range *range, ArrayIndex len, RangeEnv env, FlatType *indexed_type) { Expr *start = exprptr(range->start); ASSERT(start); @@ -4482,14 +4482,26 @@ INLINE bool sema_expr_analyse_range_internal(SemaContext *context, Range *range, { if (range->start_from_end) { + if (indexed_type->type_kind == TYPE_POINTER && type_is_any_arraylike(indexed_type->pointer)) + { + RETURN_SEMA_ERROR(start, "Indexing from the end is not allowed for pointers, did you perhaps forget to dereference the pointer before []?"); + } RETURN_SEMA_ERROR(start, "Indexing from the end is not allowed for pointers or flexible array members."); } if (!end) { + if (indexed_type->type_kind == TYPE_POINTER && type_is_any_arraylike(indexed_type->pointer)) + { + RETURN_SEMA_ERROR(start, "Omitting the end index is not allowed for pointers, did you perhaps forget to dereference the pointer before slicing wih []?"); + } RETURN_SEMA_ERROR(start, "Omitting end index is not allowed for pointers or flexible array members."); } if (end && range->end_from_end) { + if (indexed_type->type_kind == TYPE_POINTER && type_is_any_arraylike(indexed_type->pointer)) + { + RETURN_SEMA_ERROR(start, "Indexing from the end is not allowed for pointers, did you perhaps forget to dereference the pointer before []?"); + } RETURN_SEMA_ERROR(end, "Indexing from the end is not allowed for pointers or flexible array members."); } } @@ -4609,7 +4621,7 @@ INLINE bool sema_expr_analyse_range_internal(SemaContext *context, Range *range, } -static inline bool sema_expr_analyse_range(SemaContext *context, Range *range, ArrayIndex len, RangeEnv env) +static inline bool sema_expr_analyse_range(SemaContext *context, Range *range, ArrayIndex len, RangeEnv env, FlatType *indexed_type) { switch (range->status) { @@ -4617,7 +4629,7 @@ static inline bool sema_expr_analyse_range(SemaContext *context, Range *range, A return true; case RESOLVE_NOT_DONE: range->status = RESOLVE_RUNNING; - if (!sema_expr_analyse_range_internal(context, range, len, env)) + if (!sema_expr_analyse_range_internal(context, range, len, env, indexed_type)) { range->status = RESOLVE_NOT_DONE; return false; @@ -4733,7 +4745,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) } ArrayIndex length = sema_len_from_expr(subscripted); Range *range = &expr->slice_expr.range; - if (!sema_expr_analyse_range(context, range, length, env)) return false; + if (!sema_expr_analyse_range(context, range, length, env, type)) return false; if (range->is_optional) optional = true; if (sema_cast_const(subscripted) && range->range_type == RANGE_CONST_RANGE) { diff --git a/test/test_suite/slices/slice_error_improvement.c3 b/test/test_suite/slices/slice_error_improvement.c3 new file mode 100644 index 000000000..49e92d09c --- /dev/null +++ b/test/test_suite/slices/slice_error_improvement.c3 @@ -0,0 +1,34 @@ +import std; + + +macro transpose4x4_mat(a, b, c, d) +{ + Matrix4x4{float} mat; + + mat.m[0..3] = *a[..]; // #error: Omitting the end index is not allowed for pointers, did you perhaps forget to dereference the pointer before slicing wih []? + mat.m[4..7] = *b[..]; + mat.m[8..11] = *c[..]; + mat.m[12..15] = *d[..]; + + mat = mat.transpose(); + + *a = mat.m[0..3]; + *b = mat.m[4..7]; + *c = mat.m[8..11]; + *d = mat.m[12..15]; +} + +fn void main() +{ + float[<4>] a = { 0,1,2,3 }; + float[<4>] b = { 4,5,6,7 }; + float[<4>] c = { 8,9,10,11 }; + float[<4>] d = { 12,13,14,15 }; + + transpose4x4_mat(&a, &b, &c, &d); + + io::printn(a); + io::printn(b); + io::printn(c); + io::printn(d); +}