From b79970241a401b37322d8f1ada20e6f4bae36ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=8B=9C=EC=9B=90?= Date: Sun, 16 Aug 2026 21:40:22 +0900 Subject: [PATCH] extend ownership through M7 wrappers --- fec/src/own.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/fec/src/own.c b/fec/src/own.c index ee37c9b..8b51c37 100644 --- a/fec/src/own.c +++ b/fec/src/own.c @@ -24,6 +24,10 @@ int fe_own_is_copy_type(FeType *type) if (type->kind == FE_TYPE_OWNED) return 0; if (type->kind == FE_TYPE_REF || type->kind == FE_TYPE_SLICE) return !type->ref_mut; + if (type->kind == FE_TYPE_OPTIONAL) + return fe_own_is_copy_type(type->elem); + if (type->kind == FE_TYPE_ERROR_UNION) + return fe_own_is_copy_type(type->error_value); if (type->kind == FE_TYPE_ARRAY) return fe_own_is_copy_type(type->elem); if (type->kind == FE_TYPE_STRUCT) { @@ -314,9 +318,6 @@ static int fe_own_live_add(FeOwnLiveness *live, FeNode *decl) FeOwnLastUse *slot; unsigned capacity; const char *cname; - /* This prepass runs before local inference. Recording every local is - harmless (only reference bindings consume the result) and lets an - inferred `let r = &x` participate in last-use analysis. */ if (!live || !decl || !live->arena) return 1; cname = decl->cname ? decl->cname : decl->text; @@ -450,6 +451,23 @@ const FeOwnLastUse *fe_own_last_use(const FeOwnLiveness *live, return 0; } +static int fe_own_replace_unwrap(FeNode *expr) +{ + FeNode *call; + FeNode *member; + if (!expr || expr->kind != FE_N_MEMBER || !expr->text || + strcmp(expr->text,".?") != 0) + return 0; + call=expr->a; + if (!call || call->kind != FE_N_CALL || !call->a || + call->a->kind != FE_N_MEMBER) + return 0; + member=call->a; + return member->a && member->a->kind==FE_N_IDENT && member->a->text && + strcmp(member->a->text,"mem")==0 && member->b && member->b->text && + strcmp(member->b->text,"replace")==0; +} + void fe_own_mark_consumed(FeDiags *diags, int *state, FeNode *decl, FeNode *expr, FeType *type, int in_defer) { @@ -457,7 +475,8 @@ void fe_own_mark_consumed(FeDiags *diags, int *state, FeNode *decl, if (expr->kind == FE_N_INDEX && type->kind == FE_TYPE_SLICE && (expr->c || !expr->b)) return; - if (expr->kind == FE_N_MEMBER || expr->kind == FE_N_INDEX) { + if ((expr->kind == FE_N_MEMBER || expr->kind == FE_N_INDEX) && + !fe_own_replace_unwrap(expr)) { fe_diag_error(diags, expr->loc, "cannot move a non-Copy value out of a projection; use mem.replace"); return; @@ -470,8 +489,6 @@ void fe_own_mark_consumed(FeDiags *diags, int *state, FeNode *decl, } *state = FE_OWN_MOVED; - /* The consuming use owns the live-flag transition. The declaration must - stay live on control-flow paths where the move did not execute. */ expr->flags |= FE_OWN_NODE_CONSUMED; }