diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 9f83157981b5..43b035bcedfa 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -222,7 +222,9 @@ object ProtoTypes { class UnapplySelectionProto(name: Name) extends SelectionProto(name, WildcardType, NoViewsAllowed, true) trait ApplyingProto extends ProtoType // common trait of ViewProto and FunProto - trait FunOrPolyProto extends ProtoType // common trait of PolyProto and FunProto + trait FunOrPolyProto extends ProtoType { // common trait of PolyProto and FunProto + def isGivenApply: Boolean = false + } class FunProtoState { @@ -244,7 +246,7 @@ object ProtoTypes { * [](args): resultType */ case class FunProto(args: List[untpd.Tree], resType: Type)(typer: Typer, - val isGivenApply: Boolean, state: FunProtoState = new FunProtoState)(implicit val ctx: Context) + override val isGivenApply: Boolean, state: FunProtoState = new FunProtoState)(implicit val ctx: Context) extends UncachedGroundType with ApplyingProto with FunOrPolyProto { override def resultType(implicit ctx: Context): Type = resType diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 00289794ee73..bbe69402fcd1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2421,18 +2421,26 @@ class Typer extends Namer case alt :: Nil => readaptSimplified(tree.withType(alt)) case Nil => + // If alternative matches, there are still two ways to recover: + // 1. If context is an application, try to insert an apply or implicit + // 2. If context is not an application, pick a alternative that does + // not take parameters. def noMatches = errorTree(tree, NoMatchingOverload(altDenots, pt)(err)) def hasEmptyParams(denot: SingleDenotation) = denot.info.paramInfoss == ListOfNil pt match { - case pt: FunProto if !pt.isGivenApply => - // insert apply or convert qualifier only for a regular application + case pt: FunOrPolyProto if !pt.isGivenApply => + // insert apply or convert qualifier, but only for a regular application tryInsertApplyOrImplicit(tree, pt, locked)(noMatches) case _ => - if (altDenots exists (_.info.paramInfoss == ListOfNil)) - typed(untpd.Apply(untpd.TypedSplice(tree), Nil), pt, locked) - else - noMatches + alts.filter(_.info.isParameterless) match { + case alt :: Nil => readaptSimplified(tree.withType(alt)) + case _ => + if (altDenots exists (_.info.paramInfoss == ListOfNil)) + typed(untpd.Apply(untpd.TypedSplice(tree), Nil), pt, locked) + else + noMatches + } } case alts => if (tree.tpe.isErroneous || pt.isErroneous) tree.withType(UnspecifiedErrorType) diff --git a/tests/pos/i6705.scala b/tests/pos/i6705.scala new file mode 100644 index 000000000000..40ad62cf1713 --- /dev/null +++ b/tests/pos/i6705.scala @@ -0,0 +1,14 @@ +trait StringTempl { + def mkString: String + def mkString(x: String): String +} + + +object Test { + def (x: String) shouldBe(y: String): Boolean = ??? + + def test(tmpl: StringTempl): Unit = { + tmpl.mkString shouldBe "hello" // error + tmpl.mkString(", world") shouldBe "hello, world" + } +} \ No newline at end of file