summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim8
-rw-r--r--compiler/injectdestructors.nim2
-rw-r--r--compiler/semexprs.nim4
-rw-r--r--compiler/semstmts.nim12
-rw-r--r--compiler/types.nim5
-rw-r--r--tests/ccgbugs/t5701.nim27
-rw-r--r--tests/ccgbugs/tccgissues.nim14
-rw-r--r--tests/errmsgs/ttypeAllowed.nim28
-rw-r--r--tests/iter/titerassignerr.nim8
9 files changed, 54 insertions, 54 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index f24008b30..fdf01cb77 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 95de5777e..5765721d7 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 7a72f1602..019c30226 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 8acc5ce2f..f5a82b910 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 8ff109b37..dc5068d0e 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 19d64a230..000000000
--- 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..<len:
-    echo (a[i], b[i])
-
-proc foo(args: varargs[int]) =
-  for i in zip(args,args):
-    discard
-
-foo(1,2,3)
-
-# 10999
-
-proc varargsToSeq(vals: varargs[int32]): seq[int32] =
-  result = newSeqOfCap[int32](vals.len)
-  for v in vals:
-    result.add v
-
-echo varargsToSeq(1, 2, 3, 4)
diff --git a/tests/ccgbugs/tccgissues.nim b/tests/ccgbugs/tccgissues.nim
new file mode 100644
index 000000000..8207ccbba
--- /dev/null
+++ b/tests/ccgbugs/tccgissues.nim
@@ -0,0 +1,14 @@
+discard """
+  output: '''
+@[1, 2, 3, 4]
+'''
+"""
+
+# issue #10999
+
+proc varargsToSeq(vals: varargs[int32]): seq[int32] =
+  result = newSeqOfCap[int32](vals.len)
+  for v in vals:
+    result.add v
+
+echo varargsToSeq(1, 2, 3, 4)
diff --git a/tests/errmsgs/ttypeAllowed.nim b/tests/errmsgs/ttypeAllowed.nim
new file mode 100644
index 000000000..a5b335faa
--- /dev/null
+++ b/tests/errmsgs/ttypeAllowed.nim
@@ -0,0 +1,28 @@
+discard """
+cmd: "nim check $file"
+errmsg: ""
+nimout: '''
+ttypeAllowed.nim(13, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for let
+ttypeAllowed.nim(17, 7) Error: invalid type for const: iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}
+ttypeAllowed.nim(21, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for var
+ttypeAllowed.nim(26, 10) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for result
+'''
+"""
+
+
+let f1 = case true
+  of true:  countup[int]
+  of false: countdown[int]
+
+const f2 = case true
+  of true:  countup[int]
+  of false: countdown[int]
+
+var f3 = case true
+  of true:  countup[int]
+  of false: countdown[int]
+
+proc foobar(): auto =
+  result = case true
+    of true:  countup[int]
+    of false: countdown[int]
diff --git a/tests/iter/titerassignerr.nim b/tests/iter/titerassignerr.nim
deleted file mode 100644
index caa56c4ad..000000000
--- a/tests/iter/titerassignerr.nim
+++ /dev/null
@@ -1,8 +0,0 @@
-discard """
-  errormsg: "inline iterators are not first-class / cannot be assigned to variables"
-  line: 8
-"""
-
-iterator foo: int =
-  yield 2
-let x = foo