Skip to content

Commit c8556ef

Browse files
metagnnarimiran
authored andcommitted
consider generic param type as typedesc in tuple type expressions (#25316)
fixes #25312 Tuple expressions `(a, b, c)` can be either types or values depending on if their elements are typedescs or values, this is checked by checking if the type of the element is `tyTypeDesc`. However when an `skGenericParam` symbol is semchecked by `semSym` it is given its own `tyGenericParam` type rather than a `tyTypeDesc` type, this seems to be necessary for signatures to allow wildcard generic params passed to static constrained generic params (tested in #25315). The reason `semSym` is called is that `semGeneric` for generic invocations calls `matches` which sems its arguments like normal expressions. To deal with this, an expression of type `tyGenericParam` and with a `skGenericParam` sym is allowed as a type in the tuple expression. A problem is that this might consider a value with a wildcard generic param type as a type. But this is a very niche problem, and I'm not sure how to check for this. `skGenericParam` symbols stay as idents when semchecked so it can't be checked that the node is an `skGenericParam` symbol. It could be checked that it's an ident but I don't know how robust this is. And maybe there is another way to refer to a wildcard generic param type instead of just its symbol, i.e. another kind of node. This also makes #5647 finally work but a test case for that can be added after. (cherry picked from commit 44d2472)
1 parent 6c8ab9f commit c8556ef

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

compiler/semexprs.nim

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,13 @@ proc semExport(c: PContext, n: PNode): PNode =
30533053

30543054
s = nextOverloadIter(o, c, a)
30553055

3056+
proc isTypeTupleField(n: PNode): bool {.inline.} =
3057+
result = n.typ.kind == tyTypeDesc or
3058+
(n.typ.kind == tyGenericParam and n.typ.sym.kind == skGenericParam)
3059+
# `skGenericParam` stays as `tyGenericParam` type rather than being wrapped in `tyTypeDesc`
3060+
# would check if `n` itself is an `skGenericParam` symbol, but these symbols semcheck to an ident
3061+
# maybe check if `n` is an ident to ensure this is not a value with the generic param type?
3062+
30563063
proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
30573064
result = semTuplePositionsConstr(c, n, flags, expectedType)
30583065
if result.typ.kind == tyFromExpr:
@@ -3063,10 +3070,10 @@ proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp
30633070
var isTupleType: bool = false
30643071
if tupexp.len > 0: # don't interpret () as type
30653072
internalAssert c.config, tupexp.kind == nkTupleConstr
3066-
isTupleType = tupexp[0].typ.kind == tyTypeDesc
3073+
isTupleType = isTypeTupleField(tupexp[0])
30673074
# check if either everything or nothing is tyTypeDesc
30683075
for i in 1..<tupexp.len:
3069-
if isTupleType != (tupexp[i].typ.kind == tyTypeDesc):
3076+
if isTupleType != isTypeTupleField(tupexp[i]):
30703077
return localErrorNode(c, n, tupexp[i].info, "Mixing types and values in tuples is not allowed.")
30713078
if isTupleType: # expressions as ``(int, string)`` are reinterpret as type expressions
30723079
result = n
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# issue #25312
2+
3+
import heapqueue
4+
5+
proc test1[T](test: (float, T)) = # Works
6+
discard
7+
8+
proc test2[T](test: seq[(float, T)]) = # Works
9+
discard
10+
11+
proc test3[T](test: HeapQueue[tuple[sqd: float, data: T]]) = # Works
12+
discard
13+
14+
proc test4(test: HeapQueue[(float, float)]) = # Works
15+
discard
16+
17+
type ExampleObj = object
18+
a: string
19+
b: seq[float]
20+
21+
proc test5(test: HeapQueue[(float, ExampleObj)]) = # Works
22+
discard
23+
24+
proc failingTest[T](test: HeapQueue[(float, T)]) = # (Compile) Error: Mixing types and values in tuples is not allowed.
25+
discard
26+
27+
proc failingTest2[T](test: HeapQueue[(T, float)]) = # (Compile) Error: Mixing types and values in tuples is not allowed.
28+
discard
29+
30+
proc test6[T](test: HeapQueue[(T, T)]) = # works
31+
discard
32+
33+
proc test7[T, U](test: HeapQueue[(T, U)]) = # works
34+
discard

0 commit comments

Comments
 (0)