mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-10 15:04:59 +00:00
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:
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user