diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index bf9c2d20503ae..496e52ad7bb30 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1757,6 +1757,21 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, let ff = last(f) if ff != nil: result = typeRel(c, ff, a, flags) + if result == isNone and a.kind == tyGenericInst and trBindGenericParam in flags: + var depth = -1 + # Generic-parameter constraints like `F: Future` can miss in `last(f)` + # when the actual type inherits from a concrete generic instantiation. + # Keep this fallback scoped to generic-parameter matching so typedesc + # overloads such as `type Future[T]` still prefer more specific + # descendants like `InternalRaisesFuture[T, E]`. + if isGenericSubtype(c, a, f, depth, f) and depth > 0: + var askip = skippedNone + let aobj = a.skipToObject(askip) + if aobj != nil and tfFinal notin aobj.flags: + # Keep overload ranking consistent with other inheritance-based + # matches: deeper descendants are slightly worse candidates. + inc c.inheritancePenalty, depth + int(c.inheritancePenalty < 0) + result = isGeneric of tyGenericInvocation: var x = a.skipGenericAlias if x.kind == tyGenericParam and x.len > 0: diff --git a/tests/typerel/t8905.nim b/tests/typerel/t8905.nim index 9383962cf660e..01ade68d0a691 100644 --- a/tests/typerel/t8905.nim +++ b/tests/typerel/t8905.nim @@ -5,3 +5,31 @@ type proc newFoo[T](): Foo[T] = Foo[T](newSeq[T]()) var x = newFoo[Bar[int]]() + +# issue #22936 + +import std/macros + +type + InternalFutureBase = object of RootObj + + FutureBase = ref object of InternalFutureBase + + Future[T] = ref object of FutureBase + internalValue: T + + B[T, E] = ref object of Future[T] + +proc take[F: Future](fut: F) = discard + +proc takeMany[F: Future](futs: seq[F]) = discard + +macro checkFutures[F: Future](futs: seq[F]): untyped = + newEmptyNode() + +var future: B[void, void] +var futures: seq[B[void, void]] + +take(future) +takeMany(futures) +checkFutures(futures)