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.
This commit is contained in:
metagn
2025-04-22 18:24:22 +03:00
committed by GitHub
parent dc100c5caa
commit d966ee3fc3
2 changed files with 28 additions and 6 deletions

View File

@@ -38,21 +38,27 @@ const
errNoGenericParamsAllowedForX = "no generic parameters allowed for $1"
errInOutFlagNotExtern = "the '$1' modifier can be used only with imported types"
proc reusePrev(prev: PType): bool {.inline.} =
# only overwrite `prev` if it is a forward type, partial object or magic type
result = prev != nil and (prev.kind == tyForward or (prev.sym != nil and
# partial object marks sym as `sfForward`
(sfForward in prev.sym.flags or prev.sym.magic != mNone)))
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext, son: sink PType): PType =
if prev == nil or prev.kind == tyGenericBody:
result = newTypeS(kind, c, son)
else:
if reusePrev(prev):
result = prev
result.setSon(son)
if result.kind == tyForward: result.kind = kind
else:
result = newTypeS(kind, c, son)
#if kind == tyError: result.flags.incl tfCheckedForDestructor
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
if prev == nil or prev.kind == tyGenericBody:
result = newTypeS(kind, c)
else:
if reusePrev(prev):
result = prev
if result.kind == tyForward: result.kind = kind
else:
result = newTypeS(kind, c)
proc newConstraint(c: PContext, k: TTypeKind): PType =
result = newTypeS(tyBuiltInTypeClass, c)

View File

@@ -41,6 +41,16 @@ foo:
discard Bar[int](x: 123)
discard Bar[string](x: "abc")
type
Generic1[T] = object
Generic2[T] = ref int
Generic3[T] = ref Generic1[T]
Generic4[T] = Generic2[T]
GenericInst1 = Generic1[int]
GenericInst2 = Generic2[int]
GenericInst3 = Generic3[int]
GenericInst4 = Generic4[int]
# regression test:
template templ(): untyped =
proc injected() {.inject.} = discard
@@ -49,7 +59,13 @@ foo:
type TestInject = templ()
var x1: TestInject
injected() # normally works
echo $NONE
echo a
var x2: TestInject
injected()
block: # issue #24898
type V[W] = object
template g(d: int) = discard d
g((; type J = V[int]; 0))