Skip to content

Eta-expansion of methods with implicit and dependent arguments #5288

Closed
@OlivierBlanvillain

Description

@OlivierBlanvillain

They are some inconsistencies between eta-expansion of normal methods and methods with implicit arguments or dependent result type:

scala> def m4(implicit i: Int): Int = 4
def m4(implicit i: Int): Int

scala> val f4_Inferred = m4 _
1 |val f4_Inferred = m4 _
  |                  ^^^^
  |Only function types can be followed by _ but the current expression has type <error no implicit values were found that match expected type>

scala> val f4Inferred = m4
1 |val f4Inferred = m4
  |                   ^
  |   no implicit argument of type Int was found for parameter i of method m4

scala> val f4_Expected: implicit Int => Int = m4 _
1 |val f4_Expected: implicit Int => Int = m4 _
  |                                        ^^^^
  |Only function types can be followed by _ but the current expression has type Int

So, to turn methods with implicit arguments into function the only option is to give an explicit expected type and not use the underscore syntax:

scala> val f4Expected: implicit Int => Int = m4 // Works as expected
val f4Expected: implicit Int => Int = Lambda$1398/1407952056@437bd805

Dependent methods are also inconsistent, in a different way:

scala> trait C { type M; val m: M }
// defined trait C

scala> val f7Expected: (c: C) => c.M = m7
1 |val f7Expected: (c: C) => c.M = m7
  |                                ^^
  |                                missing arguments for method m7

scala> val f7_Exptected: (c: C) => c.M = m7 _
1 |val f7_Exptected: (c: C) => c.M = m7 _
  |                                  ^^^^
  |Only function types can be followed by _ but the current expression has type (c: C) => c.M

Eta-expansion fails in the presence of explicit return types. Both underscore and non underscore syntax work as expected:

scala> val f7_Inferred = m7 _
val f7_Inferred: (c: C) => c.M = Lambda$1408/127401209@16bd7ae1

scala> val f7Inferred = m7
val f7Inferred: (c: C) => c.M = Lambda$1409/1612539426@76216830

Eta-expansion of dependent methods with two arguments or curried arguments seems to also be broken as the dependency is lost entirely:

scala> def m9(c1: C, c2: C): c1.M | c2.M = c1.m
def m9(c1: C, c2: C): c1.M | c2.M

scala> val f9Inferred = m9 _
val f9Inferred: (C, C) => Any = Lambda$1457/1138992016@44aa91e2
scala> def mD(c1: C)(c2: C): c1.M | c2.M = c1.m
def mD(c1: C)(c2: C): c1.M | c2.M

scala> val fDInferred = mD
val fDInferred: C => C => Any = Lambda$1458/934352027@1187dc82

Here is the test case I wrote for eta-expansion of all combinations of normal/implicit/dependent methods up to arity 2.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions