Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit c8fbc41

Browse files
committed
Merge pull request scala#4569 from retronym/ticket/6985
SI-6895 Test cases to explain the limitations in tcpoly inference
2 parents 6ca8847 + 4a61719 commit c8fbc41

File tree

9 files changed

+102
-2
lines changed

9 files changed

+102
-2
lines changed

src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ trait TypeDiagnostics {
309309
// save the name because it will be mutated until it has been
310310
// distinguished from the other types in the same error message
311311
private val savedName = sym.name
312+
private var postQualifiedWith: List[Symbol] = Nil
312313
def restoreName() = sym.name = savedName
313314
def modifyName(f: String => String) = sym setName newTypeName(f(sym.name.toString))
314315

@@ -317,12 +318,12 @@ trait TypeDiagnostics {
317318
*/
318319
def qualifyDefaultNamespaces() = {
319320
val intersect = Set(trueOwner, aliasOwner) intersect UnqualifiedOwners
320-
if (intersect.nonEmpty) preQualify()
321+
if (intersect.nonEmpty && tp.typeSymbolDirect.name == tp.typeSymbol.name) preQualify()
321322
}
322323

323324
// functions to manipulate the name
324325
def preQualify() = modifyName(trueOwner.fullName + "." + _)
325-
def postQualify() = modifyName(_ + "(in " + trueOwner + ")")
326+
def postQualify() = if (!(postQualifiedWith contains trueOwner)) { postQualifiedWith ::= trueOwner; modifyName(_ + "(in " + trueOwner + ")") }
326327
def typeQualify() = if (sym.isTypeParameterOrSkolem) postQualify()
327328
def nameQualify() = if (trueOwner.isPackageClass) preQualify() else postQualify()
328329

test/files/neg/t6895.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
t6895.scala:19: error: polymorphic expression cannot be instantiated to expected type;
2+
found : [F3[F3_P]]Foo[F3]
3+
required: Foo[[X3]Bar[[X1]String]]
4+
val nok: Foo[({type L[X3] = Bar[M]})#L] = barFoo /* Type inference can't unify F with L */
5+
^
6+
one error found

test/files/neg/t6895.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
trait Foo[F1[F1_P]]
2+
trait Bar[F2[F2_P]]
3+
4+
class Test {
5+
def barFoo[F3[F3_P]]: Foo[F3] = ???
6+
7+
// Now we can define a couple of type aliases:
8+
type M[X1] = String
9+
type N[X2] = Bar[M]
10+
11+
// val ok1: Foo[N] = barFoo
12+
// Foo[?F3] <:< Foo[Test.this.N]
13+
// [X2]Test.this.N[X2] <:< [F3_P]?F3[F3_P]
14+
// Test.this.N[X2] <:< ?F3[X2]
15+
// true, ?F3=N
16+
17+
// val ok2: Foo[({type L[X] = Bar[M]})#L] = barFoo[N]
18+
19+
val nok: Foo[({type L[X3] = Bar[M]})#L] = barFoo /* Type inference can't unify F with L */
20+
// Foo[?F3] <:< Foo[[X3]Bar[[X1]String]]
21+
// [X3]Bar[[X1]String] <:< ?F3
22+
// [X3]Bar[[X1]String] <:< [F3_P]?F3[F3_P]
23+
// Bar[[X1]String] <:< ?F3[X3]
24+
// X3 <:< [X1]String
25+
// false
26+
}

test/files/neg/t6895b.check

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
t6895b.scala:20: error: could not find implicit value for parameter e: Foo[[X]Bar[[X]Or[String,X],X]]
2+
implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]]
3+
^
4+
t6895b.scala:23: error: polymorphic expression cannot be instantiated to expected type;
5+
found : [F[_]]Foo[[X(in type L)]Bar[F,X(in type L)]]
6+
required: Foo[[X(in type L)]Bar[[X]Or[String,X],X(in type L)]]
7+
barFoo(null) : Foo[({type L[X] = Bar[StringOr, X]})#L]
8+
^
9+
two errors found

test/files/neg/t6895b.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
trait Foo[F[_]]
2+
trait Bar[F[_], A]
3+
4+
trait Or[A, B]
5+
6+
class Test {
7+
implicit def orFoo[A]: Foo[({type L[X] = Or[A, X]})#L] = ???
8+
implicit def barFoo[F[_]](implicit f: Foo[F]): Foo[({type L[X] = Bar[F, X]})#L] = ???
9+
10+
// Now we can define a couple of type aliases:
11+
type StringOr[X] = Or[String, X]
12+
type BarStringOr[X] = Bar[StringOr, X]
13+
14+
// ok
15+
implicitly[Foo[BarStringOr]]
16+
barFoo[StringOr](null) : Foo[BarStringOr]
17+
barFoo(null) : Foo[BarStringOr]
18+
19+
// nok
20+
implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]]
21+
// Let's write the application explicitly, and then
22+
// compile with just this line enabled and -explaintypes.
23+
barFoo(null) : Foo[({type L[X] = Bar[StringOr, X]})#L]
24+
25+
// Foo[[X]Bar[F,X]] <: Foo[[X]Bar[[X]Or[String,X],X]]?
26+
// Bar[[X]Or[String,X],X] <: Bar[F,X]?
27+
// F[_] <: Or[String,_]?
28+
// false
29+
// false
30+
// false
31+
32+
// Note that the type annotation above is typechecked as
33+
// Foo[[X]Bar[[X]Or[String,X],X]], ie the type alias `L`
34+
// is eta expanded.
35+
//
36+
// This is done so that it does not escape its defining scope.
37+
// However, one this is done, higher kinded inference
38+
// no longer is able to unify F with `StringOr` (SI-2712)
39+
}

test/files/neg/t8777.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
t8777.scala:3: error: type mismatch;
2+
found : Foo.this.TreePrinter(in trait Printers)
3+
required: Foo.this.TreePrinter(in trait Printers)
4+
super.newCodePrinter(out, tree, printRootPkg)
5+
^
6+
one error found

test/files/neg/t8777.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
trait Foo extends scala.tools.nsc.Global {
2+
override def newCodePrinter(out: java.io.PrintWriter, tree: Tree, printRootPkg: Boolean): TreePrinter =
3+
super.newCodePrinter(out, tree, printRootPkg)
4+
}

test/files/neg/t8892.check

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
t8892.scala:2: error: type mismatch;
2+
found : B
3+
required: C.this.B
4+
(which expands to) String
5+
class C[B](x: B) extends A { def f: B = x }
6+
^
7+
one error found

test/files/neg/t8892.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
trait A { type B = String }
2+
class C[B](x: B) extends A { def f: B = x }

0 commit comments

Comments
 (0)