diff options
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Mode.scala | 3 | ||||
-rw-r--r-- | test/dotc/tests.scala | 1 | ||||
-rw-r--r-- | tests/neg/t1048.scala | 21 |
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 + } +} + |