Skip to content

Commit 9e14f5f

Browse files
Merge pull request #14242 from dotty-staging/fix-tuple-member-selection
Adapt generic tuples to be able to access members
2 parents 7939ddb + 584c05b commit 9e14f5f

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3854,6 +3854,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38543854
gadts.println(i"Member selection healed by GADT approximation")
38553855
tree.cast(gadtApprox)
38563856
else tree
3857+
else if tree.tpe.derivesFrom(defn.PairClass) && !defn.isTupleNType(tree.tpe.widenDealias) then
3858+
// If this is a generic tuple we need to cast it to make the TupleN/ members accessible.
3859+
// This only works for generic tuples of know size up to 22.
3860+
defn.tupleTypes(tree.tpe.widenTermRefExpr, Definitions.MaxTupleArity) match
3861+
case Some(elems) => tree.cast(defn.tupleType(elems))
3862+
case None => tree
38573863
else tree // other adaptations for selections are handled in typedSelect
38583864
case _ if ctx.mode.is(Mode.ImplicitsEnabled) && tree.tpe.isValueType =>
38593865
checkConversionsSpecific(pt, tree.srcPos)

tests/neg/genericTupleMembers.scala

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
def Test: Unit =
2+
val tup1 = 1 *: EmptyTuple
3+
val tup2 = 1 *: 2 *: EmptyTuple
4+
val tup3 = 1 *: 2 *: 3 *: EmptyTuple
5+
val tup4 = 1 *: 2 *: 3 *: 4 *: EmptyTuple
6+
val tup5 = 1 *: 2 *: 3 *: 4 *: 5 *: EmptyTuple
7+
val tup22 = 1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: EmptyTuple
8+
val tup23 = 1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: 23 *: EmptyTuple
9+
10+
tup1._2 // error
11+
12+
tup2._3 // error
13+
14+
tup22._23 // error
15+
16+
tup23._1 // error
17+
tup23._2 // error
18+
tup23._3 // error
19+
tup23._4 // error
20+
tup23._5 // error
21+
tup23._6 // error
22+
tup23._7 // error
23+
tup23._8 // error
24+
tup23._9 // error
25+
tup23._10 // error
26+
tup23._11 // error
27+
tup23._12 // error
28+
tup23._13 // error
29+
tup23._14 // error
30+
tup23._15 // error
31+
tup23._16 // error
32+
tup23._17 // error
33+
tup23._18 // error
34+
tup23._19 // error
35+
tup23._20 // error
36+
tup23._21 // error
37+
tup23._22 // error
38+
tup23._23 // error

tests/run/genericTupleMembers.scala

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
@main def Test: Unit =
3+
val tup1 = 1 *: EmptyTuple
4+
val tup2 = 1 *: 2 *: EmptyTuple
5+
val tup3 = 1 *: 2 *: 3 *: EmptyTuple
6+
val tup4 = 1 *: 2 *: 3 *: 4 *: EmptyTuple
7+
val tup5 = 1 *: 2 *: 3 *: 4 *: 5 *: EmptyTuple
8+
val tup22 = 1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: EmptyTuple
9+
10+
tup1._1
11+
12+
tup2._1
13+
tup2._2
14+
tup2.swap
15+
16+
tup3._1
17+
tup3._2
18+
tup3._3
19+
20+
tup4._1
21+
tup4._2
22+
tup4._3
23+
tup4._4
24+
25+
tup22._1
26+
tup22._2
27+
tup22._3
28+
tup22._4
29+
tup22._5
30+
tup22._6
31+
tup22._7
32+
tup22._8
33+
tup22._9
34+
tup22._10
35+
tup22._11
36+
tup22._12
37+
tup22._13
38+
tup22._14
39+
tup22._15
40+
tup22._16
41+
tup22._17
42+
tup22._18
43+
tup22._19
44+
tup22._20
45+
tup22._21
46+
tup22._22

tests/run/i14215.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
def f[T <: Tuple2[Int, Int]](tup: T): T = tup
2+
3+
@main def Test: Unit =
4+
(1, 2)._1
5+
f((1, 2))._1
6+
7+
(1 *: 2 *: EmptyTuple)._1
8+
f(1 *: 2 *: EmptyTuple)._1
9+
f[Int *: Int *: EmptyTuple](1 *: 2 *: EmptyTuple)._1
10+
11+
f[Int *: Int *: EmptyTuple]((1, 2))._1
12+
f[Tuple2[Int, Int]](1 *: 2 *: EmptyTuple)._1

0 commit comments

Comments
 (0)