From caff1fe69caed417818fc0aeb6abb2f18b0fad9b Mon Sep 17 00:00:00 2001 From: Enno Runne Date: Tue, 2 May 2017 21:50:59 +0200 Subject: [PATCH 1/3] Moved Ambiguous Overload error in Typer to case class --- .../reporting/diagnostic/ErrorMessageID.java | 1 + .../dotc/reporting/diagnostic/messages.scala | 22 +++++++++++++++ .../src/dotty/tools/dotc/typer/Typer.scala | 8 ++---- .../dotc/reporting/ErrorMessagesTests.scala | 27 +++++++++++++++++++ 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index 73bec87c01df..6e50d9580711 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -57,6 +57,7 @@ public enum ErrorMessageID { CyclicReferenceInvolvingImplicitID, SuperQualMustBeParentID, AmbiguousImportID, + AmbiguousOverloadID, ; public int errorNumber() { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index aa70443db42e..7ff9e98bc422 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -18,6 +18,7 @@ import dotc.parsing.Tokens import printing.Highlighting._ import printing.Formatting import ErrorMessageID._ +import Denotations.SingleDenotation import dotty.tools.dotc.core.SymDenotations.SymDenotation object messages { @@ -1253,4 +1254,25 @@ object messages { |""" } + case class AmbiguousOverload(tree: tpd.Tree, alts: List[SingleDenotation], pt: Type)( + err: typer.ErrorReporting.Errors)( + implicit ctx: Context) + extends Message(AmbiguousOverloadID) { + + private def all = if (alts.length == 2) "both" else "all" + + override def msg: String = + s"""|Ambiguous overload. The ${err.overloadedAltsStr(alts)} + |$all match ${err.expectedTypeStr(pt)}""".stripMargin + + override def kind: String = "Reference" + + override def explanation: String = + s"""|There are ${alts.length} methods that could be referenced as the compiler knows too little about the expected type. + |You may specify the expected type e.g. by + |- assigning it to a value with a specified type, or + |- adding a type ascription as in (MyClass.myMethod: String => Int) + |""".stripMargin + } + } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index bc5d3c882bda..46afdffa03f9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1791,7 +1791,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit typr.println(i"adapt overloaded $ref with alternatives ${altDenots map (_.info)}%, %") val alts = altDenots map (alt => TermRef.withSigAndDenot(ref.prefix, ref.name, alt.info.signature, alt)) - def expectedStr = err.expectedTypeStr(pt) resolveOverloaded(alts, pt) match { case alt :: Nil => adapt(tree.withType(alt), pt, original) @@ -1799,7 +1798,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def noMatches = errorTree(tree, em"""none of the ${err.overloadedAltsStr(altDenots)} - |match $expectedStr""") + |match ${err.expectedTypeStr(pt)}""") def hasEmptyParams(denot: SingleDenotation) = denot.info.paramInfoss == ListOfNil pt match { case pt: FunProto => @@ -1812,10 +1811,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } case alts => val remainingDenots = alts map (_.denot.asInstanceOf[SingleDenotation]) - def all = if (remainingDenots.length == 2) "both" else "all" - errorTree(tree, - em"""Ambiguous overload. The ${err.overloadedAltsStr(remainingDenots)} - |$all match $expectedStr""") + errorTree(tree, AmbiguousOverload(tree, remainingDenots, pt)(err)) } } diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 789d8e3cc9b1..0efef736f511 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -4,6 +4,7 @@ package reporting import core.Contexts.Context import diagnostic.messages._ +import dotty.tools.dotc.core.Types.WildcardType import dotty.tools.dotc.parsing.Tokens import org.junit.Assert._ import org.junit.{Ignore, Test} @@ -358,4 +359,30 @@ class ErrorMessagesTests extends ErrorMessagesTest { assertEquals(namedImport, newPrec) assertEquals(namedImport, prevPrec) } + + @Test def ambiugousOverloadWithWildcard = + checkMessagesAfter("frontend") { + """object Context { + | trait A { + | def foo(s: String): String + | def foo: String = foo("foo") + | } + | object B extends A { + | def foo(s: String): String = s + | } + | B.foo + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + val defn = ictx.definitions + + assertMessageCount(1, messages) + val AmbiguousOverload(tree, List(alt1, alt2), pt: WildcardType) :: Nil = messages + assertEquals("method foo", alt1.show) + assertEquals("(s: String)String", alt1.info.show) + assertEquals("method foo", alt2.show) + } + } From 2cef3860679fb43c6dbb981fbe6f0234e40c82f4 Mon Sep 17 00:00:00 2001 From: Enno Runne Date: Wed, 3 May 2017 08:22:21 +0200 Subject: [PATCH 2/3] Correct type ascription example in explanation --- .../src/dotty/tools/dotc/reporting/diagnostic/messages.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 7ff9e98bc422..430b0c9f31fd 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1271,7 +1271,7 @@ object messages { s"""|There are ${alts.length} methods that could be referenced as the compiler knows too little about the expected type. |You may specify the expected type e.g. by |- assigning it to a value with a specified type, or - |- adding a type ascription as in (MyClass.myMethod: String => Int) + |- adding a type ascription as in `(instance.myMethod: String => Int)` |""".stripMargin } From 458ee55a8d723feb2efe39dcea38fc05a2bb0c7c Mon Sep 17 00:00:00 2001 From: Enno Runne Date: Wed, 3 May 2017 21:33:11 +0200 Subject: [PATCH 3/3] Clean up message signatures --- .../dotc/reporting/diagnostic/messages.scala | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 430b0c9f31fd..08a8e5650c38 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1194,7 +1194,6 @@ object messages { extends Message(SuperQualMustBeParentID) { val msg = hl"""|$qual does not name a parent of $cls""" - val kind = "Reference" private val parents: Seq[String] = (cls.info.parents map (_.name.show)).sorted @@ -1209,15 +1208,13 @@ object messages { } case class VarArgsParamMustComeLast()(implicit ctx: Context) - extends Message(IncorrectRepeatedParameterSyntaxID) { - override def msg: String = "varargs parameter must come last" - - override def kind: String = "Syntax" - - override def explanation: String = + extends Message(IncorrectRepeatedParameterSyntaxID) { + val msg = "varargs parameter must come last" + val kind = "Syntax" + val explanation = hl"""|The varargs field must be the last field in the method signature. |Attempting to define a field in a method signature after a varargs field is an error. - |""".stripMargin + |""" } case class AmbiguousImport(name: Names.Name, newPrec: Int, prevPrec: Int, prevCtx: Context)(implicit ctx: Context) @@ -1259,20 +1256,18 @@ object messages { implicit ctx: Context) extends Message(AmbiguousOverloadID) { - private def all = if (alts.length == 2) "both" else "all" - - override def msg: String = + private val all = if (alts.length == 2) "both" else "all" + val msg = s"""|Ambiguous overload. The ${err.overloadedAltsStr(alts)} |$all match ${err.expectedTypeStr(pt)}""".stripMargin - - override def kind: String = "Reference" - - override def explanation: String = - s"""|There are ${alts.length} methods that could be referenced as the compiler knows too little about the expected type. + val kind = "Reference" + val explanation = + hl"""|There are ${alts.length} methods that could be referenced as the compiler knows too little + |about the expected type. |You may specify the expected type e.g. by |- assigning it to a value with a specified type, or - |- adding a type ascription as in `(instance.myMethod: String => Int)` - |""".stripMargin + |- adding a type ascription as in `${"instance.myMethod: String => Int"}` + |""" } }