Align bare-int array-init assignability to Hare's literal-fits rule (ref/harec/src/types.c promote_flexible): accept untyped-int array elements that FIT the element type, reject out-of-range loud. cstage (rejected all bare-int arrays, over-strict) and wwstage (accepted + silently truncated out-of-range, over-loose) converge to the same accept-if-fits rule. Per-element: foldable int literal range-checked against element type [min,max] via def_cast_fits (rule-13 type-table widths); non-foldable element falls back to type_assignable. cstage: new arrlit_init_fits, N_LET decl-check fallback after whole- array type_assignable fails. wwstage: checkletassign array branch + route top-level lets through checkletassign (were unchecked — only function-body lets ran assignability; closes #146 wwstage str->u8 over-accept). Scalar-init range-check (let X:u8=300 truncates, both stages, pre-existing) deferred to #148 — language-wide, needs bootstrap audit + explicit-cast conversion. def-array accept-if-fits deferred to #151 (def constfold machinery, different risk). Both bootstrap-NEUTRAL. Test 920 (14 rows — accept: in-range u8/u32/u64/i32 + u8/i8 boundary + typed regression + non-foldable-body; reject: over-range + over-256 + i8-over + neg-for-unsigned + str->u8 + non-foldable-wider). Non- foldable else-branch cs==ww verified (matching-type accept + byte-id; wider-runtime-int reject both stages). Make test: 183/183 incl 990-997 byte-id + combined_ww_fresh.
This commit is contained in:
@@ -322,6 +322,49 @@ def_cast_fits(Type *t, u64 v)
|
||||
return ext == v;
|
||||
}
|
||||
|
||||
/* arrlit_init_fits — #130: accept-if-fits for `let/def A: [N]T = [..]`
|
||||
* where the whole-array type_assignable failed (bare-int elements
|
||||
* synthesize [N]i32 via type_default, losing the literal flavor that
|
||||
* the scalar coercion rule honours). Per element:
|
||||
* - foldable int literal → range-check against T via def_cast_fits.
|
||||
* In-range accepts; out-of-range REJECTS loud (rule-7 / Drew:
|
||||
* Hare range-checks at literal-value level, ref/harec types.c:923
|
||||
* promote_flexible — never a silent truncate).
|
||||
* - non-foldable element → type_assignable(T, elem->type), reusing
|
||||
* the same coercion rule the scalar path uses (untyped-int→u8 ok,
|
||||
* str→u8 not).
|
||||
* Returns 1 iff every element fits; the caller only consults this
|
||||
* after type_assignable already said no, so a 0 means a genuine
|
||||
* reject. Scoped to the ARRAY path — scalar overflow stays a separate
|
||||
* language-wide gap (#148). */
|
||||
static int
|
||||
arrlit_init_fits(Checker *c, Type *dt, Node *rhs)
|
||||
{
|
||||
if (rhs == NULL || rhs->kind != N_ARRLIT) return 0;
|
||||
Type *u = (dt && dt->kind == TY_NAMED) ? dt->under : dt;
|
||||
if (u == NULL || u->kind != TY_ARRAY) return 0;
|
||||
Type *et = u->sub;
|
||||
Type *eu = (et && et->kind == TY_NAMED) ? et->under : et;
|
||||
for (Node *e = rhs->list; e; e = e->next) {
|
||||
if (e->kind == N_FIELD && e->str
|
||||
&& strcmp(e->str, "...") == 0)
|
||||
continue;
|
||||
Node *ev = e;
|
||||
while (ev && ev->kind == N_CAST) ev = ev->lhs;
|
||||
u64 v;
|
||||
if (ev && type_isint(eu) && fold_int_literal(ev, &v)) {
|
||||
if (!def_cast_fits(eu, v)) {
|
||||
err(c, e->pos, "array element out of range "
|
||||
"for %s", type_name(c->a, et));
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!type_assignable(et, e->type)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* eval_def_const — fold a top-level def's rhs to a u64 constant,
|
||||
* resolving sibling and imported def references, casts, and
|
||||
* arithmetic (#88). Reuses the shared fold_int_literal leaf/unary
|
||||
@@ -2355,7 +2398,8 @@ check_file(Checker *c, Node *file)
|
||||
Type *rt = cexpr(c, d->rhs);
|
||||
if (d->type == NULL) d->type = type_default(rt);
|
||||
if (d->type && rt != ty_err && d->type != ty_err
|
||||
&& !type_assignable(d->type, rt))
|
||||
&& !type_assignable(d->type, rt)
|
||||
&& !arrlit_init_fits(c, d->type, d->rhs))
|
||||
err(c, d->pos, "let %s init not assignable",
|
||||
d->str);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user