don't allow instantiations resolving to generic body types (#24273)

fixes #24091, refs #24092

Any instantiations resolving to a generic body type now gives an error.
Due to #24092, this does not error in cases like matching against `type
M` in generics because generic body type symbols are just not
instantiated. But this prevents parameters with type `type M` from being
used, although there doesn't seem to be any code which does this. Just
in case such code exists, we still allow `typedesc` types resolving to
generic body types.

(cherry picked from commit 2f904535d0)
This commit is contained in:
metagn
2024-10-10 16:35:51 +03:00
committed by narimiran
parent 1f418de2cc
commit d102571d78
5 changed files with 43 additions and 8 deletions

View File

@@ -53,7 +53,9 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: LayeredIdTable):
if q.typ.kind != tyCompositeTypeClass:
localError(c.config, a.info, errCannotInstantiateX % s.name.s)
t = errorType(c)
elif t.kind in {tyGenericParam, tyConcept, tyFromExpr}:
elif t.kind in {tyGenericParam, tyConcept, tyFromExpr} or
# generic body types are accepted as typedesc arguments
(t.kind == tyGenericBody and q.typ.kind != tyTypeDesc):
localError(c.config, a.info, errCannotInstantiateX % q.name.s)
t = errorType(c)
elif isUnresolvedStatic(t) and (q.typ.kind == tyStatic or

View File

@@ -0,0 +1,9 @@
discard """
errormsg: "cannot instantiate: 'T'"
file: "system.nim"
"""
# issue #24091
type M[V] = object
echo default(M)

View File

@@ -0,0 +1,11 @@
discard """
errormsg: "cannot instantiate: 'T'"
file: "system.nim"
"""
# issue #24091
type M[V] = object
type Foo = object # notice not generic
x: typeof(default(M))
echo Foo() # ()

View File

@@ -0,0 +1,13 @@
discard """
errormsg: "cannot instantiate: 'ShouldNotResolve'"
"""
# issue #24091
type Generic[U] = object
proc foo[ShouldNotResolve](x: typedesc[ShouldNotResolve]): ShouldNotResolve =
echo ShouldNotResolve # Generic
echo declared(result) # true
echo typeof(result) # Generic
echo typeof(foo(Generic)) # void
foo(Generic)

View File

@@ -421,17 +421,17 @@ block: # issue #24090
doAssert a.x is M[int]
var b: Foo[float]
doAssert b.x is M[float]
# related to #24091:
doAssert not (compiles do:
type Bar[T] = object
x: typeof(M()) # actually fails here immediately
var bar: Bar[int])
# ideally fails here immediately since the inside of `typeof` does not
# depend on an unresolved parameter
# but if typechecking gets too lazy, then we need to instantiate to error
x: typeof(M()))
doAssert not (compiles do:
type Bar[T] = object
x: typeof(default(M))
var bar: Bar[int]
# gives "undeclared identifier x" because of #24091,
# normally it should fail in the line above
echo bar.x)
# again, ideally fails here immediately
x: typeof(default(M)))
proc foo[T: M](x: T = default(T)) = discard x
foo[M[int]]()
doAssert not compiles(foo())