aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala8
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala6
-rw-r--r--src/dotty/tools/dotc/typer/Mode.scala3
-rw-r--r--test/dotc/tests.scala1
-rw-r--r--tests/neg/t1048.scala21
5 files changed, 33 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index eb57119ff..805941c5d 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -364,7 +364,7 @@ class TypeComparer(initctx: Context) extends DotClass {
private def traceInfo(tp1: Type, tp2: Type) =
s"${tp1.show} <:< ${tp2.show}" +
- (if (ctx.settings.verbose.value) s"${tp1.getClass} ${tp2.getClass}" else "")
+ (if (ctx.settings.verbose.value) s" ${tp1.getClass} ${tp2.getClass}${if (frozenConstraint) " frozen" else ""}" else "")
def isSubType(tp1: Type, tp2: Type): Boolean = /*>|>*/ ctx.traceIndented(s"isSubType ${traceInfo(tp1, tp2)}", subtyping) /*<|<*/ {
if (tp2 eq NoType) false
@@ -592,7 +592,8 @@ class TypeComparer(initctx: Context) extends DotClass {
NamedType(tp1.prefix, tp1.name, sd.derivedSingleDenotation(sd.symbol, tp))
secondTry(OrType.make(derivedRef(tp11), derivedRef(tp12)), tp2)
case TypeBounds(lo1, hi1) =>
- if ((tp1.symbol is GADTFlexType) && !isSubTypeWhenFrozen(hi1, tp2))
+ if ((ctx.mode is Mode.GADTflexible) && (tp1.symbol is GADTFlexType) &&
+ !isSubTypeWhenFrozen(hi1, tp2))
trySetType(tp1, TypeBounds(lo1, hi1 & tp2))
else if (lo1 eq hi1) isSubType(hi1, tp2)
else tryRebase2nd
@@ -610,7 +611,8 @@ class TypeComparer(initctx: Context) extends DotClass {
}
def compareNamed: Boolean = tp2.info match {
case TypeBounds(lo2, hi2) =>
- if ((tp2.symbol is GADTFlexType) && !isSubTypeWhenFrozen(tp1, lo2))
+ if ((ctx.mode is Mode.GADTflexible) && (tp2.symbol is GADTFlexType) &&
+ !isSubTypeWhenFrozen(tp1, lo2))
trySetType(tp2, TypeBounds(lo2 | tp1, hi2))
else
((frozenConstraint || !isCappable(tp1)) && isSubType(tp1, lo2)
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index b2572dcda..2ff116f46 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -653,7 +653,7 @@ 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 =
+ def isSubTypeOfParent(subtp: Type, tp: Type)(implicit ctx: Context): Boolean =
if (subtp <:< tp) true
else tp match {
case RefinedType(parent, _) => isSubTypeOfParent(subtp, parent)
@@ -671,7 +671,7 @@ trait Applications extends Compatibility { self: Typer =>
//fullyDefinedType(unapplyArgType, "extractor argument", tree.pos)
unapp.println(i"case 1 $unapplyArgType ${ctx.typerState.constraint}")
selType
- } else if (isSubTypeOfParent(unapplyArgType, wpt)) {
+ } else if (isSubTypeOfParent(unapplyArgType, wpt)(ctx.addMode(Mode.GADTflexible))) {
maximizeType(unapplyArgType) match {
case Some(tvar) =>
def msg =
@@ -703,7 +703,7 @@ trait Applications extends Compatibility { self: Typer =>
tree.pos)
}
- val dummyArg = dummyTreeOfType(ownType)
+ val dummyArg = dummyTreeOfType(unapplyArgType)
val unapplyApp = typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil)))
val unapplyImplicits = unapplyApp match {
case Apply(Apply(unapply, `dummyArg` :: Nil), args2) => assert(args2.nonEmpty); args2
diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala
index f855ef1c2..8e62adfdd 100644
--- a/src/dotty/tools/dotc/typer/Mode.scala
+++ b/src/dotty/tools/dotc/typer/Mode.scala
@@ -48,5 +48,8 @@ object Mode {
*/
val FutureDefsOK = newMode(7, "FutureDefsOK")
+ /** Allow GADTFlexType labelled types to have their bounds adjusted */
+ val GADTflexible = newMode(8, "GADTflexible")
+
val PatternOrType = Pattern | Type
} \ No newline at end of file
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 0a545919b..c01d12e50 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -84,6 +84,7 @@ class tests extends CompilerTest {
@Test def neg_tailcall = compileFile(negDir, "tailcall/tailrec", xerrors = 7)
@Test def neg_tailcall2 = compileFile(negDir, "tailcall/tailrec-2", xerrors = 2)
@Test def neg_tailcall3 = compileFile(negDir, "tailcall/tailrec-3", xerrors = 2)
+ @Test def neg_t1048 = compileFile(negDir, "t1048", xerrors = 1)
@Test def nef_t1279a = compileFile(negDir, "t1279a", xerrors = 1)
@Test def neg_t1843 = compileFile(negDir, "t1843", xerrors = 1)
@Test def neg_t1843_variances = compileFile(negDir, "t1843-variances", xerrors = 1)
diff --git a/tests/neg/t1048.scala b/tests/neg/t1048.scala
new file mode 100644
index 000000000..4b8e78b4c
--- /dev/null
+++ b/tests/neg/t1048.scala
@@ -0,0 +1,21 @@
+trait T[U] {
+ def x: T[_ <: U]
+}
+
+object T {
+ def unapply[U](t: T[U]): Option[T[_ <: U]] = Some(t.x)
+}
+
+object Test {
+ def f[W](t: T[W]) = t match {
+ case T(T(_)) => ()
+// Gives:
+// t1048.scala:11: error: There is no best instantiation of pattern type T[Any']
+// that makes it a subtype of selector type T[_ <: W].
+// Non-variant type variable U cannot be uniquely instantiated.
+// case T(T(_)) => ()
+// ^
+// one error found
+ }
+}
+