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.
This commit is contained in:
LemonBoy 2019-02-08 09:56:32 +01:00 • committed by Andreas Rumpf
commit 631a8ab57f
3 changed files with 32 additions and 13 deletions

View file

@ -165,7 +165,6 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of tySet: of tySet:
if mapSetType(conf, base) == ctArray: result = ctPtrToArray if mapSetType(conf, base) == ctArray: result = ctPtrToArray
else: result = ctPtr else: result = ctPtr
# XXX for some reason this breaks the pegs module
else: result = ctPtr else: result = ctPtr
of tyPointer: result = ctPtr of tyPointer: result = ctPtr
of tySequence: result = ctNimSeq of tySequence: result = ctNimSeq

View file

@ -196,18 +196,23 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
else: else:
c.hashSym(t.sym) c.hashSym(t.sym)
if {sfAnon, sfGenSym} * t.sym.flags != {}: if {sfAnon, sfGenSym} * t.sym.flags != {}:
# generated object names can be identical, so we need to # Generated object names can be identical, so we need to
# disambiguate furthermore by hashing the field types and names: # disambiguate furthermore by hashing the field types and names.
# mild hack to prevent endless recursions (makes nimforum compile again): if t.n.len > 0:
let oldFlags = t.sym.flags let oldFlags = t.sym.flags
t.sym.flags = t.sym.flags - {sfAnon, sfGenSym} # Mild hack to prevent endless recursion.
let n = t.n t.sym.flags = t.sym.flags - {sfAnon, sfGenSym}
for i in 0 ..< n.len: for n in t.n:
assert n[i].kind == nkSym assert(n.kind == nkSym)
let s = n[i].sym let s = n.sym
c.hashSym s c.hashSym s
c.hashType s.typ, flags c.hashType s.typ, flags
t.sym.flags = oldFlags 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: else:
c &= t.id c &= t.id
if t.len > 0 and t.sons[0] != nil: if t.len > 0 and t.sons[0] != nil:

View file

@ -15,3 +15,18 @@ proc foo[T](t: T) =
foo(123) foo(123)
foo("baz") 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)