Skip to content

Commit

Permalink
8268312: Compilation error with nested generic functional interface
Browse files Browse the repository at this point in the history
Reviewed-by: mcimadamore
  • Loading branch information
Vicente Romero committed Jul 15, 2022
1 parent 92deab5 commit f3abb82
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

Expand Down Expand Up @@ -4174,16 +4175,11 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
return null;

Pair<Symbol, JCDiagnostic> c = errCandidate();
if (compactMethodDiags) {
JCDiagnostic simpleDiag =
MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd);
if (simpleDiag != null) {
return simpleDiag;
}
}
Symbol ws = c.fst.asMemberOf(site, types);
return diags.create(dkind, log.currentSource(), pos,
"cant.apply.symbol",
compactMethodDiags ?
d -> MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd) : null,
kindName(ws),
ws.name == names.init ? ws.owner.name : ws.name,
methodArguments(ws.type.getParameterTypes()),
Expand Down Expand Up @@ -4244,8 +4240,8 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
JCDiagnostic err = diags.create(dkind,
null,
truncatedDiag ?
EnumSet.of(DiagnosticFlag.COMPRESSED) :
EnumSet.noneOf(DiagnosticFlag.class),
EnumSet.of(DiagnosticFlag.COMPRESSED) :
EnumSet.noneOf(DiagnosticFlag.class),
log.currentSource(),
pos,
"cant.apply.symbols",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,11 @@ protected String formatArgument(JCDiagnostic d, Object arg, Locale l) {
String s = null;
depth++;
try {
s = formatMessage(diagnostic, l);
JCDiagnostic rewrittenDiagnostic = null;
if (diagnostic.hasRewriter()) {
rewrittenDiagnostic = diagnostic.rewrite();
}
s = formatMessage(rewrittenDiagnostic != null ? rewrittenDiagnostic : diagnostic, l);
}
finally {
depth--;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
package com.sun.tools.javac.util;

import java.util.EnumSet;
import java.util.function.UnaryOperator;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Stream;
Expand Down Expand Up @@ -243,6 +244,21 @@ public JCDiagnostic create(
return create(null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, prefix, key, args));
}

/**
* Create a new diagnostic of the given kind, which is not mandatory and which has
* no lint category.
* @param kind The diagnostic kind
* @param source The source of the compilation unit, if any, in which to report the message.
* @param pos The source position at which to report the message.
* @param key The key for the localized message.
* @param rewriter A rewriter function used if this diagnostic needs to be rewritten
* @param args Fields of the message.
*/
public JCDiagnostic create(
DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, UnaryOperator<JCDiagnostic> rewriter, Object... args) {
return create(null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, prefix, key, args), rewriter);
}

/**
* Create a new diagnostic of the given kind, which is not mandatory and which has
* no lint category.
Expand Down Expand Up @@ -282,6 +298,11 @@ public JCDiagnostic create(
LintCategory lc, Set<DiagnosticFlag> flags, DiagnosticSource source, DiagnosticPosition pos, DiagnosticInfo diagnosticInfo) {
return new JCDiagnostic(formatter, normalize(diagnosticInfo), lc, flags, source, pos);
}

public JCDiagnostic create(
LintCategory lc, Set<DiagnosticFlag> flags, DiagnosticSource source, DiagnosticPosition pos, DiagnosticInfo diagnosticInfo, UnaryOperator<JCDiagnostic> rewriter) {
return new JCDiagnostic(formatter, normalize(diagnosticInfo), lc, flags, source, pos, rewriter);
}
//where
DiagnosticInfo normalize(DiagnosticInfo diagnosticInfo) {
//replace all nested FragmentKey with full-blown JCDiagnostic objects
Expand Down Expand Up @@ -446,6 +467,8 @@ public enum DiagnosticFlag {
/** source line position (set lazily) */
private SourcePosition sourcePosition;

private final UnaryOperator<JCDiagnostic> rewriter;

/**
* This class is used to defer the line/column position fetch logic after diagnostic construction.
*/
Expand Down Expand Up @@ -596,6 +619,25 @@ protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
Set<DiagnosticFlag> flags,
DiagnosticSource source,
DiagnosticPosition pos) {
this(formatter, diagnosticInfo, lc, flags, source, pos, null);
}

/**
* Create a diagnostic object.
* @param formatter the formatter to use for the diagnostic
* @param diagnosticInfo the diagnostic key
* @param lc the lint category for the diagnostic
* @param source the name of the source file, or null if none.
* @param pos the character offset within the source file, if given.
* @param rewriter the rewriter function used if this diagnostic needs to be rewritten
*/
protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
DiagnosticInfo diagnosticInfo,
LintCategory lc,
Set<DiagnosticFlag> flags,
DiagnosticSource source,
DiagnosticPosition pos,
UnaryOperator<JCDiagnostic> rewriter) {
if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
throw new IllegalArgumentException();

Expand All @@ -605,6 +647,7 @@ protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
this.flags = flags;
this.source = source;
this.position = pos;
this.rewriter = rewriter;
}

/**
Expand Down Expand Up @@ -807,6 +850,14 @@ public boolean isFlagSet(DiagnosticFlag flag) {
return flags.contains(flag);
}

boolean hasRewriter() {
return rewriter != null;
}

JCDiagnostic rewrite() {
return rewriter.apply(this);
}

public static class MultilineDiagnostic extends JCDiagnostic {

private final List<JCDiagnostic> subdiagnostics;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import java.io.*;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
Expand Down Expand Up @@ -671,6 +670,11 @@ public void report(JCDiagnostic diagnostic) {
if (expectDiagKeys != null)
expectDiagKeys.remove(diagnostic.getCode());

if (diagnostic.hasRewriter()) {
JCDiagnostic rewrittenDiag = diagnostic.rewrite();
diagnostic = rewrittenDiag != null ? rewrittenDiag : diagnostic;
}

switch (diagnostic.getType()) {
case FRAGMENT:
throw new IllegalArgumentException();
Expand Down
46 changes: 46 additions & 0 deletions test/langtools/tools/javac/diags/DiagnosticRewriterTest3.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 8268312
* @summary Compilation error with nested generic functional interface
* @compile DiagnosticRewriterTest3.java
*/

import java.util.Optional;

class DiagnosticRewriterTest3 {
void m() {
Optional.of("").map(outer -> {
Optional.of("")
.map(inner -> returnGeneric(outer))
.ifPresent(String::toString);
return "";
});
}

<T> T returnGeneric(T generic) {
return generic;
}
}

1 comment on commit f3abb82

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.