Skip to content

Commit

Permalink
Avoid SAM with param-dependent result crashing
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed Jun 5, 2023
1 parent 8812638 commit 9880cea
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 7 deletions.
11 changes: 11 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5568,6 +5568,17 @@ object Types {
else None
}
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

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

// ----- TypeMaps --------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ trait Applications extends Compatibility {

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

isCompatible(argtpe, formal)
Expand Down
9 changes: 3 additions & 6 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1335,10 +1335,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.DependentTypeTree(syms => restpe.substParams(mt, syms.map(_.termRef))))
case pt1 @ SAMType(mt @ MethodTpe(_, formals, methResType)) =>
val restpe = methResType match
case mt: MethodType if !mt.isParamDependent => mt.toFunctionType(isJava = pt1.classSymbol.is(JavaDefined))
case tp => tp
case SAMType.WithFunctionType(mt @ MethodTpe(_, formals, _), defn.FunctionOf(_, restpe, _)) =>
(formals,
if (mt.isResultDependent)
untpd.DependentTypeTree(syms => restpe.substParams(mt, syms.map(_.termRef)))
Expand Down Expand Up @@ -4131,8 +4128,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
case closure(Nil, id @ Ident(nme.ANON_FUN), _)
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) =>
pt match {
case SAMType(sam)
if wtp <:< sam.toFunctionType(isJava = pt.classSymbol.is(JavaDefined)) =>
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
Expand Down
14 changes: 14 additions & 0 deletions tests/neg/i17183.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- [E081] Type Error: tests/neg/i17183.scala:11:24 ---------------------------------------------------------------------
11 |def test = Context(f = (_, _) => ???) // error // error
| ^
| Missing parameter type
|
| I could not infer the type of the parameter _$1 of expanded function:
| (_$1, _$2) => ???.
-- [E081] Type Error: tests/neg/i17183.scala:11:27 ---------------------------------------------------------------------
11 |def test = Context(f = (_, _) => ???) // error // error
| ^
| Missing parameter type
|
| I could not infer the type of the parameter _$2 of expanded function:
| (_$1, _$2) => ???.
11 changes: 11 additions & 0 deletions tests/neg/i17183.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
trait Dependency {
trait More
}

trait MyFunc {
def apply(a: Int, b: String)(using dep: Dependency, more: dep.More): String
}

case class Context(f: MyFunc)

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

0 comments on commit 9880cea

Please sign in to comment.