11import ast, lineinfos, msgs, options, renderer
22import std/ [strutils]
33
4+ when defined (nimPreviewSlimSystem):
5+ import std/ assertions
6+
47type
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+
144175proc 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+
147200type
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