From 3aeaa90bd828975a8accfb271ad02cf22639a250 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 8 Feb 2019 09:56:32 +0100 Subject: [PATCH] Fix edge case in type hashing (#10601) [backport] Empty types introduced by a template produced the same hash of the "clean" type sharing the same name. (cherry picked from commit 631a8ab57f6935d34d290089b7cc36d23dc03504) --- compiler/ccgtypes.nim | 1 - compiler/sighashes.nim | 29 +++++++++++-------- .../ccgbugs/tsighash_typename_regression.nim | 15 ++++++++++ 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 8b2cd6b282..ec59c703b7 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -165,7 +165,6 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind = of tySet: if mapSetType(conf, base) == ctArray: result = ctPtrToArray else: result = ctPtr - # XXX for some reason this breaks the pegs module else: result = ctPtr of tyPointer: result = ctPtr of tySequence: result = ctNimSeq diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim index 218011b1d6..3096d94a0c 100644 --- a/compiler/sighashes.nim +++ b/compiler/sighashes.nim @@ -196,18 +196,23 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) = else: c.hashSym(t.sym) if {sfAnon, sfGenSym} * t.sym.flags != {}: - # generated object names can be identical, so we need to - # disambiguate furthermore by hashing the field types and names: - # mild hack to prevent endless recursions (makes nimforum compile again): - let oldFlags = t.sym.flags - t.sym.flags = t.sym.flags - {sfAnon, sfGenSym} - let n = t.n - for i in 0 ..< n.len: - assert n[i].kind == nkSym - let s = n[i].sym - c.hashSym s - c.hashType s.typ, flags - t.sym.flags = oldFlags + # Generated object names can be identical, so we need to + # disambiguate furthermore by hashing the field types and names. + if t.n.len > 0: + let oldFlags = t.sym.flags + # Mild hack to prevent endless recursion. + t.sym.flags = t.sym.flags - {sfAnon, sfGenSym} + for n in t.n: + assert(n.kind == nkSym) + let s = n.sym + c.hashSym s + c.hashType s.typ, flags + t.sym.flags = oldFlags + else: + # The object has no fields: we _must_ add something here in order to + # make the hash different from the one we produce by hashing only the + # type name. + c &= ".empty" else: c &= t.id if t.len > 0 and t.sons[0] != nil: diff --git a/tests/ccgbugs/tsighash_typename_regression.nim b/tests/ccgbugs/tsighash_typename_regression.nim index 7122902d98..457902b767 100644 --- a/tests/ccgbugs/tsighash_typename_regression.nim +++ b/tests/ccgbugs/tsighash_typename_regression.nim @@ -8,3 +8,18 @@ proc foo[T](t: T) = foo(123) foo("baz") + +# Empty type in template is correctly disambiguated +block: + template foo() = + type M = object + discard + var y = M() + + foo() + + type M = object + x: int + + var x = M(x: 1) + doAssert(x.x == 1)