Skip to content

Commit 61aa3d9

Browse files
authored
Merge pull request #1399 from dotty-staging/fix-patmat-typing
Fix typing of match expressions
2 parents a307a90 + 198817b commit 61aa3d9

File tree

3 files changed

+37
-8
lines changed

3 files changed

+37
-8
lines changed

src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -740,27 +740,31 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
740740

741741
def fromScala2x = unapplyFn.symbol.exists && (unapplyFn.symbol.owner is Scala2x)
742742

743-
/** Can `subtp` be made to be a subtype of `tp`, possibly by dropping some
744-
* refinements in `tp`?
743+
/** Is `subtp` a subtype of `tp` or of some generalization of `tp`?
744+
* The generalizations of a type T are the smallest set G such that
745+
*
746+
* - T is in G
747+
* - If a typeref R in G represents a trait, R's superclass is in G.
748+
* - If a type proxy P is not a reference to a class, P's supertype is in G
745749
*/
746750
def isSubTypeOfParent(subtp: Type, tp: Type)(implicit ctx: Context): Boolean =
747751
if (subtp <:< tp) true
748752
else tp match {
749-
case tp: RefinedType => isSubTypeOfParent(subtp, tp.parent)
753+
case tp: TypeRef if tp.symbol.isClass =>
754+
tp.symbol.is(Trait) && isSubTypeOfParent(subtp, tp.firstParent)
755+
case tp: TypeProxy => isSubTypeOfParent(subtp, tp.superType)
750756
case _ => false
751757
}
752758

753759
unapplyFn.tpe.widen match {
754760
case mt: MethodType if mt.paramTypes.length == 1 =>
755761
val unapplyArgType = mt.paramTypes.head
756762
unapp.println(i"unapp arg tpe = $unapplyArgType, pt = $selType")
757-
def wpt = widenForMatchSelector(selType) // needed?
758763
val ownType =
759764
if (selType <:< unapplyArgType) {
760-
//fullyDefinedType(unapplyArgType, "extractor argument", tree.pos)
761765
unapp.println(i"case 1 $unapplyArgType ${ctx.typerState.constraint}")
762766
selType
763-
} else if (isSubTypeOfParent(unapplyArgType, wpt)(ctx.addMode(Mode.GADTflexible))) {
767+
} else if (isSubTypeOfParent(unapplyArgType, selType)(ctx.addMode(Mode.GADTflexible))) {
764768
maximizeType(unapplyArgType) match {
765769
case Some(tvar) =>
766770
def msg =
@@ -786,9 +790,9 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
786790
unapplyArgType
787791
} else {
788792
unapp.println("Neither sub nor super")
789-
unapp.println(TypeComparer.explained(implicit ctx => unapplyArgType <:< wpt))
793+
unapp.println(TypeComparer.explained(implicit ctx => unapplyArgType <:< selType))
790794
errorType(
791-
d"Pattern type $unapplyArgType is neither a subtype nor a supertype of selector type $wpt",
795+
d"Pattern type $unapplyArgType is neither a subtype nor a supertype of selector type $selType",
792796
tree.pos)
793797
}
794798

tests/neg/i1212.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@ann class ann extends scala.annotation.Annotation // error: cyclic reference

tests/neg/patmat.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
trait A
2+
trait B
3+
class C extends A with B
4+
case class D()
5+
object X {
6+
def unapply(x: B): Boolean = false
7+
}
8+
9+
object Test {
10+
def main(args: Array[String]) = {
11+
val ca: A = new C
12+
ca match {
13+
case x: B =>
14+
case X() =>
15+
case D() => // ok, but scalac disagrees
16+
}
17+
val cc = new C
18+
cc match {
19+
case x: B =>
20+
case X() =>
21+
case D() => // error: neither a subtype not a supertype
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)