Skip to content

Closes #1731 by fixing error message for overloaded method without re… #2823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

bbarker
Copy link
Contributor

@bbarker bbarker commented Jul 1, 2017

This was achieved by adding a more specific conditional to note the specific error and by overloading apply for the already existing OverloadedOrRecursiveMethodNeedsResultType.

While this is an improvement, it is still not quite right, as the error message now behaves like:

scala> case class Foo[T](x: T); object Foo { def apply[T]() = Foo(null.asInstanceOf[T]) } 
-- [E043] Syntax Error: <console>:4:55 -----------------------------------------
4 |case class Foo[T](x: T); object Foo { def apply[T]() = Foo(null.asInstanceOf[T]) }
  |                                                       ^^^
  |                      overloaded or recursive method Foo needs return type

To improve beyond this, it seems we would need some way to walk up the tree to get to the LHS (not sure if possible), or, catch it higher up the tree in the first place.

Copy link
Member

@dottybot dottybot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, and thank you for opening this PR! 🎉

All contributors have signed the CLA, thank you! ❤️

Have an awesome day! ☀️

Copy link
Contributor

@felixmulder felixmulder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to submit this PR! We really appreciate the thought going into these contributions.

There are a couple of things I'm hesitant about, but I await your response :)

OverloadedOrRecursiveMethodNeedsResultType(tree.name.toString)(ctx)
def apply(symbol: Symbol)(implicit ctx: Context)
: OverloadedOrRecursiveMethodNeedsResultType =
OverloadedOrRecursiveMethodNeedsResultType(symbol.name.toString)(ctx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a "Showable" type class that can be accessed for both trees and symbols via .show

@@ -48,7 +48,7 @@ object ProtoTypes {

private def disregardProto(pt: Type)(implicit ctx: Context): Boolean = pt.dealias match {
case _: OrType => true
case pt => pt.isRef(defn.UnitClass)
case ptd => ptd.isRef(defn.UnitClass)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe an unnecessary diff?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the 'case' pt shadows the outer pt, which may not be an issue here, but could crop up later if the function became more complex, I suppose. Happy to take it out though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the point here is to specifically shadow it, we do this all over the compiler :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -1872,8 +1872,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
*/
def adaptInterpolated(tree: Tree, pt: Type, original: untpd.Tree)(implicit ctx: Context): Tree = {

assert(pt.exists)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this assertion removed?

Copy link
Contributor Author

@bbarker bbarker Jul 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, I don't know - it shouldn't have been, sorry that typo slipped through (I really do not remember making this change, but still should have spotted it, hmm).

// val OverloadedOrRecursiveMethodNeedsResultType(treeName2) :: Nil = messages
// assertEquals("Foo", treeName2)
// }
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fine as it is reported after the front end (of which typer is a part). Why can't this test be enabled?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cloned your branch and tried out the commented out test - and it runs fine for me. Did you do git submodule update --init?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I thought I did but can't quite remember exactly which submodule command I originally ran. I tried this but it didn't make a difference. I'll uncomment for now and try to figure out my issue later.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submit it uncommented and we'll see what the CI says 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do, I'm getting a number of failures from sbt test so will see how this compares.

@@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

|""".stripMargin
}

object OverloadedOrRecursiveMethodNeedsResultType {
@specialized def apply[T >: Trees.Untyped](tree: NameTree[T])(implicit ctx: Context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the @specialized annotation, Dotty will have its own form of specialization that does not require the annotation. Also, the bootstrapped compiler currently doesn't do anything for @specialized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why make the name private? If you're an IDE, wouldn't you want to be able to extract the name from the message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought was to prevent accidental use that might happen by passing in a string directly; I may not understand all the implications, but even with private it seems I can still extract the string in ErrorMessagesTests.scala:

      val OverloadedOrRecursiveMethodNeedsResultType(treeName) :: Nil = messages
      assertEquals("i", treeName)

Seems to work

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I did correct this before having coffee. Ignore this comment, it's just the constructor marked private, not the members ☕️

@@ -126,7 +126,7 @@ object Contexts {
protected def sstate_=(sstate: SettingsState) = _sstate = sstate
def sstate: SettingsState = _sstate

/** The current tree */
/** The current compilation unit */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@bbarker
Copy link
Contributor Author

bbarker commented Jul 3, 2017

I'm thinking about revising the commit message to "fixes for #1731" instead of "closes", and just update the issue. I'll plan to come back to it soon for a full fix.

@bbarker bbarker force-pushed the 1731_overload_unhelpful_error_message branch from 3bc3c31 to 30ac9e2 Compare July 3, 2017 12:19
@felixmulder
Copy link
Contributor

felixmulder commented Jul 3, 2017

Looks like it ran just fine - except that the test fails with:

recursiveMethodNeedsReturnType failed:
org.junit.ComparisonFailure: expected:<[i]> but was:<[def i = i + 5]>

// and

overloadedMethodNeedsReturnType failed:
org.junit.ComparisonFailure: expected:<[foo]> but was:<[def foo(i: Int) = foo(i.toString)]>

hint:

tree.show      // string of tree as "scala-like" code
tree.name.show // string of name without encodings

@bbarker
Copy link
Contributor Author

bbarker commented Jul 3, 2017

Thanks again for the review ,and the help. I reviewed the dotty build instructions and started afresh on another system; I think the --recursive option may have been needed for git submodule update --init; also I don't think I ran sbt managedSources previously, which (may) have been causing other tests to fail.

Unfortunately, I still get the error for this test as originally reported in #1731, and now I seem to have managed (by means unknown) to have gotten the CI build system to replicate the issue:

[info] Test dotty.tools.dotc.reporting.ErrorMessagesTests.traitMayNotBeFinal started
[info] Test dotty.tools.dotc.reporting.ErrorMessagesTests.overloadedMethodNeedsReturnType started
[error] Test dotty.tools.dotc.reporting.ErrorMessagesTests.overloadedMethodNeedsReturnType failed: java.lang.AssertionError: assertion failed: denotation module _root_ invalid in run 2. ValidFor: Period(1..2, run = 3), took 0.023 sec
[error]     at scala.Predef$.assert(Predef.scala:170)
[error]     at dotty.tools.dotc.core.Denotations$SingleDenotation.bringForward(Denotations.scala:727)
[error]     at dotty.tools.dotc.core.Denotations$SingleDenotation.current(Denotations.scala:783)
[error]     at dotty.tools.dotc.core.Symbols$Symbol.denot(Symbols.scala:406)
[error]     at dotty.tools.dotc.core.Symbols$Symbol.isType(Symbols.scala:429)
[error]     at dotty.tools.dotc.core.Scopes$MutableScope.enter(Scopes.scala:270)
[error]     at dotty.tools.dotc.Compiler.rootContext(Compiler.scala:134)
[error]     at dotty.tools.DottyTest$class.checkCompile(DottyTest.scala:60)
[error]     at dotty.tools.dotc.reporting.ErrorMessagesTests.checkCompile(ErrorMessagesTests.scala:14)
[error]     at dotty.tools.dotc.reporting.ErrorMessagesTest$class.checkMessagesAfter(ErrorMessagesTest.scala:60)
[error]     at dotty.tools.dotc.reporting.ErrorMessagesTests.checkMessagesAfter(ErrorMessagesTests.scala:14)
[error]     at dotty.tools.dotc.reporting.ErrorMessagesTests.overloadedMethodNeedsReturnType(ErrorMessagesTests.scala:222)
[error]     ...
[info] Test dotty.tools.dotc.reporting.ErrorMessagesTests.expectedClassOrObjectDef started
[info] Test dotty.tools.dotc.reporting.ErrorMessagesTests.methodDoesNotTakeMorePrameters started
[info] Test dotty.tools.dotc.reporting.ErrorMessagesTests.missingTypeParameter started
[info] Test dotty.tools.dotc.reporting.ErrorMessagesTests.typeDoesNotTakeParameters started

@felixmulder
Copy link
Contributor

That's great, I should be able to reproduce it now!

@felixmulder
Copy link
Contributor

felixmulder commented Jul 5, 2017

#2832 should have fixed your issue! :)

@bbarker
Copy link
Contributor Author

bbarker commented Jul 5, 2017

Thanks @felixmulder - looks like CI is happy now

@felixmulder felixmulder merged commit 91d3ec1 into scala:master Aug 22, 2017
@felixmulder
Copy link
Contributor

@bbarker it does indeed! I'm sorry this fell through the cracks, I went on vacation and simply haven't gotten around to merging this until today.

So, again, sorry for the belated merge, and thanks a bunch for contributing! 🎉

allanrenucci added a commit to dotty-staging/dotty that referenced this pull request Jan 4, 2018
@allanrenucci allanrenucci mentioned this pull request Jan 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants