| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e8c0011 commit 615ff23
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,7 +2,6 @@ | |||
| 2 | 2 | ||
| 3 | 3 | import java.util.*; | |
| 4 | 4 | import edu.rice.cs.plt.tuple.Pair; | |
| 5 | - import edu.rice.cs.plt.tuple.Triple; | ||
| 6 | 5 | import edu.rice.cs.plt.tuple.Option; | |
| 7 | 6 | import edu.rice.cs.plt.tuple.Wrapper; | |
| 8 | 7 | import edu.rice.cs.plt.recur.*; | |
@@ -28,7 +27,15 @@ | |||
| 28 | 27 | ||
| 29 | 28 | public class ExtendedTypeSystem extends StandardTypeSystem { | |
| 30 | 29 | ||
| 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 | + } | ||
| 32 | 39 | ||
| 33 | 40 | /** Determine if the type is well-formed. */ | |
| 34 | 41 | public boolean isWellFormed(Type t) { | |
@@ -134,7 +141,7 @@ public boolean contains(final Type subT, final Type superT) { | |||
| 134 | 141 | ||
| 135 | 142 | @Override public Boolean forVariableType(final VariableType superT) { | |
| 136 | 143 | return subT.apply(new TypeAbstractVisitor<Boolean>() { | |
| 137 | - public Boolean defaultCase(final Type subT) { | ||
| 144 | + @Override public Boolean defaultCase(final Type subT) { | ||
| 138 | 145 | Thunk<Boolean> checkLowerBound = new Thunk<Boolean>() { | |
| 139 | 146 | public Boolean value() { | |
| 140 | 147 | Type bound = new Normalizer(NormSubtyper.this).value(superT.symbol().lowerBound()); | |
@@ -152,23 +159,30 @@ public Boolean value() { | |||
| 152 | 159 | @Override public Boolean forIntersectionType(IntersectionType subT) { | |
| 153 | 160 | return defaultCase(subT) ? true : null; | |
| 154 | 161 | } | |
| 162 | + @Override public Boolean forUnionType(UnionType subT) { return null; } | ||
| 155 | 163 | @Override public Boolean forBottomType(BottomType subT) { return true; } | |
| 156 | 164 | }); | |
| 157 | 165 | } | |
| 158 | 166 | ||
| 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 | + }); | ||
| 162 | 175 | } | |
| 163 | 176 | ||
| 164 | 177 | @Override public Boolean forUnionType(final UnionType superT) { | |
| 165 | 178 | return subT.apply(new TypeAbstractVisitor<Boolean>() { | |
| 166 | 179 | @Override public Boolean defaultCase(Type t) { | |
| 167 | 180 | return IterUtil.or(superT.ofTypes(), supertypes(subT)); | |
| 168 | 181 | } | |
| 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; } | ||
| 172 | 186 | }); | |
| 173 | 187 | } | |
| 174 | 188 | ||
@@ -560,7 +574,7 @@ public String toString() { | |||
| 560 | 574 | result.append("{ "); | |
| 561 | 575 | boolean firstVar = true; | |
| 562 | 576 | for (VariableType var : s.boundVariables()) { | |
| 563 | - if (firstVar) { result.append(", "); } | ||
| 577 | + if (!firstVar) { result.append(", "); } | ||
| 564 | 578 | firstVar = false; | |
| 565 | 579 | result.append(printer.print(s.lowerBound(var))); | |
| 566 | 580 | result.append(" <: "); | |
@@ -765,7 +779,23 @@ protected Iterable<Type> inferTypeArguments(Iterable<? extends VariableType> tpa | |||
| 765 | 779 | //debug.logValue("constraints", constraints); | |
| 766 | 780 | if (!transConstraints.isSatisfiable()) { return null; } | |
| 767 | 781 | ||
| 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 | ||
| 769 | 799 | for (final ConstraintScenario s : transConstraints.scenarios()) { | |
| 770 | 800 | Iterable<Type> result = IterUtil.mapSnapshot(tparams, new Lambda<VariableType, Type>() { | |
| 771 | 801 | public Type value(VariableType param) { return s.lowerBound(param); } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1479,6 +1479,7 @@ private class Visitor extends TypeVisitorRunnable1 { | |||
| 1479 | 1479 | private final RecursionStack<Type> _stack = new RecursionStack<Type>(); | |
| 1480 | 1480 | // variables that have bounds that should be printed in appendConstraints() | |
| 1481 | 1481 | private final List<VariableType> _boundedVars = new ArrayList<VariableType>(); | |
| 1482 | + private final Set<VariableType> _seenVars = new HashSet<VariableType>(); | ||
| 1482 | 1483 | ||
| 1483 | 1484 | public String result() { return _result.toString(); } | |
| 1484 | 1485 | ||
@@ -1517,12 +1518,15 @@ private String nameForVariable(VariableType t) { | |||
| 1517 | 1518 | if (t.symbol().generated()) { _captureVars++; name = "?T" + _captureVars; } | |
| 1518 | 1519 | else { name = t.symbol().name(); } | |
| 1519 | 1520 | _names.put(t, name); | |
| 1521 | + } | ||
| 1522 | + if (!_seenVars.contains(t)) { | ||
| 1523 | + _seenVars.add(t); | ||
| 1520 | 1524 | // check to see if bounds need to be printed | |
| 1521 | 1525 | Type upper = t.symbol().upperBound(); | |
| 1522 | 1526 | Type lower = t.symbol().lowerBound(); | |
| 1523 | 1527 | boolean printUpper = !isEqual(upper, OBJECT) /*&& !isEqual(upper, TOP)*/; | |
| 1524 | 1528 | boolean printLower = !isEqual(lower, NULL) /*&& !isEqual(lower, BOTTOM)*/; | |
| 1525 | - if (printUpper || printLower) _boundedVars.add(t); | ||
| 1529 | + if (printUpper || printLower) { _boundedVars.add(t); } | ||
| 1526 | 1530 | } | |
| 1527 | 1531 | return name; | |
| 1528 | 1532 | } | |
@@ -2064,8 +2068,45 @@ else if (IterUtil.sizeOf(tparams) == IterUtil.sizeOf(targs) && inBounds(tparams, | |||
| 2064 | 2068 | * SignatureMatchers. This relation is defined in JLS 15.12.2.5. | |
| 2065 | 2069 | */ | |
| 2066 | 2070 | 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), | ||
| 2069 | 2110 | BOTTOM, NONE_TYPE_OPTION); | |
| 2070 | 2111 | return m.matches(); | |
| 2071 | 2112 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -241,5 +241,11 @@ public static Iterable<Type> parameterTypes(Function f) { | |||
| 241 | 241 | private static final Lambda<Variable, Type> TYPE_OF_VARIABLE = new Lambda<Variable, Type>() { | |
| 242 | 242 | public Type value(Variable v) { return v.type(); } | |
| 243 | 243 | }; | |
| 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 | + } | ||
| 244 | 250 | ||
| 245 | 251 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments