From 8a725f3ee6d5e9fd7b61229853791e9e7e5f2737 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 28 Jul 2019 17:27:10 +0200 Subject: [PATCH 1/2] Fix #6705: Improve adaptation of overloaded terms If a term is overloaded and the expected type is not an application, prefer the parameterless alternative. --- .../dotty/tools/dotc/typer/ProtoTypes.scala | 6 ++++-- .../src/dotty/tools/dotc/typer/Typer.scala | 20 +++++++++++++------ tests/pos/i6705.scala | 14 +++++++++++++ 3 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 tests/pos/i6705.scala 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..b6cc34594263 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 and 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 From 311b72614b1afc58e95b75f157ed576018f7e80c Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 31 Jul 2019 10:12:22 +0200 Subject: [PATCH 2/2] Update compiler/src/dotty/tools/dotc/typer/Typer.scala Co-Authored-By: Guillaume Martres --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index b6cc34594263..bbe69402fcd1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2422,7 +2422,7 @@ class Typer extends Namer 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 and apply or implicit + // 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 =