-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8268312: Compilation error with nested generic functional interface #5586
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
8268312: Compilation error with nested generic functional interface #5586
Conversation
👋 Welcome back vromero! A progress list of the required criteria for merging this PR into |
@vicente-romero-oracle The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
1 similar comment
@vicente-romero-oracle The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
ping |
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.
Very tricky issue. Basically, the deferred diagnostic handler checks whether the diagnostic is associated with the tree being speculatively attributed. This is required, because sometimes, when attributing a piece of code, we could have completion events, causing the compiler to jump from one file to another - it is important that completion related issues are logged, even if we're inside deferred attribution, which is why the logic is there.
The resolution diagnostic rewrite throws a spanner in the work though - because it can sometime update the diagnostic position to make it appear like the error was on an outermost node, which then will fall outside the tree covered by the deferred diagnostic handler, and result in spurious errors being generated.
I think a more robust solution would be to leave the diagnostic as is (since the diagnostic handler in DeferredAttr depends on it), but at the same time, maybe record something on the JCDiagnostic object - e.g. like a Supplier which allows the diagnostic to be simplified later, by Log
, rather than eagerly, by Resolve
. It is possible that, if we do this, we might no longer require a COMPRESSED flag on the diagnostic at all - after all, if Log is in charge of the rewriting, it knows which diagnostics have been touched.
final DiagnosticPosition pos = d.getDiagnosticPosition(); | ||
UnaryOperator<JCDiagnostic> rewriter = pos != null ? | ||
diag -> diags.create(preferredKind, preferredSource, pos, "prob.found.req", cause) : | ||
null; | ||
return diags.create(preferredKind, preferredSource, preferredPos, |
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.
I guess here we should return the diagnostic unmodified? E.g. you are still returning a rewritten diagnostic here, the only thing that changes is the position (which is what avoids the bug). What I'm hoping is that we can obtain a new diagnostic (with a rewriter) from an existing diagnostic. See my other comment.
@@ -4135,8 +4136,7 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, | |||
|
|||
Pair<Symbol, JCDiagnostic> c = errCandidate(); | |||
if (compactMethodDiags) { |
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.
I think what 'm really after here is to drop this branch - e.g. always create the "non compressed" diagnostic (e.g. cannot.apply) with the right position.
But, before returning that, attach a rewriter to it e.g.
Symbol ws = c.fst.asMemberOf(site, types);
return diags.create(dkind, log.currentSource(), pos,
"cant.apply.symbol",
kindName(ws),
ws.name == names.init ? ws.owner.name : ws.name,
methodArguments(ws.type.getParameterTypes()),
methodArguments(argtypes),
kindName(ws.owner),
ws.owner.type,
c.snd).withRewriter(() -> MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd));
@@ -1713,9 +1713,6 @@ public void reportDeferredDiagnostics() { | |||
} | |||
chk.reportDeferredDiagnostics(); | |||
preview.reportDeferredDiagnostics(); | |||
if (log.compressedOutput) { |
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.
This can be kept, no?
@@ -707,9 +705,6 @@ public void report(JCDiagnostic diagnostic) { | |||
} | |||
break; | |||
} | |||
if (diagnostic.isFlagSet(JCDiagnostic.DiagnosticFlag.COMPRESSED)) { |
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.
Who sets this now?
@vicente-romero-oracle This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
@vicente-romero-oracle This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
/open |
@vicente-romero-oracle This pull request is now open |
@vicente-romero-oracle This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
@vicente-romero-oracle This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
/open |
@vicente-romero-oracle This pull request is now open |
/open |
@vicente-romero-oracle This pull request is already open |
ping |
@vicente-romero-oracle This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
@vicente-romero-oracle This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
@vicente-romero-oracle this pull request can not be integrated into git checkout JDK-8268312
git fetch https://git.openjdk.org/jdk master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
another stab at this one |
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.
A good step forward. I think the removal of the flag to optionally leave diagnostics uncompressed caused more changes than required - there's several changes to the raw diagnostic output that I was not expecting; ideally this patch should not change the behavior of compiler diagnostic, but should just make the current rewriting machinery work better with the speculative attribution machinery.
Symbol ws = c.fst.asMemberOf(site, types); | ||
return diags.create(dkind, log.currentSource(), pos, | ||
"cant.apply.symbol", | ||
d -> MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd), |
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.
This is a good step in the right direction - e.g. attaching a rewriting function to the diagnostic object itself. I wonder if a simpler solution is possible, as I note here that the call to rewrite
is basically just passing info that are attached to the diagnostic being created plus c.snd
which is the real new bit of info.
E.g. in principle, we could just create the new diagnostic with a "cause" (e.g. c.snd
) and then, when we're about to report the diagnostic, we check if there's a cause set and, if so, we try to late-rewrite the diagnostic. If we do this, perhaps we might be able to avoid the creation of a new instance in a very hot path.
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.
I would also check for other usages of the rewriter framework and make sure they follow the same pattern - right now we have some diagnostics using the late-bound reporting mechanism (such as this), and others (e.g. diamond, but possibly other inference ones as well) which rewrite the diagnostic eagerly. We should try to have only one way to do things. My feeling is that diagnostic rewriting should be a general mechanism, not something that belongs in Resolve (but perhaps closer to Log).
/** | ||
* Set to true if a compressed diagnostic is reported | ||
*/ | ||
public boolean compressedOutput; |
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.
I see that this patch drops the option for compressing diagnostic - this seems to go a step too far, and I'm not sure this is what we want, at least in this patch. I believe there's an orthogonal discussion to be had there. I think the flag should stay as is for now (and control whether diagnostics should be rewritten at all in Log).
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 - there seems to be some change in functionality - in the sense that the raw diagnostics now show the note re. compressed diagnostic, while before that did not happen. It would be good to understand why that happens.
@@ -1,4 +1,5 @@ | |||
T7132880.java:23:15: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer) | |||
T7132880.java:33:12: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))),(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Double), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Double)))} | |||
T7132880.java:43:12: compiler.err.ref.ambiguous: m2, kindname.method, m2(java.lang.Object,int), Outer.Inner3, kindname.method, m2(int,java.lang.Object), Outer.Inner3 | |||
- compiler.note.compressed.diags |
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.
Why are these showing up now?
@@ -4174,16 +4175,10 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, | |||
return null; | |||
|
|||
Pair<Symbol, JCDiagnostic> c = errCandidate(); | |||
if (compactMethodDiags) { |
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.
I believe the issue is here - the old code made the rewriting dependent on the value of compactMethodDiags
, which in turns looked at which diagnostic formatter was installed. I think we should either move this check in Log
(when we decide if we need to rewrite), or don't attach a rewriter if the compactMethodDiags
is not set. I think it would be preferable to keep existing diagnostics as they are (and maybe cleanup the behavior of compactMethodDiags
later, as an orthogonal fix).
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.
yep I think this is the reason, will upload an updated iteration
@@ -22,7 +22,9 @@ | |||
*/ | |||
|
|||
// key: compiler.err.prob.found.req | |||
// key: compiler.misc.prob.found.req | |||
// key: compiler.misc.kindname.class |
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.
Uhm - this sample is meant to test compiler.misc.prob.found.req
(e.g. the fragment version). Perhaps we might need to look at the test framework that runs these diagnostic test to understand what we have to change - or what has changed - for this to work as before?
@@ -1,7 +1,7 @@ | |||
T8012003b.java:30:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, java.lang.String, compiler.misc.no.args, kindname.class, T8012003b, (compiler.misc.arg.length.mismatch))) | |||
T8012003b.java:31:16: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) | |||
T8012003b.java:32:22: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.conditional.target.cant.be.void)) | |||
T8012003b.java:33:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String))) | |||
T8012003b.java:33:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, java.lang.String, java.lang.Integer, kindname.class, T8012003b, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String)))) |
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.
Seems like this diagnostic is not getting compressed?
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.
yep good catch, checking what's going on
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.
uploaded another iteration as discussed offline, thanks
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!
src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
Outdated
Show resolved
Hide resolved
@vicente-romero-oracle This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 152 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore@users.noreply.github.com>
…ctDiagnosticFormatter.java Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore@users.noreply.github.com>
/integrate |
Going to push as commit f3abb82.
Your commit was automatically rebased without conflicts. |
@vicente-romero-oracle Pushed as commit f3abb82. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
Please review this PR, which is my proposal to fix an existing regression. This code:
is not accepted by javac but if the user passes the
-Xdiags:verbose
option then the code compiles. I tracked down the reason for this puzzling difference and I found that it is due to our diagnostic rewriters which can generate more detailed positions for error messages but in cases like the one above can trick the compiler to generate an error message too early. The code deciding if an error message should be deferred or not, depending on the position, is atDeferredDiagnosticHandler::report
. We decide to do the rewriting if we are in diagnostics compact mode, this is why the error doesn't occur with the-Xdiags:verbose
option. This fix will made some diagnostics to appear at a slightly different position, but won't make the compiler reject correct code. Comments?TIA
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/5586/head:pull/5586
$ git checkout pull/5586
Update a local copy of the PR:
$ git checkout pull/5586
$ git pull https://git.openjdk.org/jdk pull/5586/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 5586
View PR using the GUI difftool:
$ git pr show -t 5586
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/5586.diff