diff options
author | Araq <rumpf_a@web.de> | 2013-12-13 15:58:03 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-12-13 15:58:03 +0100 |
commit | 8c553fa8a2e9476c67c6348bf64c02ea0f19a679 (patch) | |
tree | ce32cf3cd815f4dbb7e5f0f00942f43e1a7871c0 /compiler | |
parent | 328f1932925889d5bb7f91c68fb1504b9b26ba8c (diff) | |
parent | 01661daf76daa713d25d06d202f83c842a6f1fe3 (diff) | |
download | Nim-8c553fa8a2e9476c67c6348bf64c02ea0f19a679.tar.gz |
Merge branch 'master' into vm2
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 11 | ||||
-rw-r--r-- | compiler/ccgutils.nim | 2 | ||||
-rw-r--r-- | compiler/cgen.nim | 2 | ||||
-rw-r--r-- | compiler/evals.nim | 4 | ||||
-rw-r--r-- | compiler/jsgen.nim | 2 | ||||
-rw-r--r-- | compiler/main.nim | 4 | ||||
-rw-r--r-- | compiler/nimrod.nim | 6 | ||||
-rw-r--r-- | compiler/nimrod.nimrod.cfg | 1 | ||||
-rw-r--r-- | compiler/semexprs.nim | 2 | ||||
-rw-r--r-- | compiler/seminst.nim | 5 | ||||
-rw-r--r-- | compiler/semtypes.nim | 9 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 248 | ||||
-rw-r--r-- | compiler/testability.nim | 5 | ||||
-rw-r--r-- | compiler/types.nim | 25 |
14 files changed, 283 insertions, 43 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 1eb5bffc4..a3e034140 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -335,12 +335,19 @@ type tyConst, tyMutable, tyVarargs, tyIter, # unused tyProxy # used as errornous type (for idetools) - tyTypeClass, + tyTypeClass + tyAnd + tyOr + tyNot + tyAnything + tyParametricTypeClass # structured similarly to tyGenericInst + # lastSon is the body of the type class const tyPureObject* = tyTuple GcTypeKinds* = {tyRef, tySequence, tyString} tyError* = tyProxy # as an errornous node should match everything + tyTypeClasses* = {tyTypeClass, tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything} type TTypeKinds* = set[TTypeKind] @@ -378,6 +385,7 @@ type # used as return types for return type inference) tfAll, # type class requires all constraints to be met (default) tfAny, # type class requires any constraint to be met + tfNot, # type class with a negative check tfCapturesEnv, # whether proc really captures some environment tfByCopy, # pass object/tuple by copy (C backend) tfByRef, # pass object/tuple by reference (C backend) @@ -1417,3 +1425,4 @@ 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} + diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index c37754511..310f7204a 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -86,7 +86,7 @@ proc GetUniqueType*(key: PType): PType = if result == nil: gCanonicalTypes[k] = key result = key - of tyTypeDesc, tyTypeClass: + of tyTypeDesc, tyTypeClasses: InternalError("value expected, but got a type") of tyGenericParam: InternalError("GetUniqueType") diff --git a/compiler/cgen.nim b/compiler/cgen.nim index ad9ade63c..b0c90de76 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -944,9 +944,9 @@ proc genMainProc(m: BModule) = const CommonMainBody = "\tsystemDatInit();$n" & + "\tsystemInit();$n" & "$1" & "$2" & - "\tsystemInit();$n" & "$3" & "$4" PosixNimMain = diff --git a/compiler/evals.nim b/compiler/evals.nim index 7e2c8a41d..b4ea973e8 100644 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -550,9 +550,7 @@ proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = of skProc, skConverter, skMacro, skType: result = n #result = s.getBody - of skForVar: - result = evalGlobalVar(c, s, flags) - of skVar, skLet, skTemp, skResult: + of skVar, skLet, skForVar, skTemp, skResult: if sfGlobal notin s.flags: result = evalVariable(c.tos, s, flags) else: diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 54ee43069..a3c88824d 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -130,7 +130,7 @@ proc mapType(typ: PType): TJSTypeKind = result = etyObject of tyNil: result = etyNull of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, tyNone, - tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc, tyTypeClass: + tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc, tyTypeClasses: result = etyNone of tyProc: result = etyProc of tyCString: result = etyString diff --git a/compiler/main.nim b/compiler/main.nim index 7124b6984..2a4143823 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -432,7 +432,9 @@ proc MainCommand* = else: rawMessage(errInvalidCommandX, command) - if msgs.gErrorCounter == 0 and gCmd notin {cmdInterpret, cmdRun, cmdDump}: + if (msgs.gErrorCounter == 0 and + gCmd notin {cmdInterpret, cmdRun, cmdDump} and + gVerbosity > 0): rawMessage(hintSuccessX, [$gLinesCompiled, formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3), formatSize(getTotalMem())]) diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim index 3fa80cebb..2f10e32e3 100644 --- a/compiler/nimrod.nim +++ b/compiler/nimrod.nim @@ -76,5 +76,7 @@ when compileOption("gc", "v2") or compileOption("gc", "refc"): # the new correct mark&sweet collector is too slow :-/ GC_disableMarkAndSweep() condsyms.InitDefines() -HandleCmdLine() -quit(int8(msgs.gErrorCounter > 0)) + +when not defined(selftest): + HandleCmdLine() + quit(int8(msgs.gErrorCounter > 0)) diff --git a/compiler/nimrod.nimrod.cfg b/compiler/nimrod.nimrod.cfg index 0affe86d9..b2ae97686 100644 --- a/compiler/nimrod.nimrod.cfg +++ b/compiler/nimrod.nimrod.cfg @@ -11,6 +11,7 @@ path:"$projectPath/.." path:"$lib/packages/docutils" define:booting +import:testability @if windows: cincludes: "$lib/wrappers/libffi/common" diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 4b263b3a3..450acbf29 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -322,7 +322,7 @@ proc isOpImpl(c: PContext, n: PNode): PNode = var match: bool let t2 = n[2].typ case t2.kind - of tyTypeClass: + of tyTypeClasses: var m: TCandidate InitCandidate(m, t2) match = matchUserTypeClass(c, m, emptyNode, t2, t1) != nil diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 0cf5086a8..d7d64fd54 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -20,7 +20,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable, if a.kind != nkSym: InternalError(a.info, "instantiateGenericParamList; no symbol") var q = a.sym - if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyTypeClass, tyExpr}: continue + if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyExpr}+tyTypeClasses: + continue var s = newSym(skType, q.name, getCurrOwner(), q.info) s.flags = s.flags + {sfUsed, sfFromGeneric} var t = PType(IdTableGet(pt, q.typ)) @@ -193,7 +194,7 @@ proc fixupProcType(c: PContext, genericType: PType, if result == nil: return case genericType.kind - of tyGenericParam, tyTypeClass: + of tyGenericParam, tyTypeClasses: result = inst.concreteTypes[genericType.sym.position] of tyTypeDesc: result = inst.concreteTypes[genericType.sym.position] diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 92f47f585..6c9c476d9 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -676,8 +676,13 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, if lifted != nil: paramType.sons[i] = lifted result = paramType - - if result != nil: + + if paramType.lastSon.kind == tyTypeClass: + result = paramType + result.kind = tyParametricTypeClass + result = addImplicitGeneric(copyType(result, + getCurrOwner(), false)) + elif result != nil: result.kind = tyGenericInvokation result.sons.setLen(result.sons.len - 1) of tyTypeClass: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 00f3b2b10..cacf4782e 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -203,7 +203,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string = add(result, argTypeToString(arg)) if i != sonsLen(n) - 1: add(result, ", ") -proc typeRel*(c: var TCandidate, f, a: PType): TTypeRelation +proc typeRel*(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation proc concreteType(c: TCandidate, t: PType): PType = case t.kind of tyArrayConstr: @@ -213,7 +213,7 @@ proc concreteType(c: TCandidate, t: PType): PType = addSonSkipIntLit(result, t.sons[1]) # XXX: semantic checking for the type? of tyNil: result = nil # what should it be? - of tyGenericParam: + of tyGenericParam, tyAnything: result = t while true: result = PType(idTableGet(c.bindings, t)) @@ -385,8 +385,23 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} = else: result = isNone -proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation = - # is a subtype of f? +proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation = + # typeRel can be used to establish various relationships between types: + # + # 1) When used with concrete types, it will check for type equivalence + # or a subtype relationship. + # + # 2) When used with a concrete type against a type class (such as generic + # signature of a proc), it will check whether the concrete type is a member + # of the designated type class. + # + # 3) When used with two type classes, it will check whether the types + # matching the first type class are a strict subset of the types matching + # the other. This allows us to compare the signatures of generic procs in + # order to give preferrence to the most specific one: + # + # seq[seq[any]] is a strict subset of seq[any] and hence more specific. + result = isNone assert(f != nil) assert(a != nil) @@ -397,6 +412,50 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation = return typeRel(c, f, lastSon(a)) if a.kind == tyVar and f.kind != tyVar: return typeRel(c, f, a.sons[0]) + + template bindingRet(res) = + when res == isGeneric: put(c.bindings, f, a) + return res + + case a.kind + of tyOr: + # seq[int|string] vs seq[number] + # both int and string must match against number + for branch in a.sons: + if typeRel(c, f, branch, false) == isNone: + return isNone + + return isGeneric + + of tyAnd: + # seq[Sortable and Iterable] vs seq[Sortable] + # only one match is enough + for branch in a.sons: + if typeRel(c, f, branch, false) != isNone: + return isGeneric + + return isNone + + of tyNot: + case f.kind + of tyNot: + # seq[!int] vs seq[!number] + # seq[float] matches the first, but not the second + # we must turn the problem around: + # is number a subset of int? + return typeRel(c, a.lastSon, f.lastSon) + + else: + # negative type classes are essentially infinite, + # so only the `any` type class is their superset + return if f.kind == tyAnything: isGeneric + else: isNone + + of tyAnything: + return if f.kind == tyAnything: isGeneric + else: isNone + else: nil + case f.kind of tyEnum: if a.kind == f.kind and sameEnumTypes(f, a): result = isEqual @@ -485,9 +544,12 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation = of tyOrdinal: if isOrdinalType(a): var x = if a.kind == tyOrdinal: a.sons[0] else: a - - result = typeRel(c, f.sons[0], x) - if result < isGeneric: result = isNone + + if f.sonsLen == 0: + result = isGeneric + else: + result = typeRel(c, f.sons[0], x) + if result < isGeneric: result = isNone elif a.kind == tyGenericParam: result = isGeneric of tyForward: InternalError("forward type in typeRel()") @@ -574,13 +636,17 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation = (a.sons[1].kind == tyChar): result = isConvertible else: nil - of tyEmpty: + + of tyEmpty: if a.kind == tyEmpty: result = isEqual - of tyGenericInst: + + of tyGenericInst: result = typeRel(c, lastSon(f), a) - of tyGenericBody: + + of tyGenericBody: let ff = lastSon(f) if ff != nil: result = typeRel(c, ff, a) + of tyGenericInvokation: var x = a.skipGenericAlias if x.kind == tyGenericInvokation or f.sons[0].kind != tyGenericBody: @@ -604,6 +670,38 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation = if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}: InternalError("wrong instantiated type!") put(c.bindings, f.sons[i], x) + + of tyAnd: + for branch in f.sons: + if typeRel(c, branch, a) == isNone: + return isNone + + bindingRet isGeneric + + of tyOr: + for branch in f.sons: + if typeRel(c, branch, a) != isNone: + bindingRet isGeneric + + return isNone + + of tyNot: + for branch in f.sons: + if typeRel(c, branch, a) != isNone: + return isNone + + bindingRet isGeneric + + of tyAnything: + var prev = PType(idTableGet(c.bindings, f)) + if prev == nil: + var concrete = concreteType(c, a) + if concrete != nil and doBind: + put(c.bindings, f, concrete) + return isGeneric + else: + return typeRel(c, prev, a) + of tyGenericParam, tyTypeClass: var x = PType(idTableGet(c.bindings, f)) if x == nil: @@ -634,7 +732,7 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation = if concrete == nil: result = isNone else: - put(c.bindings, f, concrete) + if doBind: put(c.bindings, f, concrete) elif a.kind == tyEmpty: result = isGeneric elif x.kind == tyGenericParam: @@ -809,8 +907,8 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType, InternalAssert a.len > 0 r = typeRel(m, f.lastSon, a.lastSon) else: - let match = matchTypeClass(m, fMaybeExpr, a) - if match != isGeneric: r = isNone + let match = matchTypeClass(m.bindings, fMaybeExpr, a) + if not match: r = isNone else: # XXX: Ideally, this should happen much earlier somewhere near # semOpAux, but to do that, we need to be able to query the @@ -827,7 +925,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType, if r == isGeneric: put(m.bindings, f, arg.typ) - of tyTypeClass: + of tyTypeClass, tyParametricTypeClass: if fMaybeExpr.n != nil: let match = matchUserTypeClass(c, m, arg, fMaybeExpr, a) if match != nil: @@ -1130,7 +1228,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = var f = 1 while f < sonsLen(m.callee.n): var formal = m.callee.n.sons[f].sym - if not ContainsOrIncl(marker, formal.position): + if not ContainsOrIncl(marker, formal.position): if formal.ast == nil: if formal.typ.kind == tyVarargs: var container = newNodeIT(nkBracket, n.info, arrayConstr(c, n.info)) @@ -1145,7 +1243,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = setSon(m.call, formal.position + 1, copyTree(formal.ast)) inc(f) -proc argtypeMatches*(c: PContext, f, a: PType): bool = +proc argtypeMatches*(c: PContext, f, a: PType): bool = var m: TCandidate initCandidate(m, f) let res = paramTypesMatch(c, m, f, a, ast.emptyNode, nil) @@ -1155,3 +1253,121 @@ proc argtypeMatches*(c: PContext, f, a: PType): bool = result = res != nil include suggest + +tests: + var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo()) + + proc `|` (t1, t2: PType): PType = + result = newType(tyOr, dummyOwner) + result.rawAddSon(t1) + result.rawAddSon(t2) + + proc `&` (t1, t2: PType): PType = + result = newType(tyAnd, dummyOwner) + result.rawAddSon(t1) + result.rawAddSon(t2) + + proc `!` (t: PType): PType = + result = newType(tyNot, dummyOwner) + result.rawAddSon(t) + + proc seq(t: PType): PType = + result = newType(tySequence, dummyOwner) + result.rawAddSon(t) + + proc array(x: int, t: PType): PType = + result = newType(tyArray, dummyOwner) + + var n = newNodeI(nkRange, UnknownLineInfo()) + addSon(n, newIntNode(nkIntLit, 0)) + addSon(n, newIntNode(nkIntLit, x)) + let range = newType(tyRange, dummyOwner) + + result.rawAddSon(range) + result.rawAddSon(t) + + suite "type classes": + let + int = newType(tyInt, dummyOwner) + float = newType(tyFloat, dummyOwner) + string = newType(tyString, dummyOwner) + ordinal = newType(tyOrdinal, dummyOwner) + any = newType(tyAnything, dummyOwner) + number = int | float + + var TFoo = newType(tyObject, dummyOwner) + TFoo.sym = newSym(skType, getIdent"TFoo", dummyOwner, UnknownLineInfo()) + + var T1 = newType(tyGenericParam, dummyOwner) + T1.sym = newSym(skType, getIdent"T1", dummyOwner, UnknownLineInfo()) + T1.sym.position = 0 + + var T2 = newType(tyGenericParam, dummyOwner) + T2.sym = newSym(skType, getIdent"T2", dummyOwner, UnknownLineInfo()) + T2.sym.position = 1 + + setup: + var c: TCandidate + InitCandidate(c, nil) + + template yes(x, y) = + test astToStr(x) & " is " & astToStr(y): + check typeRel(c, y, x) == isGeneric + + template no(x, y) = + test astToStr(x) & " is not " & astToStr(y): + check typeRel(c, y, x) == isNone + + yes seq(any), array(10, int) | seq(any) + # Sure, seq[any] is directly included + + yes seq(int), seq(any) + yes seq(int), seq(number) + # Sure, the int sequence is certainly + # part of the number sequences (and all sequences) + + no seq(any), seq(float) + # Nope, seq[any] includes types that are not seq[float] (e.g. seq[int]) + + yes seq(int|string), seq(any) + # Sure + + yes seq(int&string), seq(any) + # Again + + yes seq(int&string), seq(int) + # A bit more complicated + # seq[int&string] is not a real type, but it's analogous to + # seq[Sortable and Iterable], which is certainly a subset of seq[Sortable] + + no seq(int|string), seq(int|float) + # Nope, seq[string] is not included in not included in + # the seq[int|float] set + + no seq(!(int|string)), seq(string) + # A sequence that is neither seq[int] or seq[string] + # is obviously not seq[string] + + no seq(!int), seq(number) + # Now your head should start to hurt a bit + # A sequence that is not seq[int] is not necessarily a number sequence + # it could well be seq[string] for example + + yes seq(!(int|string)), seq(!string) + # all sequnece types besides seq[int] and seq[string] + # are subset of all sequence types that are not seq[string] + + no seq(!(int|string)), seq(!(string|TFoo)) + # Nope, seq[TFoo] is included in the first set, but not in the second + + no seq(!string), seq(!number) + # Nope, seq[int] in included in the first set, but not in the second + + yes seq(!number), seq(any) + yes seq(!int), seq(any) + no seq(any), seq(!any) + no seq(!int), seq(!any) + + yes int, ordinal + no string, ordinal + diff --git a/compiler/testability.nim b/compiler/testability.nim new file mode 100644 index 000000000..ceefd0a5e --- /dev/null +++ b/compiler/testability.nim @@ -0,0 +1,5 @@ +template tests*(body: stmt) {.immediate.} = + when defined(selftest): + when not defined(unittest): import unittest + body + diff --git a/compiler/types.nim b/compiler/types.nim index 4dec9ea2f..7e07a0667 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -382,33 +382,34 @@ proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator, if t.n != nil: result.n = mutateNode(marker, t.n, iter, closure) assert(result != nil) -proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType = +proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType = var marker = InitIntSet() result = mutateTypeAux(marker, t, iter, closure) -proc ValueToString(a: PNode): string = +proc ValueToString(a: PNode): string = case a.kind of nkCharLit..nkUInt64Lit: result = $(a.intVal) of nkFloatLit..nkFloat128Lit: result = $(a.floatVal) of nkStrLit..nkTripleStrLit: result = a.strVal else: result = "<invalid value>" -proc rangeToStr(n: PNode): string = +proc rangeToStr(n: PNode): string = assert(n.kind == nkRange) result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1]) const - typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty", - "Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc", - "GenericInvokation", "GenericBody", "GenericInst", "GenericParam", - "distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple", - "set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc", + typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty", + "Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc", + "GenericInvokation", "GenericBody", "GenericInst", "GenericParam", + "distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple", + "set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc", "pointer", "OpenArray[$1]", "string", "CString", "Forward", "int", "int8", "int16", "int32", "int64", "float", "float32", "float64", "float128", "uint", "uint8", "uint16", "uint32", "uint64", "bignum", "const ", - "!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass"] + "!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass", + "ParametricTypeClass", "and", "or", "not", "any"] proc consToStr(t: PType): string = if t.len > 0: result = t.typeToString @@ -421,7 +422,7 @@ proc constraintsToStr(t: PType): string = if i > 0: result.add(sep) result.add(t.sons[i].consToStr) -proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string = +proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string = var t = typ result = "" if t == nil: return @@ -861,7 +862,7 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = of tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr, tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter, - tyOrdinal, tyTypeClass: + tyOrdinal, tyTypeClasses: CycleCheck() result = sameChildrenAux(a, b, c) and sameFlags(a, b) if result and (a.kind == tyProc): @@ -1042,7 +1043,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind, # XXX er ... no? these should not be allowed! of tyEmpty: result = taField in flags - of tyTypeClass: + of tyTypeClasses: result = true of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation: result = false |