diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 9ebc930079..a0ea8baac7 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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) diff --git a/tests/types/tresemtypesection.nim b/tests/types/tresemtypesection.nim index ac6c8610ca..255e6c8637 100644 --- a/tests/types/tresemtypesection.nim +++ b/tests/types/tresemtypesection.nim @@ -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))