diff --git a/compiler/seminst.nim b/compiler/seminst.nim index d5afb8389f..b9b1a97be1 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -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 diff --git a/tests/generics/tgenericbodyreturn1.nim b/tests/generics/tgenericbodyreturn1.nim new file mode 100644 index 0000000000..110498f4d9 --- /dev/null +++ b/tests/generics/tgenericbodyreturn1.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "cannot instantiate: 'T'" + file: "system.nim" +""" + +# issue #24091 + +type M[V] = object +echo default(M) diff --git a/tests/generics/tgenericbodyreturn2.nim b/tests/generics/tgenericbodyreturn2.nim new file mode 100644 index 0000000000..8327d6b968 --- /dev/null +++ b/tests/generics/tgenericbodyreturn2.nim @@ -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() # () diff --git a/tests/generics/tgenericbodyreturn3.nim b/tests/generics/tgenericbodyreturn3.nim new file mode 100644 index 0000000000..7fb0767966 --- /dev/null +++ b/tests/generics/tgenericbodyreturn3.nim @@ -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) diff --git a/tests/generics/tuninstantiatedgenericcalls.nim b/tests/generics/tuninstantiatedgenericcalls.nim index f33fc8967c..b21c1f981d 100644 --- a/tests/generics/tuninstantiatedgenericcalls.nim +++ b/tests/generics/tuninstantiatedgenericcalls.nim @@ -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())