This commit is contained in:
Andreas Rumpf 2016-07-08 10:34:12 +02:00
commit b47d9b7b91
21 changed files with 84 additions and 39 deletions

View file

@ -395,6 +395,9 @@ type
# sons[1]: field type # sons[1]: field type
# .n: nkDotExpr storing the field name # .n: nkDotExpr storing the field name
tyVoid #\
# now different from tyEmpty, hurray!
static: static:
# remind us when TTypeKind stops to fit in a single 64-bit word # remind us when TTypeKind stops to fit in a single 64-bit word
assert TTypeKind.high.ord <= 63 assert TTypeKind.high.ord <= 63
@ -528,8 +531,6 @@ const
tfOldSchoolExprStmt* = tfVarargs # for now used to distinguish \ tfOldSchoolExprStmt* = tfVarargs # for now used to distinguish \
# 'varargs[expr]' from 'varargs[untyped]'. Eventually 'expr' will be # 'varargs[expr]' from 'varargs[untyped]'. Eventually 'expr' will be
# deprecated and this mess can be cleaned up. # 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 tfReturnsNew* = tfInheritable
skError* = skUnknown skError* = skUnknown
@ -1588,7 +1589,7 @@ proc isAtom*(n: PNode): bool {.inline.} =
proc isEmptyType*(t: PType): bool {.inline.} = proc isEmptyType*(t: PType): bool {.inline.} =
## 'void' and 'stmt' types are often equivalent to 'nil' these days: ## '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 = proc makeStmtList*(n: PNode): PNode =
if n.kind == nkStmtList: if n.kind == nkStmtList:

View file

@ -124,7 +124,7 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
result = "(*$1)->data, (*$1)->$2" % [a.rdLoc, lenField(p)] result = "(*$1)->data, (*$1)->$2" % [a.rdLoc, lenField(p)]
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(lastSon(a.t)))] result = "$1, $2" % [rdLoc(a), rope(lengthOrd(lastSon(a.t)))]
else: else:
internalError("openArrayLoc: " & typeToString(a.t)) internalError("openArrayLoc: " & typeToString(a.t))
else: internalError("openArrayLoc: " & typeToString(a.t)) else: internalError("openArrayLoc: " & typeToString(a.t))

View file

@ -1320,7 +1320,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
putIntoDest(p, d, e.typ, putIntoDest(p, d, e.typ,
ropecg(p.module, "#reprAny($1, $2)", [ ropecg(p.module, "#reprAny($1, $2)", [
rdLoc(a), genTypeInfo(p.module, t)]), a.s) rdLoc(a), genTypeInfo(p.module, t)]), a.s)
of tyEmpty: of tyEmpty, tyVoid:
localError(e.info, "'repr' doesn't support 'void' type") localError(e.info, "'repr' doesn't support 'void' type")
else: else:
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)", putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",

View file

@ -416,7 +416,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
addf(result, "union{$n$1} $2;$n", [unionBody, uname]) addf(result, "union{$n$1} $2;$n", [unionBody, uname])
of nkSym: of nkSym:
field = n.sym field = n.sym
if field.typ.kind == tyEmpty: return if field.typ.kind == tyVoid: return
#assert(field.ast == nil) #assert(field.ast == nil)
sname = mangleRecFieldName(field, rectype) sname = mangleRecFieldName(field, rectype)
if accessExpr != nil: ae = "$1.$2" % [accessExpr, sname] if accessExpr != nil: ae = "$1.$2" % [accessExpr, sname]
@ -663,7 +663,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
chunkStart = i chunkStart = i
let typeInSlot = resolveStarsInCppType(typ, idx + 1, stars) let typeInSlot = resolveStarsInCppType(typ, idx + 1, stars)
if typeInSlot == nil or typeInSlot.kind == tyEmpty: if typeInSlot == nil or typeInSlot.kind == tyVoid:
result.add(~"void") result.add(~"void")
else: else:
result.add getTypeDescAux(m, typeInSlot, check) result.add getTypeDescAux(m, typeInSlot, check)
@ -1022,7 +1022,7 @@ proc genTypeInfo(m: BModule, t: PType): Rope =
[result, rope(typeToString(t))]) [result, rope(typeToString(t))])
return "(&".rope & result & ")".rope return "(&".rope & result & ")".rope
case t.kind case t.kind
of tyEmpty: result = rope"0" of tyEmpty, tyVoid: result = rope"0"
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar: of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar:
genTypeInfoAuxBase(m, t, t, result, rope"0") genTypeInfoAuxBase(m, t, t, result, rope"0")
of tyProc: of tyProc:

View file

@ -93,7 +93,7 @@ proc getUniqueType*(key: PType): PType =
# produced instead of ``NI``. # produced instead of ``NI``.
result = key result = key
of tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString, of tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
tyCString, tyNone, tyBigNum: tyCString, tyNone, tyBigNum, tyVoid:
result = gCanonicalTypes[k] result = gCanonicalTypes[k]
if result == nil: if result == nil:
gCanonicalTypes[k] = key gCanonicalTypes[k] = key

View file

@ -163,7 +163,7 @@ proc mapType(typ: PType): TJSTypeKind =
of tyNil: result = etyNull of tyNil: result = etyNull
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation, of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor, tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses: tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses, tyVoid:
result = etyNone result = etyNone
of tyProc: result = etyProc of tyProc: result = etyProc
of tyCString: result = etyString of tyCString: result = etyString

View file

@ -75,7 +75,7 @@ proc checkTypes(c: PPatternContext, p: PSym, n: PNode): bool =
result = matchNodeKinds(p.constraint, n) result = matchNodeKinds(p.constraint, n)
if not result: return if not result: return
if isNil(n.typ): if isNil(n.typ):
result = p.typ.kind in {tyEmpty, tyStmt} result = p.typ.kind in {tyVoid, tyStmt}
else: else:
result = sigmatch.argtypeMatches(c.c, p.typ, n.typ) result = sigmatch.argtypeMatches(c.c, p.typ, n.typ)

View file

@ -183,7 +183,7 @@ proc newSeqCall(c: PContext; x, y: PNode): PNode =
proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) = proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case t.kind case t.kind
of tyNone, tyEmpty: discard of tyNone, tyEmpty, tyVoid: discard
of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString, of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
tyPtr, tyString, tyRef: tyPtr, tyString, tyRef:
defaultOp(c, t, body, x, y) defaultOp(c, t, body, x, y)

View file

@ -32,8 +32,7 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# XXX tyGenericInst here? # XXX tyGenericInst here?
if result.typ.kind == tyVar: result = newDeref(result) if result.typ.kind == tyVar: result = newDeref(result)
elif {efWantStmt, efAllowStmt} * flags != {}: elif {efWantStmt, efAllowStmt} * flags != {}:
result.typ = newTypeS(tyEmpty, c) result.typ = newTypeS(tyVoid, c)
result.typ.flags.incl tfVoid
else: else:
localError(n.info, errExprXHasNoType, localError(n.info, errExprXHasNoType,
renderTree(result, {renderNoComments})) renderTree(result, {renderNoComments}))

View file

@ -138,7 +138,7 @@ proc fixNilType(n: PNode) =
proc discardCheck(c: PContext, result: PNode) = proc discardCheck(c: PContext, result: PNode) =
if c.inTypeClass > 0: return 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: if result.kind == nkNilLit:
result.typ = nil result.typ = nil
message(result.info, warnNilStatement) message(result.info, warnNilStatement)
@ -711,7 +711,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
a.sons[1] = s.typ.n a.sons[1] = s.typ.n
s.typ.size = -1 # could not be computed properly s.typ.size = -1 # could not be computed properly
# we fill it out later. For magic generics like 'seq', it won't be filled # 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 # like: mydata.seq
rawAddSon(s.typ, newTypeS(tyNone, c)) rawAddSon(s.typ, newTypeS(tyNone, c))
s.ast = a s.ast = a

View file

@ -945,7 +945,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
if isType: localError(a.info, "':' expected") if isType: localError(a.info, "':' expected")
if kind in {skTemplate, skMacro}: if kind in {skTemplate, skMacro}:
typ = newTypeS(tyExpr, c) typ = newTypeS(tyExpr, c)
elif skipTypes(typ, {tyGenericInst}).kind == tyEmpty: elif skipTypes(typ, {tyGenericInst}).kind == tyVoid:
continue continue
for j in countup(0, length-3): for j in countup(0, length-3):
var arg = newSymG(skParam, a.sons[j], c) var arg = newSymG(skParam, a.sons[j], c)
@ -977,7 +977,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
if r != nil: if r != nil:
# turn explicit 'void' return type into 'nil' because the rest of the # turn explicit 'void' return type into 'nil' because the rest of the
# compiler only checks for 'nil': # 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: # 'auto' as a return type does not imply a generic:
if r.kind == tyAnything: if r.kind == tyAnything:
# 'p(): auto' and 'p(): expr' are equivalent, but the rest of the # '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) setMagicType(m, tyTypeDesc, 0)
rawAddSon(m.typ, newTypeS(tyNone, c)) rawAddSon(m.typ, newTypeS(tyNone, c))
of mVoidType: of mVoidType:
setMagicType(m, tyEmpty, 0) setMagicType(m, tyVoid, 0)
# for historical reasons we conflate 'void' with 'empty' so that '@[]'
# has the type 'seq[void]'.
m.typ.flags.incl tfVoid
of mArray: of mArray:
setMagicType(m, tyArray, 0) setMagicType(m, tyArray, 0)
of mOpenArray: of mOpenArray:

View file

@ -162,7 +162,7 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
discard discard
of nkSym: of nkSym:
result.sym = replaceTypeVarsS(cl, n.sym) result.sym = replaceTypeVarsS(cl, n.sym)
if result.sym.typ.kind == tyEmpty: if result.sym.typ.kind == tyVoid:
# don't add the 'void' field # don't add the 'void' field
result = newNode(nkRecList, n.info) result = newNode(nkRecList, n.info)
of nkRecWhen: of nkRecWhen:
@ -316,15 +316,15 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
proc eraseVoidParams*(t: PType) = proc eraseVoidParams*(t: PType) =
# transform '(): void' into '()' because old parts of the compiler really # transform '(): void' into '()' because old parts of the compiler really
# don't deal with '(): void': # 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 t.sons[0] = nil
for i in 1 .. <t.sonsLen: for i in 1 .. <t.sonsLen:
# don't touch any memory unless necessary # don't touch any memory unless necessary
if t.sons[i].kind == tyEmpty: if t.sons[i].kind == tyVoid:
var pos = i var pos = i
for j in i+1 .. <t.sonsLen: 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.sons[pos] = t.sons[j]
t.n.sons[pos] = t.n.sons[j] t.n.sons[pos] = t.n.sons[j]
inc pos inc pos

View file

@ -949,8 +949,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
result = isConvertible result = isConvertible
else: discard else: discard
of tyEmpty: of tyEmpty, tyVoid:
if a.kind == tyEmpty: result = isEqual if a.kind == f.kind: result = isEqual
of tyGenericInst: of tyGenericInst:
result = typeRel(c, lastSon(f), a) result = typeRel(c, lastSon(f), a)

View file

@ -407,7 +407,8 @@ const
"!", "varargs[$1]", "iter[$1]", "Error Type", "!", "varargs[$1]", "iter[$1]", "Error Type",
"BuiltInTypeClass", "UserTypeClass", "BuiltInTypeClass", "UserTypeClass",
"UserTypeClassInst", "CompositeTypeClass", "UserTypeClassInst", "CompositeTypeClass",
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"] "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
"void"]
const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg} const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
@ -923,7 +924,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
case a.kind case a.kind
of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
tyInt..tyBigNum, tyStmt, tyExpr: tyInt..tyBigNum, tyStmt, tyExpr, tyVoid:
result = sameFlags(a, b) result = sameFlags(a, b)
of tyStatic, tyFromExpr: of tyStatic, tyFromExpr:
result = exprStructuralEquivalent(a.n, b.n) and sameFlags(a, b) 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 result = nil
of tyExpr, tyStmt, tyStatic: of tyExpr, tyStmt, tyStatic:
if kind notin {skParam, skResult}: result = t if kind notin {skParam, skResult}: result = t
of tyEmpty: of tyVoid:
if taField notin flags: result = t if taField notin flags: result = t
of tyTypeClasses: of tyTypeClasses:
if not (tfGenericTypeParam in t.flags or taField notin flags): result = t 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 != nil: break
if result.isNil and t.n != nil: if result.isNil and t.n != nil:
result = typeAllowedNode(marker, t.n, kind, flags) 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 # for now same as error node; we say it's a valid type as it should
# prevent cascading errors: # prevent cascading errors:
result = nil result = nil

View file

@ -80,7 +80,7 @@ proc mapTypeToBracketX(name: string; m: TMagic; t: PType; info: TLineInfo;
for i in 0 .. < t.len: for i in 0 .. < t.len:
if t.sons[i] == nil: if t.sons[i] == nil:
let void = atomicTypeX("void", mVoid, t, info) let void = atomicTypeX("void", mVoid, t, info)
void.typ = newType(tyEmpty, t.owner) void.typ = newType(tyVoid, t.owner)
result.add void result.add void
else: else:
result.add mapTypeToAstX(t.sons[i], info, inst) 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 tyNil: result = atomicType("nil", mNil)
of tyExpr: result = atomicType("expr", mExpr) of tyExpr: result = atomicType("expr", mExpr)
of tyStmt: result = atomicType("stmt", mStmt) 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: of tyArrayConstr, tyArray:
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t) result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
result.add atomicType("array", mArray) result.add atomicType("array", mArray)

View file

@ -267,7 +267,7 @@ proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister =
proc clearDest(c: PCtx; n: PNode; dest: var TDest) {.inline.} = proc clearDest(c: PCtx; n: PNode; dest: var TDest) {.inline.} =
# stmt is different from 'void' in meta programming contexts. # stmt is different from 'void' in meta programming contexts.
# So we only set dest to -1 if 'void': # 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) c.freeTemp(dest)
dest = -1 dest = -1

View file

@ -1699,8 +1699,10 @@ proc processBody(node, retFutureSym: NimNode,
else: else:
result.add newCall(newIdentNode("complete"), retFutureSym) result.add newCall(newIdentNode("complete"), retFutureSym)
else: else:
result.add newCall(newIdentNode("complete"), retFutureSym, let x = node[0].processBody(retFutureSym, subTypeIsVoid, tryStmt)
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()) result.add newNimNode(nnkReturnStmt, node).add(newNilLit())
return # Don't process the children of this return stmt return # Don't process the children of this return stmt

View file

@ -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

View file

@ -1,5 +1,5 @@
discard """ discard """
output: "empty" output: "void"
""" """
# bug #898 # bug #898

View file

@ -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"

View file

@ -1,6 +1,6 @@
discard """ discard """
line: 16 line: 16
errormsg: "type mismatch: got (empty)" errormsg: "type mismatch: got (void)"
""" """
# bug #950 # bug #950