Skip to content

Commit f3abb82

Browse files
author
Vicente Romero
committedJul 15, 2022
8268312: Compilation error with nested generic functional interface
Reviewed-by: mcimadamore
1 parent 92deab5 commit f3abb82

File tree

5 files changed

+112
-11
lines changed

5 files changed

+112
-11
lines changed
 

‎src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java

+5-9
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import java.util.function.Consumer;
6969
import java.util.function.Function;
7070
import java.util.function.Predicate;
71+
import java.util.function.UnaryOperator;
7172
import java.util.stream.Stream;
7273
import java.util.stream.StreamSupport;
7374

@@ -4174,16 +4175,11 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
41744175
return null;
41754176

41764177
Pair<Symbol, JCDiagnostic> c = errCandidate();
4177-
if (compactMethodDiags) {
4178-
JCDiagnostic simpleDiag =
4179-
MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd);
4180-
if (simpleDiag != null) {
4181-
return simpleDiag;
4182-
}
4183-
}
41844178
Symbol ws = c.fst.asMemberOf(site, types);
41854179
return diags.create(dkind, log.currentSource(), pos,
41864180
"cant.apply.symbol",
4181+
compactMethodDiags ?
4182+
d -> MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd) : null,
41874183
kindName(ws),
41884184
ws.name == names.init ? ws.owner.name : ws.name,
41894185
methodArguments(ws.type.getParameterTypes()),
@@ -4244,8 +4240,8 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
42444240
JCDiagnostic err = diags.create(dkind,
42454241
null,
42464242
truncatedDiag ?
4247-
EnumSet.of(DiagnosticFlag.COMPRESSED) :
4248-
EnumSet.noneOf(DiagnosticFlag.class),
4243+
EnumSet.of(DiagnosticFlag.COMPRESSED) :
4244+
EnumSet.noneOf(DiagnosticFlag.class),
42494245
log.currentSource(),
42504246
pos,
42514247
"cant.apply.symbols",

‎src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,11 @@ protected String formatArgument(JCDiagnostic d, Object arg, Locale l) {
182182
String s = null;
183183
depth++;
184184
try {
185-
s = formatMessage(diagnostic, l);
185+
JCDiagnostic rewrittenDiagnostic = null;
186+
if (diagnostic.hasRewriter()) {
187+
rewrittenDiagnostic = diagnostic.rewrite();
188+
}
189+
s = formatMessage(rewrittenDiagnostic != null ? rewrittenDiagnostic : diagnostic, l);
186190
}
187191
finally {
188192
depth--;

‎src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java

+51
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package com.sun.tools.javac.util;
2727

2828
import java.util.EnumSet;
29+
import java.util.function.UnaryOperator;
2930
import java.util.Locale;
3031
import java.util.Set;
3132
import java.util.stream.Stream;
@@ -243,6 +244,21 @@ public JCDiagnostic create(
243244
return create(null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, prefix, key, args));
244245
}
245246

247+
/**
248+
* Create a new diagnostic of the given kind, which is not mandatory and which has
249+
* no lint category.
250+
* @param kind The diagnostic kind
251+
* @param source The source of the compilation unit, if any, in which to report the message.
252+
* @param pos The source position at which to report the message.
253+
* @param key The key for the localized message.
254+
* @param rewriter A rewriter function used if this diagnostic needs to be rewritten
255+
* @param args Fields of the message.
256+
*/
257+
public JCDiagnostic create(
258+
DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, UnaryOperator<JCDiagnostic> rewriter, Object... args) {
259+
return create(null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, prefix, key, args), rewriter);
260+
}
261+
246262
/**
247263
* Create a new diagnostic of the given kind, which is not mandatory and which has
248264
* no lint category.
@@ -282,6 +298,11 @@ public JCDiagnostic create(
282298
LintCategory lc, Set<DiagnosticFlag> flags, DiagnosticSource source, DiagnosticPosition pos, DiagnosticInfo diagnosticInfo) {
283299
return new JCDiagnostic(formatter, normalize(diagnosticInfo), lc, flags, source, pos);
284300
}
301+
302+
public JCDiagnostic create(
303+
LintCategory lc, Set<DiagnosticFlag> flags, DiagnosticSource source, DiagnosticPosition pos, DiagnosticInfo diagnosticInfo, UnaryOperator<JCDiagnostic> rewriter) {
304+
return new JCDiagnostic(formatter, normalize(diagnosticInfo), lc, flags, source, pos, rewriter);
305+
}
285306
//where
286307
DiagnosticInfo normalize(DiagnosticInfo diagnosticInfo) {
287308
//replace all nested FragmentKey with full-blown JCDiagnostic objects
@@ -446,6 +467,8 @@ public enum DiagnosticFlag {
446467
/** source line position (set lazily) */
447468
private SourcePosition sourcePosition;
448469

470+
private final UnaryOperator<JCDiagnostic> rewriter;
471+
449472
/**
450473
* This class is used to defer the line/column position fetch logic after diagnostic construction.
451474
*/
@@ -596,6 +619,25 @@ protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
596619
Set<DiagnosticFlag> flags,
597620
DiagnosticSource source,
598621
DiagnosticPosition pos) {
622+
this(formatter, diagnosticInfo, lc, flags, source, pos, null);
623+
}
624+
625+
/**
626+
* Create a diagnostic object.
627+
* @param formatter the formatter to use for the diagnostic
628+
* @param diagnosticInfo the diagnostic key
629+
* @param lc the lint category for the diagnostic
630+
* @param source the name of the source file, or null if none.
631+
* @param pos the character offset within the source file, if given.
632+
* @param rewriter the rewriter function used if this diagnostic needs to be rewritten
633+
*/
634+
protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
635+
DiagnosticInfo diagnosticInfo,
636+
LintCategory lc,
637+
Set<DiagnosticFlag> flags,
638+
DiagnosticSource source,
639+
DiagnosticPosition pos,
640+
UnaryOperator<JCDiagnostic> rewriter) {
599641
if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
600642
throw new IllegalArgumentException();
601643

@@ -605,6 +647,7 @@ protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
605647
this.flags = flags;
606648
this.source = source;
607649
this.position = pos;
650+
this.rewriter = rewriter;
608651
}
609652

