Skip to content

Commit 9eed7be

Browse files
committed
add checks for call kinds
1 parent cceb7a1 commit 9eed7be

File tree

1 file changed

+57
-1
lines changed

1 file changed

+57
-1
lines changed

compiler/semderefs.nim

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import ast, lineinfos, msgs, options, renderer
22
import std/[strutils]
33

4+
when defined(nimPreviewSlimSystem):
5+
import std/assertions
6+
47
type
58
Expects = enum
69
WantT
@@ -108,7 +111,7 @@ proc borrowsFromReadonly(c: var Context; n: PNode; allowLet = false): bool =
108111
result = tk notin {tyVar, tyLent, tySink}
109112
else:
110113
result = false
111-
elif n.kind in nkLiterals + {nkObjConstr}:
114+
elif n.kind in nkLiterals + {nkBracket, nkObjConstr}:
112115
result = true
113116
else:
114117
result = false
@@ -141,9 +144,59 @@ proc trProcDecl(c: var Context; n: PNode): PNode =
141144
result[bodyPos] = tr(c, n[bodyPos], c.r.returnExpects)
142145
swap c.r, r
143146

147+
proc trCallArgs(c: var Context; n: PNode; fnType: PType): PNode =
148+
result = n
149+
var p = 1
150+
for i in 1 ..< n.len:
151+
var e = WantT
152+
if p >= fnType.len:
153+
if tfVarargs in fnType.flags:
154+
discard "call proc with varargs pragma"
155+
else:
156+
assert false
157+
else:
158+
let param = fnType[p]
159+
let pk = param.kind
160+
if pk in {tyVar, tyLent}:
161+
e = WantVarT
162+
if pk != tyVarargs:
163+
# do not advance formal parameter when it is tyVarargs
164+
inc p
165+
result[i] = tr(c, n[i], e)
166+
167+
proc firstArgIsMutable(c: var Context; n: PNode): bool =
168+
assert n.kind in nkCallKinds
169+
170+
if n.len > 1:
171+
result = not borrowsFromReadonly(c, n[1])
172+
else:
173+
result = false
174+
144175
proc cannotPassToVar(c: var Context; info: TLineInfo; arg: PNode) =
145176
localError(c.config, info, "cannot pass '$1' to var/out T parameter" % [renderTree(arg, {renderNoComments})])
146177

178+
proc trCall(c: var Context; n: PNode; e: Expects): PNode =
179+
result = n
180+
assert n.len > 0
181+
let fnType = if n[0].kind == nkOpenSymChoice: n[0][0].typ else: n[0].typ
182+
let retType = if fnType != nil and fnType.len > 0: fnType[0] else: nil
183+
result[0] = tr(c, n[0], WantT)
184+
185+
if fnType == nil:
186+
discard
187+
elif retType != nil and retType.kind in {tyVar, tyLent}:
188+
if e in {WantT, WantForwarding}:
189+
result = trCallArgs(c, n, fnType)
190+
elif e in {WantVarTResult, WantTButSkipDeref} or firstArgIsMutable(c, n):
191+
result = trCallArgs(c, n, fnType)
192+
else:
193+
cannotPassToVar c, n.info, n
194+
result = n
195+
elif e.wantMutable:
196+
cannotPassToVar c, n.info, n
197+
else:
198+
result = trCallArgs(c, n, fnType)
199+
147200
type
148201
LvalueStatus = enum
149202
Valid
@@ -154,6 +207,7 @@ proc trAsgn(c: var Context; n: PNode): PNode =
154207
var e = WantT
155208
var err = Valid
156209
if n[0].kind == nkSym and n[0].sym.kind == skResult and n[0].sym == c.r.resultSym:
210+
e = c.r.returnExpects
157211
if c.r.returnExpects == WantVarTResult:
158212
if not validBorrowsFrom(c, n[1]):
159213
err = InvalidBorrow
@@ -203,6 +257,8 @@ proc tr(c: var Context; n: PNode; e: Expects): PNode =
203257
if e.wantMutable:
204258
cannotPassToVar c, n.info, n
205259
result = n
260+
of nkCallKinds:
261+
result = trCall(c, n, e)
206262
of nkDotExpr, nkCheckedFieldExpr, nkBracketExpr:
207263
result = trLocation(c, n, e)
208264
of nkAsgn:

0 commit comments

Comments
 (0)