Skip to content

Commit 13f877b

Browse files
authored
Curried methods are not valid SAM methods (#18110)
This reverts most of #17740 and instead add a check on currying in SAMType. We could consider allowing curried methods in SAM types, but this would be a language change that requires a SIP, and the implementation would need an adaptation step in erasure since the invokedynamic method needs to have a compatible signature with the abstract method in the trait.
2 parents 819c625 + 6087293 commit 13f877b

File tree

4 files changed

+17
-19
lines changed

4 files changed

+17
-19
lines changed

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

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5552,6 +5552,7 @@ object Types {
55525552
if (absMems.size == 1)
55535553
absMems.head.info match {
55545554
case mt: MethodType if !mt.isParamDependent &&
5555+
mt.resultType.isValueTypeOrWildcard &&
55555556
!defn.isContextFunctionType(mt.resultType) =>
55565557
val cls = tp.classSymbol
55575558

@@ -5604,16 +5605,6 @@ object Types {
56045605
else None
56055606
}
56065607
else None
5607-
5608-
def isSamCompatible(lhs: Type, rhs: Type)(using Context): Boolean = rhs match
5609-
case SAMType(mt) if !isParamDependentRec(mt) =>
5610-
lhs <:< mt.toFunctionType(isJava = rhs.classSymbol.is(JavaDefined))
5611-
case _ => false
5612-
5613-
def isParamDependentRec(mt: MethodType)(using Context): Boolean =
5614-
mt.isParamDependent || mt.resultType.match
5615-
case mt: MethodType => isParamDependentRec(mt)
5616-
case _ => false
56175608
}
56185609

56195610
// ----- TypeMaps --------------------------------------------------------------------

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,9 @@ trait Applications extends Compatibility {
695695
val argtpe1 = argtpe.widen
696696

697697
def SAMargOK =
698-
defn.isFunctionType(argtpe1) && SAMType.isSamCompatible(argtpe, formal)
698+
defn.isFunctionType(argtpe1) && formal.match
699+
case SAMType(sam) => argtpe <:< sam.toFunctionType(isJava = formal.classSymbol.is(JavaDefined))
700+
case _ => false
699701

700702
isCompatible(argtpe, formal)
701703
// Only allow SAM-conversion to PartialFunction if implicit conversions

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13271327
case RefinedType(parent, nme.apply, mt @ MethodTpe(_, formals, restpe))
13281328
if (defn.isNonRefinedFunction(parent) || defn.isErasedFunctionType(parent)) && formals.length == defaultArity =>
13291329
(formals, untpd.InLambdaTypeTree(isResult = true, (_, syms) => restpe.substParams(mt, syms.map(_.termRef))))
1330-
case pt1 @ SAMType(mt @ MethodTpe(_, formals, _)) if !SAMType.isParamDependentRec(mt) =>
1330+
case pt1 @ SAMType(mt @ MethodTpe(_, formals, _)) =>
13311331
val restpe = mt.resultType match
13321332
case mt: MethodType => mt.toFunctionType(isJava = pt1.classSymbol.is(JavaDefined))
13331333
case tp => tp
@@ -4188,12 +4188,17 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
41884188
// convert function literal to SAM closure
41894189
tree match {
41904190
case closure(Nil, id @ Ident(nme.ANON_FUN), _)
4191-
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) && SAMType.isSamCompatible(wtp, pt) =>
4192-
// was ... && isFullyDefined(pt, ForceDegree.flipBottom)
4193-
// but this prevents case blocks from implementing polymorphic partial functions,
4194-
// since we do not know the result parameter a priori. Have to wait until the
4195-
// body is typechecked.
4196-
return toSAM(tree)
4191+
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) =>
4192+
pt match {
4193+
case SAMType(sam)
4194+
if wtp <:< sam.toFunctionType(isJava = pt.classSymbol.is(JavaDefined)) =>
4195+
// was ... && isFullyDefined(pt, ForceDegree.flipBottom)
4196+
// but this prevents case blocks from implementing polymorphic partial functions,
4197+
// since we do not know the result parameter a priori. Have to wait until the
4198+
// body is typechecked.
4199+
return toSAM(tree)
4200+
case _ =>
4201+
}
41974202
case _ =>
41984203
}
41994204

tests/pos/i17183.scala renamed to tests/neg/i17183b.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ trait MyFunc {
66

77
case class Context(f: MyFunc)
88

9-
def test = Context(f = (_, _) => ???)
9+
def test = Context(f = (_, _) => ???) // error // error

0 commit comments

Comments
 (0)