From 06c20dbec4bb2d76ea7ce5ada08bce94bf0f4be8 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Fri, 7 Aug 2026 23:52:08 +0900 Subject: [PATCH] check: stamp a str for-range binding u8 in the wwstage cstage types the binding ty_u8; the wwstage single-binder arm peeled the element only for slice/array iterables, so a str scrutinee fell to the N_FORRANGE fallback decl and exprtype stamped the binding str. The stamp-keyed call-arg marshal then pushed the 3-word str ABI for a 1-word scalar, and an uncast compare on the binding was falsely rejected. Route str through the same synthetic-N_LET binder with a u8 element. Graduates r940_str_forrange_arg. --- Makefile | 3 +-- selfhost/cmd/wcc/check.ww | 14 +++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 38fa65a1..d2c29ab4 100644 --- a/Makefile +++ b/Makefile @@ -584,8 +584,7 @@ DATABYTEID_EXPECTED_MIN = 911 # this list rather than silently widening coverage. Tracked with the #59 # divergence family. DATABYTEID_DIVERGED = r76_typeeq_fn_diff_arity r76_typeeq_fn_diff_param_type \ - r76_typeeq_fn_io_vtable_shape r76_typeeq_fn_variadic_vs_fixed \ - r940_str_forrange_arg + r76_typeeq_fn_io_vtable_shape r76_typeeq_fn_variadic_vs_fixed $(if $(DATABYTEID_FILES),,$(error test-byteid: empty data corpus)) test-data-byteid: $(BIN)/ww $(BIN)/w6c $(BIN)/w6c_ww @work=$$(mktemp -d "$(CURDIR)/$(DATABYTEID_DIR).XXXXXX") || exit 1; \ diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index cb958f78..776f639a 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -584,9 +584,7 @@ fn resolvewalk(c: *checker, n: *syntax.node) void = { // types it: check.c N_FORRANGE scope_define(..., // elem, ...)). Synthetic N_LET binder whose .lhs // is the element tnode — the stamptuplebinds - // `b.lhs = et` idiom. A str scrutinee keeps the - // old decl: cgen synthesises the u8 elem there - // and no dot applies to a u8 binding. + // `b.lhs = et` idiom. let et: *syntax.node = nil; let it: *syntax.node = exprtype(c, n.lhs, nil); // #80 (F2a batch-4 c4): an alias-typed iterable @@ -599,6 +597,16 @@ fn resolvewalk(c: *checker, n: *syntax.node) void = { if (it != nil) { if (it.kind == syntax.nkind.N_TSLICE) { et = it.lhs; }; if (it.kind == syntax.nkind.N_TARRAY) { et = it.lhs; }; + // A str binding is u8 (cstage check.c: elem = + // ty_u8). The old N_FORRANGE fallback decl made + // exprtype stamp the binding str, so call-arg + // marshaling pushed the 3-word str ABI for a + // 1-word scalar. + if (it.kind == syntax.nkind.N_TNAME) { + if (syntax.streq(it.str, "str")) { + et = mktname(c, "u8"); + }; + }; }; if (et != nil) { let bn: *syntax.node = syntax.newnode(syntax.nkind.N_LET, n.file, n.line, n.col);