type with same name in different scope now works (#17710)

* type with same name in different scope now works
* fix tests/enum/tenum.nim which was wrong because it was affected by this bug
This commit is contained in:
Timothee Cour
2021-04-13 23:50:15 -07:00
committed by GitHub
parent fe77c3c72f
commit 840e13deb7
4 changed files with 133 additions and 9 deletions

View File

@@ -1354,8 +1354,11 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
checkConstructedType(c.config, s.info, s.typ)
if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
checkForMetaFields(c, s.typ.n)
# fix bug #5170: ensure locally scoped object types get a unique name:
if s.typ.kind == tyObject and not isTopLevel(c): incl(s.flags, sfGenSym)
# fix bug #5170, bug #17162, bug #15526: ensure locally scoped types get a unique name:
if s.typ.kind in {tyEnum, tyRef, tyObject} and not isTopLevel(c):
incl(s.flags, sfGenSym)
#instAllTypeBoundOp(c, n.info)

View File

@@ -151,15 +151,24 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
c.hashTypeSym(t.sym)
else:
c.hashSym(t.sym)
if {sfAnon, sfGenSym} * t.sym.flags != {}:
var symWithFlags: PSym
template hasFlag(sym): bool =
let ret = {sfAnon, sfGenSym} * sym.flags != {}
if ret: symWithFlags = sym
ret
if hasFlag(t.sym) or (t.kind == tyObject and t.owner.kind == skType and t.owner.typ.kind == tyRef and hasFlag(t.owner)):
# for `PFoo:ObjectType`, arising from `type PFoo = ref object`
# 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.excl {sfAnon, sfGenSym}
let oldFlags = symWithFlags.flags
# Hack to prevent endless recursion
# xxx intead, use a hash table to indicate we've already visited a type, which
# would also be more efficient.
symWithFlags.flags.excl {sfAnon, sfGenSym}
hashTree(c, t.n, flags + {CoHashTypeInsideNode})
t.sym.flags = oldFlags
symWithFlags.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

View File

@@ -0,0 +1,111 @@
block: # bug #15526
block:
type Foo = ref object
x1: int
let f1 = Foo(x1: 1)
block:
type Foo = ref object
x2: int
let f2 = Foo(x2: 2)
block: # ditto
template fn() =
block:
type Foo = ref object
x1: int
let f1 = Foo(x1: 1)
doAssert f1.x1 == 1
block:
type Foo = ref object
x2: int
let f2 = Foo(x2: 2)
doAssert f2.x2 == 2
static: fn()
fn()
block: # bug #17162
template fn =
var ret: string
block:
type A = enum a0, a1, a2
for ai in A:
ret.add $ai
block:
type A = enum b0, b1, b2, b3
for ai in A:
ret.add $ai
doAssert ret == "a0a1a2b0b1b2b3"
static: fn() # ok
fn() # was bug
block: # ditto
proc fn =
var ret: string
block:
type A = enum a0, a1, a2
for ai in A:
ret.add $ai
block:
type A = enum b0, b1, b2, b3
for ai in A:
ret.add $ai
doAssert ret == "a0a1a2b0b1b2b3"
static: fn() # ok
fn() # was bug
block: # bug #5170
block:
type Foo = object
x1: int
let f1 = Foo(x1: 1)
block:
type Foo = object
x2: int
let f2 = Foo(x2: 2)
block: # ditto
block:
type Foo = object
bar: bool
var f1: Foo
block:
type Foo = object
baz: int
var f2: Foo
doAssert f2.baz == 0
block:
template fn() =
block:
type Foo = object
x1: int
let f1 = Foo(x1: 1)
doAssert f1.x1 == 1
block:
type Foo = object
x2: int
let f2 = Foo(x2: 2)
doAssert f2.x2 == 2
static: fn()
fn()
when true: # ditto, refs https://github.com/nim-lang/Nim/issues/5170#issuecomment-582712132
type Foo1 = object # at top level
bar: bool
var f1: Foo1
block:
type Foo1 = object
baz: int
var f2: Foo1
doAssert f2.baz == 0
block: # make sure `hashType` doesn't recurse infinitely
type
PFoo = ref object
a, b: PFoo
c: int
var a: PFoo

View File

@@ -6,7 +6,7 @@ ABCDC
foo
first0second32third64
my value A1my value Bconc2valueCabc4abc
my value A0my value Bconc1valueCabc3valueC
my value A0my value Bconc1valueCabc3abc
'''
"""
@@ -124,7 +124,8 @@ block tnamedfields:
# trick the optimizer with a variable:
var x = valueD
echo valueA, ord(valueA), valueB, ord(valueB), valueC, valueD, ord(valueD), x
doAssert $x == $valueD, $x
doAssert $x == "abc", $x
block toptions: