# HG changeset patch # User mcimadamore # Date 1420559201 0 # Node ID 43ed6b2e0e3bd219709276fce66c68e9dfa716ec # Parent d4bcdcac12118f6c737829c32dbed0ae5e105ae5 8067883: Javac misses some opportunities for diagnostic simplification Summary: Javac always report full inference diagnostic, even when message does not mention inference variables. Reviewed-by: jlahoda diff -r d4bcdcac1211 -r 43ed6b2e0e3b langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Mon Jan 05 17:35:48 2015 -0800 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Jan 06 15:46:41 2015 +0000 @@ -39,7 +39,6 @@ import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Infer.FreeTypeListener; import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; -import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.DiagnosticRewriter; import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.main.Option; @@ -55,11 +54,12 @@ import java.util.Arrays; import java.util.Collection; -import java.util.EnumMap; import java.util.EnumSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.function.BiPredicate; +import java.util.stream.Stream; import javax.lang.model.element.ElementVisitor; @@ -2546,17 +2546,7 @@ final JCDiagnostic details = sym.kind == WRONG_MTH ? ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : null; - sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) { - @Override - JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, - Symbol location, Type site, Name name, List argtypes, List typeargtypes) { - String key = details == null ? - "cant.apply.diamond" : - "cant.apply.diamond.1"; - return diags.create(dkind, log.currentSource(), pos, key, - diags.fragment("diamond", site.tsym), details); - } - }; + sym = new DiamondError(sym, currentResolutionContext); sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); env.info.pendingResolutionPhase = currentResolutionContext.step; } @@ -3724,15 +3714,10 @@ else { Pair c = errCandidate(); if (compactMethodDiags) { - for (Map.Entry _entry : - MethodResolutionDiagHelper.rewriters.entrySet()) { - if (_entry.getKey().matches(c.snd)) { - JCDiagnostic simpleDiag = - _entry.getValue().rewriteDiagnostic(diags, pos, - log.currentSource(), dkind, c.snd); - simpleDiag.setFlag(DiagnosticFlag.COMPRESSED); - return simpleDiag; - } + JCDiagnostic simpleDiag = + MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd); + if (simpleDiag != null) { + return simpleDiag; } } Symbol ws = c.fst.asMemberOf(site, types); @@ -3765,9 +3750,8 @@ } /** - * ResolveError error class indicating that a set of symbols - * (either methods, constructors or operands) is not applicable - * given an actual arguments/type argument list. + * ResolveError error class indicating that a symbol (either methods, constructors or operand) + * is not applicable given an actual arguments/type argument list. */ class InapplicableSymbolsError extends InapplicableSymbolError { @@ -3864,6 +3848,44 @@ } /** + * DiamondError error class indicating that a constructor symbol is not applicable + * given an actual arguments/type argument list using diamond inference. + */ + class DiamondError extends InapplicableSymbolError { + + Symbol sym; + + public DiamondError(Symbol sym, MethodResolutionContext context) { + super(sym.kind, "diamondError", context); + this.sym = sym; + } + + JCDiagnostic getDetails() { + return (sym.kind == WRONG_MTH) ? + ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : + null; + } + + @Override + JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, + Symbol location, Type site, Name name, List argtypes, List typeargtypes) { + JCDiagnostic details = getDetails(); + if (details != null && compactMethodDiags) { + JCDiagnostic simpleDiag = + MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, details); + if (simpleDiag != null) { + return simpleDiag; + } + } + String key = details == null ? + "cant.apply.diamond" : + "cant.apply.diamond.1"; + return diags.create(dkind, log.currentSource(), pos, key, + diags.fragment("diamond", site.tsym), details); + } + } + + /** * An InvalidSymbolError error class indicating that a symbol is not * accessible from a given site */ @@ -4146,6 +4168,28 @@ } } + /** + * Common rewriter for all argument mismatch simplifications. + */ + static class ArgMismatchRewriter implements DiagnosticRewriter { + + /** the index of the subdiagnostic to be used as primary. */ + int causeIndex; + + public ArgMismatchRewriter(int causeIndex) { + this.causeIndex = causeIndex; + } + + @Override + public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, + DiagnosticPosition preferedPos, DiagnosticSource preferredSource, + DiagnosticType preferredKind, JCDiagnostic d) { + JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex]; + return diags.create(preferredKind, preferredSource, d.getDiagnosticPosition(), + "prob.found.req", cause); + } + } + /** a dummy template that match any diagnostic argument */ static final Template skip = new Template("") { @Override @@ -4154,22 +4198,61 @@ } }; + /** template for matching inference-free arguments mismatch failures */ + static final Template argMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip); + + /** template for matching inference related arguments mismatch failures */ + static final Template inferArgMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip, skip) { + @Override + boolean matches(Object o) { + if (!super.matches(o)) { + return false; + } + JCDiagnostic d = (JCDiagnostic)o; + @SuppressWarnings("unchecked") + List tvars = (List)d.getArgs()[0]; + return !containsAny(d, tvars); + } + + BiPredicate> containsPredicate = (o, ts) -> { + if (o instanceof Type) { + return ((Type)o).containsAny(ts); + } else if (o instanceof JCDiagnostic) { + return containsAny((JCDiagnostic)o, ts); + } else { + return false; + } + }; + + boolean containsAny(JCDiagnostic d, List ts) { + return Stream.of(d.getArgs()) + .anyMatch(o -> containsPredicate.test(o, ts)); + } + }; + /** rewriter map used for method resolution simplification */ static final Map rewriters = new LinkedHashMap<>(); static { - String argMismatchRegex = MethodCheckDiag.ARG_MISMATCH.regex(); - rewriters.put(new Template(argMismatchRegex, skip), - new DiagnosticRewriter() { - @Override - public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, - DiagnosticPosition preferedPos, DiagnosticSource preferredSource, - DiagnosticType preferredKind, JCDiagnostic d) { - JCDiagnostic cause = (JCDiagnostic)d.getArgs()[0]; - return diags.create(preferredKind, preferredSource, d.getDiagnosticPosition(), - "prob.found.req", cause); + rewriters.put(argMismatchTemplate, new ArgMismatchRewriter(0)); + rewriters.put(inferArgMismatchTemplate, new ArgMismatchRewriter(1)); + } + + /** + * Main entry point for diagnostic rewriting - given a diagnostic, see if any templates matches it, + * and rewrite it accordingly. + */ + static JCDiagnostic rewrite(JCDiagnostic.Factory diags, DiagnosticPosition pos, DiagnosticSource source, + DiagnosticType dkind, JCDiagnostic d) { + for (Map.Entry _entry : rewriters.entrySet()) { + if (_entry.getKey().matches(d)) { + JCDiagnostic simpleDiag = + _entry.getValue().rewriteDiagnostic(diags, pos, source, dkind, d); + simpleDiag.setFlag(DiagnosticFlag.COMPRESSED); + return simpleDiag; } - }); + } + return null; } } diff -r d4bcdcac1211 -r 43ed6b2e0e3b langtools/test/tools/javac/Diagnostics/compressed/8067883/T8067883.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/Diagnostics/compressed/8067883/T8067883.java Tue Jan 06 15:46:41 2015 +0000 @@ -0,0 +1,29 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8067883 + * @summary Javac misses some opportunities for diagnostic simplification + * + * @compile/fail/ref=T8067883a.out -Xdiags:compact -XDrawDiagnostics T8067883.java + * @compile/fail/ref=T8067883b.out -Xdiags:verbose -XDrawDiagnostics T8067883.java + * + */ + +import java.util.List; + +class T8067883 { + void testMethod(List li) { + m(null, li); + m(1, li); + } + + void testDiamond(List li) { + new Box<>(null, li); + new Box<>(1, li); + } + + void m(List z, List ls) { } + + static class Box { + Box(List z, List ls) { } + } +} diff -r d4bcdcac1211 -r 43ed6b2e0e3b langtools/test/tools/javac/Diagnostics/compressed/8067883/T8067883a.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/Diagnostics/compressed/8067883/T8067883a.out Tue Jan 06 15:46:41 2015 +0000 @@ -0,0 +1,6 @@ +T8067883.java:15:17: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List, java.util.List) +T8067883.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List,java.util.List, int,java.util.List, kindname.class, T8067883, (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.inconvertible.types: int, java.util.List)) +T8067883.java:20:25: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List, java.util.List) +T8067883.java:21:9: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: T8067883.Box), (compiler.misc.infer.no.conforming.assignment.exists: X, (compiler.misc.inconvertible.types: int, java.util.List)) +- compiler.note.compressed.diags +4 errors diff -r d4bcdcac1211 -r 43ed6b2e0e3b langtools/test/tools/javac/Diagnostics/compressed/8067883/T8067883b.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/Diagnostics/compressed/8067883/T8067883b.out Tue Jan 06 15:46:41 2015 +0000 @@ -0,0 +1,5 @@ +T8067883.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List,java.util.List, compiler.misc.type.null,java.util.List, kindname.class, T8067883, (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.inconvertible.types: java.util.List, java.util.List)) +T8067883.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List,java.util.List, int,java.util.List, kindname.class, T8067883, (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.inconvertible.types: int, java.util.List)) +T8067883.java:20:9: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: T8067883.Box), (compiler.misc.infer.no.conforming.assignment.exists: X, (compiler.misc.inconvertible.types: java.util.List, java.util.List)) +T8067883.java:21:9: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: T8067883.Box), (compiler.misc.infer.no.conforming.assignment.exists: X, (compiler.misc.inconvertible.types: int, java.util.List)) +4 errors