From 79ddb7d89e4320b448c35b5936ce150706bbf210 Mon Sep 17 00:00:00 2001 From: Ryan McConnell Date: Sat, 15 Nov 2025 06:52:16 -0500 Subject: [PATCH] concept patch for `tyGenericInvocation` (#25288) matching between some generic invocations and equivalent instantiations did not have a code path --- compiler/concepts.nim | 10 ++++++++- tests/concepts/tconceptsv2.nim | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/compiler/concepts.nim b/compiler/concepts.nim index b808c6608b..7e547b19ce 100644 --- a/compiler/concepts.nim +++ b/compiler/concepts.nim @@ -137,7 +137,7 @@ proc bindParam(c: PContext, m: var MatchCon; key, v: PType): bool {. discardable # check previously bound value if not matchType(c, old, value, m): return false - elif key.hasElementType and key.elementType.kind != tyNone: + elif key.hasElementType and not key.elementType.isNil and key.elementType.kind != tyNone: # check constaint if matchType(c, unrollGenericParam(key), value, m) == false: return false @@ -358,6 +358,14 @@ proc matchType(c: PContext; fo, ao: PType; m: var MatchCon): bool = if not matchType(c, f[i], ea[i], m): result = false break + elif f.kind == tyGenericInvocation: + # bind potential generic constraints into body + let body = f.base + for i in 1 ..< len(f): + bindParam(c,m,body[i-1], f[i]) + result = matchType(c, body, a, m) + else: # tyGenericInst + result = matchType(c, f.last, a, m) of tyOrdinal: result = isOrdinalType(a, allowEnumWithHoles = false) or a.kind == tyGenericParam of tyStatic: diff --git a/tests/concepts/tconceptsv2.nim b/tests/concepts/tconceptsv2.nim index c735aeeacc..629ac1c876 100644 --- a/tests/concepts/tconceptsv2.nim +++ b/tests/concepts/tconceptsv2.nim @@ -546,3 +546,42 @@ proc len[T](t: DummyIndexable[T]): int = let dummyIndexable = DummyIndexable(@[1, 2]) echoAll(dummyIndexable) + +block: + type + C = concept + proc a(x: Self, i: int) + AObj[T] = object + x: T + ARef[T] = ref AObj[T] + + proc a[T: int](x: ARef[T], i: int) = + discard + + assert (ref AObj[int]) is C + +block: + type + C = concept + proc a(x: Self, i: int) + AObj[T; B] = object + x: T + ARef[T; B] = ref AObj[T,B] + + proc a[T: int, C: float](x: ARef[T, C], i: int) = + discard + + assert (ref AObj[int, int]) isnot C + assert (ref AObj[int, float]) is C + +block: + type + C = concept + proc a(x: Self, i: int) + AObj[T] = object + ARef[T] = ref AObj[T] + + proc a(x: ARef, i: int) = + discard + + assert (ref AObj[int]) is C