diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 2e7979a98c25..567647e269c5 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -126,7 +126,7 @@ object Contexts { protected def sstate_=(sstate: SettingsState) = _sstate = sstate def sstate: SettingsState = _sstate - /** The current tree */ + /** The current compilation unit */ private[this] var _compilationUnit: CompilationUnit = _ protected def compilationUnit_=(compilationUnit: CompilationUnit) = _compilationUnit = compilationUnit def compilationUnit: CompilationUnit = _compilationUnit diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index af0861ad6bf2..a4f4419b1fad 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1209,20 +1209,29 @@ object messages { |""".stripMargin } - case class OverloadedOrRecursiveMethodNeedsResultType(tree: Names.TermName)(implicit ctx: Context) + case class OverloadedOrRecursiveMethodNeedsResultType private (termName: String)(implicit ctx: Context) extends Message(OverloadedOrRecursiveMethodNeedsResultTypeID) { val kind = "Syntax" - val msg = hl"""overloaded or recursive method ${tree} needs return type""" + val msg = hl"""overloaded or recursive method $termName needs return type""" val explanation = - hl"""Case 1: ${tree} is overloaded - |If there are multiple methods named `${tree.name}` and at least one definition of + hl"""Case 1: $termName is overloaded + |If there are multiple methods named `$termName` and at least one definition of |it calls another, you need to specify the calling method's return type. | - |Case 2: ${tree} is recursive - |If `${tree.name}` calls itself on any path, you need to specify its return type. + |Case 2: $termName is recursive + |If `$termName` calls itself on any path, you need to specify its return type. |""".stripMargin } + object OverloadedOrRecursiveMethodNeedsResultType { + def apply[T >: Trees.Untyped](tree: NameTree[T])(implicit ctx: Context) + : OverloadedOrRecursiveMethodNeedsResultType = + OverloadedOrRecursiveMethodNeedsResultType(tree.name.show)(ctx) + def apply(symbol: Symbol)(implicit ctx: Context) + : OverloadedOrRecursiveMethodNeedsResultType = + OverloadedOrRecursiveMethodNeedsResultType(symbol.name.show)(ctx) + } + case class RecursiveValueNeedsResultType(tree: Names.TermName)(implicit ctx: Context) extends Message(RecursiveValueNeedsResultTypeID) { val kind = "Syntax" @@ -1320,7 +1329,8 @@ object messages { |""" } - case class MethodDoesNotTakeParameters(tree: tpd.Tree, methPartType: Types.Type)(err: typer.ErrorReporting.Errors)(implicit ctx: Context) + case class MethodDoesNotTakeParameters(tree: tpd.Tree, methPartType: Types.Type) + (err: typer.ErrorReporting.Errors)(implicit ctx: Context) extends Message(MethodDoesNotTakeParametersId) { private val more = tree match { case Apply(_, _) => " more" diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index d0ab39a988c4..209f79d9c424 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -32,7 +32,7 @@ object ErrorReporting { if (cx.mode is Mode.InferringReturnType) { cx.tree match { case tree: untpd.DefDef if !tree.tpt.typeOpt.exists => - OverloadedOrRecursiveMethodNeedsResultType(tree.name) + OverloadedOrRecursiveMethodNeedsResultType(tree) case tree: untpd.ValDef if !tree.tpt.typeOpt.exists => RecursiveValueNeedsResultType(tree.name) case _ => diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index c8f2c26874ad..b5cb7d71e72e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1929,7 +1929,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit else tree case _ => tryInsertApplyOrImplicit(tree, pt) { - errorTree(tree, MethodDoesNotTakeParameters(tree, methPart(tree).tpe)(err)) + pt.resType match { + case IgnoredProto(WildcardType(optBounds)) + if (optBounds == NoType) && (pt.args.size == tree.productArity) => + errorTree(tree, OverloadedOrRecursiveMethodNeedsResultType(tree.symbol)) + case resType => + errorTree(tree, MethodDoesNotTakeParameters(tree, methPart(tree).tpe)(err)) + } } } diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 2a3aa52cad38..b0395c5f3d93 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -200,7 +200,7 @@ class ErrorMessagesTests extends ErrorMessagesTest { assertTrue("expected trait", isTrait) } - @Test def overloadedMethodNeedsReturnType = + @Test def overloadedMethodNeedsReturnType = { checkMessagesAfter("frontend") { """ |class Scope() { @@ -214,10 +214,25 @@ class ErrorMessagesTests extends ErrorMessagesTest { val defn = ictx.definitions assertMessageCount(1, messages) - val OverloadedOrRecursiveMethodNeedsResultType(tree) :: Nil = messages - assertEquals("foo", tree.show) + val OverloadedOrRecursiveMethodNeedsResultType(treeName) :: Nil = messages + assertEquals("foo", treeName) } + + checkMessagesAfter("frontend") { + """ + |case class Foo[T](x: T) + |object Foo { def apply[T]() = Foo(null.asInstanceOf[T]) } + """.stripMargin + }.expect { (ictx, messages) => + implicit val ctx: Context = ictx + + assertMessageCount(1, messages) + val OverloadedOrRecursiveMethodNeedsResultType(treeName2) :: Nil = messages + assertEquals("Foo", treeName2) + } + } + @Test def recursiveMethodNeedsReturnType = checkMessagesAfter("frontend") { """ @@ -231,8 +246,8 @@ class ErrorMessagesTests extends ErrorMessagesTest { val defn = ictx.definitions assertMessageCount(1, messages) - val OverloadedOrRecursiveMethodNeedsResultType(tree) :: Nil = messages - assertEquals("i", tree.show) + val OverloadedOrRecursiveMethodNeedsResultType(treeName) :: Nil = messages + assertEquals("i", treeName) } @Test def recursiveValueNeedsReturnType =