Deprecating multi-level array length inference. int[*][*] is deprecated and will be removed 0.8.0.

This commit is contained in:
Christoffer Lerno
2026-01-22 23:50:39 +01:00
parent 17f3db835c
commit ae5047b73f
14 changed files with 46 additions and 30 deletions

View File

@@ -21,6 +21,7 @@
- Create optional with `~` instead of `?`. `return io::EOF?;` becomes `return io::EOF~`.
- Deprecated use of `?` to create optional.
- Make `foo.$abc` implicitly mean `foo.eval("$abc")`.
- Deprecating multi-level array length inference. `int[*][*]` is deprecated and will be removed 0.8.0.
### Fixes
- Regression with npot vector in struct triggering an assert #2219.

View File

@@ -13,6 +13,7 @@ INLINE bool sema_resolve_vatype(SemaContext *context, TypeInfo *type_info);
INLINE bool sema_resolve_evaltype(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_kind);
INLINE bool sema_resolve_typefrom(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_kind);
INLINE bool sema_resolve_typeof(SemaContext *context, TypeInfo *type_info);
static inline bool sema_check_ptr_type(SemaContext *context, TypeInfo *type_info, Type *inner);
static int compare_function(Signature *sig, FunctionPrototype *proto);
static inline bool sema_resolve_ptr_type(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_kind)
@@ -22,6 +23,8 @@ static inline bool sema_resolve_ptr_type(SemaContext *context, TypeInfo *type_in
{
return type_info_poison(type_info);
}
if (!sema_check_ptr_type(context, type_info, type_info->pointer->type)) return type_info_poison(type_info);
// Construct the type after resolving the underlying type.
type_info->type = type_get_ptr(type_info->pointer->type);
type_info->resolve_status = RESOLVE_DONE;
@@ -98,6 +101,10 @@ static inline bool sema_check_array_type(SemaContext *context, TypeInfo *origina
{
Type *distinct_base = type_flatten(base);
if (type_is_infer_type(distinct_base))
{
SEMA_DEPRECATED(original_info, "Use of inferred inner types is not well supported and support will be removed in 0.8.0.");
}
// We don't want to allow arrays with flexible members
if (distinct_base->type_kind == TYPE_STRUCT)
{
@@ -475,6 +482,23 @@ INLINE bool sema_resolve_generic_type(SemaContext *context, TypeInfo *type_info)
return true;
}
static inline bool sema_check_ptr_type(SemaContext *context, TypeInfo *type_info, Type *inner)
{
CanonicalType *type = inner->canonical;
switch (type->type_kind)
{
case CT_TYPES:
if (type_is_infer_type(type))
{
SEMA_DEPRECATED(type_info, "Using an inferred type as a pointer is not supported and will be removed in 0.8.0.");
return true;
}
RETURN_SEMA_ERROR(type_info, "Pointers to %s are not supported.", type_quoted_error_string(inner));
default:
return true;
}
}
static inline bool sema_resolve_type(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_kind)
{
// Ok, already resolved.
@@ -567,6 +591,7 @@ APPEND_QUALIFIERS:
case TYPE_COMPRESSED_NONE:
break;
case TYPE_COMPRESSED_PTR:
if (!sema_check_ptr_type(context, type_info, type_info->type)) return type_info_poison(type_info);
type_info->type = type_get_ptr(type_info->type);
break;
case TYPE_COMPRESSED_SUB:
@@ -577,9 +602,11 @@ APPEND_QUALIFIERS:
type_info->type = type_get_ptr(type_info->type);
break;
case TYPE_COMPRESSED_PTRPTR:
if (!sema_check_ptr_type(context, type_info, type_info->type)) return type_info_poison(type_info);
type_info->type = type_get_ptr(type_get_ptr(type_info->type));
break;
case TYPE_COMPRESSED_PTRSUB:
if (!sema_check_ptr_type(context, type_info, type_info->type)) return type_info_poison(type_info);
type_info->type = type_get_slice(type_get_ptr(type_info->type));
break;
case TYPE_COMPRESSED_SUBSUB:

View File

@@ -1,5 +1,5 @@
import std;
macro void test(int[*][6] a)
macro void test(int[2][6] a)
{
}
fn void main()

View File

@@ -3,8 +3,8 @@ module test;
fn void main()
{
int[*][*][2][*]? y = { {{{1}, {2}}, { {3}, {4}}}};
int[*][*][2][*] x = { {{{1}, {2}}, { {3}, {4}}}};
int[1][2][2][*]? y = { {{{1}, {2}}, { {3}, {4}}}};
int[1][2][2][*] x = { {{{1}, {2}}, { {3}, {4}}}};
}
/* #expect: test.ll

View File

@@ -2,17 +2,17 @@
fn void test1()
{
var $d = { {1}, {2, 3} };
var $e = (int[*][*])$d; // #error: contains elements that have different lengths
var $e = (int[2][*])$d; // #error: This untyped list contained an element
}
fn void test2()
{
var $d = { {1}, {3}, {2} };
var $e = (int[*][*])$d;
var $e = (int[1][*])$d;
}
fn void test3()
{
var $d = { {1}, {} };
var $e = (int[*][*])$d; // #error: This untyped list contained an element of type
var $e = (int[1][*])$d;
}

View File

@@ -2,8 +2,8 @@
module test;
char[1][*] a = { [0] = { [0] = 1 } };
char[1][1] b = { [0] = { [0] = 1 } };
char[*][*] c = { [0] = { [0] = 1 } };
char[*][1] d = { [0] = { [0] = 1 } };
char[2][*] c = { [0] = { [0] = 1 } };
char[4][1] d = { [0] = { [0] = 1 } };
fn void main()
{

View File

@@ -1,11 +1,11 @@
import std;
macro test(int[*][1] a) {
macro test(int[1][1] a) {
var b = a;
}
fn int main()
{
int[][1] b;
test(b); // #error: It is not possible to cast 'int[][1]' to 'int[*][1]'
test(b); // #error: It is not possible to cast 'int[][1]' to 'int[1][1]'
return 12;
}

View File

@@ -1,5 +1,4 @@
fn void main()
{
int[*][*][] x = (int[2][1][]) { { { 1, 2 } } };
int[*][*][*] y = (int[2][1][]) { { { 1, 2 } } };
int[2][1][*] y = (int[2][1][]) { { { 1, 2 } } };
}

View File

@@ -2,6 +2,6 @@ import std;
fn int main()
{
char[] a = "hello";
char[*] b = *(char[*]*)&a; // #error: cannot be used to infer the length
char[*] b = *(char[5]*)a.ptr;
return 0;
}

View File

@@ -1,6 +0,0 @@
import std;
fn void main()
{
char[*]* x = "abc"; // #error: You cannot cast 'String' to 'char[*]*'
io::printn($typeof(x).nameof);
}

View File

@@ -1,7 +1,7 @@
// #target: macos-x64
module test;
macro int test(int[*][*]* y)
macro int test(int[2][2]* y)
{
$typeof(*y) z = *y;
return z[1][1];
@@ -11,7 +11,7 @@ fn void main()
{
int[2][*] x = { { 2, 3}, { 5, 6 }};
int[<2>][*] y = { { 1, 3 }};
int[<*>][*] z = y;
int[<2>][*] z = y;
int[<2>][1] w = z;
int[<2>][] aa = { { 1, 3 }};
int[][*] bb = { { 1, 3 } };

View File

@@ -27,6 +27,6 @@ struct Baz { int x; }
fn void test4()
{
Baz[2][*] x = { { { 2 } , { 3 } }, {{5}, {6} }};
Bar[*][*] y = (Bar[2][2])x;
Baz[2][2] x = { { { 2 } , { 3 } }, {{5}, {6} }};
Bar[2][2] y = (Bar[2][2])x;
}

View File

@@ -1,5 +0,0 @@
fn int main()
{
int [*][] y = { }; // #error: Inferring the slice inner type from an empty initializer is not possible
return 0;
}

View File

@@ -30,6 +30,6 @@ fn void pointer_add_sub_diff()
assert(w == { -1, 2 });
int*[<2>] zz = y - (y - yy);
assert(zz[0] == &a[1] && zz[1] == &a[2]);
int[*]*[<2>] g = (int[2]*[<2>]) { null, null };
int[*]*[<*>] g2 = (int[2]*[<2>]) { null, null };
int[2]*[<2>] g = { null, null };
int[2]*[<2>] g2 = { null, null };
}