wcc/check: #14 reject def-global scalar str index (silent segfault) (both stages)
def S:str = "hi"; S[0] silently segfaulted: a def is a compile-time constant, never materialized as DATA (unlike let), so indexing it emitted an unbacked main.S(SB) reference -> cstage ran into frame garbage, wwstage link-failed. str[i] itself is valid ww (a deliberate Go-like str[i]->u8 byte-index that lib/strings compare/dup depend on), so the fix is narrow: the N_INDEX TY_STR arm now rejects an index whose operand is a bare SK_DEF scalar-str symbol, both stages -- 'cannot index a def-constant str; bind it to a let'. INDEX-ONLY: len(S) and &S are already loud, and a def's .len/.ptr field reads (the load-bearing w6l INTERP) are N_DOT, a different arm, and stay valid. A rule-9 WHY-comment records str[i]->u8 as a sanctioned divergence from Hare's strings.toutf8. The full make-it-work fold (len(S)->2, S[0]->byte) is deferred (#16). byte-id 990-997 8/8. test/wcc/821 table-driven.
This commit is contained in:
@@ -12713,7 +12713,30 @@ fn indexresult(c: *checker, e: *node) *node = {
|
||||
if (u.kind == nkind.N_TSLICE) { return u.lhs; };
|
||||
if (u.kind == nkind.N_TARRAY) { return u.lhs; };
|
||||
if (u.kind == nkind.N_TNAME) {
|
||||
if (streq(u.str, "str")) { return mktname(c, "u8"); };
|
||||
// rule-9 divergence-doc (drew .ai/drew-14-ruling.md): `str[i] ->
|
||||
// u8` is a deliberate Go-like direct byte-index, a SANCTIONED ww
|
||||
// divergence from Hare's `strings::toutf8(s)[i]` (the Hare
|
||||
// reference checker rejects str-index, harec check.c:362).
|
||||
// lib/strings is load-bearing on it (compare/dup/join).
|
||||
if (streq(u.str, "str")) {
|
||||
// #14: reject INDEX of a bare def-global scalar str — an
|
||||
// inline compile-time constant with no storage to index
|
||||
// (cgen refs an unbacked symbol -> link-fail ww / segfault
|
||||
// cs). let/param/local + string-literal operands stay
|
||||
// valid; only the SK_DEF scalar-str operand is
|
||||
// unindexable. cstage twin: check.c N_INDEX TY_STR arm.
|
||||
if (e.lhs != nil && e.lhs.kind == nkind.N_IDENT) {
|
||||
let s: *sym = scopelookupprefer(c.cur, c.curmod, e.lhs.str);
|
||||
if (s != nil && s.skind == skind.SK_DEF) {
|
||||
cerr("error: cannot index a def-constant str '");
|
||||
cerr(e.lhs.str);
|
||||
cerr("'; bind it to a `let` (def strings are inline constants, not storage-backed)\n");
|
||||
c.errs += 1;
|
||||
return nil;
|
||||
};
|
||||
};
|
||||
return mktname(c, "u8");
|
||||
};
|
||||
};
|
||||
if (u.kind == nkind.N_TPTR) {
|
||||
let inner: *node = u.lhs;
|
||||
|
||||
Reference in New Issue
Block a user