diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index e7bf09239bdf..c00ec5eec64d 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -5552,6 +5552,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 @@ -5604,16 +5605,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 -------------------------------------------------------------------- diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 08437a529a88..4604ea2873e7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -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 diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index cfb464e4fec8..cb5fae0e9799 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1327,7 +1327,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 @@ -4188,12 +4188,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 _ => } diff --git a/tests/pos/i17183.scala b/tests/neg/i17183b.scala similarity index 68% rename from tests/pos/i17183.scala rename to tests/neg/i17183b.scala index b53a2b138985..476c216c8e18 100644 --- a/tests/pos/i17183.scala +++ b/tests/neg/i17183b.scala @@ -6,4 +6,4 @@ trait MyFunc { case class Context(f: MyFunc) -def test = Context(f = (_, _) => ???) +def test = Context(f = (_, _) => ???) // error // error