Skip to content

Commit

Permalink
bypass constraints for tyFromExpr in generic bodies (#23863)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
metagn authored Jul 20, 2024
1 parent 2f5cfd6 commit 31ee75f
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
13 changes: 9 additions & 4 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions tests/generics/tuninstantiatedgenericcalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 31ee75f

Please sign in to comment.