feat(obs): bind case Some(&v) by reference
The capture is a read-only reference to the payload (RefKind=1) and registers a borrow of the subject base, so the owner cannot be del-ed while the arm runs and writes through the capture are rejected. The language server binds the capture so v.a resolves.
This commit is contained in:
1 parent
b9d84c6bda
commit
40691567f5
2 files changed
+46
No files matched your search
@@ -318,6 +318,17 @@ novirtual class MatchGenMixin:
|
||||
if pk == 2 and (self._pattern_is_nil(mc.pattern) != 0 or self._pattern_is_none_singleton(mc.pattern) != 0): return 1
|
||||
return 0
|
||||
|
||||
def _borrow_owner_name(self, expr: ast.AST*) -> str:
|
||||
"""Base binding name of a match subject (`_U` for `_U.n`), used as the borrow owner."""
|
||||
if expr is None: return None
|
||||
if expr.kind() == ast.ASTKind.Name:
|
||||
return (ast.Name*)(expr).id
|
||||
if expr.kind() == ast.ASTKind.Attribute:
|
||||
return self._borrow_owner_name((ast.Attribute*)(expr).value)
|
||||
if expr.kind() == ast.ASTKind.Subscript:
|
||||
return self._borrow_owner_name((ast.Subscript*)(expr).value)
|
||||
return None
|
||||
|
||||
# _handle_optional_ptr_match - match over a nullable pointer (`own U?` / `T?`):
|
||||
# Some(v) -> non-null branch, v = the pointer; None / Nil() -> null branch.
|
||||
def _handle_optional_ptr_match(self, trans: HT.Translator*, node: ast.Match*, subject_val: mlirlite.Value*) -> int:
|
||||
@@ -398,6 +409,22 @@ novirtual class MatchGenMixin:
|
||||
mlirlite.build_store(builder, subject_val, slot)
|
||||
self.Gen.VarGen.define_var(trans.SymTab, ma_s.name, slot)
|
||||
self.Gen.VarGen.set_var_life(trans.SymTab, ma_s.name, GenTypes.LIFE_FRAME)
|
||||
elif sub is not None and sub.kind() == ast.ASTKind.UnaryOp:
|
||||
# `Some(&v)`: bind the payload by reference (a borrow, not an owner).
|
||||
uo_s: ast.UnaryOp* = ast.UnaryOp*(sub)
|
||||
if uo_s.op == ast.OpKind.AddrOf and uo_s.operand is not None \
|
||||
and uo_s.operand.kind() == ast.ASTKind.Name:
|
||||
nm_s: ast.Name* = ast.Name*(uo_s.operand)
|
||||
if nm_s.id is not None:
|
||||
slot2: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, ptr_ty)
|
||||
if slot2 is not None:
|
||||
mlirlite.build_store(builder, subject_val, slot2)
|
||||
self.Gen.VarGen.define_var(trans.SymTab, nm_s.id, slot2)
|
||||
self.Gen.VarGen.set_var_life(trans.SymTab, nm_s.id, GenTypes.LIFE_FRAME)
|
||||
self.Gen.VarGen.set_var_ref_kind(trans.SymTab, nm_s.id, 1)
|
||||
own_r: str = self._borrow_owner_name(node.subject)
|
||||
if own_r is not None:
|
||||
self.Gen.StmtGen._BorrowAdd(trans, own_r, nm_s.id)
|
||||
if some_body is not None and some_body.children is not None:
|
||||
bi: int = 0
|
||||
while bi < int(len(some_body.children)):
|
||||
|
||||
@@ -1134,6 +1134,16 @@ def _WalkPattern(pool: memhub.MemManager*, a: LspAnalysis*, scope: LspScope*,
|
||||
_WalkPattern(pool, a, scope, mc.kwd_patterns.get(sizet(pi)))
|
||||
pi += 1
|
||||
return
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
# `case Some(&v)`: v is a reference binding inside the case body.
|
||||
uo_wp: ast.UnaryOp* = (ast.UnaryOp*)(node)
|
||||
if uo_wp.op == ast.OpKind.AddrOf and uo_wp.operand is not None \
|
||||
and uo_wp.operand.kind() == ast.ASTKind.Name:
|
||||
nm_wp: ast.Name* = (ast.Name*)(uo_wp.operand)
|
||||
if nm_wp.id is not None:
|
||||
_Declare(pool, a, scope, nm_wp.id, LSP_KIND_VARIABLE, node,
|
||||
nm_wp.lineno, nm_wp.col_offset, None)
|
||||
return
|
||||
if k == ast.ASTKind.MatchAs:
|
||||
ma_p: ast.MatchAs* = (ast.MatchAs*)(node)
|
||||
if ma_p.pattern is not None:
|
||||
@@ -1352,6 +1362,15 @@ def _WalkStmt(pool: memhub.MemManager*, a: LspAnalysis*, scope: LspScope*,
|
||||
if ma_b.name is not None:
|
||||
bs: LspSymbol* = _FindSymbol(scope, ma_b.name)
|
||||
if bs is not None and bs.type_sym is None: bs.type_sym = subj_ts
|
||||
elif sp is not None and sp.kind() == ast.ASTKind.UnaryOp:
|
||||
# `case Some(&v)`: bind v through the subject's class too.
|
||||
uo_b: ast.UnaryOp* = (ast.UnaryOp*)(sp)
|
||||
if uo_b.op == ast.OpKind.AddrOf and uo_b.operand is not None \
|
||||
and uo_b.operand.kind() == ast.ASTKind.Name:
|
||||
nm_b: ast.Name* = (ast.Name*)(uo_b.operand)
|
||||
if nm_b.id is not None:
|
||||
bs2: LspSymbol* = _FindSymbol(scope, nm_b.id)
|
||||
if bs2 is not None and bs2.type_sym is None: bs2.type_sym = subj_ts
|
||||
_WalkExpr(pool, a, scope, mc.guard)
|
||||
_WalkBody(pool, a, scope, mc.children)
|
||||
i += 1
|
||||
|
||||
Reference in new issue
Block a user