From 1c434b76381ea5a34ce72f718914fc7102b56c88 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 13 Jun 2026 20:21:30 +0200 Subject: [PATCH] IC/refc: no-op value hooks for tyUncheckedArray An UncheckedArray has no known length, so it cannot be copied, moved or destroyed as a value; it only ever lives behind a pointer. The pointer-like group emitted x = y for it, an assignment of an unsized array the C backend cannot lower (genAssignment: tyUncheckedArray) -- which surfaced under nifc's hook-driven refc codegen (e.g. ref UncheckedArray in widestrs). Give it its own discard branch so all value hooks no-op; seq/string element ops still go through the seq/string hooks, which know the length. Co-Authored-By: Claude Opus 4.8 --- compiler/liftdestructors.nim | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 1f884d8d7f..3684ec437a 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -1085,8 +1085,17 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = case t.kind of tyNone, tyEmpty, tyVoid: discard + of tyUncheckedArray: + # An UncheckedArray has no known length, so it cannot be copied, moved or + # destroyed as a value: it only ever lives behind a pointer and its bytes + # are managed manually (element ops for seqs/strings go through the + # seq/string hooks, which know the length). Emitting `x = y` for it (as the + # pointer-like group below does) produces an assignment of an unsized array, + # which the C backend cannot lower (genAssignment: tyUncheckedArray). So all + # value hooks for it are no-ops. + discard of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCstring, - tyPtr, tyUncheckedArray, tyVar, tyLent: + tyPtr, tyVar, tyLent: defaultOp(c, t, body, x, y) of tyRef: if c.g.config.selectedGC in {gcArc, gcOrc, gcYrc, gcAtomicArc}: