mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
8067767: type inference performance regression
Overhaul implememntation of inference incorporation Reviewed-by: vromero
This commit is contained in:
parent
54029caa26
commit
875bccb11e
11 changed files with 641 additions and 762 deletions
|
@ -175,8 +175,8 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
|
|||
|
||||
@Override
|
||||
public String visitUndetVar(UndetVar t, Locale locale) {
|
||||
if (t.inst != null) {
|
||||
return printAnnotations(t) + visit(t.inst, locale);
|
||||
if (t.getInst() != null) {
|
||||
return printAnnotations(t) + visit(t.getInst(), locale);
|
||||
} else {
|
||||
return printAnnotations(t) + visit(t.qtype, locale) + "?";
|
||||
}
|
||||
|
|
|
@ -26,19 +26,20 @@
|
|||
package com.sun.tools.javac.code;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.lang.model.type.*;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.TypeMetadata.Entry;
|
||||
import com.sun.tools.javac.comp.Infer.IncorporationAction;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
|
||||
import static com.sun.tools.javac.code.BoundKind.*;
|
||||
import static com.sun.tools.javac.code.Flags.*;
|
||||
import static com.sun.tools.javac.code.Kinds.Kind.*;
|
||||
|
@ -1826,17 +1827,15 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
*/
|
||||
public interface UndetVarListener {
|
||||
/** called when some inference variable bounds (of given kinds ibs) change */
|
||||
void varChanged(UndetVar uv, Set<InferenceBound> ibs);
|
||||
void varBoundChanged(UndetVar uv, InferenceBound ib, Type bound, boolean update);
|
||||
/** called when the inferred type is set on some inference variable */
|
||||
default void varInstantiated(UndetVar uv) { Assert.error(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Inference variable bound kinds
|
||||
*/
|
||||
public enum InferenceBound {
|
||||
/** upper bounds */
|
||||
UPPER {
|
||||
public InferenceBound complement() { return LOWER; }
|
||||
},
|
||||
/** lower bounds */
|
||||
LOWER {
|
||||
public InferenceBound complement() { return UPPER; }
|
||||
|
@ -1844,16 +1843,38 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
/** equality constraints */
|
||||
EQ {
|
||||
public InferenceBound complement() { return EQ; }
|
||||
},
|
||||
/** upper bounds */
|
||||
UPPER {
|
||||
public InferenceBound complement() { return LOWER; }
|
||||
};
|
||||
|
||||
public abstract InferenceBound complement();
|
||||
|
||||
public boolean lessThan(InferenceBound that) {
|
||||
if (that == this) {
|
||||
return false;
|
||||
} else {
|
||||
switch (that) {
|
||||
case UPPER: return true;
|
||||
case LOWER: return false;
|
||||
case EQ: return (this != UPPER);
|
||||
default:
|
||||
Assert.error("Cannot get here!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** list of incorporation actions (used by the incorporation engine). */
|
||||
public ArrayDeque<IncorporationAction> incorporationActions = new ArrayDeque<>();
|
||||
|
||||
/** inference variable bounds */
|
||||
protected Map<InferenceBound, List<Type>> bounds;
|
||||
|
||||
/** inference variable's inferred type (set from Infer.java) */
|
||||
public Type inst = null;
|
||||
private Type inst = null;
|
||||
|
||||
/** number of declared (upper) bounds */
|
||||
public int declaredCount;
|
||||
|
@ -1866,15 +1887,20 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
return v.visitUndetVar(this, s);
|
||||
}
|
||||
|
||||
public UndetVar(TypeVar origin, Types types) {
|
||||
public UndetVar(TypeVar origin, UndetVarListener listener, Types types) {
|
||||
// This is a synthesized internal type, so we cannot annotate it.
|
||||
super(UNDETVAR, origin);
|
||||
this.listener = listener;
|
||||
bounds = new EnumMap<>(InferenceBound.class);
|
||||
List<Type> declaredBounds = types.getBounds(origin);
|
||||
declaredCount = declaredBounds.length();
|
||||
bounds.put(InferenceBound.UPPER, declaredBounds);
|
||||
bounds.put(InferenceBound.LOWER, List.<Type>nil());
|
||||
bounds.put(InferenceBound.EQ, List.<Type>nil());
|
||||
bounds.put(InferenceBound.UPPER, List.nil());
|
||||
bounds.put(InferenceBound.LOWER, List.nil());
|
||||
bounds.put(InferenceBound.EQ, List.nil());
|
||||
for (Type t : declaredBounds.reverse()) {
|
||||
//add bound works in reverse order
|
||||
addBound(InferenceBound.UPPER, t, types, true);
|
||||
}
|
||||
}
|
||||
|
||||
@DefinedBy(Api.LANGUAGE_MODEL)
|
||||
|
@ -1904,6 +1930,32 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new copy of this undet var.
|
||||
*/
|
||||
public UndetVar dup(Types types) {
|
||||
UndetVar uv2 = new UndetVar((TypeVar)qtype, listener, types);
|
||||
dupTo(uv2, types);
|
||||
return uv2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the contents of this undet var on another undet var.
|
||||
*/
|
||||
public void dupTo(UndetVar uv2, Types types) {
|
||||
uv2.listener = null;
|
||||
uv2.bounds.clear();
|
||||
for (InferenceBound ib : InferenceBound.values()) {
|
||||
uv2.bounds.put(ib, List.nil());
|
||||
for (Type t : getBounds(ib)) {
|
||||
uv2.addBound(ib, t, types, true);
|
||||
}
|
||||
}
|
||||
uv2.inst = inst;
|
||||
uv2.listener = listener;
|
||||
uv2.incorporationActions = new ArrayDeque<>(incorporationActions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UndetVar cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to an UndetVar type");
|
||||
|
@ -1919,6 +1971,17 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
return (inst == null) ? this : inst.baseType();
|
||||
}
|
||||
|
||||
public Type getInst() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
public void setInst(Type inst) {
|
||||
this.inst = inst;
|
||||
if (listener != null) {
|
||||
listener.varInstantiated(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** get all bounds of a given kind */
|
||||
public List<Type> getBounds(InferenceBound... ibs) {
|
||||
ListBuffer<Type> buf = new ListBuffer<>();
|
||||
|
@ -1952,13 +2015,14 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
|
||||
Type bound2 = bound.map(toTypeVarMap).baseType();
|
||||
List<Type> prevBounds = bounds.get(ib);
|
||||
if (bound == qtype) return;
|
||||
for (Type b : prevBounds) {
|
||||
//check for redundancy - use strict version of isSameType on tvars
|
||||
//(as the standard version will lead to false positives w.r.t. clones ivars)
|
||||
if (types.isSameType(b, bound2, true) || bound == qtype) return;
|
||||
if (types.isSameType(b, bound2, true)) return;
|
||||
}
|
||||
bounds.put(ib, prevBounds.prepend(bound2));
|
||||
notifyChange(EnumSet.of(ib));
|
||||
notifyBoundChange(ib, bound2, false);
|
||||
}
|
||||
//where
|
||||
TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() {
|
||||
|
@ -1970,16 +2034,14 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
|
||||
/** replace types in all bounds - this might trigger listener notification */
|
||||
public void substBounds(List<Type> from, List<Type> to, Types types) {
|
||||
List<Type> instVars = from.diff(to);
|
||||
//if set of instantiated ivars is empty, there's nothing to do!
|
||||
if (instVars.isEmpty()) return;
|
||||
final EnumSet<InferenceBound> boundsChanged = EnumSet.noneOf(InferenceBound.class);
|
||||
final ListBuffer<Pair<InferenceBound, Type>> boundsChanged = new ListBuffer<>();
|
||||
UndetVarListener prevListener = listener;
|
||||
try {
|
||||
//setup new listener for keeping track of changed bounds
|
||||
listener = new UndetVarListener() {
|
||||
public void varChanged(UndetVar uv, Set<InferenceBound> ibs) {
|
||||
boundsChanged.addAll(ibs);
|
||||
public void varBoundChanged(UndetVar uv, InferenceBound ib, Type t, boolean _ignored) {
|
||||
Assert.check(uv == UndetVar.this);
|
||||
boundsChanged.add(new Pair<>(ib, t));
|
||||
}
|
||||
};
|
||||
for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
|
||||
|
@ -1989,7 +2051,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
ListBuffer<Type> deps = new ListBuffer<>();
|
||||
//step 1 - re-add bounds that are not dependent on ivars
|
||||
for (Type t : prevBounds) {
|
||||
if (!t.containsAny(instVars)) {
|
||||
if (!t.containsAny(from)) {
|
||||
newBounds.append(t);
|
||||
} else {
|
||||
deps.append(t);
|
||||
|
@ -2004,15 +2066,15 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
}
|
||||
} finally {
|
||||
listener = prevListener;
|
||||
if (!boundsChanged.isEmpty()) {
|
||||
notifyChange(boundsChanged);
|
||||
for (Pair<InferenceBound, Type> boundUpdate : boundsChanged) {
|
||||
notifyBoundChange(boundUpdate.fst, boundUpdate.snd, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyChange(EnumSet<InferenceBound> ibs) {
|
||||
private void notifyBoundChange(InferenceBound ib, Type bound, boolean update) {
|
||||
if (listener != null) {
|
||||
listener.varChanged(this, ibs);
|
||||
listener.varBoundChanged(this, ib, bound, update);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2029,10 +2091,10 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
*/
|
||||
public static class CapturedUndetVar extends UndetVar {
|
||||
|
||||
public CapturedUndetVar(CapturedType origin, Types types) {
|
||||
super(origin, types);
|
||||
public CapturedUndetVar(CapturedType origin, UndetVarListener listener, Types types) {
|
||||
super(origin, listener, types);
|
||||
if (!origin.lower.hasTag(BOT)) {
|
||||
bounds.put(InferenceBound.LOWER, List.of(origin.lower));
|
||||
addBound(InferenceBound.LOWER, origin.lower, types, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2051,6 +2113,12 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|||
public boolean isCaptured() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public UndetVar dup(Types types) {
|
||||
UndetVar uv2 = new CapturedUndetVar((CapturedType)qtype, listener, types);
|
||||
dupTo(uv2, types);
|
||||
return uv2;
|
||||
}
|
||||
}
|
||||
|
||||
/** Represents NONE.
|
||||
|
|
|
@ -3843,7 +3843,7 @@ public class Types {
|
|||
|
||||
@Override
|
||||
public Integer visitTypeVar(TypeVar t, Void ignored) {
|
||||
return System.identityHashCode(t.tsym);
|
||||
return System.identityHashCode(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -39,6 +39,7 @@ import com.sun.tools.javac.code.Type.TypeVar;
|
|||
import com.sun.tools.javac.code.Type.UndetVar;
|
||||
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
|
||||
import com.sun.tools.javac.code.Type.WildcardType;
|
||||
import com.sun.tools.javac.code.TypeTag;
|
||||
import com.sun.tools.javac.code.Types;
|
||||
import com.sun.tools.javac.comp.Infer.FreeTypeListener;
|
||||
import com.sun.tools.javac.comp.Infer.GraphSolver;
|
||||
|
@ -52,8 +53,6 @@ import com.sun.tools.javac.util.List;
|
|||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Warner;
|
||||
|
||||
import static com.sun.tools.javac.code.TypeTag.UNDETVAR;
|
||||
|
||||
/**
|
||||
* An inference context keeps track of the set of variables that are free
|
||||
* in the current context. It provides utility methods for opening/closing
|
||||
|
@ -118,7 +117,7 @@ class InferenceContext {
|
|||
List<Type> restvars() {
|
||||
return filterVars(new Filter<UndetVar>() {
|
||||
public boolean accepts(UndetVar uv) {
|
||||
return uv.inst == null;
|
||||
return uv.getInst() == null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -130,7 +129,7 @@ class InferenceContext {
|
|||
List<Type> instvars() {
|
||||
return filterVars(new Filter<UndetVar>() {
|
||||
public boolean accepts(UndetVar uv) {
|
||||
return uv.inst != null;
|
||||
return uv.getInst() != null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -224,7 +223,7 @@ class InferenceContext {
|
|||
ListBuffer<Type> buf = new ListBuffer<>();
|
||||
for (Type t : undetvars) {
|
||||
UndetVar uv = (UndetVar)t;
|
||||
buf.append(uv.inst != null ? uv.inst : uv.qtype);
|
||||
buf.append(uv.getInst() != null ? uv.getInst() : uv.qtype);
|
||||
}
|
||||
return buf.toList();
|
||||
}
|
||||
|
@ -289,15 +288,7 @@ class InferenceContext {
|
|||
List<Type> save() {
|
||||
ListBuffer<Type> buf = new ListBuffer<>();
|
||||
for (Type t : undetvars) {
|
||||
UndetVar uv = (UndetVar)t;
|
||||
UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types);
|
||||
for (InferenceBound ib : InferenceBound.values()) {
|
||||
for (Type b : uv.getBounds(ib)) {
|
||||
uv2.addBound(ib, b, types);
|
||||
}
|
||||
}
|
||||
uv2.inst = uv.inst;
|
||||
buf.add(uv2);
|
||||
buf.add(((UndetVar)t).dup(infer.types));
|
||||
}
|
||||
return buf.toList();
|
||||
}
|
||||
|
@ -315,10 +306,7 @@ class InferenceContext {
|
|||
UndetVar uv = (UndetVar)undetvars.head;
|
||||
UndetVar uv_saved = (UndetVar)saved_undet.head;
|
||||
if (uv.qtype == uv_saved.qtype) {
|
||||
for (InferenceBound ib : InferenceBound.values()) {
|
||||
uv.setBounds(ib, uv_saved.getBounds(ib));
|
||||
}
|
||||
uv.inst = uv_saved.inst;
|
||||
uv_saved.dupTo(uv, types);
|
||||
undetvars = undetvars.tail;
|
||||
saved_undet = saved_undet.tail;
|
||||
newUndetVars.add(uv);
|
||||
|
@ -367,7 +355,7 @@ class InferenceContext {
|
|||
ListBuffer<Type> minUndetVars = new ListBuffer<>();
|
||||
for (Type minVar : minVars) {
|
||||
UndetVar uv = (UndetVar)asUndetVar(minVar);
|
||||
UndetVar uv2 = new UndetVar((TypeVar)minVar, types);
|
||||
UndetVar uv2 = new UndetVar((TypeVar)minVar, infer.incorporationEngine(), types);
|
||||
for (InferenceBound ib : InferenceBound.values()) {
|
||||
List<Type> newBounds = uv.getBounds(ib).stream()
|
||||
.filter(b -> !redundantVars.contains(b))
|
||||
|
@ -416,7 +404,7 @@ class InferenceContext {
|
|||
Set<Type> deps = minMap.getOrDefault(t.qtype, new HashSet<>(Collections.singleton(t.qtype)));
|
||||
for (Type b : t.getBounds(InferenceBound.values())) {
|
||||
Type undet = asUndetVar(b);
|
||||
if (!undet.hasTag(UNDETVAR)) {
|
||||
if (!undet.hasTag(TypeTag.UNDETVAR)) {
|
||||
visit(undet);
|
||||
} else if (isEquiv((UndetVar)undet, b)){
|
||||
deps.add(b);
|
||||
|
@ -438,7 +426,7 @@ class InferenceContext {
|
|||
@Override
|
||||
public Void visitTypeVar(TypeVar t, Void aVoid) {
|
||||
Type undet = asUndetVar(t);
|
||||
if (undet.hasTag(UNDETVAR)) {
|
||||
if (undet.hasTag(TypeTag.UNDETVAR)) {
|
||||
visitUndetVar((UndetVar)undet, null);
|
||||
}
|
||||
return null;
|
||||
|
@ -519,23 +507,23 @@ class InferenceContext {
|
|||
/**
|
||||
* Apply a set of inference steps
|
||||
*/
|
||||
private boolean solveBasic(EnumSet<InferenceStep> steps) {
|
||||
private List<Type> solveBasic(EnumSet<InferenceStep> steps) {
|
||||
return solveBasic(inferencevars, steps);
|
||||
}
|
||||
|
||||
boolean solveBasic(List<Type> varsToSolve, EnumSet<InferenceStep> steps) {
|
||||
boolean changed = false;
|
||||
List<Type> solveBasic(List<Type> varsToSolve, EnumSet<InferenceStep> steps) {
|
||||
ListBuffer<Type> solvedVars = new ListBuffer<>();
|
||||
for (Type t : varsToSolve.intersect(restvars())) {
|
||||
UndetVar uv = (UndetVar)asUndetVar(t);
|
||||
for (InferenceStep step : steps) {
|
||||
if (step.accepts(uv, this)) {
|
||||
uv.inst = step.solve(uv, this);
|
||||
changed = true;
|
||||
uv.setInst(step.solve(uv, this));
|
||||
solvedVars.add(uv.qtype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
return solvedVars.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -547,11 +535,11 @@ class InferenceContext {
|
|||
*/
|
||||
public void solveLegacy(boolean partial, Warner warn, EnumSet<InferenceStep> steps) {
|
||||
while (true) {
|
||||
boolean stuck = !solveBasic(steps);
|
||||
List<Type> solvedVars = solveBasic(steps);
|
||||
if (restvars().isEmpty() || partial) {
|
||||
//all variables have been instantiated - exit
|
||||
break;
|
||||
} else if (stuck) {
|
||||
} else if (solvedVars.isEmpty()) {
|
||||
//some variables could not be instantiated because of cycles in
|
||||
//upper bounds - provide a (possibly recursive) default instantiation
|
||||
infer.instantiateAsUninferredVars(restvars(), this);
|
||||
|
@ -561,11 +549,11 @@ class InferenceContext {
|
|||
//variables in remaining upper bounds and continue
|
||||
for (Type t : undetvars) {
|
||||
UndetVar uv = (UndetVar)t;
|
||||
uv.substBounds(inferenceVars(), instTypes(), types);
|
||||
uv.substBounds(solvedVars, asInstTypes(solvedVars), types);
|
||||
}
|
||||
}
|
||||
}
|
||||
infer.checkWithinBounds(this, warn);
|
||||
infer.doIncorporation(this, warn);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1981,18 +1981,6 @@ compiler.misc.incompatible.upper.lower.bounds=\
|
|||
upper bounds: {1}\n\
|
||||
lower bounds: {2}
|
||||
|
||||
# 0: type, 1: list of type, 2: list of type
|
||||
compiler.misc.incompatible.upper.eq.bounds=\
|
||||
inference variable {0} has incompatible bounds\n\
|
||||
upper bounds: {1}\n\
|
||||
equality constraints: {2}
|
||||
|
||||
# 0: type, 1: list of type, 2: list of type
|
||||
compiler.misc.incompatible.eq.lower.bounds=\
|
||||
inference variable {0} has incompatible bounds\n\
|
||||
equality constraints: {1}\n\
|
||||
lower bounds: {2}
|
||||
|
||||
# 0: type, 1: list of type, 2: list of type
|
||||
compiler.misc.incompatible.eq.lower.bounds=\
|
||||
inference variable {0} has incompatible bounds\n\
|
||||
|
|
|
@ -114,4 +114,3 @@ compiler.warn.file.from.future # warning for future mod
|
|||
compiler.err.cant.inherit.from.anon # error for subclass of anonymous class
|
||||
compiler.misc.bad.class.file # class file is malformed
|
||||
compiler.misc.bad.const.pool.entry # constant pool entry has wrong type
|
||||
compiler.misc.incompatible.upper.eq.bounds
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
T7154127.java:20:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: Y, T7154127.B<U>,T7154127.D)
|
||||
T7154127.java:20:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: U, T7154127.B<Y>,T7154127.E)
|
||||
1 error
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 8067767
|
||||
* @summary type inference performance regression
|
||||
* @compile T8067767.java
|
||||
*/
|
||||
class T8067767 {
|
||||
|
||||
static class Pair<A, B> {
|
||||
static <A, B> Pair<A, B> of(A a, B b) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
static class List<T> {
|
||||
static <T> List<T> of(T... tx) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
static final List<Pair<String, String>> PAIRS = List.of(
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
|
||||
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"));
|
||||
}
|
|
@ -1,2 +1,2 @@
|
|||
TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, R,java.lang.String, java.lang.Object,java.lang.Number)
|
||||
TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Object,java.lang.Number)
|
||||
1 error
|
||||
|
|
|
@ -1304,7 +1304,7 @@ public class DPrinter {
|
|||
for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values())
|
||||
printList("bounds." + ib, type.getBounds(ib));
|
||||
printInt("declaredCount", type.declaredCount);
|
||||
printType("inst", type.inst, Details.SUMMARY);
|
||||
printType("inst", type.getInst(), Details.SUMMARY);
|
||||
return visitDelegatedType(type);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue