Skip to content

Commit 78ab82d

Browse files
authored
Merge pull request #4333 from dotty-staging/fix-4314
Fix #4314: revert changes in #4299
2 parents 4b2497e + 0dc0502 commit 78ab82d

File tree

7 files changed

+78
-38
lines changed

7 files changed

+78
-38
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1678,7 +1678,7 @@ object SymDenotations {
16781678
case tp @ AppliedType(tycon, args) =>
16791679
val subsym = tycon.typeSymbol
16801680
if (subsym eq symbol) tp
1681-
else tycon.typeParams match {
1681+
else (tycon.typeParams: @unchecked) match {
16821682
case LambdaParam(_, _) :: _ =>
16831683
baseTypeOf(tp.superType)
16841684
case tparams: List[Symbol @unchecked] =>

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2674,7 +2674,7 @@ object Types {
26742674
* either a list of type parameter symbols or a list of lambda parameters
26752675
*/
26762676
def integrate(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type =
2677-
tparams match {
2677+
(tparams: @unchecked) match {
26782678
case LambdaParam(lam, _) :: _ => tp.subst(lam, this)
26792679
case params: List[Symbol @unchecked] => tp.subst(params, paramRefs)
26802680
}

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ trait SpaceLogic {
113113
case Prod(tp, fun, sym, spaces, full) =>
114114
val sp = Prod(tp, fun, sym, spaces.map(simplify(_)), full)
115115
if (sp.params.contains(Empty)) Empty
116+
else if (canDecompose(tp) && decompose(tp).isEmpty) Empty
116117
else sp
117118
case Or(spaces) =>
118119
val set = spaces.map(simplify(_)).flatMap {
@@ -349,18 +350,19 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
349350
Empty
350351
}
351352

352-
/* Erase a type binding according to erasure semantics in pattern matching */
353-
def erase(tp: Type): Type = tp match {
354-
case tp @ AppliedType(tycon, args) =>
355-
if (tycon.isRef(defn.ArrayClass)) tp.derivedAppliedType(tycon, args.map(erase))
356-
else tp.derivedAppliedType(tycon, args.map(t => WildcardType))
357-
case OrType(tp1, tp2) =>
358-
OrType(erase(tp1), erase(tp2))
359-
case AndType(tp1, tp2) =>
360-
AndType(erase(tp1), erase(tp2))
361-
case tp @ RefinedType(parent, refinedName, _) if refinedName.isTermName => // see pos/dependent-extractors.scala
362-
tp.derivedRefinedType(erase(parent), refinedName, WildcardType)
363-
case _ => tp
353+
/* Erase pattern bound types with WildcardType */
354+
def erase(tp: Type) = {
355+
def isPatternTypeSymbol(sym: Symbol) = !sym.isClass && sym.is(Case)
356+
357+
val map = new TypeMap {
358+
def apply(tp: Type) = tp match {
359+
case tref: TypeRef if isPatternTypeSymbol(tref.typeSymbol) =>
360+
tref.underlying.bounds
361+
case _ => mapOver(tp)
362+
}
363+
}
364+
365+
map(tp)
364366
}
365367

366368
/** Space of the pattern: unapplySeq(a, b, c: _*)
@@ -384,7 +386,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
384386
/** Is `tp1` a subtype of `tp2`? */
385387
def isSubType(tp1: Type, tp2: Type): Boolean = {
386388
val res = (tp1 != nullType || tp2 == nullType) && tp1 <:< tp2
387-
debug.println(s"${tp1.show} <:< ${tp2.show} = $res")
389+
debug.println(s"${tp1} <:< ${tp2} = $res")
388390
res
389391
}
390392

@@ -587,8 +589,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
587589
noClassConflict &&
588590
(!isSingleton(tp1) || tp1 <:< tp2) &&
589591
(!isSingleton(tp2) || tp2 <:< tp1) &&
590-
(!bases1.exists(_ is Final) || tp1 <:< tp2) &&
591-
(!bases2.exists(_ is Final) || tp2 <:< tp1)
592+
(!bases1.exists(_ is Final) || tp1 <:< maxTypeMap.apply(tp2)) &&
593+
(!bases2.exists(_ is Final) || tp2 <:< maxTypeMap.apply(tp1))
592594
}
593595
case OrType(tp1, tp2) =>
594596
recur(tp1) || recur(tp2)
@@ -607,6 +609,41 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
607609
res
608610
}
609611

612+
/** expose abstract type references to their bounds or tvars according to variance */
613+
private class AbstractTypeMap(maximize: Boolean)(implicit ctx: Context) extends TypeMap {
614+
def expose(lo: Type, hi: Type): Type =
615+
if (variance == 0)
616+
newTypeVar(TypeBounds(lo, hi))
617+
else if (variance == 1)
618+
if (maximize) hi else lo
619+
else
620+
if (maximize) lo else hi
621+
622+
def apply(tp: Type): Type = tp match {
623+
case tp: TypeRef if tp.underlying.isInstanceOf[TypeBounds] =>
624+
val lo = this(tp.info.loBound)
625+
val hi = this(tp.info.hiBound)
626+
// See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
627+
val exposed = expose(lo, hi)
628+
debug.println(s"$tp exposed to =====> $exposed")
629+
exposed
630+
631+
case AppliedType(tycon: TypeRef, args) if tycon.underlying.isInstanceOf[TypeBounds] =>
632+
val args2 = args.map(this)
633+
val lo = this(tycon.info.loBound).applyIfParameterized(args2)
634+
val hi = this(tycon.info.hiBound).applyIfParameterized(args2)
635+
val exposed = expose(lo, hi)
636+
debug.println(s"$tp exposed to =====> $exposed")
637+
exposed
638+
639+
case _ =>
640+
mapOver(tp)
641+
}
642+
}
643+
644+
private def minTypeMap(implicit ctx: Context) = new AbstractTypeMap(maximize = false)
645+
private def maxTypeMap(implicit ctx: Context) = new AbstractTypeMap(maximize = true)
646+
610647
/** Instantiate type `tp1` to be a subtype of `tp2`
611648
*
612649
* Return the instantiated type if type parameters and this type
@@ -616,25 +653,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
616653
*
617654
*/
618655
def instantiate(tp1: NamedType, tp2: Type)(implicit ctx: Context): Type = {
619-
// expose type param references to their bounds according to variance
620-
class AbstractTypeMap(maximize: Boolean)(implicit ctx: Context) extends ApproximatingTypeMap {
621-
variance = if (maximize) 1 else -1
622-
623-
def apply(tp: Type): Type = tp match {
624-
case tp: TypeRef if tp.underlying.isInstanceOf[TypeBounds] =>
625-
val lo = this(tp.info.loBound)
626-
val hi = this(tp.info.hiBound)
627-
// See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
628-
range(lo, hi)
629-
630-
case _ =>
631-
mapOver(tp)
632-
}
633-
}
634-
635-
def minTypeMap(implicit ctx: Context) = new AbstractTypeMap(maximize = false)
636-
def maxTypeMap(implicit ctx: Context) = new AbstractTypeMap(maximize = true)
637-
638656
// Fix subtype checking for child instantiation,
639657
// such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
640658
// See tests/patmat/i3938.scala

tests/pos-special/isInstanceOf/t2755.scala renamed to tests/neg-custom-args/isInstanceOf/t2755.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ object Test {
1717
case x: Array[String] => x.size
1818
case x: Array[AnyRef] => 5
1919
case x: Array[_] => 6
20-
case _ => 7
20+
case _ => 7 // error: only null is matched
2121
}
2222
def f3[T](a: Array[T]) = a match {
2323
case x: Array[Int] => x(0)
@@ -26,7 +26,7 @@ object Test {
2626
case x: Array[String] => x.size
2727
case x: Array[AnyRef] => 5
2828
case x: Array[_] => 6
29-
case _ => 7
29+
case _ => 7 // error: only null is matched
3030
}
3131

3232

tests/patmat/i4314.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
sealed trait Foo[A]
2+
case class One[A]() extends Foo[A]
3+
sealed abstract case class Bar[A]() extends Foo[A]
4+
class Two() extends Bar[String]
5+
6+
object Test {
7+
def test(x: Foo[Int]) = x match {
8+
case One() =>
9+
}
10+
}

tests/patmat/i4314b.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
9: Match case Unreachable

tests/patmat/i4314b.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
sealed trait Foo[A]
2+
case class One[A]() extends Foo[A]
3+
sealed abstract case class Bar[A]() extends Foo[A]
4+
class Two() extends Bar[String]
5+
6+
object Test {
7+
def test(x: Foo[Int]) = x match {
8+
case One() =>
9+
case Bar() =>
10+
}
11+
}

0 commit comments

Comments
 (0)