aboutsummaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 15:01:29 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 15:01:29 +0330
commit5aaf70abdda0026a7b4d647746a109d94b25f7a0 (patch)
tree6e2448d5133ed2afba58dc66762400827c890c3b /src/compiler
parentstd.Io.print/println take any mix of printable arguments (compiler expands pe... (diff)
analyzer: a .u (declared or inferred) function can't return a borrowed parameter or a value derived from one; fixtures
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/analyzer.zc8
-rw-r--r--src/compiler/decl.zc2
2 files changed, 9 insertions, 1 deletions
diff --git a/src/compiler/analyzer.zc b/src/compiler/analyzer.zc
index 839c1ef..55a96bb 100644
--- a/src/compiler/analyzer.zc
+++ b/src/compiler/analyzer.zc
@@ -1644,6 +1644,7 @@ int assigncheck(int k, int i, int rc) {
// the function has no .u (its callers compiled after this point see it). an m
// object is lent, not given, so returning it is an error, and so is a plain word
// from an owned function that was called before its body.
+int ret_borrowed;
int retcheck(int c) {
int i;
if (isptr(xty) || xty == tword) {
@@ -1670,9 +1671,16 @@ int retcheck(int c) {
if ((isptr(xty) || isagg(xty)) && ((xaf && xaf[2] == 4) || (xbor >= 0 && lafact[xbor] && lafact[xbor][2] == 4))) { cerr("an array literal cannot escape its function through return"); return 0; }
i = -1;
if (c >= C_VAR && tracked(c - C_VAR)) i = c - C_VAR;
+ // a value that comes from a parameter the caller still owns (not a .d one,
+ // which is tracked) is a borrow: it can't become the caller's owned result.
+ if (c != C_FRESH && i < 0 && isptr(xty) && effect_mask(c)) {
+ if (fret) { cerr("a borrowed parameter cannot be returned as an owned result"); return 0; }
+ ret_borrowed = 1;
+ }
if (i >= 0 && lstate[lroot(i)] == S_DEAD) { cerrn(i, "used after it was given away"); return 0; }
if (i >= 0 && (lstate[i] == S_D || (lstate[i] == S_M && lown[i])) && (fret || finfer)) lstate[i] = S_U; // returning an owned object (a d object, or a local that owns one) gives it up, as u*x does
if (!fret && finfer && (c == C_FRESH || (i >= 0 && lstate[i] == S_U))) {
+ if (ret_borrowed) cerr("this function also returns a borrowed parameter, so its result can't be owned");
if (sflag[finsym] & F_EARLY) serrn(sname[finsym], "is called before its body, so its owned return can't be known there; declare the return type with .u");
ssig[finsym] = ssig[finsym] | 1; // the return is owned: callers read it from the signature
sflag[finsym] = sflag[finsym] | F_RETOWN;
diff --git a/src/compiler/decl.zc b/src/compiler/decl.zc
index 6bc8245..e2c3613 100644
--- a/src/compiler/decl.zc
+++ b/src/compiler/decl.zc
@@ -435,7 +435,7 @@ int fndef(int chk, int rty, int ret, int n) {
fixall(sfix[s], here); sfix[s] = 0;
fn_begin(chk, ret);
lt = lt_begin(sval[s], sname[s], lfl); xc_fn = sname[s];
- finsym = s; finfer = !ret;
+ finsym = s; finfer = !ret; ret_borrowed = 0;
effect_current = effect_record(s); rt.fill_w(effect_current, 0, 50); effect_current[0] = 1; if (!chk || stubgen) effect_current[0] = 2; effect_current[1] = np;
i = 0; while (i < np) { if (pt[i] == 2) { effect_current[2 + i] = EF_CONSUME; effect_current[26 + i] = EF_CONSUME; } i++; }
if (typed && explicit_rty) fty = rty;