diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 32c5e39a7e22..b58a923457cd 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -5569,16 +5569,15 @@ object Types { } else None - object WithFunctionType: - def unapply(tp: Type)(using Context): Option[(MethodType, Type)] = tp match - case SAMType(mt) if !isParamDependentRec(mt) => - Some((mt, mt.toFunctionType(isJava = tp.classSymbol.is(JavaDefined)))) - case _ => 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 - private def isParamDependentRec(mt: MethodType)(using Context): Boolean = - mt.isParamDependent || mt.resultType.match - case mt: MethodType => isParamDependentRec(mt) - 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 4d03e9760ff6..17b79ab0f801 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -695,9 +695,7 @@ trait Applications extends Compatibility { val argtpe1 = argtpe.widen def SAMargOK = - defn.isFunctionType(argtpe1) && formal.match - case SAMType.WithFunctionType(_, fntpe) => argtpe <:< fntpe - case _ => false + defn.isFunctionType(argtpe1) && SAMType.isSamCompatible(argtpe, formal) 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 3f3c4021edbd..e42c0eec165f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1335,7 +1335,10 @@ 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.DependentTypeTree(syms => restpe.substParams(mt, syms.map(_.termRef)))) - case SAMType.WithFunctionType(mt @ MethodTpe(_, formals, _), defn.FunctionOf(_, restpe, _)) => + case pt1 @ SAMType(mt @ MethodTpe(_, formals, _)) if !SAMType.isParamDependentRec(mt) => + val restpe = mt.resultType match + case mt: MethodType => mt.toFunctionType(isJava = pt1.classSymbol.is(JavaDefined)) + case tp => tp (formals, if (mt.isResultDependent) untpd.DependentTypeTree(syms => restpe.substParams(mt, syms.map(_.termRef))) @@ -4126,17 +4129,12 @@ 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) => - pt match { - case SAMType.WithFunctionType(_, fntpe) - if wtp <:< fntpe => - // 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 _ => - } + 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) case _ => }