check: lower an array-variable borrow into a union slice success variant (#17)

This commit is contained in:
2026-06-28 10:43:34 +09:00
parent fa1b6b77d4
commit 5fb18876b9
3 changed files with 147 additions and 0 deletions

View File

@@ -1221,6 +1221,25 @@ desugar_arrayslice(Checker *c, Type *dst, Node *expr)
return;
Type *du = type_chase_named(dst);
Type *su = type_chase_named(expr->type);
/* #17: the borrow target may be the SLICE success variant of a tagged
* union (`return/assign/let/f(arr)` into `([]T|e)`). Chase du to that
* variant so an array VARIABLE lowers to a full slice exactly as a
* bare []T dst does — the existing slice cgen then builds the full
* {ptr,len,cap} header and the union widen's slice arm wraps it,
* closing the silent len/cap drop. Mirrors #13's reject_arrlit_borrow
* TY_TAGGED chase (an array LITERAL has no outliving backing and is
* rejected there first; a variable has storage, so this borrow is
* legal). An array-typed variant is the separate #5/#60 reject. */
if (du && du->kind == TY_TAGGED && su && su->kind == TY_ARRAY) {
for (Tparam *p = du->params; p; p = p->next) {
Type *pu = type_chase_named(p->type);
if (pu && pu->kind == TY_SLICE
&& type_eq(pu->sub, su->sub)) {
du = pu;
break;
}
}
}
if (du == NULL || su == NULL ||
du->kind != TY_SLICE || su->kind != TY_ARRAY)
return;