From e34555f69e7cdd6d19d0d1ed969127f4ee65c36e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 1 Feb 2017 17:18:13 +1100 Subject: Disallow taking a class tag of Nothing or Null. It seems in most cases this leads to weird behavior and cause confusing error messages later. It also means we cannot create an Array[Nothing], except by passing the classtag explicitly. --- compiler/src/dotty/tools/dotc/typer/Implicits.scala | 2 ++ tests/neg/i1802.scala | 4 ++-- tests/neg/i1907.scala | 7 +++++++ tests/neg/undet-classtag.scala | 5 +++++ tests/pos/t3859.scala | 2 +- tests/pos/t5859.scala | 4 ++-- tests/run/array-addition.scala | 4 ++-- 7 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 tests/neg/i1907.scala create mode 100644 tests/neg/undet-classtag.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 2112b1221..f7d8556a7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -521,6 +521,8 @@ trait Implicits { self: Typer => 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) 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..563596d14 --- /dev/null +++ b/tests/neg/undet-classtag.scala @@ -0,0 +1,5 @@ +object Test { + def f[T: reflect.ClassTag](x: T) = ??? + + f(???) // 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]()) } } -- cgit v1.2.3