Skip to content

Commit 99ff973

Browse files
adriaanmlrytz
authored andcommitted
Use FUNmode and wild pt in typing the m in m _
We'll use the expected type when we type the eta-expansion that was requested. We know `m` is expected to be a method, since only methods can be followed by `_` to request eta-expansion. So, have the expected type reflect that. Since the original expected type won't be compatible with the method type that FUNmode gives us (method values are not first class), we have to defer using the given expected type until we eta-expanded, which results in a function, which is first class. When typing under FUNmode under pt=* we can let implicit conversion do its thing, before we wrap this in a function. See scala/bug#8299.
1 parent 33a56a3 commit 99ff973

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

src/compiler/scala/tools/nsc/typechecker/Typers.scala

+9-1
Original file line numberDiff line numberDiff line change
@@ -5373,7 +5373,15 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
53735373
// because `expr` might contain nested macro calls (see scala/bug#6673).
53745374
// Otherwise, (check for dead code, and) eta-expand.
53755375
case MethodValue(expr) =>
5376-
typed1(suppressMacroExpansion(expr), mode, pt) match {
5376+
// Need to type in FUNmode so that we accept a method type (which also means we can't use our pt),
5377+
// this does mean no overloading is performed. The main reason to ignore pt and move to FUNmode is that
5378+
// the `m` in `m _` could involve an implicit conversion, which will go through adapt after converting,
5379+
// which will run afoul of the restriction that a method-typed tree is only allowed when a function type is expected.
5380+
// We peeled off the `_` marker for the typed1 call, so we don't know that the user has requested eta-expansion.
5381+
// See scala/bug#8299.
5382+
val funTyped = typed1(suppressMacroExpansion(expr), mode | FUNmode, WildcardType)
5383+
if (funTyped.tpe.isInstanceOf[OverloadedType]) inferExprAlternative(funTyped, pt)
5384+
funTyped match {
53775385
case macroDef if treeInfo.isMacroApplication(macroDef) => MacroEtaError(macroDef)
53785386
case methodValue => typedEta(checkDead(methodValue))
53795387
}

test/files/pos/t8299.scala

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
object Test extends App {
2+
class C
3+
4+
implicit class CompatibleC(c: C) {
5+
def foo(x: Int) = ???
6+
}
7+
8+
val c: C = ???
9+
println(c.foo _)
10+
11+
object B {
12+
def f(x: Int) = x
13+
def f(x: String) = x
14+
}
15+
16+
val fun: Int => Int = B.f _
17+
val funs: String => String = B.f _
18+
}

0 commit comments

Comments
 (0)