Skip to content

Commit d966ee3

Browse files
authored
whitelist prev types to reuse in newOrPrevType (#24899)
fixes #24898 A type is only overwritten if it is definitely a forward type, partial object (symbol marked `sfForward`) or a magic type. Maybe worse for performance but should be more correct. Another option might be to provide a different value for `prev` for the `preserveSym` case but then we cannot easily ignore only nominal type nodes.
1 parent dc100c5 commit d966ee3

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

compiler/semtypes.nim

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,27 @@ const
3838
errNoGenericParamsAllowedForX = "no generic parameters allowed for $1"
3939
errInOutFlagNotExtern = "the '$1' modifier can be used only with imported types"
4040

41+
proc reusePrev(prev: PType): bool {.inline.} =
42+
# only overwrite `prev` if it is a forward type, partial object or magic type
43+
result = prev != nil and (prev.kind == tyForward or (prev.sym != nil and
44+
# partial object marks sym as `sfForward`
45+
(sfForward in prev.sym.flags or prev.sym.magic != mNone)))
46+
4147
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext, son: sink PType): PType =
42-
if prev == nil or prev.kind == tyGenericBody:
43-
result = newTypeS(kind, c, son)
44-
else:
48+
if reusePrev(prev):
4549
result = prev
4650
result.setSon(son)
4751
if result.kind == tyForward: result.kind = kind
52+
else:
53+
result = newTypeS(kind, c, son)
4854
#if kind == tyError: result.flags.incl tfCheckedForDestructor
4955

5056
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
51-
if prev == nil or prev.kind == tyGenericBody:
52-
result = newTypeS(kind, c)
53-
else:
57+
if reusePrev(prev):
5458
result = prev
5559
if result.kind == tyForward: result.kind = kind
60+
else:
61+
result = newTypeS(kind, c)
5662

5763
proc newConstraint(c: PContext, k: TTypeKind): PType =
5864
result = newTypeS(tyBuiltInTypeClass, c)

tests/types/tresemtypesection.nim

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ foo:
4141
discard Bar[int](x: 123)
4242
discard Bar[string](x: "abc")
4343

44+
type
45+
Generic1[T] = object
46+
Generic2[T] = ref int
47+
Generic3[T] = ref Generic1[T]
48+
Generic4[T] = Generic2[T]
49+
GenericInst1 = Generic1[int]
50+
GenericInst2 = Generic2[int]
51+
GenericInst3 = Generic3[int]
52+
GenericInst4 = Generic4[int]
53+
4454
# regression test:
4555
template templ(): untyped =
4656
proc injected() {.inject.} = discard
@@ -49,7 +59,13 @@ foo:
4959
type TestInject = templ()
5060
var x1: TestInject
5161
injected() # normally works
62+
5263
echo $NONE
5364
echo a
5465
var x2: TestInject
5566
injected()
67+
68+
block: # issue #24898
69+
type V[W] = object
70+
template g(d: int) = discard d
71+
g((; type J = V[int]; 0))

0 commit comments

Comments
 (0)