From 2701a2d3390ff344c8d34c17aa86dfa8a18662a1 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 19 Oct 2023 10:56:45 +0200 Subject: [PATCH 1/2] Properly dealias tuple types when specializing Fixes #18638 --- .../dotc/transform/SpecializeTuples.scala | 8 ++++---- tests/run/i18638.scala | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 tests/run/i18638.scala diff --git a/compiler/src/dotty/tools/dotc/transform/SpecializeTuples.scala b/compiler/src/dotty/tools/dotc/transform/SpecializeTuples.scala index 5237ecbcef8a..1013a6f88ab2 100644 --- a/compiler/src/dotty/tools/dotc/transform/SpecializeTuples.scala +++ b/compiler/src/dotty/tools/dotc/transform/SpecializeTuples.scala @@ -37,10 +37,10 @@ class SpecializeTuples extends MiniPhase: end transformApply override def transformSelect(tree: Select)(using Context): Tree = tree match - case Select(qual, nme._1) if isAppliedSpecializableTuple(qual.tpe.widen) => - Select(qual, nme._1.specializedName(qual.tpe.widen.argInfos.slice(0, 1))) - case Select(qual, nme._2) if isAppliedSpecializableTuple(qual.tpe.widen) => - Select(qual, nme._2.specializedName(qual.tpe.widen.argInfos.slice(1, 2))) + case Select(qual, nme._1) if isAppliedSpecializableTuple(qual.tpe.widenDealias) => + Select(qual, nme._1.specializedName(qual.tpe.widenDealias.argInfos.slice(0, 1))) + case Select(qual, nme._2) if isAppliedSpecializableTuple(qual.tpe.widenDealias) => + Select(qual, nme._2.specializedName(qual.tpe.widenDealias.argInfos.slice(1, 2))) case _ => tree private def isAppliedSpecializableTuple(tp: Type)(using Context) = tp match diff --git a/tests/run/i18638.scala b/tests/run/i18638.scala new file mode 100644 index 000000000000..87877b5ba4e7 --- /dev/null +++ b/tests/run/i18638.scala @@ -0,0 +1,18 @@ +type U[H, T] = (Unit, Unit) +object O: + opaque type U[H, T] <: (Unit, Unit) = (Unit, Unit) + def u: U[Int, Int] = ((), ()) + + +def test1(u: (Unit, Unit)) = u._1 +def test2(u: U[Int, Int]) = u._1 +def test3(u: O.U[Int, Int]) = u._1 +def test4() = + (((), ()): U[Int, Int]) match + case ((), ()) => println("ok") + +@main def Test: Unit = + test1(((), ())) + test2(((), ())) + test3(O.u) + test4() From 22b273f0d4feb01bfee4d0764e427aa348f4a6a4 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 19 Oct 2023 11:10:03 +0200 Subject: [PATCH 2/2] Optimize `SpecializeTuples.transformSelect` --- .../tools/dotc/transform/SpecializeTuples.scala | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/SpecializeTuples.scala b/compiler/src/dotty/tools/dotc/transform/SpecializeTuples.scala index 1013a6f88ab2..264659930505 100644 --- a/compiler/src/dotty/tools/dotc/transform/SpecializeTuples.scala +++ b/compiler/src/dotty/tools/dotc/transform/SpecializeTuples.scala @@ -37,15 +37,14 @@ class SpecializeTuples extends MiniPhase: end transformApply override def transformSelect(tree: Select)(using Context): Tree = tree match - case Select(qual, nme._1) if isAppliedSpecializableTuple(qual.tpe.widenDealias) => - Select(qual, nme._1.specializedName(qual.tpe.widenDealias.argInfos.slice(0, 1))) - case Select(qual, nme._2) if isAppliedSpecializableTuple(qual.tpe.widenDealias) => - Select(qual, nme._2.specializedName(qual.tpe.widenDealias.argInfos.slice(1, 2))) + case Select(qual, name @ (nme._1 | nme._2)) => + qual.tpe.widenDealias match + case AppliedType(tycon, args) if defn.isSpecializableTuple(tycon.classSymbol, args) => + val argIdx = if name == nme._1 then 0 else 1 + Select(qual, name.specializedName(args(argIdx) :: Nil)) + case _ => + tree case _ => tree - - private def isAppliedSpecializableTuple(tp: Type)(using Context) = tp match - case AppliedType(tycon, args) => defn.isSpecializableTuple(tycon.classSymbol, args) - case _ => false end SpecializeTuples object SpecializeTuples: