Skip to content

Commit f641a87

Browse files
committed
Fix guarding & converting SAM result type to a function type
In decomposeProtoFunction I wanted to reuse WithFunctionType by running toFunctionType on the whole SAM and then dropping the first parameters. But with result dependent functions that results in a refined type, which is composed of: * the function with a result that is a non-depedent approximation * the original, non-function, method type So I went back to calling toFunctionType on the method result type specifically, like it used to be. Which means I stopped using the SAMType.WithFunctionType extract, so I merged it with its remaining usage with subtype checking and called the SAMType.isSamCompatible.
1 parent 9880cea commit f641a87

File tree

3 files changed

+19
-24
lines changed

3 files changed

+19
-24
lines changed

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

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5569,16 +5569,15 @@ object Types {
55695569
}
55705570
else None
55715571

5572-
object WithFunctionType:
5573-
def unapply(tp: Type)(using Context): Option[(MethodType, Type)] = tp match
5574-
case SAMType(mt) if !isParamDependentRec(mt) =>
5575-
Some((mt, mt.toFunctionType(isJava = tp.classSymbol.is(JavaDefined))))
5576-
case _ => None
5572+
def isSamCompatible(lhs: Type, rhs: Type)(using Context): Boolean = rhs match
5573+
case SAMType(mt) if !isParamDependentRec(mt) =>
5574+
lhs <:< mt.toFunctionType(isJava = rhs.classSymbol.is(JavaDefined))
5575+
case _ => false
55775576

5578-
private def isParamDependentRec(mt: MethodType)(using Context): Boolean =
5579-
mt.isParamDependent || mt.resultType.match
5580-
case mt: MethodType => isParamDependentRec(mt)
5581-
case _ => false
5577+
def isParamDependentRec(mt: MethodType)(using Context): Boolean =
5578+
mt.isParamDependent || mt.resultType.match
5579+
case mt: MethodType => isParamDependentRec(mt)
5580+
case _ => false
55825581
}
55835582

55845583
// ----- TypeMaps --------------------------------------------------------------------

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

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

697697
def SAMargOK =
698-
defn.isFunctionType(argtpe1) && formal.match
699-
case SAMType.WithFunctionType(_, fntpe) => argtpe <:< fntpe
700-
case _ => false
698+
defn.isFunctionType(argtpe1) && SAMType.isSamCompatible(argtpe, formal)
701699

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

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13351335
case RefinedType(parent, nme.apply, mt @ MethodTpe(_, formals, restpe))
13361336
if (defn.isNonRefinedFunction(parent) || defn.isErasedFunctionType(parent)) && formals.length == defaultArity =>
13371337
(formals, untpd.DependentTypeTree(syms => restpe.substParams(mt, syms.map(_.termRef))))
1338-
case SAMType.WithFunctionType(mt @ MethodTpe(_, formals, _), defn.FunctionOf(_, restpe, _)) =>
1338+
case pt1 @ SAMType(mt @ MethodTpe(_, formals, _)) if !SAMType.isParamDependentRec(mt) =>
1339+
val restpe = mt.resultType match
1340+
case mt: MethodType => mt.toFunctionType(isJava = pt1.classSymbol.is(JavaDefined))
1341+
case tp => tp
13391342
(formals,
13401343
if (mt.isResultDependent)
13411344
untpd.DependentTypeTree(syms => restpe.substParams(mt, syms.map(_.termRef)))
@@ -4126,17 +4129,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
41264129
// convert function literal to SAM closure
41274130
tree match {
41284131
case closure(Nil, id @ Ident(nme.ANON_FUN), _)
4129-
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) =>
4130-
pt match {
4131-
case SAMType.WithFunctionType(_, fntpe)
4132-
if wtp <:< fntpe =>
4133-
// was ... && isFullyDefined(pt, ForceDegree.flipBottom)
4134-
// but this prevents case blocks from implementing polymorphic partial functions,
4135-
// since we do not know the result parameter a priori. Have to wait until the
4136-
// body is typechecked.
4137-
return toSAM(tree)
4138-
case _ =>
4139-
}
4132+
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) && SAMType.isSamCompatible(wtp, pt) =>
4133+
// was ... && isFullyDefined(pt, ForceDegree.flipBottom)
4134+
// but this prevents case blocks from implementing polymorphic partial functions,
4135+
// since we do not know the result parameter a priori. Have to wait until the
4136+
// body is typechecked.
4137+
return toSAM(tree)
41404138
case _ =>
41414139
}
41424140

0 commit comments

Comments
 (0)