more bugfixes for closures
This commit is contained in:
parent
991b3096e8
commit
5e570bae47
3 changed files with 20 additions and 5 deletions
|
|
@ -236,7 +236,8 @@ proc dummyClosureParam(o: POuterContext, i: PInnerContext) =
|
||||||
if i.closureParam == nil: addClosureParam(i, e)
|
if i.closureParam == nil: addClosureParam(i, e)
|
||||||
|
|
||||||
proc illegalCapture(s: PSym): bool {.inline.} =
|
proc illegalCapture(s: PSym): bool {.inline.} =
|
||||||
result = skipTypes(s.typ, abstractInst).kind in {tyVar, tyOpenArray} or
|
result = skipTypes(s.typ, abstractInst).kind in
|
||||||
|
{tyVar, tyOpenArray, tyVarargs} or
|
||||||
s.kind == skResult
|
s.kind == skResult
|
||||||
|
|
||||||
proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
|
proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
|
||||||
|
|
@ -246,7 +247,8 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
|
||||||
var it = PEnv(IdTableGet(o.localsToEnv, local))
|
var it = PEnv(IdTableGet(o.localsToEnv, local))
|
||||||
if it == nil: return
|
if it == nil: return
|
||||||
|
|
||||||
if illegalCapture(local) or o.fn.id != local.owner.id:
|
if illegalCapture(local) or o.fn.id != local.owner.id or
|
||||||
|
i.fn.typ.callConv notin {ccClosure, ccDefault}:
|
||||||
# Currently captures are restricted to a single level of nesting:
|
# Currently captures are restricted to a single level of nesting:
|
||||||
LocalError(info, errIllegalCaptureX, local.name.s)
|
LocalError(info, errIllegalCaptureX, local.name.s)
|
||||||
i.fn.typ.callConv = ccClosure
|
i.fn.typ.callConv = ccClosure
|
||||||
|
|
@ -280,7 +282,7 @@ proc interestingVar(s: PSym): bool {.inline.} =
|
||||||
|
|
||||||
proc semCaptureSym*(s, owner: PSym) =
|
proc semCaptureSym*(s, owner: PSym) =
|
||||||
if interestingVar(s) and owner.id != s.owner.id:
|
if interestingVar(s) and owner.id != s.owner.id:
|
||||||
if owner.typ != nil:
|
if owner.typ != nil and not isGenericRoutine(owner):
|
||||||
owner.typ.callConv = ccClosure
|
owner.typ.callConv = ccClosure
|
||||||
# since the analysis is not entirely correct, we don't set 'tfCapturesEnv'
|
# since the analysis is not entirely correct, we don't set 'tfCapturesEnv'
|
||||||
# here
|
# here
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,6 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
incl(c.p.owner.flags, sfSideEffect)
|
incl(c.p.owner.flags, sfSideEffect)
|
||||||
elif s.kind == skParam and s.typ.kind == tyExpr:
|
elif s.kind == skParam and s.typ.kind == tyExpr:
|
||||||
return s.typ.n
|
return s.typ.n
|
||||||
else:
|
|
||||||
semCaptureSym(s, c.p.owner)
|
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
# We cannot check for access to outer vars for example because it's still
|
# We cannot check for access to outer vars for example because it's still
|
||||||
# not sure the symbol really ends up being used:
|
# not sure the symbol really ends up being used:
|
||||||
|
|
@ -1415,6 +1413,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkIdent, nkAccQuoted:
|
of nkIdent, nkAccQuoted:
|
||||||
var s = lookUp(c, n)
|
var s = lookUp(c, n)
|
||||||
|
semCaptureSym(s, c.p.owner)
|
||||||
result = semSym(c, n, s, flags)
|
result = semSym(c, n, s, flags)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
# because of the changed symbol binding, this does not mean that we
|
# because of the changed symbol binding, this does not mean that we
|
||||||
|
|
|
||||||
14
tests/reject/tinvalidclosure2.nim
Normal file
14
tests/reject/tinvalidclosure2.nim
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
discard """
|
||||||
|
line: 10
|
||||||
|
errormsg: "invalid capture: 'A'"
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc outer() =
|
||||||
|
var A: int
|
||||||
|
|
||||||
|
proc ugh[T](x: T) {.cdecl.} =
|
||||||
|
echo "ugha", A, x
|
||||||
|
|
||||||
|
ugh[int](12)
|
||||||
|
|
||||||
|
outer()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue