cmd+selfhost+test: relax alloc-slice element-type pin via LHS retype
`alloc([], n)` synthesizes ([]u8 | nomem) at expression level — that's fine, since the slice form only legitimately appears in let-init position where the LHS carries the real element type. In clet, after type-checking the rhs, peel any N_TRYPROP/N_TRYUNW wrapper, match the alloc-slice AST shape with the same-module shadow gate (from #23), and retype the call's tagged return to ([]T | nomem) where T is the declared LHS element. Then assignability sees []T vs []T and accepts. Cgen N_LET shortcut gains a viatryprop arm next to the existing viatryunw — on rt_alloc returning null, emits the tagged-return nomem propagation (MOVQ $nidx, AX; epilogue) instead of exit(1). nidx comes from cg_tag_for_variant on the enclosing fn's return type, matching the existing TRYPROP propret path. Wwstage mirrors all four hunks (check.ww + cgenstmt.ww). Promotes the previously-silent conf=false skip into a confident accept. Unblocks #6 (dupall) and lays the path for #4/#7. Byte-identity holds modulo the pre-existing #44 alloc/rt_alloc symbol divergence.
This commit is contained in:
@@ -1494,6 +1494,48 @@ clet(Checker *c, Node *n)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* #45: alloc([], n) defers element type to the let-init context
|
||||
* (Hare-style). cexpr's alloc-slice branch synthesizes
|
||||
* ([]u8 | nomem) with no LHS context; when the let declares []T,
|
||||
* retype the inner call (and any ?/! wrapper) to ([]T | nomem) /
|
||||
* []T so the assignability check below succeeds for any T. cgen
|
||||
* already drives element size from declared->sub at the N_LET
|
||||
* shortcut (cmd/w6c/cgen.c). */
|
||||
if (declared && declared->kind == TY_SLICE && declared->sub
|
||||
&& declared->sub != ty_u8 && n->rhs) {
|
||||
Node *wrap = NULL;
|
||||
Node *call = n->rhs;
|
||||
if (call->kind == N_TRYPROP || call->kind == N_TRYUNW) {
|
||||
wrap = call;
|
||||
call = call->lhs;
|
||||
}
|
||||
if (call && call->kind == N_CALL && call->lhs
|
||||
&& call->lhs->kind == N_IDENT
|
||||
&& call->lhs->type == ty_err
|
||||
&& call->lhs->str
|
||||
&& strcmp(call->lhs->str, "alloc") == 0
|
||||
&& call->list && call->list->kind == N_ARRLIT
|
||||
&& call->list->list == NULL
|
||||
&& call->list->next
|
||||
&& call->list->next->next == NULL) {
|
||||
Type *st = type_slice(c->a, declared->sub);
|
||||
Type *tt = newtype(c->a, TY_TAGGED);
|
||||
Tparam *vs = amalloc(c->a, sizeof *vs);
|
||||
Tparam *ve = amalloc(c->a, sizeof *ve);
|
||||
vs->type = st; vs->next = ve;
|
||||
ve->type = ty_nomem; ve->next = NULL;
|
||||
tt->params = vs;
|
||||
tt->size = 32;
|
||||
tt->align = 8;
|
||||
call->type = tt;
|
||||
if (wrap) {
|
||||
wrap->type = st;
|
||||
initt = st;
|
||||
} else {
|
||||
initt = tt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (declared && initt && initt != ty_err && !has_arr_repeat &&
|
||||
!type_assignable(declared, initt))
|
||||
err(c, n->pos, "init %s not assignable to declared %s",
|
||||
|
||||
Reference in New Issue
Block a user