Eliminate transitive children, add missing object bounds

This commit is contained in:
Victorious3 2023-04-25 15:06:56 +02:00
parent af4db1817a
commit 904bdca2f4
4 changed files with 66 additions and 18 deletions

View File

@ -5,7 +5,7 @@ public class TestContraVariant {
x = y; x = y;
return y; return y;
} }
main(x) { main(x) {
return m(x); return m(x);
} }

View File

@ -1,10 +1,12 @@
public class TestTwoCalls { public class TestTwoCalls {
// <O> O -> O
id(b) { id(b) {
var c = b; var c = b;
return c; return c;
} }
// <T, S> (S, T) -> T
main(x,y) { main(x,y) {
id(x); id(x);
return id(y); return id(y);

View File

@ -552,6 +552,7 @@ public class ASTToTargetAST {
methodFindConstraints(owner, method, simplifiedConstraints, txTypeVariables, classGenerics.userDefinedGenerics, txTypeVariablesOfClass, txResult, txEquality); methodFindConstraints(owner, method, simplifiedConstraints, txTypeVariables, classGenerics.userDefinedGenerics, txTypeVariablesOfClass, txResult, txEquality);
{ // Java Generics { // Java Generics
eliminateTransitives(javaResult);
var referenced = new HashSet<TypePlaceholder>(); var referenced = new HashSet<TypePlaceholder>();
eliminateCycles(javaResult, equality, referenced); eliminateCycles(javaResult, equality, referenced);
@ -569,10 +570,12 @@ public class ASTToTargetAST {
eliminateInnerTypeVariables(referenced, javaResult); eliminateInnerTypeVariables(referenced, javaResult);
equalizeTypeVariables(javaResult, equality); equalizeTypeVariables(javaResult, equality);
usedTPHsOfMethods.put(method, usedTphs); usedTPHsOfMethods.put(method, usedTphs);
addMissingObjectBounds(javaResult, genericsOfClass);
} }
{ {
var referenced = new HashSet<TypePlaceholder>(); var referenced = new HashSet<TypePlaceholder>();
// JavaTX Generics // JavaTX Generics
eliminateTransitives(txResult);
eliminateInfima(txResult, txEquality); eliminateInfima(txResult, txEquality);
for (var param : method.getParameterList().getFormalparalist()) { for (var param : method.getParameterList().getFormalparalist()) {
@ -582,12 +585,36 @@ public class ASTToTargetAST {
referenced.addAll(txTypeVariablesOfClass); referenced.addAll(txTypeVariablesOfClass);
eliminateInnerTypeVariables(referenced, txResult); eliminateInnerTypeVariables(referenced, txResult);
addMissingObjectBounds(txResult, txGenericsOfClass);
} }
System.out.println(method.name + ": " + txResult + " & " + javaResult); System.out.println(method.name + ": " + txResult + " & " + javaResult);
return generics; return generics;
} }
private void eliminateChain(Set<ResultPair<?, ?>> result, List<TypePlaceholder> chain) {
for (var pair : new HashSet<>(result)) {
if (pair instanceof PairTPHsmallerTPH ptph && chain.get(chain.size() - 1).equals(ptph.left)) {
if (chain.contains(ptph.right)) return;
var copy = new ArrayList<>(chain);
copy.add(ptph.right);
if (copy.size() > 2)
result.remove(new PairTPHsmallerTPH(chain.get(0), ptph.right));
eliminateChain(result, copy);
}
}
}
void eliminateTransitives(Set<ResultPair<?,?>> result) {
for (var pair : new HashSet<>(result)) if (pair instanceof PairTPHsmallerTPH ptph) {
var first = ptph.left;
var chain = new ArrayList<TypePlaceholder>();
chain.add(ptph.left);
chain.add(ptph.right);
eliminateChain(result, chain);
}
}
void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set<ResultPair<?, ?>> generics, Map<TypePlaceholder, TypePlaceholder> equality) { void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set<ResultPair<?, ?>> generics, Map<TypePlaceholder, TypePlaceholder> equality) {
if (type instanceof TypePlaceholder tph) { if (type instanceof TypePlaceholder tph) {
tph = equality.getOrDefault(tph, tph); tph = equality.getOrDefault(tph, tph);
@ -632,6 +659,9 @@ public class ASTToTargetAST {
findAllBounds(field.getType(), txResult, txEquality); findAllBounds(field.getType(), txResult, txEquality);
} }
eliminateTransitives(javaResult);
eliminateTransitives(txResult);
System.out.println(javaResult);
var referenced = new HashSet<TypePlaceholder>(); var referenced = new HashSet<TypePlaceholder>();
eliminateCycles(javaResult, equality, referenced); eliminateCycles(javaResult, equality, referenced);
eliminateInfima(javaResult, equality); eliminateInfima(javaResult, equality);
@ -642,10 +672,26 @@ public class ASTToTargetAST {
equalizeTypeVariables(javaResult, equality); equalizeTypeVariables(javaResult, equality);
eliminateInnerTypeVariablesOfClass(classOrInterface, txResult, txEquality, txReferenced); eliminateInnerTypeVariablesOfClass(classOrInterface, txResult, txEquality, txReferenced);
addMissingObjectBounds(javaResult, null);
addMissingObjectBounds(txResult, null);
System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + txResult + ", " + javaResult); System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + txResult + ", " + javaResult);
return generics; return generics;
} }
void addMissingObjectBounds(Set<ResultPair<?,?>> result, Set<ResultPair<?, ?>> filter) {
outer: for (var p1 : new HashSet<>(result)) {
if (p1 instanceof PairTPHsmallerTPH ptph) {
for (var p2 : new HashSet<>(result)) {
if (ptph.right.equals(p2.getLeft()))
continue outer;
}
if (filter == null || filter.stream().noneMatch((pair) -> pair.getLeft().equals(ptph.right)))
result.add(new PairTPHequalRefTypeOrWildcardType(ptph.right, OBJECT));
}
}
}
void equalizeTypeVariables(Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality) { void equalizeTypeVariables(Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality) {
for (var pair : new HashSet<>(input)) { for (var pair : new HashSet<>(input)) {
if (pair instanceof PairTPHsmallerTPH ptph) { if (pair instanceof PairTPHsmallerTPH ptph) {

View File

@ -90,16 +90,15 @@ public class TestGenerics {
var generics = result.genericsResults.get(0); var generics = result.genericsResults.get(0);
assertEquals(0, generics.get(result.clazz).size()); assertEquals(0, generics.get(result.clazz).size());
assertEquals(2, generics.get(m).size()); assertEquals(1, generics.get(m).size());
assertEquals(2, generics.get(main).size()); assertEquals(2, generics.get(main).size());
var N = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); var N = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m);
var NChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)); var N2 = generics.getBounds(m.getReturnType(), result.clazz, m);
assertEquals(N, NChain);
var Q = generics.getBounds(m.getReturnType(), result.clazz, m); var NChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT));
var QChain = new BoundsList(new Bound(true, TypePlaceholder.of("N")), new Bound(true, ASTToTargetAST.OBJECT)); assertEquals(N, N2);
assertEquals(Q, QChain); assertEquals(N2, NChain);
var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main);
assertEquals(R, NChain); assertEquals(R, NChain);
@ -304,17 +303,18 @@ public class TestGenerics {
var main = result.findMethod("main"); var main = result.findMethod("main");
var generics = result.genericsResults.get(0); var generics = result.genericsResults.get(0);
var Q = generics.getBounds(id.getReturnType(), result.clazz, id); var O = generics.getBounds(id.getReturnType(), result.clazz, id);
var N = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); var O2 = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id);
assertEquals(Q, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); assertEquals(O, O2);
assertEquals(N, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); assertEquals(O2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)));
var Q2 = generics.getBounds(main.getReturnType(), result.clazz, main); // TODO Maybe test in other ways if the parameter generics equals the return generics
var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); var S = generics.getBounds(main.getReturnType(), result.clazz, main);
var S = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); var S2 = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main);
assertEquals(Q2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); var T = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main);
assertEquals(R, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); assertEquals(S, S2);
assertEquals(S, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); assertEquals(S2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)));
assertEquals(T, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)));
} }
@Test @Test