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:
parent
fe77c3c72f
commit
840e13deb7
4 changed files with 133 additions and 9 deletions
|
|
@ -1354,8 +1354,11 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
|
||||||
checkConstructedType(c.config, s.info, s.typ)
|
checkConstructedType(c.config, s.info, s.typ)
|
||||||
if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
|
if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
|
||||||
checkForMetaFields(c, s.typ.n)
|
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)
|
#instAllTypeBoundOp(c, n.info)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,15 +151,24 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||||
c.hashTypeSym(t.sym)
|
c.hashTypeSym(t.sym)
|
||||||
else:
|
else:
|
||||||
c.hashSym(t.sym)
|
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
|
# 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.
|
||||||
if t.n.len > 0:
|
if t.n.len > 0:
|
||||||
let oldFlags = t.sym.flags
|
let oldFlags = symWithFlags.flags
|
||||||
# Mild hack to prevent endless recursion.
|
# Hack to prevent endless recursion
|
||||||
t.sym.flags.excl {sfAnon, sfGenSym}
|
# 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})
|
hashTree(c, t.n, flags + {CoHashTypeInsideNode})
|
||||||
t.sym.flags = oldFlags
|
symWithFlags.flags = oldFlags
|
||||||
else:
|
else:
|
||||||
# The object has no fields: we _must_ add something here in order to
|
# 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
|
# make the hash different from the one we produce by hashing only the
|
||||||
|
|
|
||||||
111
tests/ccgbugs/tsamename3.nim
Normal file
111
tests/ccgbugs/tsamename3.nim
Normal 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
|
||||||
|
|
@ -6,7 +6,7 @@ ABCDC
|
||||||
foo
|
foo
|
||||||
first0second32third64
|
first0second32third64
|
||||||
my value A1my value Bconc2valueCabc4abc
|
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:
|
# trick the optimizer with a variable:
|
||||||
var x = valueD
|
var x = valueD
|
||||||
echo valueA, ord(valueA), valueB, ord(valueB), valueC, valueD, ord(valueD), x
|
echo valueA, ord(valueA), valueB, ord(valueB), valueC, valueD, ord(valueD), x
|
||||||
|
doAssert $x == $valueD, $x
|
||||||
|
doAssert $x == "abc", $x
|
||||||
|
|
||||||
|
|
||||||
block toptions:
|
block toptions:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue