summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim7
-rw-r--r--compiler/ccgcalls.nim2
-rw-r--r--compiler/ccgexprs.nim2
-rw-r--r--compiler/ccgtypes.nim6
-rw-r--r--compiler/ccgutils.nim2
-rw-r--r--compiler/jsgen.nim2
-rw-r--r--compiler/patterns.nim2
-rw-r--r--compiler/semasgn.nim2
-rw-r--r--compiler/semexprs.nim3
-rw-r--r--compiler/semstmts.nim4
-rw-r--r--compiler/semtypes.nim9
-rw-r--r--compiler/semtypinst.nim8
-rw-r--r--compiler/sigmatch.nim4
-rw-r--r--compiler/types.nim9
-rw-r--r--compiler/vmdeps.nim5
-rw-r--r--compiler/vmgen.nim2
-rw-r--r--lib/pure/asyncdispatch.nim6
-rw-r--r--tests/async/treturn_await.nim23
-rw-r--r--tests/metatype/tautoproc.nim2
-rw-r--r--tests/metatype/tvoid_must_not_match.nim21
-rw-r--r--tests/typerel/temptynode.nim2
21 files changed, 84 insertions, 39 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 34ffd6f58..2b4de75cc 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -395,6 +395,9 @@ type
       # sons[1]: field type
       # .n: nkDotExpr storing the field name
 
+    tyVoid #\
+      # now different from tyEmpty, hurray!
+
 static:
   # remind us when TTypeKind stops to fit in a single 64-bit word
   assert TTypeKind.high.ord <= 63
@@ -528,8 +531,6 @@ const
   tfOldSchoolExprStmt* = tfVarargs # for now used to distinguish \
     # 'varargs[expr]' from 'varargs[untyped]'. Eventually 'expr' will be
     # deprecated and this mess can be cleaned up.
-  tfVoid* = tfVarargs # for historical reasons we conflated 'void' with
-                      # 'empty' ('@[]' has the type 'seq[empty]').
   tfReturnsNew* = tfInheritable
   skError* = skUnknown
 
@@ -1588,7 +1589,7 @@ proc isAtom*(n: PNode): bool {.inline.} =
 
 proc isEmptyType*(t: PType): bool {.inline.} =
   ## 'void' and 'stmt' types are often equivalent to 'nil' these days:
-  result = t == nil or t.kind in {tyEmpty, tyStmt}
+  result = t == nil or t.kind in {tyVoid, tyStmt}
 
 proc makeStmtList*(n: PNode): PNode =
   if n.kind == nkStmtList:
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index bd1a4101a..dffb8a9a5 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -124,7 +124,7 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
         result = "(*$1)->data, (*$1)->$2" % [a.rdLoc, lenField(p)]
       of tyArray, tyArrayConstr:
         result = "$1, $2" % [rdLoc(a), rope(lengthOrd(lastSon(a.t)))]
-      else: 
+      else:
         internalError("openArrayLoc: " & typeToString(a.t))
     else: internalError("openArrayLoc: " & typeToString(a.t))
 
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 0a67ca0af..179119bad 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1320,7 +1320,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
     putIntoDest(p, d, e.typ,
                 ropecg(p.module, "#reprAny($1, $2)", [
                 rdLoc(a), genTypeInfo(p.module, t)]), a.s)
-  of tyEmpty:
+  of tyEmpty, tyVoid:
     localError(e.info, "'repr' doesn't support 'void' type")
   else:
     putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index e637b6c24..a10f3b838 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -416,7 +416,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
       addf(result, "union{$n$1} $2;$n", [unionBody, uname])
   of nkSym:
     field = n.sym
-    if field.typ.kind == tyEmpty: return
+    if field.typ.kind == tyVoid: return
     #assert(field.ast == nil)
     sname = mangleRecFieldName(field, rectype)
     if accessExpr != nil: ae = "$1.$2" % [accessExpr, sname]
@@ -663,7 +663,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
             chunkStart = i
 
             let typeInSlot = resolveStarsInCppType(typ, idx + 1, stars)
-            if typeInSlot == nil or typeInSlot.kind == tyEmpty:
+            if typeInSlot == nil or typeInSlot.kind == tyVoid:
               result.add(~"void")
             else:
               result.add getTypeDescAux(m, typeInSlot, check)
@@ -1022,7 +1022,7 @@ proc genTypeInfo(m: BModule, t: PType): Rope =
          [result, rope(typeToString(t))])
     return "(&".rope & result & ")".rope
   case t.kind
-  of tyEmpty: result = rope"0"
+  of tyEmpty, tyVoid: result = rope"0"
   of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar:
     genTypeInfoAuxBase(m, t, t, result, rope"0")
   of tyProc:
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 6dfd7b52c..27b432c2c 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -93,7 +93,7 @@ proc getUniqueType*(key: PType): PType =
     # produced instead of ``NI``.
     result = key
   of  tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
-      tyCString, tyNone, tyBigNum:
+      tyCString, tyNone, tyBigNum, tyVoid:
     result = gCanonicalTypes[k]
     if result == nil:
       gCanonicalTypes[k] = key
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index d7aa7f0f4..0b62b8480 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -163,7 +163,7 @@ proc mapType(typ: PType): TJSTypeKind =
   of tyNil: result = etyNull
   of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
      tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
-     tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses:
+     tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses, tyVoid:
     result = etyNone
   of tyProc: result = etyProc
   of tyCString: result = etyString
diff --git a/compiler/patterns.nim b/compiler/patterns.nim
index 2336e44e7..09b8d3305 100644
--- a/compiler/patterns.nim
+++ b/compiler/patterns.nim
@@ -75,7 +75,7 @@ proc checkTypes(c: PPatternContext, p: PSym, n: PNode): bool =
     result = matchNodeKinds(p.constraint, n)
     if not result: return
   if isNil(n.typ):
-    result = p.typ.kind in {tyEmpty, tyStmt}
+    result = p.typ.kind in {tyVoid, tyStmt}
   else:
     result = sigmatch.argtypeMatches(c.c, p.typ, n.typ)
 
diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim
index a1e209263..9702128ba 100644
--- a/compiler/semasgn.nim
+++ b/compiler/semasgn.nim
@@ -183,7 +183,7 @@ proc newSeqCall(c: PContext; x, y: PNode): PNode =
 
 proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
   case t.kind
-  of tyNone, tyEmpty: discard
+  of tyNone, tyEmpty, tyVoid: discard
   of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
       tyPtr, tyString, tyRef:
     defaultOp(c, t, body, x, y)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 7cf0755b4..f8723bf64 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -32,8 +32,7 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     # XXX tyGenericInst here?
     if result.typ.kind == tyVar: result = newDeref(result)
   elif {efWantStmt, efAllowStmt} * flags != {}:
-    result.typ = newTypeS(tyEmpty, c)
-    result.typ.flags.incl tfVoid
+    result.typ = newTypeS(tyVoid, c)
   else:
     localError(n.info, errExprXHasNoType,
                renderTree(result, {renderNoComments}))
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 7155f9c7a..0fb770875 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -138,7 +138,7 @@ proc fixNilType(n: PNode) =
 
 proc discardCheck(c: PContext, result: PNode) =
   if c.inTypeClass > 0: return
-  if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
+  if result.typ != nil and result.typ.kind notin {tyStmt, tyVoid}:
     if result.kind == nkNilLit:
       result.typ = nil
       message(result.info, warnNilStatement)
@@ -711,7 +711,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       a.sons[1] = s.typ.n
       s.typ.size = -1 # could not be computed properly
       # we fill it out later. For magic generics like 'seq', it won't be filled
-      # so we use tyEmpty instead of nil to not crash for strange conversions
+      # so we use tyNone instead of nil to not crash for strange conversions
       # like: mydata.seq
       rawAddSon(s.typ, newTypeS(tyNone, c))
       s.ast = a
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index e9a2be1bd..bef104914 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -945,7 +945,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       if isType: localError(a.info, "':' expected")
       if kind in {skTemplate, skMacro}:
         typ = newTypeS(tyExpr, c)
-    elif skipTypes(typ, {tyGenericInst}).kind == tyEmpty:
+    elif skipTypes(typ, {tyGenericInst}).kind == tyVoid:
       continue
     for j in countup(0, length-3):
       var arg = newSymG(skParam, a.sons[j], c)
@@ -977,7 +977,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
   if r != nil:
     # turn explicit 'void' return type into 'nil' because the rest of the
     # compiler only checks for 'nil':
-    if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
+    if skipTypes(r, {tyGenericInst}).kind != tyVoid:
       # 'auto' as a return type does not imply a generic:
       if r.kind == tyAnything:
         # 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
@@ -1390,10 +1390,7 @@ proc processMagicType(c: PContext, m: PSym) =
     setMagicType(m, tyTypeDesc, 0)
     rawAddSon(m.typ, newTypeS(tyNone, c))
   of mVoidType:
-    setMagicType(m, tyEmpty, 0)
-    # for historical reasons we conflate 'void' with 'empty' so that '@[]'
-    # has the type 'seq[void]'.
-    m.typ.flags.incl tfVoid
+    setMagicType(m, tyVoid, 0)
   of mArray:
     setMagicType(m, tyArray, 0)
   of mOpenArray:
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 7ff33f918..922071ba3 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -162,7 +162,7 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
     discard
   of nkSym:
     result.sym = replaceTypeVarsS(cl, n.sym)
-    if result.sym.typ.kind == tyEmpty:
+    if result.sym.typ.kind == tyVoid:
       # don't add the 'void' field
       result = newNode(nkRecList, n.info)
   of nkRecWhen:
@@ -316,15 +316,15 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
 proc eraseVoidParams*(t: PType) =
   # transform '(): void' into '()' because old parts of the compiler really
   # don't deal with '(): void':
-  if t.sons[0] != nil and t.sons[0].kind == tyEmpty:
+  if t.sons[0] != nil and t.sons[0].kind == tyVoid:
     t.sons[0] = nil
 
   for i in 1 .. <t.sonsLen:
     # don't touch any memory unless necessary
-    if t.sons[i].kind == tyEmpty:
+    if t.sons[i].kind == tyVoid:
       var pos = i
       for j in i+1 .. <t.sonsLen:
-        if t.sons[j].kind != tyEmpty:
+        if t.sons[j].kind != tyVoid:
           t.sons[pos] = t.sons[j]
           t.n.sons[pos] = t.n.sons[j]
           inc pos
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 70fbe7358..511a44954 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -949,8 +949,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         result = isConvertible
     else: discard
 
-  of tyEmpty:
-    if a.kind == tyEmpty: result = isEqual
+  of tyEmpty, tyVoid:
+    if a.kind == f.kind: result = isEqual
 
   of tyGenericInst:
     result = typeRel(c, lastSon(f), a)
diff --git a/compiler/types.nim b/compiler/types.nim
index 107bd9f75..4d6bf0502 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -407,7 +407,8 @@ const
     "!", "varargs[$1]", "iter[$1]", "Error Type",
     "BuiltInTypeClass", "UserTypeClass",
     "UserTypeClassInst", "CompositeTypeClass",
-    "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"]
+    "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
+    "void"]
 
 const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
 
@@ -923,7 +924,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
 
   case a.kind
   of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
-     tyInt..tyBigNum, tyStmt, tyExpr:
+     tyInt..tyBigNum, tyStmt, tyExpr, tyVoid:
     result = sameFlags(a, b)
   of tyStatic, tyFromExpr:
     result = exprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
@@ -1109,7 +1110,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     result = nil
   of tyExpr, tyStmt, tyStatic:
     if kind notin {skParam, skResult}: result = t
-  of tyEmpty:
+  of tyVoid:
     if taField notin flags: result = t
   of tyTypeClasses:
     if not (tfGenericTypeParam in t.flags or taField notin flags): result = t
@@ -1154,7 +1155,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
       if result != nil: break
     if result.isNil and t.n != nil:
       result = typeAllowedNode(marker, t.n, kind, flags)
-  of tyProxy:
+  of tyProxy, tyEmpty:
     # for now same as error node; we say it's a valid type as it should
     # prevent cascading errors:
     result = nil
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 00b13e6b6..a10e7c12e 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -80,7 +80,7 @@ proc mapTypeToBracketX(name: string; m: TMagic; t: PType; info: TLineInfo;
   for i in 0 .. < t.len:
     if t.sons[i] == nil:
       let void = atomicTypeX("void", mVoid, t, info)
-      void.typ = newType(tyEmpty, t.owner)
+      void.typ = newType(tyVoid, t.owner)
       result.add void
     else:
       result.add mapTypeToAstX(t.sons[i], info, inst)
@@ -124,7 +124,8 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
   of tyNil: result = atomicType("nil", mNil)
   of tyExpr: result = atomicType("expr", mExpr)
   of tyStmt: result = atomicType("stmt", mStmt)
-  of tyEmpty: result = atomicType("void", mVoid)
+  of tyVoid: result = atomicType("void", mVoid)
+  of tyEmpty: result = atomicType("empty", mNone)
   of tyArrayConstr, tyArray:
     result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
     result.add atomicType("array", mArray)
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index ce13f81eb..b8c206bb3 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -267,7 +267,7 @@ proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister =
 proc clearDest(c: PCtx; n: PNode; dest: var TDest) {.inline.} =
   # stmt is different from 'void' in meta programming contexts.
   # So we only set dest to -1 if 'void':
-  if dest >= 0 and (n.typ.isNil or n.typ.kind == tyEmpty):
+  if dest >= 0 and (n.typ.isNil or n.typ.kind == tyVoid):
     c.freeTemp(dest)
     dest = -1
 
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index be6522c36..f47bfeee3 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -1699,8 +1699,10 @@ proc processBody(node, retFutureSym: NimNode,
       else:
         result.add newCall(newIdentNode("complete"), retFutureSym)
     else:
-      result.add newCall(newIdentNode("complete"), retFutureSym,
-        node[0].processBody(retFutureSym, subTypeIsVoid, tryStmt))
+      let x = node[0].processBody(retFutureSym, subTypeIsVoid, tryStmt)
+      if x.kind == nnkYieldStmt: result.add x
+      else:
+        result.add newCall(newIdentNode("complete"), retFutureSym, x)
 
     result.add newNimNode(nnkReturnStmt, node).add(newNilLit())
     return # Don't process the children of this return stmt
diff --git a/tests/async/treturn_await.nim b/tests/async/treturn_await.nim
new file mode 100644
index 000000000..8d266d665
--- /dev/null
+++ b/tests/async/treturn_await.nim
@@ -0,0 +1,23 @@
+
+# bug #4371
+
+import strutils, asyncdispatch, asynchttpserver
+
+type
+  List[A] = ref object
+    value: A
+    next: List[A]
+  StrPair* = tuple[k, v: string]
+  Context* = object
+    position*: int
+    accept*: bool
+    headers*: List[StrPair]
+  Handler* = proc(req: ref Request, ctx: Context): Future[Context]
+
+proc logging*(handler: Handler): auto =
+  proc h(req: ref Request, ctx: Context): Future[Context] {.async.} =
+    let ret = handler(req, ctx)
+    debugEcho "$3 $1 $2".format(req.reqMethod, req.url.path, req.hostname)
+    return await ret
+
+  return h
diff --git a/tests/metatype/tautoproc.nim b/tests/metatype/tautoproc.nim
index ef5377096..2c8f6a3f7 100644
--- a/tests/metatype/tautoproc.nim
+++ b/tests/metatype/tautoproc.nim
@@ -1,5 +1,5 @@
 discard """
-  output: "empty"
+  output: "void"
 """
 
 # bug #898
diff --git a/tests/metatype/tvoid_must_not_match.nim b/tests/metatype/tvoid_must_not_match.nim
new file mode 100644
index 000000000..240c3f751
--- /dev/null
+++ b/tests/metatype/tvoid_must_not_match.nim
@@ -0,0 +1,21 @@
+discard """
+  errormsg: "type mismatch: got (Future[system.int], void)"
+  line: 20
+"""
+
+type
+  Future[T] = object
+    value: T
+
+proc complete[T](x: T) =
+  echo "completed"
+  let y = x
+
+
+proc complete*[T](future: var Future[T], val: T) =
+  future.value = val
+
+var a: Future[int]
+
+complete(a):
+  echo "yielding void"
diff --git a/tests/typerel/temptynode.nim b/tests/typerel/temptynode.nim
index 91e45f3ca..b32b16121 100644
--- a/tests/typerel/temptynode.nim
+++ b/tests/typerel/temptynode.nim
@@ -1,6 +1,6 @@
 discard """
   line: 16
-  errormsg: "type mismatch: got (empty)"
+  errormsg: "type mismatch: got (void)"
 """
 
 # bug #950