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) {
|
||||
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);
|
||||
if (src == nil) { return; };
|
||||
let conf: bool = false;
|
||||
|
||||
@@ -4842,6 +4842,19 @@ fn checkretassign(c: *checker, n: *node) void = {
|
||||
if (n.lhs.kind == nkind.N_ARRLIT) {
|
||||
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);
|
||||
if (src == nil) { return; };
|
||||
let conf: bool = false;
|
||||
|
||||
@@ -15123,6 +15123,19 @@ fn checkretassign(c: *checker, n: *node) void = {
|
||||
if (n.lhs.kind == nkind.N_ARRLIT) {
|
||||
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);
|
||||
if (src == nil) { return; };
|
||||
let conf: bool = false;
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
* 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_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
|
||||
* -------------------+----------------------------------------------+------
|
||||
@@ -116,6 +118,25 @@ static const char *neg[] = {
|
||||
"\tlet t: ([2]int, ([2]int, i32)) = ([1, 2], ([3, 4, 5], 6));\n"
|
||||
"\treturn t.0[0]: i32;\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
|
||||
|
||||
Reference in New Issue
Block a user