diff --git a/compiler/ast.nim b/compiler/ast.nim index f24008b305..fdf01cb77e 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1810,11 +1810,11 @@ template getBody*(s: PSym): PNode = s.ast[bodyPos] template detailedInfo*(sym: PSym): string = sym.name.s -proc isInlineIterator*(s: PSym): bool {.inline.} = - s.kind == skIterator and s.typ.callConv != ccClosure +proc isInlineIterator*(typ: PType): bool {.inline.} = + typ.kind == tyProc and tfIterator in typ.flags and typ.callConv != ccClosure -proc isClosureIterator*(s: PSym): bool {.inline.} = - s.kind == skIterator and s.typ.callConv == ccClosure +proc isClosureIterator*(typ: PType): bool {.inline.} = + typ.kind == tyProc and tfIterator in typ.flags and typ.callConv == ccClosure proc isSinkParam*(s: PSym): bool {.inline.} = s.kind == skParam and (s.typ.kind == tySink or tfHasOwned in s.typ.flags) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 95de5777ef..5765721d7e 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -636,7 +636,7 @@ 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 isInlineIterator(owner): 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) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 7a72f16023..019c302262 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1724,7 +1724,7 @@ proc semReturn(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1, c.config) if c.p.owner.kind in {skConverter, skMethod, skProc, skFunc, skMacro} or - isClosureIterator(c.p.owner): + isClosureIterator(c.p.owner.typ): if n.sons[0].kind != nkEmpty: # transform ``return expr`` to ``result = expr; return`` if c.p.resultSym != nil: @@ -1771,7 +1771,7 @@ proc semProcBody(c: PContext, n: PNode): PNode = else: localError(c.config, c.p.resultSym.info, errCannotInferReturnType % c.p.owner.name.s) - if isInlineIterator(c.p.owner) and c.p.owner.typ.sons[0] != nil and + if isInlineIterator(c.p.owner.typ) and c.p.owner.typ.sons[0] != nil and c.p.owner.typ.sons[0].kind == tyUntyped: localError(c.config, c.p.owner.info, errCannotInferReturnType % c.p.owner.name.s) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8acc5ce2fd..f5a82b910a 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -38,7 +38,6 @@ const errPragmaOnlyInHeaderOfProcX = "pragmas are only allowed in the header of a proc; redefinition of $1" errCannotAssignMacroSymbol = "cannot assign macro symbol to $1 here. Forgot to invoke the macro with '()'?" errInvalidTypeDescAssign = "'typedesc' metatype is not valid here; typed '=' instead of ':'?" - errInlineIteratorNotFirstClass = "inline iterators are not first-class / cannot be assigned to variables" proc semDiscard(c: PContext, n: PNode): PNode = result = n @@ -456,9 +455,6 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = if def.sym.kind == skMacro: localError(c.config, def.info, errCannotAssignMacroSymbol % "variable") def.typ = errorType(c) - elif isInlineIterator(def.sym): - localError(c.config, def.info, errInlineIteratorNotFirstClass) - def.typ = errorType(c) elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro: # prevent the all too common 'var x = int' bug: localError(c.config, def.info, errInvalidTypeDescAssign) @@ -601,9 +597,6 @@ proc semConst(c: PContext, n: PNode): PNode = if def.sym.kind == skMacro: localError(c.config, def.info, errCannotAssignMacroSymbol % "constant") def.typ = errorType(c) - elif isInlineIterator(def.sym): - localError(c.config, def.info, errInlineIteratorNotFirstClass) - def.typ = errorType(c) elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro: # prevent the all too common 'const x = int' bug: localError(c.config, def.info, errInvalidTypeDescAssign) @@ -1589,7 +1582,7 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) = let resultType = sysTypeFromName(c.graph, n.info, "NimNode") addResult(c, resultType, n.info, s.kind) addResultNode(c, n) - elif s.typ.sons[0] != nil and not isInlineIterator(s): + elif s.typ.sons[0] != nil and not isInlineIterator(s.typ): addResult(c, s.typ.sons[0], n.info, s.kind) addResultNode(c, n) @@ -1969,7 +1962,6 @@ proc determineType(c: PContext, s: PSym) = proc semIterator(c: PContext, n: PNode): PNode = # gensym'ed iterator? - let isAnon = n[namePos].kind == nkEmpty if n[namePos].kind == nkSym: # gensym'ed iterators might need to become closure iterators: n[namePos].sym.owner = getCurrOwner(c) @@ -1983,8 +1975,6 @@ proc semIterator(c: PContext, n: PNode): PNode = var t = s.typ if t.sons[0] == nil and s.typ.callConv != ccClosure: localError(c.config, n.info, "iterator needs a return type") - if isAnon and s.typ.callConv == ccInline: - localError(c.config, n.info, errInlineIteratorNotFirstClass) # iterators are either 'inline' or 'closure'; for backwards compatibility, # we require first class iterators to be marked with 'closure' explicitly # -- at least for 0.9.2. diff --git a/compiler/types.nim b/compiler/types.nim index 8ff109b378..dc5068d0e2 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1280,10 +1280,13 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, if kind notin {skParam, skResult}: result = t else: result = typeAllowedAux(marker, t2, kind, flags) of tyProc: + if isInlineIterator(typ) and kind in {skVar, skLet, skConst, skParam, skResult}: + # only closure iterators my be assigned to anything. + result = t let f = if kind in {skProc, skFunc}: flags+{taNoUntyped} else: flags for i in 1 ..< len(t): - result = typeAllowedAux(marker, t.sons[i], skParam, f-{taIsOpenArray}) if result != nil: break + result = typeAllowedAux(marker, t.sons[i], skParam, f-{taIsOpenArray}) if result.isNil and t.sons[0] != nil: result = typeAllowedAux(marker, t.sons[0], skResult, flags) of tyTypeDesc: diff --git a/tests/ccgbugs/t5701.nim b/tests/ccgbugs/t5701.nim deleted file mode 100644 index 19d64a2304..0000000000 --- a/tests/ccgbugs/t5701.nim +++ /dev/null @@ -1,27 +0,0 @@ -discard """ - output: '''(1, 1) -(2, 2) -(3, 3) -@[1, 2, 3, 4] -''' -""" - -iterator zip[T1, T2](a: openarray[T1], b: openarray[T2]): iterator() {.inline.} = - let len = min(a.len, b.len) - for i in 0..