Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

SI-7983 Fix regression in implicit divergence checking

As seen in Slick. Regressed in 039b1cb.

In that commit, a call to `normalize` was replaced with `dealiasWiden`
as part of a broad sweeping change. However, while the latter does
less than the former with regards to eta expansion ofhigher kinded
type refs (the motivation of that commit), it also does more when it
comes to singleton types: they are widened to the underlying type.

This was widening away `SingleType(<<package a.b>>, <<package c>>)`
before the special case assiging that type component a complexity of
zero could kick in.

In the test case, extracted from Slick, this meant that the
divergence check would consider that the second type below to
outrank the first in the complexity measure, and abort the implicit
search.

    Shape[?,                        ?  (Coffees, Coffees), ?]
    Shape[DivergenceTest.this.Flat, ?, Coffees,            ?]

After this change, the number of packages enclosing `DivergenceTest`
no longer has a bearing on the complexity score of the type.

Here's how the race was run before hand:

	complexity(<noprefix>): 0
	complexity(<root>): 1
	complexity(foo.type): 2
	complexity(foo.bar.type): 3
	complexity(foo.bar.baz.type): 4
	complexity(DivergenceTest.this.type): 5
	complexity(<noprefix>): 0
	complexity(<root>): 1
	complexity(foo.type): 2
	complexity(foo.bar.type): 3
	complexity(foo.bar.baz.type): 4
	complexity(DivergenceTest.this.type): 5
	complexity(DivergenceTest.this.Flat): 6
	complexity(<noprefix>): 0
	complexity(<root>): 1
	complexity(scala.type): 2
	complexity(Int): 3
	complexity(?): 1
	complexity(DivergenceTest.this.Shape2[DivergenceTest.this.Flat,Int,?]): 16

	complexity(<noprefix>): 0
	complexity(<root>): 1
	complexity(foo.type): 2
	complexity(foo.bar.type): 3
	complexity(foo.bar.baz.type): 4
	complexity(DivergenceTest.this.type): 5
	complexity(?): 1
	complexity(<noprefix>): 0
	complexity(<root>): 1
	complexity(scala.type): 2
	complexity(<noprefix>): 0
	complexity(Coffees): 1
	complexity(<noprefix>): 0
	complexity(<root>): 1
	complexity(scala.type): 2
	complexity(Int): 3
	complexity((Coffees, Int)): 7
	complexity(?): 1
	complexity(DivergenceTest.this.Shape2[?,(Coffees, Int),?]): 15

	dominates(DivergenceTest.this.Shape2[_ <: DivergenceTest.this.Flat, Int, U2], DivergenceTest.this.Shape2[_ <: Level, (Coffees, Int), U1]): true

And afterwards:

	complexity(DivergenceTest.this.type): 1
	complexity(DivergenceTest.this.type): 1
	complexity(DivergenceTest.this.Flat): 2
	complexity(scala.type): 1
	complexity(Int): 2
	complexity(?): 1
	complexity(DivergenceTest.this.Shape2[DivergenceTest.this.Flat,Int,?]): 7

	complexity(DivergenceTest.this.type): 1
	complexity(?): 1
	complexity(scala.type): 1
	complexity(<noprefix>): 0
	complexity(Coffees): 1
	complexity(scala.type): 1
	complexity(Int): 2
	complexity((Coffees, Int)): 5
	complexity(?): 1
	complexity(DivergenceTest.this.Shape2[?,(Coffees, Int),?]): 9

	dominates(DivergenceTest.this.Shape2[_ <: DivergenceTest.this.Flat, Int, U2], DivergenceTest.this.Shape2[_ <: Level, (Coffees, Int), U1]): false

Notice that even in the after shot, `scala.Int` has a complexity of 2.
It should be 1; this will be fixed in a separate commit.
  • Loading branch information...
commit dfe0ba847e8751896948522df5a24e13754b43bf 1 parent c243435
@retronym retronym authored
View
2  src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -402,7 +402,7 @@ trait Implicits {
deriveTypeWithWildcards(syms.distinct)(tp)
}
def sum(xs: List[Int]) = (0 /: xs)(_ + _)
- def complexity(tp: Type): Int = tp.dealiasWiden match {
+ def complexity(tp: Type): Int = tp.dealias match {
case NoPrefix =>
0
case SingleType(pre, sym) =>
View
31 test/files/pos/t7983.scala
@@ -0,0 +1,31 @@
+package foo.bar.baz // the package nesting level material to this bug
+
+class DivergenceTest {
+
+ trait ColumnBase[T]
+
+ trait ShapeLevel
+ trait Flat extends ShapeLevel
+ trait Lower extends Flat
+
+ class Shape2[Level <: ShapeLevel, -M, U]
+
+ implicit final def columnBaseShape[Level >: Flat <: ShapeLevel, T, C <: ColumnBase[_]]
+ (implicit ev: C <:< ColumnBase[T]
+ ): Shape2[Level, C, T] = ???
+
+ implicit final def intShape[Level <: ShapeLevel, T]: Shape2[Level, Int, Int] = ???
+ implicit final def tuple2Shape[Level <: ShapeLevel, M1,M2, U1,U2]
+ (implicit u1: Shape2[_ <: Level, M1, U1],
+ u2: Shape2[_ <: Level, M2, U2]
+ ): Shape2[Level, (M1,M2), (U1,U2)] = ???
+
+ def foo {
+ class Coffees extends ColumnBase[Int]
+
+ def map1[F, T](f: F)(implicit shape: Shape2[_ <: Flat, F, T]) = ???
+
+ map1(((1, null: Coffees), 1))
+ map1(((null: Coffees, 1), 1)) // fails with implicit divergence error in 2.11.0-M6, works under 2.10.3
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.