From 3de6ae4a6a74b2c4fa14c3f2d6fbfff3bb83c5f5 Mon Sep 17 00:00:00 2001 From: zinc Date: Thu, 15 Oct 2026 02:35:44 +0330 Subject: destructors: nothing moves out of a value with a drop: pop on an array with a drop, or on an array field of a value with a drop, is error: a: can't move out of a value with drop (fields were already borrowed projections); spec 6.15.5, four conformance programs --- src/compiler/builtins.zc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/compiler') diff --git a/src/compiler/builtins.zc b/src/compiler/builtins.zc index 8c00636..44ed3b1 100644 --- a/src/compiler/builtins.zc +++ b/src/compiler/builtins.zc @@ -670,13 +670,18 @@ int typearg() { } // len(a), cap(a), push(a, x), pop(a), resize(a, n): growable arrays. // len of a T[n] is just n. +// arrroot: the local the array belongs to (itself, or the owner of the struct it is a field of), or -1 +int arrroot = 0 - 1; word arrvalue(int c) { - argloc = -1; arrloc = -1; + argloc = -1; arrloc = -1; arrroot = -1; if (lv && lvk == LV_LOCAL && xty[0] == TY_DYN) { arrloc = lvi; if (o3on && o3cache[lvi]) argloc = lvi; } effect_value = effect_mask(c); rval(); plainuse(c); af_access(xaf, tpack()); + if (arrloc >= 0) arrroot = lroot(arrloc); + else if (c >= C_VAR && tracked(c - C_VAR)) arrroot = lroot(c - C_VAR); + else if (xbor >= 0 && tracked(xbor)) arrroot = lroot(xbor); return xty; } // parse an array argument and retain the receiver's mutation and bounds facts. @@ -803,6 +808,8 @@ int array_pop(word t) { if (isfl(xty)) xfloat = 1; xaf = 0; xbor = -1; effect_value = 0; if (isref(xty)) { + // pop moves the element out: not out of an array with a drop, whose drop may need it (6.15.5) + if (fchk && arrroot >= 0 && ldroppable(arrroot)) cerrn(arrroot, "can't move out of a value with drop"); xcls = C_FRESH; xaf = af_new(-1, 2, tpack()); newsz = -1; newleaf = 0; return C_FRESH; } return 0; -- cgit v1.2.3