Skip to content

Commit

Permalink
Fix #2201: Less aggressive type application reduction for better infe…
Browse files Browse the repository at this point in the history
…rence

Previously we believed that reducing type applications did not affect
type inference as long as the reduced type constructor had the same
arity as the unreduced one, for example reducing `Foo[X, Y]` is fine
when `Foo` is defined as:

type Foo[A, B] = Bar[A, B]

but not when it's defined as:

type Foo[A] = Bar[A, A]

But this is not a sufficient condition: the bounds of the type
constructor arguments also matter for type inference, so we need to be
more strict and disallow reductions in cases like:

type Foo[A, B] = Bar[B, A]

and:

type Foo[A, B] = Bar[A, Int]
  • Loading branch information
smarter committed Apr 8, 2017
1 parent 4d76265 commit b159489
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 3 deletions.
9 changes: 6 additions & 3 deletions compiler/src/dotty/tools/dotc/core/TypeApplications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,12 @@ class TypeApplications(val self: Type) extends AnyVal {
if (!args.exists(_.isInstanceOf[TypeBounds])) {
val followAlias = Config.simplifyApplications && {
dealiased.resType match {
case AppliedType(tyconBody, _) =>
sameLength(dealiased.typeParams, tyconBody.typeParams)
// Reducing is safe for type inference, as kind arity of type constructor does not change
case AppliedType(tyconBody, dealiasedArgs) =>
// Reduction should not affect type inference when it's
// just eta-reduction (ignoring variance annotations).
// See i2201*.scala for examples where more aggressive
// reduction would break type inference.
dealiased.paramRefs == dealiasedArgs
case _ => false
}
}
Expand Down
8 changes: 8 additions & 0 deletions tests/pos/i2201a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Foo[T]

class Fix[F[_]](unfix: F[Fix[F]])
object DocTree {
type Const[T] = Foo[Int]
type FixConst = Fix[Const]
def docTree(s: Const[FixConst]): FixConst = new Fix(s)
}
14 changes: 14 additions & 0 deletions tests/pos/i2201b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
trait X
trait Y

object Test {
type One[A <: X, B <: Y]

type Two[TA <: Y, TB <: X] = One[TB, TA]

def foo[M[_ <: Y, _ <: X]](x: M[_ <: Y, _ <: X]) = x

val a: Two[Y, X] = ???

foo(a)
}
11 changes: 11 additions & 0 deletions tests/pos/i2201c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
object Test {
implicit val theAnswer: Int = 42

type Swap[A, B] = (B, A)

def foo[M[_, _], T, S](x: M[T, S])(implicit ev: T) = ev

val a: Swap[Int, String] = ("hi", 1)

foo(a)
}

0 comments on commit b159489

Please sign in to comment.