diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index bf9c2d2050..994a2a6bc2 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1754,6 +1754,19 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, considerPreviousT: if a == f or a.kind == tyGenericInst and a.skipGenericAlias[0] == f: bindingRet isGeneric + var depth = -1 + # Generic constraints like `F: Future` reach sigmatch as a `tyGenericBody`. + # Accept descendants of the generic family here as well, not just direct + # `Future[...]` instantiations. + if isGenericSubtype(c, a, f, depth, f): + if 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) + bindingRet(if depth == 0: isGeneric else: isSubtype) let ff = last(f) if ff != nil: result = typeRel(c, ff, a, flags) diff --git a/tests/typerel/t8905.nim b/tests/typerel/t8905.nim index 9383962cf6..01ade68d0a 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)