diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 30ce24500d92..c36dabc99313 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1905,10 +1905,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, # when `f` is an unresolved typedesc, `a` could be any # type, so we should not perform this check earlier if c.c.inGenericContext > 0 and - a.skipTypes({tyTypeDesc}).kind == tyGenericParam: + a.skipTypes({tyTypeDesc}).kind == tyGenericParam and + not (c.calleeSym != nil and c.calleeSym.kind in {skMacro, skTemplate}): # generic type bodies can sometimes compile call expressions # prevent unresolved generic parameters from being passed to procs as # typedesc parameters + # macros and templates receive a pass for practicality result = isNone elif a.kind != tyTypeDesc: if a.kind == tyGenericParam and tfWildcard in a.flags: diff --git a/tests/generics/tmacrotype.nim b/tests/generics/tmacrotype.nim new file mode 100644 index 000000000000..ad42569c03a1 --- /dev/null +++ b/tests/generics/tmacrotype.nim @@ -0,0 +1,28 @@ +import std/[sequtils, macros] + +block: # issue #23432 + type + Future[T] = object + InternalRaisesFuture[T, E] = object + + macro Raising[T](F: typedesc[Future[T]], E: varargs[typedesc]): untyped = + ## Given a Future type instance, return a type storing `{.raises.}` + ## information + ## + ## Note; this type may change in the future + E.expectKind(nnkBracket) + + let raises = nnkTupleConstr.newTree(E.mapIt(it)) + nnkBracketExpr.newTree( + ident "InternalRaisesFuture", + nnkDotExpr.newTree(F, ident"T"), + raises + ) + + type X[E] = Future[void].Raising(E) + + proc f(x: X) = discard + + + var v: Future[void].Raising([ValueError]) + f(v)