Skip to content

Commit e0f566b

Browse files
committed
Fix #2367: Allow SAM conversion for overloaded functions
If just one of a number of alternatives is a SAM, allow a lambda argument, just like we do for non-overloaded methods with SAM type parameters.
1 parent 56933ec commit e0f566b

File tree

3 files changed

+32
-17
lines changed

3 files changed

+32
-17
lines changed

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

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -474,21 +474,24 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
474474
type TypedArg = Arg
475475
type Result = Unit
476476

477+
protected def argOK(arg: TypedArg, formal: Type) = argType(arg, formal) match {
478+
case ref: TermRef if ref.denot.isOverloaded =>
479+
// in this case we could not resolve overloading because no alternative
480+
// matches expected type
481+
false
482+
case argtpe =>
483+
def SAMargOK = formal match {
484+
case SAMType(meth) =>argtpe <:< meth.info.toFunctionType()
485+
case _ => false
486+
}
487+
isCompatible(argtpe, formal) || SAMargOK
488+
}
489+
477490
/** The type of the given argument */
478491
protected def argType(arg: Arg, formal: Type): Type
479492

480493
def typedArg(arg: Arg, formal: Type): Arg = arg
481-
def addArg(arg: TypedArg, formal: Type) =
482-
ok = ok & {
483-
argType(arg, formal) match {
484-
case ref: TermRef if ref.denot.isOverloaded =>
485-
// in this case we could not resolve overloading because no alternative
486-
// matches expected type
487-
false
488-
case argtpe =>
489-
isCompatible(argtpe, formal)
490-
}
491-
}
494+
final def addArg(arg: TypedArg, formal: Type) = ok = ok & argOK(arg, formal)
492495
def makeVarArg(n: Int, elemFormal: Type) = {}
493496
def fail(msg: => Message, arg: Arg) =
494497
ok = false
@@ -512,11 +515,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
512515
}
513516

514517
/** Subclass of Application for applicability tests with type arguments and value
515-
* argument trees.
516-
*/
518+
* argument trees.
519+
*/
517520
class ApplicableToTreesDirectly(methRef: TermRef, targs: List[Type], args: List[Tree], resultType: Type)(implicit ctx: Context) extends ApplicableToTrees(methRef, targs, args, resultType)(ctx) {
518-
override def addArg(arg: TypedArg, formal: Type) =
519-
ok = ok & (argType(arg, formal) <:< formal)
521+
override def argOK(arg: TypedArg, formal: Type) = argType(arg, formal) <:< formal
520522
}
521523

522524
/** Subclass of Application for applicability tests with value argument types. */

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,6 +2161,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
21612161
}
21622162
}
21632163

2164+
def toSAM(tree: Tree): Tree = tree match {
2165+
case tree: Block => tpd.cpy.Block(tree)(tree.stats, toSAM(tree.expr))
2166+
case tree: Closure => tpd.cpy.Closure(tree)(tpt = TypeTree(pt)).withType(pt)
2167+
}
2168+
21642169
def adaptToSubType(wtp: Type): Tree = {
21652170
// try converting a constant to the target type
21662171
val folded = ConstFold(tree, pt)
@@ -2172,7 +2177,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
21722177
return tpd.Block(adapt(tree, WildcardType) :: Nil, Literal(Constant(())))
21732178
// convert function literal to SAM closure
21742179
tree match {
2175-
case Closure(Nil, id @ Ident(nme.ANON_FUN), _)
2180+
case closure(Nil, id @ Ident(nme.ANON_FUN), _)
21762181
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) =>
21772182
pt match {
21782183
case SAMType(meth)
@@ -2181,7 +2186,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
21812186
// but this prevents case blocks from implementing polymorphic partial functions,
21822187
// since we do not know the result parameter a priori. Have to wait until the
21832188
// body is typechecked.
2184-
return cpy.Closure(tree)(Nil, id, TypeTree(pt)).withType(pt)
2189+
return toSAM(tree)
21852190
case _ =>
21862191
}
21872192
case _ =>

tests/pos/i2367.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Test {
2+
new Thread(() => println("hi"))
3+
4+
def foo(x: Int => Int, y: Int): Int = 1
5+
def foo(x: Int, y: Int): Int = 2
6+
foo(1, 2)
7+
foo(x => x, 2)
8+
}

0 commit comments

Comments
 (0)