aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2017-02-08 22:21:05 +1100
committerGitHub <noreply@github.com>2017-02-08 22:21:05 +1100
commit18d5913821064fffa0c74524ba1a8ead9a7def31 (patch)
tree502b93ffc33390ec0f433dfa5b71b7e9c384edd2
parent99679cffc0a5d20e7e7f3c090eb310a6134eeee7 (diff)
parentabbee9e28ef3f0150c9afa48f485ecc49e0e3787 (diff)
downloaddotty-18d5913821064fffa0c74524ba1a8ead9a7def31.tar.gz
dotty-18d5913821064fffa0c74524ba1a8ead9a7def31.tar.bz2
dotty-18d5913821064fffa0c74524ba1a8ead9a7def31.zip
Merge pull request #1921 from dotty-staging/fix-#1907
Fix #1907: Improve error message
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala49
-rw-r--r--compiler/test/dotty/tools/dotc/CompilerTest.scala33
-rw-r--r--library/src/dotty/DottyPredef.scala3
-rw-r--r--tests/neg/i1802.scala4
-rw-r--r--tests/neg/i1907.scala7
-rw-r--r--tests/neg/undet-classtag.scala27
-rw-r--r--tests/pos/t3859.scala2
-rw-r--r--tests/pos/t5859.scala4
-rw-r--r--tests/run/array-addition.scala4
9 files changed, 90 insertions, 43 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index d4e74cf7d..6949221fb 100644
--- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
@@ -507,7 +507,36 @@ trait Implicits { self: Typer =>
* which is itself parameterized by another string,
* indicating where the implicit parameter is needed
*/
- def inferImplicitArg(formal: Type, error: (String => String) => Unit, pos: Position)(implicit ctx: Context): Tree =
+ def inferImplicitArg(formal: Type, error: (String => String) => Unit, pos: Position)(implicit ctx: Context): Tree = {
+
+ /** If `formal` is of the form ClassTag[T], where `T` is a class type,
+ * synthesize a class tag for `T`.
+ */
+ def synthesizedClassTag(formal: Type, pos: Position)(implicit ctx: Context): Tree = {
+ if (formal.isRef(defn.ClassTagClass))
+ formal.argTypes match {
+ case arg :: Nil =>
+ fullyDefinedType(arg, "ClassTag argument", pos) match {
+ case defn.ArrayOf(elemTp) =>
+ val etag = inferImplicitArg(defn.ClassTagType.appliedTo(elemTp), error, pos)
+ if (etag.isEmpty) etag else etag.select(nme.wrap)
+ case tp if hasStableErasure(tp) =>
+ if (defn.isBottomClass(tp.typeSymbol))
+ error(where => i"attempt to take ClassTag of undetermined type for $where")
+ ref(defn.ClassTagModule)
+ .select(nme.apply)
+ .appliedToType(tp)
+ .appliedTo(clsOf(erasure(tp)))
+ .withPos(pos)
+ case tp =>
+ EmptyTree
+ }
+ case _ =>
+ EmptyTree
+ }
+ else EmptyTree
+ }
+
inferImplicit(formal, EmptyTree, pos) match {
case SearchSuccess(arg, _, _, _) =>
arg
@@ -534,24 +563,6 @@ trait Implicits { self: Typer =>
EmptyTree
}
}
-
- /** If `formal` is of the form ClassTag[T], where `T` is a class type,
- * synthesize a class tag for `T`.
- */
- def synthesizedClassTag(formal: Type, pos: Position)(implicit ctx: Context): Tree = {
- if (formal.isRef(defn.ClassTagClass))
- formal.argTypes match {
- case arg :: Nil =>
- val tp = fullyDefinedType(arg, "ClassTag argument", pos)
- if (hasStableErasure(tp))
- return ref(defn.ClassTagModule)
- .select(nme.apply)
- .appliedToType(tp)
- .appliedTo(clsOf(erasure(tp)))
- .withPos(pos)
- case _ =>
- }
- EmptyTree
}
private def assumedCanEqual(ltp: Type, rtp: Type)(implicit ctx: Context) = {
diff --git a/compiler/test/dotty/tools/dotc/CompilerTest.scala b/compiler/test/dotty/tools/dotc/CompilerTest.scala
index eaa0bea84..5d16917cc 100644
--- a/compiler/test/dotty/tools/dotc/CompilerTest.scala
+++ b/compiler/test/dotty/tools/dotc/CompilerTest.scala
@@ -397,20 +397,25 @@ abstract class CompilerTest {
/** Gives an error message for one line where the expected number of errors and
* the number of compiler errors differ. */
def compareLines(fileName: String, expectedLines: List[(Int, Int)], foundLines: List[(Int, Int)]) = {
- expectedLines.foreach({ case (line, expNr) =>
- foundLines.find(_._1 == line) match {
- case Some((_, `expNr`)) => // this line is ok
- case Some((_, foundNr)) => errorMsg(fileName, Some(line), expNr, foundNr)
- case None => errorMsg(fileName, Some(line), expNr, 0)
- }
- })
- foundLines.foreach({ case (line, foundNr) =>
- expectedLines.find(_._1 == line) match {
- case Some((_, `foundNr`)) => // this line is ok
- case Some((_, expNr)) => errorMsg(fileName, Some(line), expNr, foundNr)
- case None => errorMsg(fileName, Some(line), 0, foundNr)
- }
- })
+ expectedLines foreach{
+ case (line, expNr) =>
+ foundLines.find(_._1 == line) match {
+ case Some((_, `expNr`)) => // this line is ok
+ case Some((_, foundNr)) => errorMsg(fileName, Some(line), expNr, foundNr)
+ case None =>
+ println(s"expected lines = $expectedLines%, %")
+ println(s"found lines = $foundLines%, %")
+ errorMsg(fileName, Some(line), expNr, 0)
+ }
+ }
+ foundLines foreach {
+ case (line, foundNr) =>
+ expectedLines.find(_._1 == line) match {
+ case Some((_, `foundNr`)) => // this line is ok
+ case Some((_, expNr)) => errorMsg(fileName, Some(line), expNr, foundNr)
+ case None => errorMsg(fileName, Some(line), 0, foundNr)
+ }
+ }
}
// ========== PARTEST HELPERS =============
diff --git a/library/src/dotty/DottyPredef.scala b/library/src/dotty/DottyPredef.scala
index cd90c4882..c7cf2a906 100644
--- a/library/src/dotty/DottyPredef.scala
+++ b/library/src/dotty/DottyPredef.scala
@@ -9,9 +9,6 @@ import scala.collection.Seq
object DottyPredef {
implicit def typeTag[T]: TypeTag[T] = ???
- implicit def arrayTag[T](implicit ctag: ClassTag[T]): ClassTag[Array[T]] =
- ctag.wrap
-
/** A fall-back implicit to compare values of any types.
* The compiler will restrict implicit instances of `eqAny`. An instance
* `eqAny[T, U]` is _valid_ if `T <: U` or `U <: T` or both `T` and `U` are
diff --git a/tests/neg/i1802.scala b/tests/neg/i1802.scala
index 56da672a8..93e790f18 100644
--- a/tests/neg/i1802.scala
+++ b/tests/neg/i1802.scala
@@ -14,8 +14,8 @@ object Exception {
def apply(x: Throwable): T = f(downcast(x).get)
}
- def mkThrowableCatcher[T](isDef: Throwable => Boolean, f: Throwable => T) = mkCatcher(isDef, f)
+ def mkThrowableCatcher[T](isDef: Throwable => Boolean, f: Throwable => T) = mkCatcher(isDef, f) // error: undetermined ClassTag
- implicit def throwableSubtypeToCatcher[Ex <: Throwable: ClassTag, T](pf: PartialFunction[Ex, T]) = // error: cyclic reference
+ implicit def throwableSubtypeToCatcher[Ex <: Throwable: ClassTag, T](pf: PartialFunction[Ex, T]) =
mkCatcher(pf.isDefinedAt _, pf.apply _)
}
diff --git a/tests/neg/i1907.scala b/tests/neg/i1907.scala
new file mode 100644
index 000000000..6bc3bb56f
--- /dev/null
+++ b/tests/neg/i1907.scala
@@ -0,0 +1,7 @@
+import java.io.File
+
+object Test {
+ Some(new File("."))
+ .map(_.listFiles).getOrElse(Array.empty) // error: undetermined ClassTag
+ .map(_.listFiles)
+}
diff --git a/tests/neg/undet-classtag.scala b/tests/neg/undet-classtag.scala
new file mode 100644
index 000000000..dfe0eb2db
--- /dev/null
+++ b/tests/neg/undet-classtag.scala
@@ -0,0 +1,27 @@
+import scala.reflect.ClassTag
+
+object Test {
+ def f[T: reflect.ClassTag](x: T) = ???
+
+ f(???) // error: undetermined ClassTag
+}
+
+// SI 9754
+object Program {
+ def test[T: ClassTag](x: T) = {
+ val arr = new Array[T](1)
+ println(arr.getClass)
+ println(x.getClass)
+ arr(0) = x
+ }
+
+ def main(args: Array[String]): Unit = {
+ test(new Array[Nothing](0)) // error: undetermined ClassTag
+ }
+}
+
+// SI 5353
+object t5353 {
+ if (false) Array("qwe") else Array() // error: undetermined ClassTag
+}
+
diff --git a/tests/pos/t3859.scala b/tests/pos/t3859.scala
index 992207301..486c1d4b2 100644
--- a/tests/pos/t3859.scala
+++ b/tests/pos/t3859.scala
@@ -1,4 +1,4 @@
class Test {
- def foo: Unit = bar(Array(): _*)
+ def foo: Unit = bar(Array[AnyRef](): _*)
def bar(values: AnyRef*): Unit = ()
}
diff --git a/tests/pos/t5859.scala b/tests/pos/t5859.scala
index 2a31e68ee..60ec8b4cb 100644
--- a/tests/pos/t5859.scala
+++ b/tests/pos/t5859.scala
@@ -7,9 +7,9 @@ class A {
f(List[AnyRef](): _*)
f(List(): _*)
f(Nil: _*)
- f(Array(): _*)
+ // f(Array(): _*) // undetermined ClassTag
f(Array[AnyRef](): _*)
f(List(1))
f(List(1), Nil: _*)
- f(List(1), Array(): _*)
+ // f(List(1), Array(): _*) // undetermined ClassTag
}
diff --git a/tests/run/array-addition.scala b/tests/run/array-addition.scala
index 8def48e85..09a1b0bad 100644
--- a/tests/run/array-addition.scala
+++ b/tests/run/array-addition.scala
@@ -4,8 +4,8 @@ object Test {
def main(args: Array[String]): Unit = {
prettyPrintArray(Array(1,2,3) :+ 4)
prettyPrintArray(1 +: Array(2,3,4))
- prettyPrintArray(Array() :+ 1)
- prettyPrintArray(1 +: Array())
+ prettyPrintArray(Array[Int]() :+ 1)
+ prettyPrintArray(1 +: Array[Int]())
}
}