提交 cb22b5bc 编写于 作者: M mcimadamore

8007463: Cleanup inference related classes

Summary: Make Infer.InferenceContext an inner class; adjust bound replacement logic in Type.UndetVar
Reviewed-by: jjg
上级 e737e185
......@@ -1309,6 +1309,9 @@ public class Type implements PrimitiveType {
/** inference variable's inferred type (set from Infer.java) */
public Type inst = null;
/** number of declared (upper) bounds */
public int declaredCount;
/** inference variable's change listener */
public UndetVarListener listener = null;
......@@ -1318,13 +1321,11 @@ public class Type implements PrimitiveType {
}
public UndetVar(TypeVar origin, Types types) {
this(origin, types, true);
}
public UndetVar(TypeVar origin, Types types, boolean includeBounds) {
super(UNDETVAR, origin);
bounds = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
bounds.put(InferenceBound.UPPER, includeBounds ? types.getBounds(origin) : List.<Type>nil());
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());
}
......@@ -1340,38 +1341,89 @@ public class Type implements PrimitiveType {
}
/** get all bounds of a given kind */
public List<Type> getBounds(InferenceBound ib) {
return bounds.get(ib);
public List<Type> getBounds(InferenceBound... ibs) {
ListBuffer<Type> buf = ListBuffer.lb();
for (InferenceBound ib : ibs) {
buf.appendList(bounds.get(ib));
}
return buf.toList();
}
/** get the list of declared (upper) bounds */
public List<Type> getDeclaredBounds() {
ListBuffer<Type> buf = ListBuffer.lb();
int count = 0;
for (Type b : getBounds(InferenceBound.UPPER)) {
if (count++ == declaredCount) break;
buf.append(b);
}
return buf.toList();
}
/** add a bound of a given kind - this might trigger listener notification */
public void addBound(InferenceBound ib, Type bound, Types types) {
Type bound2 = toTypeVarMap.apply(bound);
List<Type> prevBounds = bounds.get(ib);
for (Type b : prevBounds) {
if (types.isSameType(b, bound)) {
return;
}
//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)) return;
}
bounds.put(ib, prevBounds.prepend(bound));
bounds.put(ib, prevBounds.prepend(bound2));
notifyChange(EnumSet.of(ib));
}
//where
Type.Mapping toTypeVarMap = new Mapping("toTypeVarMap") {
@Override
public Type apply(Type t) {
if (t.hasTag(UNDETVAR)) {
UndetVar uv = (UndetVar)t;
return uv.qtype;
} else {
return t.map(this);
}
}
};
/** replace types in all bounds - this might trigger listener notification */
public void substBounds(List<Type> from, List<Type> to, Types types) {
EnumSet<InferenceBound> changed = EnumSet.noneOf(InferenceBound.class);
Map<InferenceBound, List<Type>> bounds2 = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
InferenceBound ib = _entry.getKey();
List<Type> prevBounds = _entry.getValue();
List<Type> newBounds = types.subst(prevBounds, from, to);
bounds2.put(ib, newBounds);
if (prevBounds != newBounds) {
changed.add(ib);
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);
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);
}
};
for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
InferenceBound ib = _entry.getKey();
List<Type> prevBounds = _entry.getValue();
ListBuffer<Type> newBounds = ListBuffer.lb();
ListBuffer<Type> deps = ListBuffer.lb();
//step 1 - re-add bounds that are not dependent on ivars
for (Type t : prevBounds) {
if (!t.containsAny(instVars)) {
newBounds.append(t);
} else {
deps.append(t);
}
}
//step 2 - replace bounds
bounds.put(ib, newBounds.toList());
//step 3 - for each dependency, add new replaced bound
for (Type dep : deps) {
addBound(ib, types.subst(dep, from, to), types);
}
}
} finally {
listener = prevListener;
if (!boundsChanged.isEmpty()) {
notifyChange(boundsChanged);
}
}
if (!changed.isEmpty()) {
bounds = bounds2;
notifyChange(changed);
}
}
......
......@@ -976,9 +976,12 @@ public class Types {
* lists are of different length, return false.
*/
public boolean isSameTypes(List<Type> ts, List<Type> ss) {
return isSameTypes(ts, ss, false);
}
public boolean isSameTypes(List<Type> ts, List<Type> ss, boolean strict) {
while (ts.tail != null && ss.tail != null
/*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
isSameType(ts.head, ss.head)) {
isSameType(ts.head, ss.head, strict)) {
ts = ts.tail;
ss = ss.tail;
}
......@@ -990,10 +993,15 @@ public class Types {
* Is t the same type as s?
*/
public boolean isSameType(Type t, Type s) {
return isSameType.visit(t, s);
return isSameType(t, s, false);
}
public boolean isSameType(Type t, Type s, boolean strict) {
return strict ?
isSameTypeStrict.visit(t, s) :
isSameTypeLoose.visit(t, s);
}
// where
private TypeRelation isSameType = new TypeRelation() {
abstract class SameTypeVisitor extends TypeRelation {
public Boolean visitType(Type t, Type s) {
if (t == s)
......@@ -1010,8 +1018,7 @@ public class Types {
if (s.tag == TYPEVAR) {
//type-substitution does not preserve type-var types
//check that type var symbols and bounds are indeed the same
return t.tsym == s.tsym &&
visit(t.getUpperBound(), s.getUpperBound());
return sameTypeVars((TypeVar)t, (TypeVar)s);
}
else {
//special case for s == ? super X, where upper(s) = u
......@@ -1026,6 +1033,8 @@ public class Types {
}
}
abstract boolean sameTypeVars(TypeVar tv1, TypeVar tv2);
@Override
public Boolean visitWildcardType(WildcardType t, Type s) {
if (s.isPartial())
......@@ -1060,9 +1069,11 @@ public class Types {
}
return t.tsym == s.tsym
&& visit(t.getEnclosingType(), s.getEnclosingType())
&& containsTypeEquivalent(t.getTypeArguments(), s.getTypeArguments());
&& containsTypes(t.getTypeArguments(), s.getTypeArguments());
}
abstract protected boolean containsTypes(List<Type> ts1, List<Type> ts2);
@Override
public Boolean visitArrayType(ArrayType t, Type s) {
if (t == s)
......@@ -1115,6 +1126,36 @@ public class Types {
public Boolean visitErrorType(ErrorType t, Type s) {
return true;
}
}
/**
* Standard type-equality relation - type variables are considered
* equals if they share the same type symbol.
*/
TypeRelation isSameTypeLoose = new SameTypeVisitor() {
@Override
boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
return tv1.tsym == tv2.tsym && visit(tv1.getUpperBound(), tv2.getUpperBound());
}
@Override
protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
return containsTypeEquivalent(ts1, ts2);
}
};
/**
* Strict type-equality relation - type variables are considered
* equals if they share the same object identity.
*/
TypeRelation isSameTypeStrict = new SameTypeVisitor() {
@Override
boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
return tv1 == tv2;
}
@Override
protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
return isSameTypes(ts1, ts2, true);
}
};
// </editor-fold>
......
......@@ -43,7 +43,7 @@ import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.comp.Check.CheckContext;
import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import com.sun.tools.javac.comp.Infer.FreeTypeListener;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
......@@ -244,8 +244,8 @@ public class Attr extends JCTree.Visitor {
@Override
public void typesInferred(InferenceContext inferenceContext) {
ResultInfo pendingResult =
resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
check(tree, inferenceContext.asInstType(found, types), ownkind, pendingResult);
resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
check(tree, inferenceContext.asInstType(found), ownkind, pendingResult);
}
});
return tree.type = resultInfo.pt;
......@@ -2415,7 +2415,7 @@ public class Attr extends JCTree.Visitor {
inferenceContext.addFreeTypeListener(ts, new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
checkAccessibleTypes(pos, env, inferenceContext, inferenceContext.asInstTypes(ts, types));
checkAccessibleTypes(pos, env, inferenceContext, inferenceContext.asInstTypes(ts));
}
});
} else {
......@@ -2440,7 +2440,7 @@ public class Attr extends JCTree.Visitor {
@Override
public boolean compatible(Type found, Type req, Warner warn) {
//return type must be compatible in both current context and assignment context
return chk.basicHandler.compatible(found, inferenceContext().asFree(req, types), warn);
return chk.basicHandler.compatible(found, inferenceContext().asFree(req), warn);
}
@Override
......@@ -2475,7 +2475,7 @@ public class Attr extends JCTree.Visitor {
* descriptor.
*/
private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext, boolean speculativeAttr) {
Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType(), types);
Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType());
//return values have already been checked - but if lambda has no return
//values, we must ensure that void/value compatibility is correct;
......@@ -2487,13 +2487,13 @@ public class Attr extends JCTree.Visitor {
diags.fragment("missing.ret.val", returnType)));
}
List<Type> argTypes = checkContext.inferenceContext().asFree(descriptor.getParameterTypes(), types);
List<Type> argTypes = checkContext.inferenceContext().asFree(descriptor.getParameterTypes());
if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) {
checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
}
if (!speculativeAttr) {
List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes(), types);
List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes());
if (chk.unhandled(tree.inferredThrownTypes == null ? List.<Type>nil() : tree.inferredThrownTypes, thrownTypes).nonEmpty()) {
log.error(tree, "incompatible.thrown.types.in.lambda", tree.inferredThrownTypes);
}
......@@ -2680,7 +2680,7 @@ public class Attr extends JCTree.Visitor {
@SuppressWarnings("fallthrough")
void checkReferenceCompatible(JCMemberReference tree, Type descriptor, Type refType, CheckContext checkContext, boolean speculativeAttr) {
Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType(), types);
Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType());
Type resType;
switch (tree.getMode()) {
......@@ -2712,7 +2712,7 @@ public class Attr extends JCTree.Visitor {
}
if (!speculativeAttr) {
List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes(), types);
List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes());
if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) {
log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes());
}
......@@ -2728,7 +2728,7 @@ public class Attr extends JCTree.Visitor {
if (inferenceContext.free(descriptorType)) {
inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() {
public void typesInferred(InferenceContext inferenceContext) {
setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType, types), inferenceContext);
setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType), inferenceContext);
}
});
} else {
......
......@@ -42,7 +42,7 @@ import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import com.sun.tools.javac.comp.Infer.FreeTypeListener;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
......@@ -530,7 +530,7 @@ public class Check {
inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
checkType(pos, found, inferenceContext.asInstType(req, types), checkContext);
checkType(pos, found, inferenceContext.asInstType(req), checkContext);
}
});
}
......
......@@ -373,8 +373,8 @@ public class DeferredAttr extends JCTree.Visitor {
if (!progress) {
//remove all variables that have already been instantiated
//from the list of stuck variables
inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars)), types, infer);
inferenceContext.notifyChange(types);
inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars)));
inferenceContext.notifyChange();
}
}
}
......@@ -383,7 +383,7 @@ public class DeferredAttr extends JCTree.Visitor {
* Class representing a deferred attribution node. It keeps track of
* a deferred type, along with the expected target type information.
*/
class DeferredAttrNode implements Infer.InferenceContext.FreeTypeListener {
class DeferredAttrNode implements Infer.FreeTypeListener {
/** underlying deferred type */
DeferredType dt;
......@@ -406,7 +406,7 @@ public class DeferredAttr extends JCTree.Visitor {
@Override
public void typesInferred(InferenceContext inferenceContext) {
stuckVars = List.nil();
resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
}
/**
......
......@@ -241,7 +241,7 @@ public class Infer {
for (Type t : todo) {
UndetVar uv = (UndetVar)t;
TypeVar ct = (TypeVar)uv.inst;
ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct), types));
ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct)));
if (ct.bound.isErroneous()) {
//report inference error if glb fails
reportBoundError(uv, BoundErrorKind.BAD_UPPER);
......@@ -265,7 +265,7 @@ public class Infer {
Resolve.MethodCheck methodCheck,
Warner warn) throws InferenceException {
//-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
final InferenceContext inferenceContext = new InferenceContext(tvars, this, true);
final InferenceContext inferenceContext = new InferenceContext(tvars);
inferenceException.clear();
DeferredAttr.DeferredAttrContext deferredAttrContext =
......@@ -288,7 +288,7 @@ public class Infer {
checkWithinBounds(inferenceContext, warn);
mt = (MethodType)inferenceContext.asInstType(mt, types);
mt = (MethodType)inferenceContext.asInstType(mt);
List<Type> restvars = inferenceContext.restvars();
......@@ -299,7 +299,7 @@ public class Infer {
}
instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
checkWithinBounds(inferenceContext, warn);
mt = (MethodType)inferenceContext.asInstType(mt, types);
mt = (MethodType)inferenceContext.asInstType(mt);
if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
}
......@@ -309,7 +309,7 @@ public class Infer {
// return instantiated version of method type
return mt;
} finally {
inferenceContext.notifyChange(types);
inferenceContext.notifyChange();
}
}
//where
......@@ -320,7 +320,7 @@ public class Infer {
to = mt.getReturnType().isPrimitiveOrVoid() ?
mt.getReturnType() : syms.objectType;
}
Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types);
Type qtype1 = inferenceContext.asFree(mt.getReturnType());
Warner retWarn = new Warner();
if (!resultInfo.checkContext.compatible(qtype1, qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to, retWarn) ||
//unchecked conversion is not allowed
......@@ -342,9 +342,9 @@ public class Infer {
uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars());
if (!inferenceContext.restvars().contains(uv.qtype)) {
Type inst = inferenceContext.asInstType(t, types);
Type inst = inferenceContext.asInstType(t);
for (Type u : uv.getBounds(InferenceBound.UPPER)) {
if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u, types), warn)) {
if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u), warn)) {
reportBoundError(uv, BoundErrorKind.UPPER);
}
}
......@@ -478,7 +478,7 @@ public class Infer {
} else {
Type formalInterface = funcInterface.tsym.type;
InferenceContext funcInterfaceContext =
new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false);
new InferenceContext(funcInterface.tsym.type.getTypeArguments());
Assert.check(paramTypes != null);
//get constraints from explicit params (this is done by
//checking that explicit param types are equal to the ones
......@@ -489,7 +489,7 @@ public class Infer {
return types.createErrorType(funcInterface);
}
for (Type p : descParameterTypes) {
if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
if (!types.isSameType(funcInterfaceContext.asFree(p), paramTypes.head)) {
checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
return types.createErrorType(funcInterface);
}
......@@ -498,17 +498,19 @@ public class Infer {
List<Type> actualTypeargs = funcInterface.getTypeArguments();
for (Type t : funcInterfaceContext.undetvars) {
UndetVar uv = (UndetVar)t;
minimizeInst(uv, types.noWarnings);
if (uv.inst == null &&
Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
maximizeInst(uv, types.noWarnings);
}
if (uv.inst == null) {
if (funcInterfaceContext.boundedVars().contains(uv.qtype)) {
minimizeInst(uv, types.noWarnings);
if (uv.inst == null &&
Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
maximizeInst(uv, types.noWarnings);
}
} else {
uv.inst = actualTypeargs.head;
}
Assert.check(uv.inst != null);
actualTypeargs = actualTypeargs.tail;
}
Type owntype = funcInterfaceContext.asInstType(formalInterface, types);
Type owntype = funcInterfaceContext.asInstType(formalInterface);
if (!chk.checkValidGenericType(owntype)) {
//if the inferred functional interface type is not well-formed,
//or if it's not a subtype of the original target, issue an error
......@@ -585,23 +587,13 @@ public class Infer {
}
/**
* Mapping that turns inference variables into undet vars
* (used by inference context)
* Functional interface for defining inference callbacks. Certain actions
* (i.e. subtyping checks) might need to be redone after all inference variables
* have been fixed.
*/
class FromTypeVarFun extends Mapping {
boolean includeBounds;
FromTypeVarFun(boolean includeBounds) {
super("fromTypeVarFunWithBounds");
this.includeBounds = includeBounds;
}
public Type apply(Type t) {
if (t.hasTag(TYPEVAR)) return new UndetVar((TypeVar)t, types, includeBounds);
else return t.map(this);
}
};
interface FreeTypeListener {
void typesInferred(InferenceContext inferenceContext);
}
/**
* An inference context keeps track of the set of variables that are free
......@@ -611,16 +603,7 @@ public class Infer {
* it can be used as an entry point for performing upper/lower bound inference
* (see InferenceKind).
*/
static class InferenceContext {
/**
* Single-method-interface for defining inference callbacks. Certain actions
* (i.e. subtyping checks) might need to be redone after all inference variables
* have been fixed.
*/
interface FreeTypeListener {
void typesInferred(InferenceContext inferenceContext);
}
class InferenceContext {
/** list of inference vars as undet vars */
List<Type> undetvars;
......@@ -633,10 +616,18 @@ public class Infer {
List<FreeTypeListener> freetypeListeners = List.nil();
public InferenceContext(List<Type> inferencevars, Infer infer, boolean includeBounds) {
this.undetvars = Type.map(inferencevars, infer.new FromTypeVarFun(includeBounds));
public InferenceContext(List<Type> inferencevars) {
this.undetvars = Type.map(inferencevars, fromTypeVarFun);
this.inferencevars = inferencevars;
}
//where
Mapping fromTypeVarFun = new Mapping("fromTypeVarFunWithBounds") {
// mapping that turns inference variables into undet vars
public Type apply(Type t) {
if (t.hasTag(TYPEVAR)) return new UndetVar((TypeVar)t, types);
else return t.map(this);
}
};
/**
* returns the list of free variables (as type-variables) in this
......@@ -648,19 +639,51 @@ public class Infer {
/**
* returns the list of uninstantiated variables (as type-variables) in this
* inference context (usually called after instantiate())
* inference context
*/
List<Type> restvars() {
List<Type> undetvars = this.undetvars;
ListBuffer<Type> restvars = ListBuffer.lb();
for (Type t : instTypes()) {
UndetVar uv = (UndetVar)undetvars.head;
if (uv.qtype == t) {
restvars.append(t);
return filterVars(new Filter<UndetVar>() {
public boolean accepts(UndetVar uv) {
return uv.inst == null;
}
});
}
/**
* returns the list of instantiated variables (as type-variables) in this
* inference context
*/
List<Type> instvars() {
return filterVars(new Filter<UndetVar>() {
public boolean accepts(UndetVar uv) {
return uv.inst != null;
}
});
}
/**
* Get list of bounded inference variables (where bound is other than
* declared bounds).
*/
final List<Type> boundedVars() {
return filterVars(new Filter<UndetVar>() {
public boolean accepts(UndetVar uv) {
return uv.getBounds(InferenceBound.UPPER)
.diff(uv.getDeclaredBounds())
.appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty();
}
});
}
private List<Type> filterVars(Filter<UndetVar> fu) {
ListBuffer<Type> res = ListBuffer.lb();
for (Type t : undetvars) {
UndetVar uv = (UndetVar)t;
if (fu.accepts(uv)) {
res.append(uv.qtype);
}
undetvars = undetvars.tail;
}
return restvars.toList();
return res.toList();
}
/**
......@@ -709,14 +732,14 @@ public class Infer {
* undet vars (used ahead of subtyping/compatibility checks to allow propagation
* of inference constraints).
*/
final Type asFree(Type t, Types types) {
final Type asFree(Type t) {
return types.subst(t, inferencevars, undetvars);
}
final List<Type> asFree(List<Type> ts, Types types) {
final List<Type> asFree(List<Type> ts) {
ListBuffer<Type> buf = ListBuffer.lb();
for (Type t : ts) {
buf.append(asFree(t, types));
buf.append(asFree(t));
}
return buf.toList();
}
......@@ -735,14 +758,14 @@ public class Infer {
* instantiated types - if one or more free variable has not been
* fully instantiated, it will still be available in the resulting type.
*/
Type asInstType(Type t, Types types) {
Type asInstType(Type t) {
return types.subst(t, inferencevars, instTypes());
}
List<Type> asInstTypes(List<Type> ts, Types types) {
List<Type> asInstTypes(List<Type> ts) {
ListBuffer<Type> buf = ListBuffer.lb();
for (Type t : ts) {
buf.append(asInstType(t, types));
buf.append(asInstType(t));
}
return buf.toList();
}
......@@ -758,7 +781,7 @@ public class Infer {
* Mark the inference context as complete and trigger evaluation
* of all deferred checks.
*/
void notifyChange(Types types) {
void notifyChange() {
InferenceException thrownEx = null;
for (Map.Entry<FreeTypeListener, List<Type>> entry :
new HashMap<FreeTypeListener, List<Type>>(freeTypeListeners).entrySet()) {
......@@ -780,22 +803,23 @@ public class Infer {
}
}
void solveAny(List<Type> varsToSolve, Types types, Infer infer) {
void solveAny(List<Type> varsToSolve) {
boolean progress = false;
for (Type t : varsToSolve) {
UndetVar uv = (UndetVar)asFree(t, types);
UndetVar uv = (UndetVar)asFree(t);
if (uv.inst == null) {
infer.minimizeInst(uv, types.noWarnings);
minimizeInst(uv, types.noWarnings);
if (uv.inst != null) {
progress = true;
}
}
}
if (!progress) {
throw infer.inferenceException.setMessage("cyclic.inference", varsToSolve);
throw inferenceException.setMessage("cyclic.inference", varsToSolve);
}
}
}
final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this, false);
final InferenceContext emptyContext = new InferenceContext(List.<Type>nil());
// </editor-fold>
}
......@@ -35,7 +35,7 @@ import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import com.sun.tools.javac.comp.Infer.FreeTypeListener;
import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.*;
......@@ -741,7 +741,7 @@ public class Resolve {
inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
varargsAccessible(env, inferenceContext.asInstType(t, types), inferenceContext);
varargsAccessible(env, inferenceContext.asInstType(t), inferenceContext);
}
});
} else {
......@@ -785,8 +785,8 @@ public class Resolve {
public boolean compatible(Type found, Type req, Warner warn) {
return strict ?
types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asFree(req, types), warn) :
types.isConvertible(found, deferredAttrContext.inferenceContext.asFree(req, types), warn);
types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asFree(req), warn) :
types.isConvertible(found, deferredAttrContext.inferenceContext.asFree(req), warn);
}
public void report(DiagnosticPosition pos, JCDiagnostic details) {
......
......@@ -96,6 +96,26 @@ public class List<A> extends AbstractCollection<A> implements java.util.List<A>
return res.reverse();
}
public List<A> intersect(List<A> that) {
ListBuffer<A> buf = ListBuffer.lb();
for (A el : this) {
if (that.contains(el)) {
buf.append(el);
}
}
return buf.toList();
}
public List<A> diff(List<A> that) {
ListBuffer<A> buf = ListBuffer.lb();
for (A el : this) {
if (!that.contains(el)) {
buf.append(el);
}
}
return buf.toList();
}
/** Construct a list consisting of given element.
*/
public static <A> List<A> of(A x1) {
......
T7154127.java:19:49: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: Y, T7154127.D,T7154127.B<U>)
T7154127.java:19:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: Y, T7154127.B<U>,T7154127.D)
1 error
......@@ -1006,6 +1006,7 @@ public class DPrinter {
public Void visitUndetVar(UndetVar type, Void ignore) {
for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values())
printList("bounds." + ib, type.getBounds(ib));
printInt("declaredCount", type.declaredCount);
printType("inst", type.inst, Details.SUMMARY);
return visitDelegatedType(type);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册