From 2beb67e908941ff71aafce163c3c0df766cb1622 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Tue, 26 Mar 2024 12:45:23 +0100 Subject: [PATCH] Do match type reduction atPhaseNoLater than ElimOpaque If a match type pattern is an opaque type, we use its bounds when checking the validity of the pattern. Following the ElimOpaque phase however, the pattern is beta-reduced (as normal applied type aliases), which may result in an illegal pattern. --- compiler/src/dotty/tools/dotc/core/Phases.scala | 4 ++++ compiler/src/dotty/tools/dotc/core/Types.scala | 2 +- tests/pos/i19434.scala | 11 +++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i19434.scala diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index c704846a82da..043c5beb9076 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -220,6 +220,7 @@ object Phases { private var myPatmatPhase: Phase = uninitialized private var myElimRepeatedPhase: Phase = uninitialized private var myElimByNamePhase: Phase = uninitialized + private var myElimOpaquePhase: Phase = uninitialized private var myExtensionMethodsPhase: Phase = uninitialized private var myExplicitOuterPhase: Phase = uninitialized private var myGettersPhase: Phase = uninitialized @@ -245,6 +246,7 @@ object Phases { final def patmatPhase: Phase = myPatmatPhase final def elimRepeatedPhase: Phase = myElimRepeatedPhase final def elimByNamePhase: Phase = myElimByNamePhase + final def elimOpaquePhase: Phase = myElimOpaquePhase final def extensionMethodsPhase: Phase = myExtensionMethodsPhase final def explicitOuterPhase: Phase = myExplicitOuterPhase final def gettersPhase: Phase = myGettersPhase @@ -272,6 +274,7 @@ object Phases { myRefChecksPhase = phaseOfClass(classOf[RefChecks]) myElimRepeatedPhase = phaseOfClass(classOf[ElimRepeated]) myElimByNamePhase = phaseOfClass(classOf[ElimByName]) + myElimOpaquePhase = phaseOfClass(classOf[ElimOpaque]) myExtensionMethodsPhase = phaseOfClass(classOf[ExtensionMethods]) myErasurePhase = phaseOfClass(classOf[Erasure]) myElimErasedValueTypePhase = phaseOfClass(classOf[ElimErasedValueType]) @@ -511,6 +514,7 @@ object Phases { def refchecksPhase(using Context): Phase = ctx.base.refchecksPhase def elimRepeatedPhase(using Context): Phase = ctx.base.elimRepeatedPhase def elimByNamePhase(using Context): Phase = ctx.base.elimByNamePhase + def elimOpaquePhase(using Context): Phase = ctx.base.elimOpaquePhase def extensionMethodsPhase(using Context): Phase = ctx.base.extensionMethodsPhase def explicitOuterPhase(using Context): Phase = ctx.base.explicitOuterPhase def gettersPhase(using Context): Phase = ctx.base.gettersPhase diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index e38fbbb4b355..f6210b3a9883 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -5026,7 +5026,7 @@ object Types extends TypeUtils { private def thisMatchType = this - def reduced(using Context): Type = { + def reduced(using Context): Type = atPhaseNoLater(elimOpaquePhase) { def contextInfo(tp: Type): Type = tp match { case tp: TypeParamRef => diff --git a/tests/pos/i19434.scala b/tests/pos/i19434.scala new file mode 100644 index 000000000000..e8595fa252d0 --- /dev/null +++ b/tests/pos/i19434.scala @@ -0,0 +1,11 @@ + +object Test: + + object Named: + opaque type Named[name <: String & Singleton, A] >: A = A + + type DropNames[T <: Tuple] = T match + case Named.Named[_, x] *: xs => x *: DropNames[xs] + case _ => T + + def f[T <: Tuple]: DropNames[T] = ??? \ No newline at end of file