|
| 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