Skip to content

Commit 58b1b49

Browse files
committed
Handle case where expected type of a SeqLiteral has an undetermined element type.
Test case is isApplicableSafe -Ycheck:first.
1 parent 9e1b30d commit 58b1b49

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
895895
}
896896

897897
def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = track("typedSeqLiteral") {
898-
val proto1 = pt.elemType orElse WildcardType
898+
val proto1 = pt.elemType match {
899+
case NoType => WildcardType
900+
case bounds: TypeBounds => WildcardType(bounds)
901+
case elemtp => elemtp
902+
}
899903
val elems1 = tree.elems mapconserve (typed(_, proto1))
900904
val proto2 = // the computed type of the `elemtpt` field
901905
if (!tree.elemtpt.isEmpty) WildcardType

tests/pending/pos/isApplicableSafe.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/pos/isApplicableSafe.scala

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import reflect.ClassTag
2+
3+
// The same problems arise in real arrays.
4+
class A {
5+
6+
class Array[T]
7+
object Array {
8+
def apply[T: ClassTag](xs: T*): Array[T] = ???
9+
def apply(x: Int, xs: Int*): Array[Int] = ???
10+
}
11+
12+
// Any of Array[List[Symbol]], List[Array[Symbol]], or List[List[Symbol]] compile.
13+
var xs: Array[Array[Symbol]] = _
14+
var ys: Array[Map[Symbol, Set[Symbol]]] = _
15+
16+
//xs = Array(Array())
17+
// gives:
18+
//
19+
// isApplicableSafe.scala:15: error: type mismatch:
20+
// found : A.this.Array[Nothing]
21+
// required: A.this.Array[Symbol]
22+
// xs = Array(Array())
23+
//
24+
// Here's the sequence of events that leads to this problem:
25+
//
26+
// 1. the outer Array.apply is overloaded, so we need to typecheck the inner one
27+
// without an expected prototype
28+
//
29+
// 2. The inner Array.apply needs a ClassTag, so we need to instantiate
30+
// its type variable, and the best instantiation is Nothing.
31+
//
32+
// To prevent this, we'd need to do several things:
33+
//
34+
// 1. Pass argument types lazily into the isApplicable call in resolveOverloaded,
35+
// so that we can call constrainResult before any arguments are evaluated.
36+
//
37+
// 2. This is still not enough because the result type is initially an IgnoredProto.
38+
// (because an implicit might have to be inserted around the call, so we cannot
39+
// automatically assume that the call result is a subtype of the expected type).
40+
// Hence, we need to somehow create a closure in constrainResult that does the
41+
// comparison with the real expected result type "on demand".
42+
//
43+
// 3. When instantiating a type variable we need to categorize that some instantiations
44+
// are suspicous (e.g. scalac avoids instantiating to Nothing). In these
45+
// circumstances we should try to excute the delayed constrainResult closures
46+
// in order to get a better instance type.
47+
//
48+
// Quite a lot of work. It's looking really complicated to fix this.
49+
50+
51+
ys = Array(Map(), Map())
52+
53+
val zs = Array(Map())
54+
}

0 commit comments

Comments
 (0)