-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #7986: Warn on cyclic references when looking for extension methods #7988
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
Conversation
The first attempt to simply propagate cyclic references breaks existing tests. We now issue a warning instead. On i7986.scala you get:
Unfortunately I cannot test that a warning is issued with a .check file since the .check files did not show the warning (maybe it was suppressed since there was an error?). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good as a temporary measure before we have a more systematic way to treat extension methods on type checking. Will direct people in the right direction.
if ex.denot.is(Extension) && ex.denot.name == name then | ||
origCtx.warning( | ||
em"""An extension method was tried but could not be fully constructed | ||
|since there was a cyclic reference involving ${ex.denot.symbol.showLocated}""", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a user, I do not necessarily understand what's a cyclic reference and how to fix it. Would it be exhaustive to say here that the user must explicitly specify the return types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It turns out to be quite hard to figure out accurately that a return type is missing.
tests/neg/i7986.scala
Outdated
@@ -0,0 +1,3 @@ | |||
case class Project(name: String) | |||
def (name: String) dependencies = ??? | |||
def (project: Project) dependencies = project.name.dependencies // error, following a cyclic reference warning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check files log only errors, the assumption being that warnings are irrelevant for negative tests since they do not cause the compilation failure. We could move the test to tests/neg-custom-args/fatal-warnings
, then the warning will turn into an error and will be testable via a check file.
case ex: TypeError => errorTree(tree, ex, tree.sourcePos) | ||
} | ||
catch | ||
case ex: CyclicReference => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could probably do:
case ex: CyclicReference =>
if ex.denot.is(Extension) && ex.denot.name == name
throw ex
else
errorTree(tree, ex, tree.sourcePos)
It fixes the failing tests.
…thods are tried
Avoid `@main def main`, for known reasons.
There was something really funky going on. Basically, we had extension (sym: Symbol) def documentation = sym.documentation match ... How is this not an infinite loop? Well, name resolution tried the current method, failed because of a cyclic reference and then fell back to an alternative extension method elsewhere. So compilation relied crucially on a missing result type in `documentation`. This is terrible! This PR plugs the specific hole, but I fear there are others that could be exploited in user code. Morale: Leaving out result types has an upside in that it detects compiler bugs. But for robust software, it's better do add return types to all public methods.
There was something really funky going on. Basically, we had in dokka/BasicSupport:
How is this not an infinite loop? Well, name resolution tried the current method, Morale: Leaving out result types has an upside in that it detects compiler |
@romanowski Can you check that my changes to BasicSupport are correct? |
The previous code in BasicSupport.scala shows that this should not be a warning we can recover from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes in scal3doc looks ok. I've take a look why we had documentation
calling documentation
and it seems that originally we used comment
method that gets renamed later on and we simply changed it and since it worked we leaved it be wihtout realizing that we exploited the compiler.
#10902 provides a better fix |
Propagate cyclic reference errors when searching extension methods