From 8703e2c85a8ecdea9e869e876e347ebd4cb6ef88 Mon Sep 17 00:00:00 2001 From: zinc Date: Thu, 15 Oct 2026 14:59:31 +0330 Subject: analyzer: a back link (container's owner stored into it) stays a plain reference, fixing a compile hang on a<->b and a leak; ending an owner kills its owned children too (fixes use after reassigning a container); escape fixtures --- src/compiler/analyzer.zc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/compiler/analyzer.zc b/src/compiler/analyzer.zc index a1588e8..839c1ef 100644 --- a/src/compiler/analyzer.zc +++ b/src/compiler/analyzer.zc @@ -1009,7 +1009,7 @@ int end_owner(int i) { end_why = 0; end_whom = 0; local_ended[i] = info[2]; local_end_info[i] = info; lstate[i] = S_DEAD; while (j < nloc) { - if (j != i && isalias(j) && lroot(j) == i) { local_ended[j] = info[2]; local_end_info[j] = info; lstate[j] = S_DEAD; } + if (j != i && lstate[j] == S_CHILD && lroot(j) == i) { local_ended[j] = info[2]; local_end_info[j] = info; lstate[j] = S_DEAD; } // aliases and owned children go with it j++; } return 0; @@ -1612,6 +1612,9 @@ int assigncheck(int k, int i, int rc) { touch(i); if (rc == C_FRESH) { emitown(i); return C_PLAIN; } if (j < 0) return C_PLAIN; + // a back link: storing the container's own owner (or the container itself) + // into it. it stays a plain reference; ownership would form a cycle. + if (r == j) { touch(j); return C_PLAIN; } js = lstate[j]; if (js == S_CHILD) cerrn(j, "already belongs to a container"); else if (js == S_BORROW) cerrn(j, "is borrowed and can't be stored"); -- cgit v1.2.3