Skip to content

Commit 615ff23

Browse files
author
dlsmith
committed
DynamicJava: Bug fix for subtyping cases involving unions; updated "more specific" method relation to support varargs; added an option to "pack" capture variables that are the result of inference (javac does this, JLS doesn't specify it); fixed TypePrinter bug.
git-svn-id: file:///tmp/test-svn/trunk@5071 fe72c1cf-3628-48e9-8b72-1c46755d3cff
1 parent e8c0011 commit 615ff23

File tree

3 files changed

+91
-14
lines changed

3 files changed

+91
-14
lines changed

dynamicjava/src/edu/rice/cs/dynamicjava/symbol/ExtendedTypeSystem.java

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.util.*;
44
import edu.rice.cs.plt.tuple.Pair;
5-
import edu.rice.cs.plt.tuple.Triple;
65
import edu.rice.cs.plt.tuple.Option;
76
import edu.rice.cs.plt.tuple.Wrapper;
87
import edu.rice.cs.plt.recur.*;
@@ -28,7 +27,15 @@
2827

2928
public class ExtendedTypeSystem extends StandardTypeSystem {
3029

31-
public ExtendedTypeSystem(Options opt) { super(opt); }
30+
/** Whether the inference algorithm should attempt to pack capture variables that appear as inference results. */
31+
private final boolean _packCaptureVars;
32+
33+
public ExtendedTypeSystem(Options opt) { this(opt, true); }
34+
35+
public ExtendedTypeSystem(Options opt, boolean packCaptureVars) {
36+
super(opt);
37+
_packCaptureVars = packCaptureVars;
38+
}
3239

3340
/** Determine if the type is well-formed. */
3441
public boolean isWellFormed(Type t) {
@@ -134,7 +141,7 @@ public boolean contains(final Type subT, final Type superT) {
134141

135142
@Override public Boolean forVariableType(final VariableType superT) {
136143
return subT.apply(new TypeAbstractVisitor<Boolean>() {
137-
public Boolean defaultCase(final Type subT) {
144+
@Override public Boolean defaultCase(final Type subT) {
138145
Thunk<Boolean> checkLowerBound = new Thunk<Boolean>() {
139146
public Boolean value() {
140147
Type bound = new Normalizer(NormSubtyper.this).value(superT.symbol().lowerBound());
@@ -152,23 +159,30 @@ public Boolean value() {
152159
@Override public Boolean forIntersectionType(IntersectionType subT) {
153160
return defaultCase(subT) ? true : null;
154161
}
162+
@Override public Boolean forUnionType(UnionType subT) { return null; }
155163
@Override public Boolean forBottomType(BottomType subT) { return true; }
156164
});
157165
}
158166

159-
@Override public Boolean forIntersectionType(IntersectionType superT) {
160-
if (subT instanceof BottomType) { return true; }
161-
else { return IterUtil.and(superT.ofTypes(), supertypes(subT)); }
167+
@Override public Boolean forIntersectionType(final IntersectionType superT) {
168+
return subT.apply(new TypeAbstractVisitor<Boolean>() {
169+
@Override public Boolean defaultCase(Type subT) {
170+
return IterUtil.and(superT.ofTypes(), supertypes(subT));
171+
}
172+
@Override public Boolean forUnionType(UnionType subT) { return null; }
173+
@Override public Boolean forBottomType(BottomType subT) { return true; }
174+
});
162175
}
163176

164177
@Override public Boolean forUnionType(final UnionType superT) {
165178
return subT.apply(new TypeAbstractVisitor<Boolean>() {
166179
@Override public Boolean defaultCase(Type t) {
167180
return IterUtil.or(superT.ofTypes(), supertypes(subT));
168181
}
169-
public Boolean forVariableType(VariableType t) { return defaultCase(subT) ? true : null; }
170-
public Boolean forUnionType(UnionType t) { return null; }
171-
public Boolean forBottomType(BottomType t) { return true; }
182+
@Override public Boolean forVariableType(VariableType t) { return defaultCase(subT) ? true : null; }
183+
@Override public Boolean forIntersectionType(IntersectionType t) { return null; }
184+
@Override public Boolean forUnionType(UnionType t) { return null; }
185+
@Override public Boolean forBottomType(BottomType t) { return true; }
172186
});
173187
}
174188

@@ -560,7 +574,7 @@ public String toString() {
560574
result.append("{ ");
561575
boolean firstVar = true;
562576
for (VariableType var : s.boundVariables()) {
563-
if (firstVar) { result.append(", "); }
577+
if (!firstVar) { result.append(", "); }
564578
firstVar = false;
565579
result.append(printer.print(s.lowerBound(var)));
566580
result.append(" <: ");
@@ -765,7 +779,23 @@ protected Iterable<Type> inferTypeArguments(Iterable<? extends VariableType> tpa
765779
//debug.logValue("constraints", constraints);
766780
if (!transConstraints.isSatisfiable()) { return null; }
767781

768-
// try to use lower bounds
782+
// try to use packed lower bounds
783+
if (_packCaptureVars) {
784+
for (final ConstraintScenario s : transConstraints.scenarios()) {
785+
Iterable<Type> result = IterUtil.mapSnapshot(tparams, new Lambda<VariableType, Type>() {
786+
public Type value(VariableType param) {
787+
Type result = s.lowerBound(param);
788+
while (result instanceof VariableType && ((VariableType) result).symbol().generated()) {
789+
result = ((VariableType) result).symbol().upperBound();
790+
}
791+
return result;
792+
}
793+
});
794+
if (inBounds(tparams, result)) { return result; }
795+
}
796+
}
797+
798+
// packed lower bounds don't work, try to use lower bounds
769799
for (final ConstraintScenario s : transConstraints.scenarios()) {
770800
Iterable<Type> result = IterUtil.mapSnapshot(tparams, new Lambda<VariableType, Type>() {
771801
public Type value(VariableType param) { return s.lowerBound(param); }

dynamicjava/src/edu/rice/cs/dynamicjava/symbol/StandardTypeSystem.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,7 @@ private class Visitor extends TypeVisitorRunnable1 {
14791479
private final RecursionStack<Type> _stack = new RecursionStack<Type>();
14801480
// variables that have bounds that should be printed in appendConstraints()
14811481
private final List<VariableType> _boundedVars = new ArrayList<VariableType>();
1482+
private final Set<VariableType> _seenVars = new HashSet<VariableType>();
14821483

14831484
public String result() { return _result.toString(); }
14841485

@@ -1517,12 +1518,15 @@ private String nameForVariable(VariableType t) {
15171518
if (t.symbol().generated()) { _captureVars++; name = "?T" + _captureVars; }
15181519
else { name = t.symbol().name(); }
15191520
_names.put(t, name);
1521+
}
1522+
if (!_seenVars.contains(t)) {
1523+
_seenVars.add(t);
15201524
// check to see if bounds need to be printed
15211525
Type upper = t.symbol().upperBound();
15221526
Type lower = t.symbol().lowerBound();
15231527
boolean printUpper = !isEqual(upper, OBJECT) /*&& !isEqual(upper, TOP)*/;
15241528
boolean printLower = !isEqual(lower, NULL) /*&& !isEqual(lower, BOTTOM)*/;
1525-
if (printUpper || printLower) _boundedVars.add(t);
1529+
if (printUpper || printLower) { _boundedVars.add(t); }
15261530
}
15271531
return name;
15281532
}
@@ -2064,8 +2068,45 @@ else if (IterUtil.sizeOf(tparams) == IterUtil.sizeOf(targs) && inBounds(tparams,
20642068
* SignatureMatchers. This relation is defined in JLS 15.12.2.5.
20652069
*/
20662070
public boolean moreSpecificThan(FunctionInvocationCandidate<F> c) {
2067-
SignatureMatcher m = makeMatcher(c._f.typeParameters(), EMPTY_TYPE_ITERABLE, SymbolUtil.parameterTypes(c._f),
2068-
IterUtil.mapSnapshot(SymbolUtil.parameterTypes(_f), EMPTY_EXPRESSION_FOR_TYPE),
2071+
Iterable<Type> supParams = SymbolUtil.parameterTypes(c._f);
2072+
Iterable<Type> subParams = SymbolUtil.parameterTypes(_f);
2073+
if (SymbolUtil.isVararg(c._f)) {
2074+
// Adjust param type lists to match arities, if possible. Can't use SignatureMatcher.matchesWithVarargs()
2075+
// because it uses boxing, which is not allowed here.
2076+
int supArity = IterUtil.sizeOf(supParams);
2077+
int subArity = IterUtil.sizeOf(subParams);
2078+
if (SymbolUtil.isVararg(_f)) {
2079+
if (subArity < supArity) { // fill in extra sub args
2080+
Iterable<Type> prefixSubs = IterUtil.skipLast(subParams);
2081+
Type lastSub = IterUtil.last(subParams);
2082+
Iterable<Type> subExtras = IterUtil.copy(((ArrayType) lastSub).ofType(), supArity-subArity);
2083+
subParams = IterUtil.compose(IterUtil.compose(prefixSubs, subExtras), lastSub);
2084+
}
2085+
else if (subArity > supArity) {
2086+
Iterable<Type> prefixSups = IterUtil.skipLast(supParams);
2087+
Type lastSup = IterUtil.last(supParams);
2088+
Iterable<Type> supExtras = IterUtil.copy(((ArrayType) lastSup).ofType(), subArity-supArity);
2089+
supParams = IterUtil.compose(IterUtil.compose(prefixSups, supExtras), lastSup);
2090+
}
2091+
// if they're equal, no adjustments are needed
2092+
}
2093+
else {
2094+
// This case doesn't occur in practice, because "more specific" is only used to compare
2095+
// methods that all match in the same phase (directly, with boxing, or with varargs).
2096+
if (subArity < supArity) { supParams = IterUtil.skipLast(supParams); } // allow sub to elide the vararg param
2097+
else if (subArity > supArity) {
2098+
Iterable<Type> prefixSups = IterUtil.skipLast(supParams);
2099+
Type lastSup = IterUtil.last(supParams);
2100+
int varargArgs = subArity-(supArity-1); // expect this many args of the vararg type
2101+
supParams = IterUtil.compose(prefixSups, IterUtil.copy(((ArrayType) lastSup).ofType(), varargArgs));
2102+
}
2103+
// if they're equal, no adjustments are needed
2104+
// (If lastSup is T..., lastSub might be a subtype of T or of T[]. For the purposes of
2105+
// "more specific", we arbitrarily require it to be a subtype of T[].)
2106+
}
2107+
}
2108+
SignatureMatcher m = makeMatcher(c._f.typeParameters(), EMPTY_TYPE_ITERABLE, supParams,
2109+
IterUtil.mapSnapshot(subParams, EMPTY_EXPRESSION_FOR_TYPE),
20692110
BOTTOM, NONE_TYPE_OPTION);
20702111
return m.matches();
20712112
}

dynamicjava/src/edu/rice/cs/dynamicjava/symbol/SymbolUtil.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,5 +241,11 @@ public static Iterable<Type> parameterTypes(Function f) {
241241
private static final Lambda<Variable, Type> TYPE_OF_VARIABLE = new Lambda<Variable, Type>() {
242242
public Type value(Variable v) { return v.type(); }
243243
};
244+
245+
/** Test whether the function's last parameter has a VarargArrayType type. */
246+
public static boolean isVararg(Function f) {
247+
Iterable<LocalVariable> params = f.parameters();
248+
return !IterUtil.isEmpty(params) && (IterUtil.last(params).type() instanceof VarargArrayType);
249+
}
244250

245251
}

0 commit comments

Comments
 (0)