From b2618bb8c641ecfdbae38f98b11c466969add716 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 27 Nov 2017 18:22:53 +0100 Subject: [PATCH] Fix #3467: Don't pre-check kinds in TypeAssigner In the existing tests we only need to pre-check kinds in Typer in order to avoid self-applications that can lead to crashes. By avoiding them in TypeAssigner we also avoid the error exhibited by i3467 in the strawman collections. This change required some changes in the tests because errors now get reported at different times. --- .../dotty/tools/dotc/typer/TypeAssigner.scala | 6 +++--- tests/neg/i2771.scala | 11 +++------- tests/neg/i2771a.scala | 11 ++++++++++ tests/neg/kinds1.scala | 16 ++++++++++++++ tests/neg/{kinds.scala => kinds2.scala} | 1 - tests/neg/tcpoly_overloaded.scala | 2 +- tests/pos/i3467/Test_2.scala | 7 +++++++ tests/pos/i3467/collection_1.scala | 21 +++++++++++++++++++ 8 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 tests/neg/i2771a.scala create mode 100644 tests/neg/kinds1.scala rename tests/neg/{kinds.scala => kinds2.scala} (75%) create mode 100644 tests/pos/i3467/Test_2.scala create mode 100644 tests/pos/i3467/collection_1.scala diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 338f0c2da0bf..13f2dbb1c316 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -13,7 +13,7 @@ import NameOps._ import collection.mutable import reporting.diagnostic.Message import reporting.diagnostic.messages._ -import Checking.{preCheckKind, preCheckKinds, checkNoPrivateLeaks} +import Checking.checkNoPrivateLeaks trait TypeAssigner { import tpd._ @@ -375,7 +375,7 @@ trait TypeAssigner { else if (!paramNames.contains(name)) ctx.error(UndefinedNamedTypeParameter(name, paramNames), arg.pos) else - namedArgMap(name) = preCheckKind(arg, paramBoundsByName(name.asTypeName)).tpe + namedArgMap(name) = arg.tpe // Holds indexes of non-named typed arguments in paramNames val gapBuf = new mutable.ListBuffer[Int] @@ -408,7 +408,7 @@ trait TypeAssigner { } } else { - val argTypes = preCheckKinds(args, pt.paramInfos).tpes + val argTypes = args.tpes if (sameLength(argTypes, paramNames)) pt.instantiate(argTypes) else wrongNumberOfTypeArgs(fn.tpe, pt.typeParams, args, tree.pos) } diff --git a/tests/neg/i2771.scala b/tests/neg/i2771.scala index 838da3eaf9dc..e0477475cd07 100644 --- a/tests/neg/i2771.scala +++ b/tests/neg/i2771.scala @@ -4,21 +4,16 @@ trait C { type M <: A } trait D { type M >: B } object Test { - def test(x: C with D): Unit = { - def f(y: x.M)(z: y.L[y.L]) = z // error: y.L has wrong kind - f(new B { type L[F[_]] = F[F] })(1) // error: F has wrong kind - } - type LB[F[_]] type LL[F[_]] <: LB[F] // ok def foo[X[_] <: Any]() = () - foo[Int]() // error: Int has wrong kind + foo[Int]() // error: Type argument Int does not conform to upper bound def bar[X, Y]() = () - bar[List, Int]() // error: List has wrong kind + bar[List, Int]() // error: missing type parameter(s) for List - bar[Y = List, X = Int]() // error: List has wrong kind + bar[Y = List, X = Int]() // error: missing type parameter(s) for List } diff --git a/tests/neg/i2771a.scala b/tests/neg/i2771a.scala new file mode 100644 index 000000000000..3a07031d2af0 --- /dev/null +++ b/tests/neg/i2771a.scala @@ -0,0 +1,11 @@ +trait A { type L[X] } +trait B { type L } +trait C { type M <: A } +trait D { type M >: B } + +object Test { + def test(x: C with D): Unit = { + def f(y: x.M)(z: y.L[y.L]) = z // error: y.L has wrong kind + f(new B { type L[F[_]] = F[F] })(1) // error: F has wrong kind + } +} diff --git a/tests/neg/kinds1.scala b/tests/neg/kinds1.scala new file mode 100644 index 000000000000..8f7a9f315dc9 --- /dev/null +++ b/tests/neg/kinds1.scala @@ -0,0 +1,16 @@ +object Test { + + class C[T] + class C2[T[X]] + + class B + + val x: C[C] = ??? // error: Type argument has not the same kind as its bound + val y: C2[C] = ??? + + def f[T] = ??? + + def f2[T[X]] = ??? + + f2[C] +} diff --git a/tests/neg/kinds.scala b/tests/neg/kinds2.scala similarity index 75% rename from tests/neg/kinds.scala rename to tests/neg/kinds2.scala index 312c5d45e481..f614ba675051 100644 --- a/tests/neg/kinds.scala +++ b/tests/neg/kinds2.scala @@ -5,7 +5,6 @@ object Test { class B - val x: C[C] = ??? // error: missing type parameter(s) val y: C2[C] = ??? def f[T] = ??? diff --git a/tests/neg/tcpoly_overloaded.scala b/tests/neg/tcpoly_overloaded.scala index 6dd5fe3f0395..69c5fa280618 100644 --- a/tests/neg/tcpoly_overloaded.scala +++ b/tests/neg/tcpoly_overloaded.scala @@ -21,5 +21,5 @@ trait Test { def flatMap[S] (f: T => List[S], foo: Int): List[S] = sys.error("foo") } - val l: MList[String] = moo.flatMap[String, List, Any, MList]((x: Int) => new MList("String")) // error: wrong kind + val l: MList[String] = moo.flatMap[String, List, Any, MList]((x: Int) => new MList("String")) } diff --git a/tests/pos/i3467/Test_2.scala b/tests/pos/i3467/Test_2.scala new file mode 100644 index 000000000000..9838919b3bba --- /dev/null +++ b/tests/pos/i3467/Test_2.scala @@ -0,0 +1,7 @@ +package collection + +class Test { + def test(xs: Array[Int]): Unit = { + new ArrayOps(xs) + } +} diff --git a/tests/pos/i3467/collection_1.scala b/tests/pos/i3467/collection_1.scala new file mode 100644 index 000000000000..dc98d107502a --- /dev/null +++ b/tests/pos/i3467/collection_1.scala @@ -0,0 +1,21 @@ +package collection + +abstract class WithFilter[+A, +CC[_]] + +trait IndexedSeq[+A] extends Any with IndexedSeqOps[A, IndexedSeq, IndexedSeq[A]] + +trait IndexedSeqOps[+A, +CC[X] <: IndexedSeq[X], +C] extends Any { + def withFilter(p: A => Boolean): WithFilter[A, CC] = ??? +} + +package immutable { + trait IndexedSeq[+A] extends collection.IndexedSeq[A] with collection.IndexedSeqOps[A, IndexedSeq, IndexedSeq[A]] +} + +object ArrayOps { + abstract class WithFilter[A] extends collection.WithFilter[A, immutable.IndexedSeq] +} + +class ArrayOps[A](val xs: Array[A]) extends AnyVal with IndexedSeqOps[A, immutable.IndexedSeq, Array[A]] { + override def withFilter(p: A => Boolean): ArrayOps.WithFilter[A] = ??? +}