diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index bbec037ebef1..32c5e39a7e22 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -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 -------------------------------------------------------------------- diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index fbed4b77d3fe..4d03e9760ff6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 375289b5b400..3f3c4021edbd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -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))) @@ -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 diff --git a/tests/neg/i17183.check b/tests/neg/i17183.check new file mode 100644 index 000000000000..37e0c5fd75c2 --- /dev/null +++ b/tests/neg/i17183.check @@ -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) => ???. diff --git a/tests/neg/i17183.scala b/tests/neg/i17183.scala new file mode 100644 index 000000000000..a7d2d51c5935 --- /dev/null +++ b/tests/neg/i17183.scala @@ -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