610653
/**
@@ -807,6 +850,14 @@ public boolean isFlagSet(DiagnosticFlag flag) {
807850
return flags.contains(flag);
808851
}
809852

853+
boolean hasRewriter() {
854+
return rewriter != null;
855+
}
856+
857+
JCDiagnostic rewrite() {
858+
return rewriter.apply(this);
859+
}
860+
810861
public static class MultilineDiagnostic extends JCDiagnostic {
811862

812863
private final List<JCDiagnostic> subdiagnostics;

‎src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import java.io.*;
2929
import java.util.Arrays;
3030
import java.util.EnumMap;
31-
import java.util.EnumSet;
3231
import java.util.HashSet;
3332
import java.util.Map;
3433
import java.util.Queue;
@@ -671,6 +670,11 @@ public void report(JCDiagnostic diagnostic) {
671670
if (expectDiagKeys != null)
672671
expectDiagKeys.remove(diagnostic.getCode());
673672

673+
if (diagnostic.hasRewriter()) {
674+
JCDiagnostic rewrittenDiag = diagnostic.rewrite();
675+
diagnostic = rewrittenDiag != null ? rewrittenDiag : diagnostic;
676+
}
677+
674678
switch (diagnostic.getType()) {
675679
case FRAGMENT:
676680
throw new IllegalArgumentException();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8268312
27+
* @summary Compilation error with nested generic functional interface
28+
* @compile DiagnosticRewriterTest3.java
29+
*/
30+
31+
import java.util.Optional;
32+
33+
class DiagnosticRewriterTest3 {
34+
void m() {
35+
Optional.of("").map(outer -> {
36+
Optional.of("")
37+
.map(inner -> returnGeneric(outer))
38+
.ifPresent(String::toString);
39+
return "";
40+
});
41+
}
42+
43+
<T> T returnGeneric(T generic) {
44+
return generic;
45+
}
46+
}

0 commit comments

Comments
 (0)
Please sign in to comment.