aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/analyzer.zc
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 14:59:31 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 14:59:31 +0330
commit8703e2c85a8ecdea9e869e876e347ebd4cb6ef88 (patch)
tree0ca06ae1f09abf9245b1eabf5d74099f829ad6e6 /src/compiler/analyzer.zc
parentanalyzer: infer .u from returns of fresh objects in the body (prescan guess, ... (diff)
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
Diffstat (limited to 'src/compiler/analyzer.zc')
-rw-r--r--src/compiler/analyzer.zc5
1 files changed, 4 insertions, 1 deletions
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");