Skip to content

Commit

Permalink
some progress on bug nim-lang#12443
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq authored and alehander92 committed Dec 2, 2019
1 parent bbaa4a5 commit 58be4c6
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 25 deletions.
3 changes: 2 additions & 1 deletion compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,8 @@ proc reverseDestroys(destroys: seq[PNode]): seq[PNode] =
result.add destroys[i]

proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
if sfGeneratedOp in owner.flags or (owner.kind == skIterator and isInlineIterator(owner.typ)): return n
if sfGeneratedOp in owner.flags or (owner.kind == skIterator and isInlineIterator(owner.typ)):
return n
var c: Con
c.owner = owner
c.destroys = newNodeI(nkStmtList, n.info)
Expand Down
48 changes: 25 additions & 23 deletions compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
var length = len(n)
let iterBase = n.sons[length-2].typ
var iter = skipTypes(iterBase, {tyGenericInst, tyAlias, tySink})
var iter = skipTypes(iterBase, {tyGenericInst, tyAlias, tySink, tyOwned})
var iterAfterVarLent = iter.skipTypes({tyLent, tyVar})
# length == 3 means that there is one for loop variable
# and thus no tuple unpacking:
Expand All @@ -683,18 +683,18 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
var v = symForVar(c, n[0][i])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
case iter.kind
of tyVar:
v.typ = newTypeS(tyVar, c)
v.typ.sons.add iterAfterVarLent[i]
if tfVarIsPtr in iter.flags:
v.typ.flags.incl tfVarIsPtr
of tyLent:
v.typ = newTypeS(tyLent, c)
v.typ.sons.add iterAfterVarLent[i]
if tfVarIsPtr in iter.flags:
v.typ.flags.incl tfVarIsPtr
else:
v.typ = iter.sons[i]
of tyVar:
v.typ = newTypeS(tyVar, c)
v.typ.sons.add iterAfterVarLent[i]
if tfVarIsPtr in iter.flags:
v.typ.flags.incl tfVarIsPtr
of tyLent:
v.typ = newTypeS(tyLent, c)
v.typ.sons.add iterAfterVarLent[i]
if tfVarIsPtr in iter.flags:
v.typ.flags.incl tfVarIsPtr
else:
v.typ = iter.sons[i]
n.sons[0][i] = newSymNode(v)
if sfGenSym notin v.flags: addDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
Expand All @@ -717,14 +717,14 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
if n.sons[i].kind == nkVarTuple:
var mutable = false
var isLent = false
iter[i] = case iter[i].kind
of tyVar:
mutable = true
iter[i].skipTypes({tyVar})
of tyLent:
isLent = true
iter[i].skipTypes({tyLent})
else: iter[i]
case iter[i].kind
of tyVar:
mutable = true
iter[i] = iter[i].skipTypes({tyVar})
of tyLent:
isLent = true
iter[i] = iter[i].skipTypes({tyLent})
else: discard

if len(n[i])-1 != len(iter[i]):
localError(c.config, n[i].info, errWrongNumberOfVariables)
Expand Down Expand Up @@ -871,8 +871,7 @@ proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
result.kind = nkParForStmt
else:
result = semForFields(c, n, call.sons[0].sym.magic)
elif isCallExpr and call.sons[0].typ.callConv == ccClosure and
tfIterator in call.sons[0].typ.flags:
elif isCallExpr and isClosureIterator(call.sons[0].typ.skipTypes(abstractInst)):
# first class iterator:
result = semForVars(c, n, flags)
elif not isCallExpr or call.sons[0].kind != nkSym or
Expand Down Expand Up @@ -1989,6 +1988,9 @@ proc semIterator(c: PContext, n: PNode): PNode =
s.typ.callConv = ccInline
if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone:
localError(c.config, n.info, errImplOfXexpected % s.name.s)
if optOwnedRefs in c.config.globalOptions and result.typ != nil:
result.typ = makeVarType(c, result.typ, tyOwned)
result.typ.callConv = ccClosure

proc semProc(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skProc, procPragmas)
Expand Down
2 changes: 1 addition & 1 deletion compiler/transf.nim
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
return result
c.breakSyms.add(labl)
if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
call.sons[0].typ.callConv == ccClosure:
call.sons[0].typ.skipTypes(abstractInst).callConv == ccClosure:
result[1] = n.PTransNode
result[1][^1] = transformLoopBody(c, n[^1])
result[1][^2] = transform(c, n[^2])
Expand Down
16 changes: 16 additions & 0 deletions tests/destructor/tsimpleclosure.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,21 @@ ok0()
var ok1 = say
ok1()

when false:
# bug #12443
func newStringIterator(s: string): owned(iterator(): char) =
result = iterator(): char =
var pos = 0
while pos < s.len:
yield s[pos]
inc pos

proc stringIter() =
let si = newStringIterator("foo")
for i in si():
echo i

stringIter()

let (a, d) = allocCounters()
discard cprintf("%ld %ld alloc/dealloc pairs: %ld\n", a, d, system.allocs)

0 comments on commit 58be4c6

Please sign in to comment.