Skip to content
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

Closed

Conversation

vicente-romero-oracle
Copy link
Contributor

@vicente-romero-oracle vicente-romero-oracle commented Sep 20, 2021

Please review this PR, which is my proposal to fix an existing regression. This code:

import java.util.Optional;

class App {
    public static void main(String[] args) {
        Optional.of("").map(outer -> {
            Optional.of("")
                .map(inner -> returnGeneric(outer))
                .ifPresent(String::toString);
            return "";
        });
    }

    private static <RG> RG returnGeneric(RG generic) {
        return generic;
    }
}

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 at DeferredDiagnosticHandler::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

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed

Issue

  • JDK-8268312: Compilation error with nested generic functional interface

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/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.java.net/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.java.net/jdk/pull/5586.diff

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented Sep 20, 2021

👋 Welcome back vromero! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk openjdk bot added the rfr label Sep 20, 2021
@openjdk
Copy link

@openjdk openjdk bot commented Sep 20, 2021

@vicente-romero-oracle The following label will be automatically applied to this pull request:

  • compiler

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
@openjdk
Copy link

@openjdk openjdk bot commented Sep 20, 2021

@vicente-romero-oracle The following label will be automatically applied to this pull request:

  • compiler

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.

@openjdk openjdk bot added the compiler label Sep 20, 2021
@mlbridge
Copy link

@mlbridge mlbridge bot commented Sep 20, 2021

Webrevs

@vicente-romero-oracle
Copy link
Contributor Author

@vicente-romero-oracle vicente-romero-oracle commented Sep 28, 2021

ping

Copy link
Contributor

@mcimadamore mcimadamore left a comment

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,
Copy link
Contributor

@mcimadamore mcimadamore Sep 29, 2021

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

@mcimadamore mcimadamore Sep 29, 2021

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

@mcimadamore mcimadamore Sep 29, 2021

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

@mcimadamore mcimadamore Sep 29, 2021

Choose a reason for hiding this comment

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

Who sets this now?

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented Oct 28, 2021

@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!

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented Nov 25, 2021

@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 pull request command.

@bridgekeeper bridgekeeper bot closed this Nov 25, 2021
@vicente-romero-oracle
Copy link
Contributor Author

@vicente-romero-oracle vicente-romero-oracle commented Jan 5, 2022

/open

@openjdk openjdk bot reopened this Jan 5, 2022
@openjdk
Copy link

@openjdk openjdk bot commented Jan 5, 2022

@vicente-romero-oracle This pull request is now open

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented Feb 2, 2022

@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!

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented Mar 3, 2022

@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 pull request command.

@bridgekeeper bridgekeeper bot closed this Mar 3, 2022
@vicente-romero-oracle
Copy link
Contributor Author

@vicente-romero-oracle vicente-romero-oracle commented Mar 23, 2022

/open

@openjdk openjdk bot reopened this Mar 23, 2022
@openjdk
Copy link

@openjdk openjdk bot commented Mar 23, 2022

@vicente-romero-oracle This pull request is now open

@vicente-romero-oracle
Copy link
Contributor Author

@vicente-romero-oracle vicente-romero-oracle commented Mar 23, 2022

/open

@openjdk
Copy link

@openjdk openjdk bot commented Mar 23, 2022

@vicente-romero-oracle This pull request is already open

@vicente-romero-oracle
Copy link
Contributor Author

@vicente-romero-oracle vicente-romero-oracle commented Mar 23, 2022

ping

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented Apr 20, 2022

@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!

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented May 19, 2022

@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 pull request command.

@bridgekeeper bridgekeeper bot closed this May 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler rfr
2 participants