diff options
-rw-r--r-- | compiler/lineinfos.nim | 5 | ||||
-rw-r--r-- | compiler/semmagic.nim | 8 | ||||
-rw-r--r-- | compiler/types.nim | 4 | ||||
-rw-r--r-- | compiler/vm.nim | 2 | ||||
-rw-r--r-- | compiler/vmgen.nim | 2 | ||||
-rw-r--r-- | tests/vm/tinheritance.nim | 51 |
6 files changed, 65 insertions, 7 deletions
diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index cd160313c..b1ecf779e 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -41,7 +41,7 @@ type hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, - hintConditionAlwaysTrue, hintName, hintPattern, + hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern, hintExecuting, hintLinking, hintDependency, hintSource, hintPerformance, hintStackTrace, hintGCStats, hintGlobalVar, @@ -107,6 +107,7 @@ const hintConf: "used config file '$1'", hintPath: "added path: '$1'", hintConditionAlwaysTrue: "condition is always true: '$1'", + hintConditionAlwaysFalse: "condition is always false: '$1'", hintName: "name should be: '$1'", hintPattern: "$1", hintExecuting: "$1", @@ -140,7 +141,7 @@ const "Success", "SuccessX", "CC", "LineTooLong", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", - "Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency", + "Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency", "Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "User", "UserRaw", "ExtendedContext", ] diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 7a6f6788d..2aae562f9 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -306,7 +306,13 @@ proc semOf(c: PContext, n: PNode): PNode = result.typ = getSysType(c.graph, n.info, tyBool) return result elif diff == high(int): - localError(c.config, n.info, "'$1' cannot be of this subtype" % typeToString(a)) + if commonSuperclass(a, b) == nil: + localError(c.config, n.info, "'$1' cannot be of this subtype" % typeToString(a)) + else: + message(c.config, n.info, hintConditionAlwaysFalse, renderTree(n)) + result = newIntNode(nkIntLit, 0) + result.info = n.info + result.typ = getSysType(c.graph, n.info, tyBool) else: localError(c.config, n.info, "'of' takes 2 arguments") n.typ = getSysType(c.graph, n.info, tyBool) diff --git a/compiler/types.nim b/compiler/types.nim index 5b14015c1..b163ca4e9 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1086,8 +1086,8 @@ proc inheritanceDiff*(a, b: PType): int = # | returns: +x iff `a` is the x'th direct subclass of `b` # | returns: `maxint` iff `a` and `b` are not compatible at all if a == b or a.kind == tyError or b.kind == tyError: return 0 - assert a.kind == tyObject - assert b.kind == tyObject + assert a.kind in {tyObject} + skipPtrs + assert b.kind in {tyObject} + skipPtrs var x = a result = 0 while x != nil: diff --git a/compiler/vm.nim b/compiler/vm.nim index 4eef91dfc..5b5b807bb 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1228,7 +1228,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcOf: decodeBC(rkInt) let typ = c.types[regs[rc].intVal.int] - regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) >= 0) + regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) <= 0) of opcIs: decodeBC(rkInt) let t1 = regs[rb].node.typ.skipTypes({tyTypeDesc}) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 00ec22a99..c37ec7c6b 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1098,7 +1098,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = var tmp = c.genx(n.sons[1]) var idx = c.getTemp(getSysType(c.graph, n.info, tyInt)) var typ = n.sons[2].typ - if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc}) + if m == mOf: typ = typ.skipTypes(abstractPtrs) c.gABx(n, opcLdImmInt, idx, c.genType(typ)) c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx) c.freeTemp(tmp) diff --git a/tests/vm/tinheritance.nim b/tests/vm/tinheritance.nim index d465e22b9..2c224abcb 100644 --- a/tests/vm/tinheritance.nim +++ b/tests/vm/tinheritance.nim @@ -27,3 +27,54 @@ proc test() = static: test() + +#---------------------------------------------- +# Bugs #9701 and #9702 +type + MyKind = enum + kA, kB, kC + + Base = ref object of RootObj + x: string + + A = ref object of Base + a: string + + B = ref object of Base + b: string + + C = ref object of B + c: string + +template check_templ(n: Base, k: MyKind) = + if k == kA: doAssert(n of A) else: doAssert(not (n of A)) + if k in {kB, kC}: doAssert(n of B) else: doAssert(not (n of B)) + if k == kC: doAssert(n of C) else: doAssert(not (n of C)) + doAssert(n of Base) + +proc check_proc(n: Base, k: MyKind) = + if k == kA: doAssert(n of A) else: doAssert(not (n of A)) + if k in {kB, kC}: doAssert(n of B) else: doAssert(not (n of B)) + if k == kC: doAssert(n of C) else: doAssert(not (n of C)) + doAssert(n of Base) + +static: + let aa = new(A) + check_templ(aa, kA) + check_proc(aa, kA) + let bb = new(B) + check_templ(bb, kB) + check_proc(bb, kB) + let cc = new(C) + check_templ(cc, kC) + check_proc(cc, kC) + +let aa = new(A) +check_templ(aa, kA) +check_proc(aa, kA) +let bb = new(B) +check_templ(bb, kB) +check_proc(bb, kB) +let cc = new(C) +check_templ(cc, kC) +check_proc(cc, kC) |