aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-08-26 16:43:30 +0200
committerMartin Odersky <odersky@gmail.com>2016-08-26 17:57:09 +0200
commita438d3e4cb39ea7c12eba2ebc3a2399a680549f6 (patch)
treec544f839c61f046e4dba76679a9902fb42d3a570
parent36648547105bc8ac53dd63a03821a27243af13cd (diff)
downloaddotty-a438d3e4cb39ea7c12eba2ebc3a2399a680549f6.tar.gz
dotty-a438d3e4cb39ea7c12eba2ebc3a2399a680549f6.tar.bz2
dotty-a438d3e4cb39ea7c12eba2ebc3a2399a680549f6.zip
Handle case where expected type of a SeqLiteral has an undetermined element type.
Test case is isApplicableSafe -Ycheck:first.
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala6
-rw-r--r--tests/pending/pos/isApplicableSafe.scala8
-rw-r--r--tests/pos/isApplicableSafe.scala54
3 files changed, 59 insertions, 9 deletions
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index f0086b0ab..fdcfe347b 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -895,7 +895,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = track("typedSeqLiteral") {
- val proto1 = pt.elemType orElse WildcardType
+ val proto1 = pt.elemType match {
+ case NoType => WildcardType
+ case bounds: TypeBounds => WildcardType(bounds)
+ case elemtp => elemtp
+ }
val elems1 = tree.elems mapconserve (typed(_, proto1))
val proto2 = // the computed type of the `elemtpt` field
if (!tree.elemtpt.isEmpty) WildcardType
diff --git a/tests/pending/pos/isApplicableSafe.scala b/tests/pending/pos/isApplicableSafe.scala
deleted file mode 100644
index b4cacbf28..000000000
--- a/tests/pending/pos/isApplicableSafe.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-class A {
- // Any of Array[List[Symbol]], List[Array[Symbol]], or List[List[Symbol]] compile.
- var xs: Array[Array[Symbol]] = _
- var ys: Array[Map[Symbol, Set[Symbol]]] = _
-
- xs = Array(Array())
- ys = Array(Map(), Map())
-}
diff --git a/tests/pos/isApplicableSafe.scala b/tests/pos/isApplicableSafe.scala
new file mode 100644
index 000000000..c54df1f22
--- /dev/null
+++ b/tests/pos/isApplicableSafe.scala
@@ -0,0 +1,54 @@
+import reflect.ClassTag
+
+// The same problems arise in real arrays.
+class A {
+
+ class Array[T]
+ object Array {
+ def apply[T: ClassTag](xs: T*): Array[T] = ???
+ def apply(x: Int, xs: Int*): Array[Int] = ???
+ }
+
+ // Any of Array[List[Symbol]], List[Array[Symbol]], or List[List[Symbol]] compile.
+ var xs: Array[Array[Symbol]] = _
+ var ys: Array[Map[Symbol, Set[Symbol]]] = _
+
+ //xs = Array(Array())
+ // gives:
+ //
+ // isApplicableSafe.scala:15: error: type mismatch:
+ // found : A.this.Array[Nothing]
+ // required: A.this.Array[Symbol]
+ // xs = Array(Array())
+ //
+ // Here's the sequence of events that leads to this problem:
+ //
+ // 1. the outer Array.apply is overloaded, so we need to typecheck the inner one
+ // without an expected prototype
+ //
+ // 2. The inner Array.apply needs a ClassTag, so we need to instantiate
+ // its type variable, and the best instantiation is Nothing.
+ //
+ // To prevent this, we'd need to do several things:
+ //
+ // 1. Pass argument types lazily into the isApplicable call in resolveOverloaded,
+ // so that we can call constrainResult before any arguments are evaluated.
+ //
+ // 2. This is still not enough because the result type is initially an IgnoredProto.
+ // (because an implicit might have to be inserted around the call, so we cannot
+ // automatically assume that the call result is a subtype of the expected type).
+ // Hence, we need to somehow create a closure in constrainResult that does the
+ // comparison with the real expected result type "on demand".
+ //
+ // 3. When instantiating a type variable we need to categorize that some instantiations
+ // are suspicous (e.g. scalac avoids instantiating to Nothing). In these
+ // circumstances we should try to excute the delayed constrainResult closures
+ // in order to get a better instance type.
+ //
+ // Quite a lot of work. It's looking really complicated to fix this.
+
+
+ ys = Array(Map(), Map())
+
+ val zs = Array(Map())
+}