Skip to content

Commit b159489

Browse files
committed
Fix #2201: Less aggressive type application reduction for better inference
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]
1 parent 4d76265 commit b159489

File tree

4 files changed

+39
-3
lines changed

4 files changed

+39
-3
lines changed

compiler/src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,12 @@ class TypeApplications(val self: Type) extends AnyVal {
391391
if (!args.exists(_.isInstanceOf[TypeBounds])) {
392392
val followAlias = Config.simplifyApplications && {
393393
dealiased.resType match {
394-
case AppliedType(tyconBody, _) =>
395-
sameLength(dealiased.typeParams, tyconBody.typeParams)
396-
// Reducing is safe for type inference, as kind arity of type constructor does not change
394+
case AppliedType(tyconBody, dealiasedArgs) =>
395+
// Reduction should not affect type inference when it's
396+
// just eta-reduction (ignoring variance annotations).
397+
// See i2201*.scala for examples where more aggressive
398+
// reduction would break type inference.
399+
dealiased.paramRefs == dealiasedArgs
397400
case _ => false
398401
}
399402
}

tests/pos/i2201a.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Foo[T]
2+
3+
class Fix[F[_]](unfix: F[Fix[F]])
4+
object DocTree {
5+
type Const[T] = Foo[Int]
6+
type FixConst = Fix[Const]
7+
def docTree(s: Const[FixConst]): FixConst = new Fix(s)
8+
}

tests/pos/i2201b.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
trait X
2+
trait Y
3+
4+
object Test {
5+
type One[A <: X, B <: Y]
6+
7+
type Two[TA <: Y, TB <: X] = One[TB, TA]
8+
9+
def foo[M[_ <: Y, _ <: X]](x: M[_ <: Y, _ <: X]) = x
10+
11+
val a: Two[Y, X] = ???
12+
13+
foo(a)
14+
}

tests/pos/i2201c.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
object Test {
2+
implicit val theAnswer: Int = 42
3+
4+
type Swap[A, B] = (B, A)
5+
6+
def foo[M[_, _], T, S](x: M[T, S])(implicit ev: T) = ev
7+
8+
val a: Swap[Int, String] = ("hi", 1)
9+
10+
foo(a)
11+
}

0 commit comments

Comments
 (0)