feat(lsp): flag owners assigned to reference fields
An attribute target whose field annotation starts with `&` only accepts `&value`, another reference or None; anything else is reported like the compiler does.
This commit is contained in:
1 parent
4ff813f5dc
commit
04aa27d8a0
1 file changed
+29
@@ -1020,6 +1020,16 @@ def _CheckAssignValue(pool: memhub.MemManager*, doc: LspDocuments.LspDocument*,
|
||||
_EmitTypeError(pool, doc, value, msg, errors)
|
||||
|
||||
|
||||
def _RefDetail(det: str) -> int:
|
||||
"""1 when an annotation text is a reference (`&T` / `&mut T`, optional trailing `?`)."""
|
||||
if det is None: return 0
|
||||
s: str = det
|
||||
while string.strlen(s) > 0 and s[0] == ' ':
|
||||
s += 1
|
||||
if string.strlen(s) == 0: return 0
|
||||
return 1 if s[0] == '&' else 0
|
||||
|
||||
|
||||
def _NullableDetail(det: str) -> int:
|
||||
"""1 when an annotation text is the nullable `T?` form."""
|
||||
if det is None: return 0
|
||||
@@ -1609,6 +1619,25 @@ def _WalkChecks(pool: memhub.MemManager*, doc: LspDocuments.LspDocument*,
|
||||
continue
|
||||
if tgt.kind() == ast.ASTKind.Attribute:
|
||||
_WalkChecksExprs(pool, doc, a, ws, table_pool, ast.Attribute*(tgt).value, errors)
|
||||
# Reference field: the slot holds a borrow, not an owner.
|
||||
det_f: str = _SymDetailAt(pool, a, tgt)
|
||||
if _RefDetail(det_f) != 0:
|
||||
ok_f: int = 0
|
||||
rv_f: ast.AST* = asn.value
|
||||
if rv_f is not None:
|
||||
if rv_f.kind() == ast.ASTKind.UnaryOp:
|
||||
if (ast.UnaryOp*)(rv_f).op == ast.OpKind.AddrOf: ok_f = 1
|
||||
elif rv_f.kind() == ast.ASTKind.Constant:
|
||||
if (ast.Constant*)(rv_f).const_kind == ast.CONST_NONE: ok_f = 1
|
||||
elif _RefDetail(_SymDetailAt(pool, a, rv_f)) != 0:
|
||||
ok_f = 1
|
||||
if ok_f == 0:
|
||||
at_f: ast.Attribute* = ast.Attribute*(tgt)
|
||||
msg_f: bytes = pool.alloc(sizet(320))
|
||||
if msg_f is not None and at_f.attr is not None:
|
||||
stdio.snprintf(msg_f, sizet(320),
|
||||
"field '.%s' is a reference: assign a borrow (`&value`), not an owner", at_f.attr)
|
||||
_EmitTypeError(pool, doc, rv_f, str(msg_f), errors)
|
||||
continue
|
||||
if tgt.kind() == ast.ASTKind.Subscript:
|
||||
sb_t: ast.Subscript* = ast.Subscript*(tgt)
|
||||
|
||||
Reference in new issue
Block a user