fix: keep M7 return context through if branches

This commit is contained in:
정시원
2026-08-16 22:09:04 +09:00
parent 24a99abd37
commit f946b14bde
+41 -43
View File
@@ -866,53 +866,51 @@ static void m7_check_stmt(FeCheckerState *s, FeNode *n)
m7_check_if_let(s,n); m7_check_if_let(s,n);
else { else {
FeType *cond; FeType *cond;
FeFlowSlot base[FE_M7_FLOW_CAP];
FeFlowSlot left[FE_M7_FLOW_CAP];
FeFlowSlot right[FE_M7_FLOW_CAP];
FeOwnState *own_base;
FeOwnState *own_left;
FeOwnState *own_right;
FeFlowBorrow *borrow_base;
FeFlowBorrow *borrow_left;
FeFlowBorrow *borrow_right;
unsigned count;
unsigned i;
cond=m7_check_expr(s,n->a); cond=m7_check_expr(s,n->a);
if (known(cond) && cond->kind!=FE_TYPE_BOOL) if (known(cond) && cond->kind!=FE_TYPE_BOOL)
err(s->c,n->loc,"if condition must be bool"); err(s->c,n->loc,"if condition must be bool");
/* Reuse the verified branch merge by letting the M6 statement /* Once a function is on the M7 checker path, branch bodies must
machinery handle branches that contain no M7-only nodes. */ remain on that path as well. In particular, return T inside
if (!m7_node_feature(n->b) && !m7_node_feature(n->c)) E!T relies on contextual success construction even when the
check_stmt(s,n); branch itself contains no surface M7 syntax. */
else { m7_capture_flow(s,base,&own_base,&borrow_base,&count);
FeFlowSlot base[FE_M7_FLOW_CAP]; m7_check_stmt(s,n->b);
FeFlowSlot left[FE_M7_FLOW_CAP]; flow_capture(s->scope,left,count);
FeFlowSlot right[FE_M7_FLOW_CAP]; own_left=flow_own_new(s,count);
FeOwnState *own_base; borrow_left=flow_borrow_new(s,count);
FeOwnState *own_left; flow_own_capture(left,own_left,count);
FeOwnState *own_right; flow_borrow_capture(left,borrow_left,count);
FeFlowBorrow *borrow_base; m7_restore_flow(base,own_base,borrow_base,count);
FeFlowBorrow *borrow_left; if (n->c) m7_check_stmt(s,n->c);
FeFlowBorrow *borrow_right; if (n->c) {
unsigned count; flow_capture(s->scope,right,count);
unsigned i; own_right=flow_own_new(s,count);
m7_capture_flow(s,base,&own_base,&borrow_base,&count); borrow_right=flow_borrow_new(s,count);
m7_check_stmt(s,n->b); flow_own_capture(right,own_right,count);
flow_capture(s->scope,left,count); flow_borrow_capture(right,borrow_right,count);
own_left=flow_own_new(s,count); } else {
borrow_left=flow_borrow_new(s,count); own_right=flow_own_new(s,count);
flow_own_capture(left,own_left,count); borrow_right=flow_borrow_new(s,count);
flow_borrow_capture(left,borrow_left,count); for (i=0;i<count;++i) right[i]=base[i];
m7_restore_flow(base,own_base,borrow_base,count); if (own_right && own_base)
if (n->c) m7_check_stmt(s,n->c); for (i=0;i<count;++i) own_right[i]=own_base[i];
if (n->c) { if (borrow_right && borrow_base)
flow_capture(s->scope,right,count); for (i=0;i<count;++i) borrow_right[i]=borrow_base[i];
own_right=flow_own_new(s,count);
borrow_right=flow_borrow_new(s,count);
flow_own_capture(right,own_right,count);
flow_borrow_capture(right,borrow_right,count);
} else {
own_right=flow_own_new(s,count);
borrow_right=flow_borrow_new(s,count);
for (i=0;i<count;++i) right[i]=base[i];
if (own_right && own_base)
for (i=0;i<count;++i) own_right[i]=own_base[i];
if (borrow_right && borrow_base)
for (i=0;i<count;++i) borrow_right[i]=borrow_base[i];
}
flow_merge(base,left,right,count);
flow_own_merge(base,own_left,own_right,count);
flow_borrow_merge(base,borrow_left,borrow_right,count);
} }
flow_merge(base,left,right,count);
flow_own_merge(base,own_left,own_right,count);
flow_borrow_merge(base,borrow_left,borrow_right,count);
} }
break; break;
case FE_N_MATCH: case FE_N_MATCH: