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
# .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:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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) =
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)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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.} =
# 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

View file

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

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 """
output: "empty"
output: "void"
"""
# 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 """
line: 16
errormsg: "type mismatch: got (empty)"
errormsg: "type mismatch: got (void)"
"""
# bug #950