From 31ee75f10e6482cd482d329507190ac850eee2cf Mon Sep 17 00:00:00 2001 From: metagn Date: Sat, 20 Jul 2024 01:02:08 -0600 Subject: [PATCH] bypass constraints for tyFromExpr in generic bodies (#23863) fixes #19819, fixes #23339 Since #22029 `tyFromExpr` does not match anything in overloading, so generic bodies can know which call expressions to delay until the type can be evaluated. However generic type invocations also run overloading to check for generic constraints even in generic bodies. To prevent them from failing early from the overload not matching, pretend that `tyFromExpr` matches. This mirrors the behavior of the compiler in more basic cases like: ```nim type Foo[T: int] = object x: T Bar[T] = object y: Foo[T] ``` Unfortunately this case doesn't respect the constraint (#21181, some other bugs) but `tyFromExpr` should easily use the same principle when it does. --- compiler/sigmatch.nim | 13 +++++++++---- tests/generics/tuninstantiatedgenericcalls.nim | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 18170ecfcc..7a12b957ba 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1196,10 +1196,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, return isGeneric of tyFromExpr: if c.c.inGenericContext > 0: - # generic type bodies can sometimes compile call expressions - # prevent expressions with unresolved types from - # being passed as parameters - return isNone + if not c.isNoCall: + # generic type bodies can sometimes compile call expressions + # prevent expressions with unresolved types from + # being passed as parameters + return isNone + else: + # Foo[templateCall(T)] shouldn't fail early if Foo has a constraint + # and we can't evaluate `templateCall(T)` yet + return isGeneric else: discard case f.kind diff --git a/tests/generics/tuninstantiatedgenericcalls.nim b/tests/generics/tuninstantiatedgenericcalls.nim index 63ba3908f5..2163789e7b 100644 --- a/tests/generics/tuninstantiatedgenericcalls.nim +++ b/tests/generics/tuninstantiatedgenericcalls.nim @@ -145,3 +145,21 @@ block: # issue #23730 proc test(M: static[int]): array[1 shl M, int] = discard doAssert len(test(3)) == 8 doAssert len(test(5)) == 32 + +block: # issue #19819 + type + Example[N: static int] = distinct int + What[E: Example] = Example[E.N + E.N] + +block: # issue #23339 + type + A = object + B = object + template aToB(t: typedesc[A]): typedesc = B + type + Inner[I] = object + innerField: I + Outer[O] = object + outerField: Inner[O.aToB] + var x: Outer[A] + doAssert typeof(x.outerField.innerField) is B