diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 01e66223d4e6..f9eaf02c0327 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -193,6 +193,12 @@ trait Applications extends Compatibility { self: Typer with Dynamic => */ protected def liftFun(): Unit = () + /** Whether `liftFun` is needed? It is the case if default arguments are used. + */ + protected def needLiftFun: Boolean = + !isJavaAnnotConstr(methRef.symbol) && + args.size < reqiredArgNum(funType) + /** A flag signalling that the typechecking the application was so far successful */ private[this] var _ok = true @@ -205,12 +211,25 @@ trait Applications extends Compatibility { self: Typer with Dynamic => /** The function's type after widening and instantiating polytypes * with TypeParamRefs in constraint set */ - val methType = funType.widen match { + lazy val methType: Type = liftedFunType.widen match { case funType: MethodType => funType case funType: PolyType => constrained(funType).resultType case tp => tp //was: funType } + def reqiredArgNum(tp: Type): Int = tp.widen match { + case funType: MethodType => funType.paramInfos.size + case funType: PolyType => reqiredArgNum(funType.resultType) + case tp => args.size + } + + lazy val liftedFunType = + if (needLiftFun) { + liftFun() + normalizedFun.tpe + } + else funType + /** The arguments re-ordered so that each named argument matches the * same-named formal parameter. */ @@ -231,6 +250,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => () else fail(err.typeMismatchMsg(methType.resultType, resultType)) + // match all arguments with corresponding formal parameters matchArgs(orderedArgs, methType.paramInfos, 0) case _ => @@ -425,8 +445,6 @@ trait Applications extends Compatibility { self: Typer with Dynamic => } def tryDefault(n: Int, args1: List[Arg]): Unit = { - if (!isJavaAnnotConstr(methRef.symbol)) - liftFun() val getter = findDefaultGetter(n + numArgs(normalizedFun)) if (getter.isEmpty) missingArg(n) else { diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 2f39b07aa998..0ebad2f1b7d4 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -46,7 +46,8 @@ abstract class Lifter { if (noLift(expr)) expr else { val name = UniqueName.fresh(prefix) - var liftedType = fullyDefinedType(expr.tpe.widen, "lifted expression", expr.pos) + // don't instantiate here, as the type params could be further constrained, see tests/pos/pickleinf.scala + var liftedType = expr.tpe.widen if (liftedFlags.is(Method)) liftedType = ExprType(liftedType) val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags, liftedType, coord = positionCoord(expr.pos)) defs += liftedDef(lifted, expr).withPos(expr.pos.focus) diff --git a/tests/pos/i4419.scala b/tests/pos/i4419.scala new file mode 100644 index 000000000000..70df572680f6 --- /dev/null +++ b/tests/pos/i4419.scala @@ -0,0 +1,12 @@ +class Foo(config: String) { + case class Bar(val x: Int) { + def doThings: String = config //Do whatever here + } +} + + +object Test { + def test(foo: Foo)(bar: foo.Bar = foo.Bar(5)) = ??? + + test(new Foo("port"))() +}