wcc/check: #25 reject overlong array-lit in a tuple return (wwstage)
This commit is contained in:
@@ -15123,6 +15123,19 @@ fn checkretassign(c: *checker, n: *node) void = {
|
|||||||
if (n.lhs.kind == nkind.N_ARRLIT) {
|
if (n.lhs.kind == nkind.N_ARRLIT) {
|
||||||
checkarrlitfits(c, c.fnret, n.lhs);
|
checkarrlitfits(c, c.fnret, n.lhs);
|
||||||
};
|
};
|
||||||
|
// #25: array-typed element of a TUPLE RETURN with an overlong array
|
||||||
|
// literal — `fn f() ([2]int,i32) = { return ([1,2,3],5); }`. #20
|
||||||
|
// wired the tuple over-fill walk at the LET position only; the
|
||||||
|
// return path runs through checkretassign which never routed tuple
|
||||||
|
// elements through checkarrlitfits. Reuse the #26 helper. Fire
|
||||||
|
// BEFORE the isassignable/conf guards (a tuple return drives
|
||||||
|
// conf=false → short-circuit), same reason as the #12 array arm
|
||||||
|
// above. Alias/!-aware on the fnret tuple type.
|
||||||
|
let rrt: *node = resolvealias(c, unwrapbang(c.fnret));
|
||||||
|
if (rrt != nil && rrt.kind == nkind.N_TTUPLE
|
||||||
|
&& n.lhs.kind == nkind.N_TUPLE) {
|
||||||
|
checktuplearrfits(c, rrt, n.lhs);
|
||||||
|
};
|
||||||
let src: *node = exprtype(c, n.lhs, nil);
|
let src: *node = exprtype(c, n.lhs, nil);
|
||||||
if (src == nil) { return; };
|
if (src == nil) { return; };
|
||||||
let conf: bool = false;
|
let conf: bool = false;
|
||||||
|
|||||||
@@ -4842,6 +4842,19 @@ fn checkretassign(c: *checker, n: *node) void = {
|
|||||||
if (n.lhs.kind == nkind.N_ARRLIT) {
|
if (n.lhs.kind == nkind.N_ARRLIT) {
|
||||||
checkarrlitfits(c, c.fnret, n.lhs);
|
checkarrlitfits(c, c.fnret, n.lhs);
|
||||||
};
|
};
|
||||||
|
// #25: array-typed element of a TUPLE RETURN with an overlong array
|
||||||
|
// literal — `fn f() ([2]int,i32) = { return ([1,2,3],5); }`. #20
|
||||||
|
// wired the tuple over-fill walk at the LET position only; the
|
||||||
|
// return path runs through checkretassign which never routed tuple
|
||||||
|
// elements through checkarrlitfits. Reuse the #26 helper. Fire
|
||||||
|
// BEFORE the isassignable/conf guards (a tuple return drives
|
||||||
|
// conf=false → short-circuit), same reason as the #12 array arm
|
||||||
|
// above. Alias/!-aware on the fnret tuple type.
|
||||||
|
let rrt: *node = resolvealias(c, unwrapbang(c.fnret));
|
||||||
|
if (rrt != nil && rrt.kind == nkind.N_TTUPLE
|
||||||
|
&& n.lhs.kind == nkind.N_TUPLE) {
|
||||||
|
checktuplearrfits(c, rrt, n.lhs);
|
||||||
|
};
|
||||||
let src: *node = exprtype(c, n.lhs, nil);
|
let src: *node = exprtype(c, n.lhs, nil);
|
||||||
if (src == nil) { return; };
|
if (src == nil) { return; };
|
||||||
let conf: bool = false;
|
let conf: bool = false;
|
||||||
|
|||||||
@@ -15123,6 +15123,19 @@ fn checkretassign(c: *checker, n: *node) void = {
|
|||||||
if (n.lhs.kind == nkind.N_ARRLIT) {
|
if (n.lhs.kind == nkind.N_ARRLIT) {
|
||||||
checkarrlitfits(c, c.fnret, n.lhs);
|
checkarrlitfits(c, c.fnret, n.lhs);
|
||||||
};
|
};
|
||||||
|
// #25: array-typed element of a TUPLE RETURN with an overlong array
|
||||||
|
// literal — `fn f() ([2]int,i32) = { return ([1,2,3],5); }`. #20
|
||||||
|
// wired the tuple over-fill walk at the LET position only; the
|
||||||
|
// return path runs through checkretassign which never routed tuple
|
||||||
|
// elements through checkarrlitfits. Reuse the #26 helper. Fire
|
||||||
|
// BEFORE the isassignable/conf guards (a tuple return drives
|
||||||
|
// conf=false → short-circuit), same reason as the #12 array arm
|
||||||
|
// above. Alias/!-aware on the fnret tuple type.
|
||||||
|
let rrt: *node = resolvealias(c, unwrapbang(c.fnret));
|
||||||
|
if (rrt != nil && rrt.kind == nkind.N_TTUPLE
|
||||||
|
&& n.lhs.kind == nkind.N_TUPLE) {
|
||||||
|
checktuplearrfits(c, rrt, n.lhs);
|
||||||
|
};
|
||||||
let src: *node = exprtype(c, n.lhs, nil);
|
let src: *node = exprtype(c, n.lhs, nil);
|
||||||
if (src == nil) { return; };
|
if (src == nil) { return; };
|
||||||
let conf: bool = false;
|
let conf: bool = false;
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
* tuple_arr_over | let t:([2]int,i32)=([1,2,3],5) | b. FAIL
|
* tuple_arr_over | let t:([2]int,i32)=([1,2,3],5) | b. FAIL
|
||||||
* tuple_nested_arr | let t:([2][3]int,i32)=([[..],[..],[..]],5) | b. FAIL
|
* tuple_nested_arr | let t:([2][3]int,i32)=([[..],[..],[..]],5) | b. FAIL
|
||||||
* tuple_in_tuple | let t:([2]int,([2]int,i32))=([..],([1,2,3],.))| #26 FAIL
|
* tuple_in_tuple | let t:([2]int,([2]int,i32))=([..],([1,2,3],.))| #26 FAIL
|
||||||
|
* tuple_return_over | fn()([2]int,i32){return([1,2,3],5)} | #25 FAIL
|
||||||
|
* tuple_return_nested| fn()([2]int,([2]int,i32)){return(..,([..3],.))| #25 FAIL
|
||||||
*
|
*
|
||||||
* pos row | shape | want
|
* pos row | shape | want
|
||||||
* -------------------+----------------------------------------------+------
|
* -------------------+----------------------------------------------+------
|
||||||
@@ -116,6 +118,25 @@ static const char *neg[] = {
|
|||||||
"\tlet t: ([2]int, ([2]int, i32)) = ([1, 2], ([3, 4, 5], 6));\n"
|
"\tlet t: ([2]int, ([2]int, i32)) = ([1, 2], ([3, 4, 5], 6));\n"
|
||||||
"\treturn t.0[0]: i32;\n"
|
"\treturn t.0[0]: i32;\n"
|
||||||
"};\n",
|
"};\n",
|
||||||
|
/* tuple_return_over (#25) — overlong [2]int in a tuple RETURN. */
|
||||||
|
"package main;\n"
|
||||||
|
"fn f() ([2]int, i32) = {\n"
|
||||||
|
"\treturn ([1, 2, 3], 5);\n"
|
||||||
|
"};\n"
|
||||||
|
"export fn main() i32 = {\n"
|
||||||
|
"\tlet t = f();\n"
|
||||||
|
"\treturn t.1;\n"
|
||||||
|
"};\n",
|
||||||
|
/* tuple_return_nested (#25 path × #26 recursion) — nested tuple in a
|
||||||
|
* RETURN, inner [2]int over-filled. */
|
||||||
|
"package main;\n"
|
||||||
|
"fn f() ([2]int, ([2]int, i32)) = {\n"
|
||||||
|
"\treturn ([1, 2], ([3, 4, 5], 6));\n"
|
||||||
|
"};\n"
|
||||||
|
"export fn main() i32 = {\n"
|
||||||
|
"\tlet t = f();\n"
|
||||||
|
"\treturn t.0[0]: i32;\n"
|
||||||
|
"};\n",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
Reference in New Issue
Block a user