aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Applications.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-01-15 19:02:41 +0100
committerMartin Odersky <odersky@gmail.com>2014-01-15 19:02:41 +0100
commit24dff883751fb5a0920f8889e6570914a0f73a26 (patch)
treeea09fa0f75d4058396a6741edcfe8d1a897d6823 /src/dotty/tools/dotc/typer/Applications.scala
parentf1cfe733d9d02dff975d2bde222db890ca6d15e6 (diff)
downloaddotty-24dff883751fb5a0920f8889e6570914a0f73a26.tar.gz
dotty-24dff883751fb5a0920f8889e6570914a0f73a26.tar.bz2
dotty-24dff883751fb5a0920f8889e6570914a0f73a26.zip
Relax type checking rule for pattern matching.
Previously, if S is the selector type and P is the type of the unapply argument, we demanded either S <: P or P <: S We now also admit P <: S' where S' can be obtained from S by dropping refinements. This lets some patterns in RefinedPrinters typecheck which did not typecheck before. It seems we can afford to be a little bit more liberal here, and thereby approximate the weaker "isPopulated" criterion of Scala2x.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Applications.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala32
1 files changed, 20 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index d5f9bded1..6b73740bb 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -621,18 +621,27 @@ trait Applications extends Compatibility { self: Typer =>
}
}
+ /** Can `subtp` be made to be a subtype of `tp`, possibly by dropping some
+ * refinements in `tp`?
+ */
+ def isSubTypeOfParent(subtp: Type, tp: Type): Boolean =
+ if (subtp <:< tp) true
+ else tp match {
+ case RefinedType(parent, _) => isSubTypeOfParent(subtp, parent)
+ case _ => false
+ }
+
unapply.tpe.widen match {
case mt: MethodType if mt.paramTypes.length == 1 && !mt.isDependent =>
val unapplyArgType = mt.paramTypes.head
unapp.println(s"unapp arg tpe = ${unapplyArgType.show}, pt = ${pt.show}")
- def wpt = widenForMatchSelector(pt)
+ def wpt = widenForMatchSelector(pt) // needed?
val ownType =
if (pt <:< unapplyArgType) {
fullyDefinedType(unapplyArgType, "extractor argument", tree.pos)
unapp.println(i"case 1 $unapplyArgType ${ctx.typerState.constraint}")
pt
- }
- else if (unapplyArgType <:< wpt) {
+ } else if (isSubTypeOfParent(unapplyArgType, wpt)) {
maximizeType(unapplyArgType) match {
case Some(tvar) =>
def msg =
@@ -640,16 +649,15 @@ trait Applications extends Compatibility { self: Typer =>
|that makes it a subtype of selector type $pt.
|Non-variant type variable ${tvar.origin} cannot be uniquely instantiated.""".stripMargin
if (fromScala2x) {
- // We can't issue an error here, because in Scala 2, ::[B] is invariant
- // whereas List[+T] is covariant. According to the strict rule, a pattern
- // match of a List[C] against a case x :: xs is illegal, because
- // B cannot be uniquely instantiated. Of course :: should have been
- // covariant in the first place, but in the Scala libraries it isn't.
- // So for now we allow these kinds of patterns, even though they
- // can open unsoundness holes. See SI-7952 for an example of the hole this opens.
+ // We can't issue an error here, because in Scala 2, ::[B] is invariant
+ // whereas List[+T] is covariant. According to the strict rule, a pattern
+ // match of a List[C] against a case x :: xs is illegal, because
+ // B cannot be uniquely instantiated. Of course :: should have been
+ // covariant in the first place, but in the Scala libraries it isn't.
+ // So for now we allow these kinds of patterns, even though they
+ // can open unsoundness holes. See SI-7952 for an example of the hole this opens.
if (ctx.settings.verbose.value) ctx.warning(msg, tree.pos)
- }
- else {
+ } else {
unapp.println(s" ${unapply.symbol.owner} ${unapply.symbol.owner is Scala2x}")
ctx.error(msg, tree.pos)
}