Skip to content

Commit fc0476f

Browse files
committed
Eta-expand methods even if the expected type is a polymorphic function
In that case, let eta-expansion produce an untyped monomorphic lambda as usual. Thanks to the previous commit, a type parameter clause for this lambda will be inferred if possible.
1 parent 92b277f commit fc0476f

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4362,6 +4362,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
43624362
if isApplyProxy(tree) then newExpr
43634363
else if pt.isInstanceOf[PolyProto] then tree
43644364
else
4365+
pt match //.strippedDealias.normalized ? or underlyingApplied ?
4366+
case RefinedType(parent, nme.apply, _: PolyType) if parent.classSymbol eq defn.PolyFunctionClass =>
4367+
poly.resultType match
4368+
case mt: MethodType =>
4369+
// Does simplify do anything?
4370+
val e = etaExpand(tree, mt, mt.paramInfos.length)
4371+
return simplify(typed(e, pt), pt, locked)
4372+
case _ =>
4373+
case _ =>
4374+
end match
43654375
var typeArgs = tree match
43664376
case Select(qual, nme.CONSTRUCTOR) => qual.tpe.widenDealias.argTypesLo.map(TypeTree(_))
43674377
case _ => Nil

tests/neg/polymorphic-functions2.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ val notSubType: [T] => T => T = [T <: Int] => x => x // error
66
val notInScope: [T] => T => T = [S] => x => (x: T) // error
77

88
val notInScopeInferred: [T] => T => T = x => (x: T) // error
9+
10+
def bar[A]: A => A = x => x
11+
val barf1: [T] => T => T = bar(_) // ok
12+
val barf2: [T] => T => T = bar // error, unlike in the original SIP-49.

tests/run/polymorphic-functions.scala

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ object Test extends App {
125125
val it3: [T, S <: List[T]] => (T, S) => List[T] = (x, y) => x :: y
126126
val tuple1: (String, String) = (1, 2.0).map[[_] =>> String](_.toString)
127127
val tuple2: (List[Int], List[Double]) = (1, 2.0).map(List(_))
128-
// Not supported yet, require eta-expansion with a polymorphic expected type
129-
// val tuple3: (List[Int], List[Double]) = (1, 2.0).map(List.apply)
128+
129+
// Eta-expansion
130+
val e1: [T] => T => Option[T] = Option.apply
131+
val tuple3: (Option[Int], Option[Double]) = (1, 2.0).map(Option.apply)
132+
133+
// Eta-expansion that wouldn't work with the original SIP-49
134+
def pair[S, T](x: S, y: T): (S, T) = (x, y)
135+
val f5: [T] => (Int, T) => (Int, T) = pair
136+
val f6: [T] => (T, Int) => (T, Int) = pair
137+
def id[T](x: T): T = x
138+
val f7: [S] => List[S] => List[S] = id
139+
130140
}

0 commit comments

Comments
 (0)