Skip to content

Commit

Permalink
Space: Use RHS of & when refining subtypes (#16573)
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand authored Dec 22, 2022
2 parents 60bae2f + dd0c9f2 commit c84e255
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 7 deletions.
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ object TypeOps:
* If the subtyping is true, the instantiated type `p.child[Vs]` is
* returned. Otherwise, `NoType` is returned.
*/
def refineUsingParent(parent: Type, child: Symbol)(using Context): Type = {
def refineUsingParent(parent: Type, child: Symbol, mixins: List[Type] = Nil)(using Context): Type = {
// <local child> is a place holder from Scalac, it is hopeless to instantiate it.
//
// Quote from scalac (from nsc/symtab/classfile/Pickler.scala):
Expand All @@ -753,7 +753,7 @@ object TypeOps:
val childTp = if (child.isTerm) child.termRef else child.typeRef

inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds.addMode(Mode.GadtConstraintInference)) {
instantiateToSubType(childTp, parent).dealias
instantiateToSubType(childTp, parent, mixins).dealias
}
}

Expand All @@ -764,7 +764,7 @@ object TypeOps:
*
* Otherwise, return NoType.
*/
private def instantiateToSubType(tp1: NamedType, tp2: Type)(using Context): Type = {
private def instantiateToSubType(tp1: NamedType, tp2: Type, mixins: List[Type])(using Context): Type = {
// In order for a child type S to qualify as a valid subtype of the parent
// T, we need to test whether it is possible S <: T.
//
Expand Down Expand Up @@ -881,6 +881,7 @@ object TypeOps:
}

def instantiate(): Type = {
for tp <- mixins.reverseIterator do protoTp1 <:< tp
maximizeType(protoTp1, NoSpan)
wildApprox(protoTp1)
}
Expand Down
10 changes: 6 additions & 4 deletions compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
Original file line number Diff line number Diff line change
Expand Up @@ -597,11 +597,11 @@ class SpaceEngine(using Context) extends SpaceLogic {
}

/** Decompose a type into subspaces -- assume the type can be decomposed */
def decompose(tp: Type): List[Typ] =
tp.dealias match {
def decompose(tp: Type): List[Typ] = trace(i"decompose($tp)", debug, show(_: Seq[Space])) {
def rec(tp: Type, mixins: List[Type]): List[Typ] = tp.dealias match {
case AndType(tp1, tp2) =>
def decomposeComponent(tpA: Type, tpB: Type): List[Typ] =
decompose(tpA).flatMap {
rec(tpA, tpB :: mixins).flatMap {
case Typ(tp, _) =>
if tp <:< tpB then
Typ(tp, decomposed = true) :: Nil
Expand Down Expand Up @@ -642,7 +642,7 @@ class SpaceEngine(using Context) extends SpaceLogic {

val parts = children.map { sym =>
val sym1 = if (sym.is(ModuleClass)) sym.sourceModule else sym
val refined = TypeOps.refineUsingParent(tp, sym1)
val refined = TypeOps.refineUsingParent(tp, sym1, mixins)

debug.println(sym1.show + " refined to " + refined.show)

Expand All @@ -663,6 +663,8 @@ class SpaceEngine(using Context) extends SpaceLogic {

parts.map(Typ(_, true))
}
rec(tp, Nil)
}

/** Abstract sealed types, or-types, Boolean and Java enums can be decomposed */
def canDecompose(tp: Type): Boolean =
Expand Down
9 changes: 9 additions & 0 deletions tests/pos/i16539.min.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// scalac: -Werror
sealed trait Tag[A]

sealed trait Foo
case class Bar[A](fn: A => Unit) extends Foo, Tag[A]

class Test:
def pmat[A](sel: Foo & Tag[A]): Unit = sel match
case Bar(_) =>
17 changes: 17 additions & 0 deletions tests/pos/i16539.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// scalac: -Werror
sealed trait Tag[A]

enum Hidden:
case Reveal[A](
init: A,
reduce: (A, A) => A
) extends Hidden with Tag[A]

trait Handle[C]:
def apply[A](c: C & Tag[A]): A

val x = new Handle[Hidden] {
def apply[A](c: Hidden & Tag[A]): A = c match {
case Hidden.Reveal(x, _) => x
}
}

0 comments on commit c84e255

Please sign in to comment.