Skip to content

Commit

Permalink
Curried methods are not valid SAM methods
Browse files Browse the repository at this point in the history
This reverts most of scala#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.
  • Loading branch information
smarter committed Jul 5, 2023
1 parent c629090 commit 6087293
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 19 deletions.
11 changes: 1 addition & 10 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5536,6 +5536,7 @@ object Types {
if (absMems.size == 1)
absMems.head.info match {
case mt: MethodType if !mt.isParamDependent &&
mt.resultType.isValueTypeOrWildcard &&
!defn.isContextFunctionType(mt.resultType) =>
val cls = tp.classSymbol

Expand Down Expand Up @@ -5588,16 +5589,6 @@ object Types {
else None
}
else None

def isSamCompatible(lhs: Type, rhs: Type)(using Context): Boolean = rhs match
case SAMType(mt) if !isParamDependentRec(mt) =>
lhs <:< mt.toFunctionType(isJava = rhs.classSymbol.is(JavaDefined))
case _ => false

def isParamDependentRec(mt: MethodType)(using Context): Boolean =
mt.isParamDependent || mt.resultType.match
case mt: MethodType => isParamDependentRec(mt)
case _ => false
}

// ----- TypeMaps --------------------------------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,9 @@ trait Applications extends Compatibility {
val argtpe1 = argtpe.widen

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

isCompatible(argtpe, formal)
// Only allow SAM-conversion to PartialFunction if implicit conversions
Expand Down
19 changes: 12 additions & 7 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
case RefinedType(parent, nme.apply, mt @ MethodTpe(_, formals, restpe))
if (defn.isNonRefinedFunction(parent) || defn.isErasedFunctionType(parent)) && formals.length == defaultArity =>
(formals, untpd.InLambdaTypeTree(isResult = true, (_, syms) => restpe.substParams(mt, syms.map(_.termRef))))
case pt1 @ SAMType(mt @ MethodTpe(_, formals, _)) if !SAMType.isParamDependentRec(mt) =>
case pt1 @ SAMType(mt @ MethodTpe(_, formals, _)) =>
val restpe = mt.resultType match
case mt: MethodType => mt.toFunctionType(isJava = pt1.classSymbol.is(JavaDefined))
case tp => tp
Expand Down Expand Up @@ -4182,12 +4182,17 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
// convert function literal to SAM closure
tree match {
case closure(Nil, id @ Ident(nme.ANON_FUN), _)
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) && SAMType.isSamCompatible(wtp, pt) =>
// was ... && isFullyDefined(pt, ForceDegree.flipBottom)
// but this prevents case blocks from implementing polymorphic partial functions,
// since we do not know the result parameter a priori. Have to wait until the
// body is typechecked.
return toSAM(tree)
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) =>
pt match {
case SAMType(sam)
if wtp <:< sam.toFunctionType(isJava = pt.classSymbol.is(JavaDefined)) =>
// was ... && isFullyDefined(pt, ForceDegree.flipBottom)
// but this prevents case blocks from implementing polymorphic partial functions,
// since we do not know the result parameter a priori. Have to wait until the
// body is typechecked.
return toSAM(tree)
case _ =>
}
case _ =>
}

Expand Down
2 changes: 1 addition & 1 deletion tests/pos/i17183.scala → tests/neg/i17183b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ trait MyFunc {

case class Context(f: MyFunc)

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

0 comments on commit 6087293

Please sign in to comment.