From 97a1bcbbe1d75cd1c629d0476b0688718bdb95dc Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Thu, 22 Jun 2023 17:13:01 +0200 Subject: [PATCH 1/7] Fix T1 & T2 refering to method signature instead of actual types --- .../target/generate/GenerateGenerics.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java index 4f264e68..53143235 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java @@ -285,7 +285,7 @@ public abstract class GenerateGenerics { superType = methodCall.receiverType; methodCall.receiver.accept(this); for (int i = 0; i < methodCall.arglist.getArguments().size(); i++) { - superType = methodCall.signature.get(i); + superType = methodCall.arglist.getArguments().get(i).getType(); methodCall.arglist.getArguments().get(i).accept(this); } @@ -345,7 +345,7 @@ public abstract class GenerateGenerics { @Override public void visit(LambdaExpression lambdaExpression) { - superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken()); + superType = new Void(new NullToken()); lambdaExpression.methodBody.accept(this); } @@ -357,9 +357,9 @@ public abstract class GenerateGenerics { @Override public void visit(BinaryExpr binary) { - superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken()); + superType = new Void(new NullToken()); binary.lexpr.accept(this); - superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken()); + superType = new Void(new NullToken()); binary.rexpr.accept(this); } @@ -373,11 +373,11 @@ public abstract class GenerateGenerics { @Override public void visit(IfStmt ifStmt) { - superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken()); + superType = new Void(new NullToken()); ifStmt.expr.accept(this); - superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken()); + superType = new Void(new NullToken()); ifStmt.then_block.accept(this); - superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken()); + superType = new Void(new NullToken()); ifStmt.else_block.accept(this); } @@ -389,7 +389,7 @@ public abstract class GenerateGenerics { @Override public void visit(WhileStmt whileStmt) { - superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken()); + superType = new Void(new NullToken()); whileStmt.expr.accept(this); superType = new Void(new NullToken()); whileStmt.loopBlock.accept(this); From 4bcb91ce2dbca71e34d77229a59e456162a4d984 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Thu, 22 Jun 2023 17:13:15 +0200 Subject: [PATCH 2/7] Refactor bounds to make the invocation smaller --- .../insertGenerics/javFiles/TestVector.jav | 4 +- .../dhbwstuttgart/target/generate/Bound.java | 14 ++++ src/test/java/targetast/TestGenerics.java | 77 ++++++++++--------- 3 files changed, 54 insertions(+), 41 deletions(-) diff --git a/resources/insertGenerics/javFiles/TestVector.jav b/resources/insertGenerics/javFiles/TestVector.jav index 6c8f97f0..76c06ff9 100644 --- a/resources/insertGenerics/javFiles/TestVector.jav +++ b/resources/insertGenerics/javFiles/TestVector.jav @@ -3,9 +3,7 @@ import java.util.Vector; public class TestVector { m(v, w) { - var a = v.elementAt(0); - var b = id(a); - w.addElement(b); + w.addElement(id(v.elementAt(0))); } id(x) { diff --git a/src/main/java/de/dhbwstuttgart/target/generate/Bound.java b/src/main/java/de/dhbwstuttgart/target/generate/Bound.java index 1b39df6c..3e749092 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/Bound.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/Bound.java @@ -6,5 +6,19 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import java.util.List; public record Bound(boolean isOnMethod, RefTypeOrTPHOrWildcardOrGeneric bound) { + public static Bound onMethod(String tph) { + return new Bound(true, TypePlaceholder.of(tph)); + } + public static Bound onMethod(RefTypeOrTPHOrWildcardOrGeneric bound) { + return new Bound(true, bound); + } + + public static Bound onClass(String tph) { + return new Bound(false, TypePlaceholder.of(tph)); + } + + public static Bound onClass(RefTypeOrTPHOrWildcardOrGeneric bound) { + return new Bound(false, bound); + } } diff --git a/src/test/java/targetast/TestGenerics.java b/src/test/java/targetast/TestGenerics.java index 3d4ad553..5f74ae3a 100644 --- a/src/test/java/targetast/TestGenerics.java +++ b/src/test/java/targetast/TestGenerics.java @@ -7,10 +7,11 @@ import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.target.generate.ASTToTargetAST; +import static de.dhbwstuttgart.target.generate.ASTToTargetAST.OBJECT; import de.dhbwstuttgart.target.generate.Bound; +import static de.dhbwstuttgart.target.generate.Bound.*; import de.dhbwstuttgart.target.generate.BoundsList; import de.dhbwstuttgart.target.generate.GenericsResult; -import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.*; @@ -23,7 +24,7 @@ import java.util.List; public class TestGenerics { - private static final String rootDirectory = System.getProperty("user.dir") + "/resources/insertGenericsJav/"; + private static final String rootDirectory = System.getProperty("user.dir") + "/resources/insertGenerics/javFiles/"; private static final String bytecodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/"; private record Result(List genericsResults, ClassOrInterface clazz) { @@ -60,12 +61,12 @@ public class TestGenerics { var ECK1 = generics.getBounds(otherMethod.getParameterList().getParameterAt(0).getType(), result.clazz, anyMethod); var ECK2 = generics.getBounds(otherMethod.getReturnType(), result.clazz, anyMethod); - var ECKChain = new BoundsList(new Bound(false, ASTToTargetAST.OBJECT)); + var ECKChain = new BoundsList(onClass(OBJECT)); assertEquals(ECK1, ECK2); assertEquals(ECK2, generics.getBounds(b.getType(), result.clazz)); var M = generics.getBounds(a.getType(), result.clazz); - var MChain = new BoundsList(new Bound(false, TypePlaceholder.of("ECK")), new Bound(false, ASTToTargetAST.OBJECT)); + var MChain = new BoundsList(onClass("ECK"), onClass(OBJECT)); assertEquals(M, MChain); } @@ -79,7 +80,7 @@ public class TestGenerics { assertEquals(0, generics.get(fReturn).size()); var N = generics.getBounds(fReturn.getReturnType(), result.clazz); - var NChain = new BoundsList(new Bound(false, ASTToTargetAST.OBJECT)); + var NChain = new BoundsList(onClass(OBJECT)); assertEquals(N, NChain); } @@ -97,7 +98,7 @@ public class TestGenerics { var N = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); var N2 = generics.getBounds(m.getReturnType(), result.clazz, m); - var NChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)); + var NChain = new BoundsList(onMethod(OBJECT)); assertEquals(N, N2); assertEquals(N2, NChain); @@ -123,13 +124,13 @@ public class TestGenerics { assertEquals(2, generics.get(m).size()); var R = generics.getBounds(a.getType(), result.clazz); - var RChain = new BoundsList(new Bound(false, ASTToTargetAST.OBJECT)); + var RChain = new BoundsList(onClass(OBJECT)); assertEquals(R, RChain); var O = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); var AB = generics.getBounds(id.getReturnType(), result.clazz, id); assertEquals(O, AB); - assertEquals(AB, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(AB, new BoundsList(onMethod(OBJECT))); var S = generics.getBounds(setA.getParameterList().getParameterAt(0).getType(), result.clazz, setA); assertEquals(S, RChain); @@ -137,7 +138,7 @@ public class TestGenerics { var X = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); var Y = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); - var XChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)); + var XChain = new BoundsList(onMethod(OBJECT)); assertEquals(X, XChain); assertEquals(Y, X); } @@ -163,25 +164,25 @@ public class TestGenerics { assertEquals(3, generics.get(main).size()); var N = generics.getBounds(a.getType(), result.clazz); - assertEquals(N, new BoundsList(new Bound(false, ASTToTargetAST.OBJECT))); + assertEquals(N, new BoundsList(onClass(OBJECT))); var P = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); var O = generics.getBounds(id.getReturnType(), result.clazz, id); assertEquals(P, O); - assertEquals(O, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(O, new BoundsList(onMethod(OBJECT))); assertEquals(generics.resolve(m.getParameterList().getParameterAt(0).getType()), generics.resolve(m.getReturnType())); var Y = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); var AA = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); assertEquals(Y, AA); - assertEquals(AA, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(AA, new BoundsList(onMethod(OBJECT))); var AI = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); var AJ = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); var AH = generics.getBounds(m.getReturnType(), result.clazz, m); assertEquals(AI, AJ); assertEquals(AJ, AH); - assertEquals(AH, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(AH, new BoundsList(onMethod(OBJECT))); } @Test @@ -193,7 +194,7 @@ public class TestGenerics { assertEquals(1, generics.get(anyMethod).size()); var M = generics.getBounds(anyMethod.getReturnType(), result.clazz, anyMethod); - assertEquals(M, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(M, new BoundsList(onMethod(OBJECT))); } @Test @@ -207,12 +208,12 @@ public class TestGenerics { var generics = result.genericsResults.get(0); var M = generics.getBounds(a.getType(), result.clazz); var DYX = generics.getBounds(b.getType(), result.clazz); - var MChain = new BoundsList(new Bound(false, TypePlaceholder.of("DYX")), new Bound(false, ASTToTargetAST.OBJECT)); - var DYXChain = new BoundsList(new Bound(false, ASTToTargetAST.OBJECT)); + var MChain = new BoundsList(onClass("DYX"), onClass(OBJECT)); + var DYXChain = new BoundsList(onClass(OBJECT)); assertEquals(M, MChain); var Q = generics.getBounds(anyMethod.getReturnType(), result.clazz, anyMethod); - assertEquals(Q, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(Q, new BoundsList(onMethod(OBJECT))); System.out.println(otherMethod.getReturnType()); var DYX2 = generics.getBounds(otherMethod.getReturnType(), result.clazz, otherMethod); @@ -235,17 +236,17 @@ public class TestGenerics { var generics = result.genericsResults.get(0); var U = generics.getBounds(id2.getParameterList().getParameterAt(0).getType(), result.clazz, id2); var FPT = generics.getBounds(id2.getReturnType(), result.clazz, id2); - assertEquals(U, new BoundsList(new Bound(true, TypePlaceholder.of("FPT")), new Bound(false, ASTToTargetAST.OBJECT))); - assertEquals(FPT, new BoundsList(new Bound(false, ASTToTargetAST.OBJECT))); + assertEquals(U, new BoundsList(onMethod("FPT"), onClass(OBJECT))); + assertEquals(FPT, new BoundsList(onClass(OBJECT))); var AA = generics.getBounds(m.getReturnType(), result.clazz, m); var AC = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); - assertEquals(AA, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); - assertEquals(AC, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(AA, new BoundsList(onMethod(OBJECT))); + assertEquals(AC, new BoundsList(onMethod(OBJECT))); var AH = generics.getBounds(m2.getReturnType(), result.clazz, m2); var AL = generics.getBounds(m2.getParameterList().getParameterAt(0).getType(), result.clazz, m2); - assertEquals(AH, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(AH, new BoundsList(onMethod(OBJECT))); assertEquals(AH, AL); } @@ -262,32 +263,32 @@ public class TestGenerics { var generics = result.genericsResults.get(0); var AO = generics.getBounds(a.getType(), result.clazz); var AOBound = new BoundsList( - new Bound(false, TypePlaceholder.of("Y")), - new Bound(false, TypePlaceholder.of("AK")), - new Bound(false, TypePlaceholder.of("AE")), - new Bound(false, ASTToTargetAST.OBJECT) + onClass("Y"), + onClass("AK"), + onClass("AE"), + onClass(OBJECT) ); assertEquals(AO, AOBound); var S = generics.getBounds(setA.getParameterList().getParameterAt(0).getType(), result.clazz, setA); var c = new ArrayList(); - c.add(new Bound(true, TypePlaceholder.of("AO"))); + c.add(onMethod("AO")); c.addAll(AOBound); var SChain = new BoundsList(c); assertEquals(S, SChain); var Y = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); - var YChain = new BoundsList(new Bound(true, TypePlaceholder.of("AE")), new Bound(false, ASTToTargetAST.OBJECT)); + var YChain = new BoundsList(onMethod("AE"), onClass(OBJECT)); var AE = generics.getBounds(m.getReturnType(), result.clazz, m); assertEquals(Y, YChain); - assertEquals(AE, new BoundsList(new Bound(false, ASTToTargetAST.OBJECT))); + assertEquals(AE, new BoundsList(onClass(OBJECT))); // TODO main seems to change between runs /*var AE2 = generics.getBounds(main.getReturnType(), result.clazz, main); var AF = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); var AG = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); assertEquals(AE, AE2)); - assertEquals(AF, new BoundsList(new Bound(true, TypePlaceholder.of("AK")), new Bound(true, TypePlaceholder.of("AE")), new Bound(false, ASTToTargetAST.OBJECT)))); + assertEquals(AF, new BoundsList(onMethod("AK"), onMethod("AE"), onClass(OBJECT)))); assertEquals(AG, SChain));*/ } @@ -307,15 +308,15 @@ public class TestGenerics { var O = generics.getBounds(id.getReturnType(), result.clazz, id); var O2 = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); assertEquals(O, O2); - assertEquals(O2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(O2, new BoundsList(onMethod(OBJECT))); // TODO Maybe test in other ways if the parameter generics equals the return generics var S = generics.getBounds(main.getReturnType(), result.clazz, main); var S2 = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); var T = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); assertEquals(S, S2); - assertEquals(S2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); - assertEquals(T, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(S2, new BoundsList(onMethod(OBJECT))); + assertEquals(T, new BoundsList(onMethod(OBJECT))); } @Test @@ -330,11 +331,11 @@ public class TestGenerics { var S = generics.getBounds(((RefType) par1).getParaList().get(0), result.clazz, m); var ACM = generics.getBounds(((RefType) par2).getParaList().get(0), result.clazz, m); - assertEquals(S, new BoundsList(new Bound(true, TypePlaceholder.of("V")), new Bound(true, ASTToTargetAST.OBJECT))); - assertEquals(ACM, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(S, new BoundsList(onMethod("V"), onMethod(OBJECT))); + assertEquals(ACM, new BoundsList(onMethod(OBJECT))); var Y = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); - assertEquals(Y, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(Y, new BoundsList(onMethod(OBJECT))); assertEquals(Y, generics.getBounds(id.getReturnType(), result.clazz, id)); } @@ -348,8 +349,8 @@ public class TestGenerics { var par1 = generics.resolve(add.getParameterList().getParameterAt(0).getType()); var ACK = generics.getBounds(((RefType) par1).getParaList().get(0), result.clazz, add); var O = generics.getBounds(add.getParameterList().getParameterAt(1).getType(), result.clazz, add); - assertEquals(ACK, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); - assertEquals(O, new BoundsList(new Bound(true, TypePlaceholder.of("ACK")), new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(ACK, new BoundsList(onMethod(OBJECT))); + assertEquals(O, new BoundsList(onMethod("ACK"), onMethod(OBJECT))); var par2 = generics.resolve(main.getParameterList().getParameterAt(0).getType()); var ACK2 = generics.getBounds(((RefType) par2).getParaList().get(0), result.clazz, add); From f5aa90bdbdfc0da51c7d27176125bb2b1276556e Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Fri, 23 Jun 2023 09:40:23 +0200 Subject: [PATCH 3/7] Add Cycle class (again) --- resources/bytecode/javFiles/Cycle.class | Bin 0 -> 454 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/bytecode/javFiles/Cycle.class diff --git a/resources/bytecode/javFiles/Cycle.class b/resources/bytecode/javFiles/Cycle.class new file mode 100644 index 0000000000000000000000000000000000000000..a7650d8b63e000e1e4cc8b1f35d7dfa6f14ac9dc GIT binary patch literal 454 zcmZWkO;5r=5Pj1E{jkV~UuRFYYQn`6ZMf8g$VWV|DR5knAc)0~s_|!WGV!2yf0Q~4 zjV5-JeY5l4%-fmIueWyq7dRs1!h?*Zw_(0T0YB>nz~5H zh0B`>!RpPXu}mIU{4TY44>9;FOlQBu6z)xm8T4vmxFd)Ft&UJn`hfsUn@#s z+xH?9`zCZ8L*otA(ZKt|V6Mbjg)`!qKYfL@RyxXjH7=-ZVwGhZJ88Mgiq5=!HthD# ghn@cVgEL-_(E)wKQmKL6)Wu0%4!CdYtEbH254V Date: Tue, 27 Jun 2023 15:00:43 +0200 Subject: [PATCH 4/7] Test more thoroughly and add a new infimum deletion strategy --- .../target/generate/BoundsList.java | 12 +++- .../target/generate/GenerateGenerics.java | 44 ++++++++++++++ .../target/generate/GenericsResult.java | 7 ++- .../target/generate/JavaGenerics.java | 1 + src/test/java/targetast/TestGenerics.java | 58 +++++++++++++------ 5 files changed, 100 insertions(+), 22 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/BoundsList.java b/src/main/java/de/dhbwstuttgart/target/generate/BoundsList.java index b92394d6..5a1f797d 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/BoundsList.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/BoundsList.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.generate; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import java.util.AbstractList; @@ -7,12 +8,19 @@ import java.util.List; public class BoundsList extends AbstractList { private final List bounds; + public final RefTypeOrTPHOrWildcardOrGeneric base; - public BoundsList(List bounds) { + public BoundsList(RefTypeOrTPHOrWildcardOrGeneric base, List bounds) { + this.base = base; this.bounds = bounds; } + + public BoundsList(List bounds) { + this(null, bounds); + } + public BoundsList(Bound... bounds) { - this.bounds = List.of(bounds); + this(null, List.of(bounds)); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java index 53143235..9c4b1439 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java @@ -826,6 +826,50 @@ public abstract class GenerateGenerics { } } + TPH findConnectionToReturnType(Set returnTypes, Set input, Set visited, TPH tph) { + if (returnTypes.contains(tph)) { + return tph; + } else { + for (var pair : input) if (pair instanceof PairLT ptph) { + if (ptph.left.equals(tph) && !visited.contains(ptph.right)) { + visited.add(ptph.right); + var result = findConnectionToReturnType(returnTypes, input, visited, ptph.right); + if (result != null) return result; + } + } + } + return null; + } + + void eliminateInfimaConnectedToReturnType(Method method, Set input, Set referenced) { + var foundInfima = false; + do { + foundInfima = false; + for (var constraint : new HashSet<>(input)) { + var left = constraint.left; + Set infima = new HashSet<>(); + for (var pair : input) { + if (pair instanceof PairLT stph) { + if (pair.left.equals(constraint.left)) + infima.add(stph); + } + } + if (infima.size() > 1) { + for (var pair : infima) { + var returnTypes = findTypeVariables(method.getReturnType()); + var returnType = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left); + if (returnType != null && !returnType.equals(pair.left)) { + System.out.println("Equals now: " + pair.left.resolve() + " " + returnType.resolve()); + addToEquality(pair.left.resolve(), returnType.resolve(), referenced); + foundInfima = true; + } + } + } + } + } while (foundInfima); + input.removeIf((i) -> !(i instanceof PairLT lt) || lt.left.equals(lt.right)); + } + void eliminateInfima(Set input, Set referenced) { var foundInfima = false; do { diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java b/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java index a30fdba9..44476211 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java @@ -31,7 +31,8 @@ public class GenericsResult { } public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz, Method method) { - type = resolve(type); + var resolvedType = resolve(type); + type = resolvedType; if (type instanceof TypePlaceholder) { var methodGenerics = get(method); var classGenerics = get(clazz); @@ -58,9 +59,9 @@ public class GenericsResult { } bound.ifPresent(result::add); } while (bound.isPresent()); - return new BoundsList(result); + return new BoundsList(resolvedType, result); } - return new BoundsList(List.of()); + return new BoundsList(resolvedType, List.of()); } public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) { diff --git a/src/main/java/de/dhbwstuttgart/target/generate/JavaGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/JavaGenerics.java index 16be617e..abe779ae 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/JavaGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/JavaGenerics.java @@ -14,6 +14,7 @@ final class JavaGenerics extends GenerateGenerics { @Override void generics(ClassOrInterface owner, Method method, Set result, Set referenced) { eliminateCycles(result, referenced); + eliminateInfimaConnectedToReturnType(method, result, referenced); eliminateInfima(result, referenced); equalizeTypeVariables(result, referenced); eliminateInnerTypeVariables(referenced, result); diff --git a/src/test/java/targetast/TestGenerics.java b/src/test/java/targetast/TestGenerics.java index 5f74ae3a..094ec4f0 100644 --- a/src/test/java/targetast/TestGenerics.java +++ b/src/test/java/targetast/TestGenerics.java @@ -37,6 +37,15 @@ public class TestGenerics { } } + private static void assertStrictlyEquals(BoundsList a, BoundsList b) { + assertEquals(a.base, b.base); + assertEquals(a, b); + } + + private static void assertStrictlyNotEquals(BoundsList a, BoundsList b) { + assertNotEquals(a.base, b.base); + } + private static Result computeGenerics(String filename) throws IOException, ClassNotFoundException { var file = Path.of(rootDirectory + filename).toFile(); var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile())); @@ -62,7 +71,7 @@ public class TestGenerics { var ECK1 = generics.getBounds(otherMethod.getParameterList().getParameterAt(0).getType(), result.clazz, anyMethod); var ECK2 = generics.getBounds(otherMethod.getReturnType(), result.clazz, anyMethod); var ECKChain = new BoundsList(onClass(OBJECT)); - assertEquals(ECK1, ECK2); + assertStrictlyEquals(ECK1, ECK2); assertEquals(ECK2, generics.getBounds(b.getType(), result.clazz)); var M = generics.getBounds(a.getType(), result.clazz); @@ -92,21 +101,36 @@ public class TestGenerics { var generics = result.genericsResults.get(0); assertEquals(0, generics.get(result.clazz).size()); - assertEquals(1, generics.get(m).size()); - assertEquals(2, generics.get(main).size()); + assertEquals(3, generics.get(m).size()); + assertEquals(3, generics.get(main).size()); - var N = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); - var N2 = generics.getBounds(m.getReturnType(), result.clazz, m); + { + var AJ = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); + var AK = generics.getBounds(m.getParameterList().getParameterAt(1).getType(), result.clazz, m); + var KWU = generics.getBounds(((RefType) generics.resolve(m.getReturnType())).getParaList().get(0), result.clazz, m); + var AK2 = generics.getBounds(((RefType) generics.resolve(m.getReturnType())).getParaList().get(1), result.clazz, m); - var NChain = new BoundsList(onMethod(OBJECT)); - assertEquals(N, N2); - assertEquals(N2, NChain); + assertStrictlyEquals(AK, AK2); + assertStrictlyNotEquals(AJ, KWU); + var NChain = new BoundsList(onMethod(OBJECT)); + assertEquals(AJ, NChain); + assertEquals(AK, NChain); + assertEquals(KWU, NChain); + } - var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); - assertEquals(R, NChain); + { + var O = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); + var P = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); + var KWQ = generics.getBounds(((RefType) generics.resolve(main.getReturnType())).getParaList().get(1), result.clazz, main); + var O2 = generics.getBounds(((RefType) generics.resolve(main.getReturnType())).getParaList().get(0), result.clazz, main); - var Q2 = generics.getBounds(main.getReturnType(), result.clazz, main); - assertEquals(Q2, NChain); + assertStrictlyEquals(O, O2); + assertStrictlyNotEquals(P, KWQ); + var NChain = new BoundsList(onMethod(OBJECT)); + assertEquals(O, NChain); + assertEquals(P, NChain); + assertEquals(KWQ, NChain); + } } @Test @@ -307,14 +331,14 @@ public class TestGenerics { var generics = result.genericsResults.get(0); var O = generics.getBounds(id.getReturnType(), result.clazz, id); var O2 = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); - assertEquals(O, O2); + assertStrictlyEquals(O, O2); assertEquals(O2, new BoundsList(onMethod(OBJECT))); // TODO Maybe test in other ways if the parameter generics equals the return generics var S = generics.getBounds(main.getReturnType(), result.clazz, main); - var S2 = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); - var T = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); - assertEquals(S, S2); + var S2 = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); + var T = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); + assertStrictlyEquals(S, S2); assertEquals(S2, new BoundsList(onMethod(OBJECT))); assertEquals(T, new BoundsList(onMethod(OBJECT))); } @@ -355,7 +379,7 @@ public class TestGenerics { var par2 = generics.resolve(main.getParameterList().getParameterAt(0).getType()); var ACK2 = generics.getBounds(((RefType) par2).getParaList().get(0), result.clazz, add); var V = generics.getBounds(add.getParameterList().getParameterAt(1).getType(), result.clazz, add); - assertEquals(ACK2, ACK); + assertStrictlyEquals(ACK2, ACK); assertEquals(V, O); } From bdaf578f86f493836e0a2e8a84005370f9e470a9 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Tue, 27 Jun 2023 15:48:15 +0200 Subject: [PATCH 5/7] Fix equality --- .../target/generate/GenerateGenerics.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java index 9c4b1439..8c06b5d6 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java @@ -14,6 +14,7 @@ import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH; import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType; import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH; import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.util.Pair; import java.util.*; import java.util.stream.Collectors; @@ -657,7 +658,12 @@ public abstract class GenerateGenerics { } } + private record ToAdd(TypePlaceholder left, TypePlaceholder right) {} + void equalizeTypeVariables(Set input, Set referenced) { + + var elementsToAddToEquality = new ArrayList(); + for (var pair : new HashSet<>(input)) { if (pair instanceof PairLT ptph && referenced.contains(ptph.left)) { var chain = new ArrayList(); @@ -698,7 +704,8 @@ public abstract class GenerateGenerics { for (var i = 1; i < index; i++) { var cur = chain.get(i); if (!referenced.contains(cur)) continue; - addToEquality(cur.resolve(), start.resolve(), referenced); + elementsToAddToEquality.add(new ToAdd(cur.resolve(), start.resolve())); + //addToEquality(cur.resolve(), start.resolve(), referenced); TPH finalPrev = prev; input.removeIf(p -> p.equals(new PairLT(finalPrev, cur))); for (var pair2 : new HashSet<>(input)) { @@ -712,6 +719,11 @@ public abstract class GenerateGenerics { } } } + + for (var pair : elementsToAddToEquality) { + System.out.println(pair); + addToEquality(pair.left, pair.right, referenced); + } } void findTphs(RefTypeOrTPHOrWildcardOrGeneric type, Set tphs) { @@ -894,6 +906,8 @@ public abstract class GenerateGenerics { } } newTph.setVariance(variance); + System.out.println(infima + " " + infima.stream().map(i -> i.right.resolve().getVariance()).toList()); + System.out.println("Infima new TPH " + newTph + " variance " + variance); //referenced.add(newTph); addToPairs(input, new PairLT(left, new TPH(newTph))); From d55b402269205edafefeaf590001025f7286b7e8 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Wed, 28 Jun 2023 14:09:24 +0200 Subject: [PATCH 6/7] Some fixes --- .../target/generate/GenerateGenerics.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java index 8c06b5d6..e966d29d 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java @@ -140,6 +140,7 @@ public abstract class GenerateGenerics { this.astToTargetAST = astToTargetAST; for (var constraint : constraints.results) { if (constraint instanceof PairTPHsmallerTPH p) { + System.out.println(p.left + " " + p.left.getVariance()); simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right))); } else if (constraint instanceof PairTPHEqualTPH p) { equality.put(p.getLeft(), p.getRight()); @@ -213,7 +214,8 @@ public abstract class GenerateGenerics { equality.put(entry.getKey(), to); } } - to.setVariance(from.getVariance()); + System.out.println(from + " -> " + to + " " + from.getVariance()); + //from.setVariance(to.getVariance()); equality.put(from, to); referenced.remove(new TPH(from)); referenced.add(new TPH(to)); @@ -838,19 +840,24 @@ public abstract class GenerateGenerics { } } - TPH findConnectionToReturnType(Set returnTypes, Set input, Set visited, TPH tph) { + Set findConnectionToReturnType(Set returnTypes, Set input, Set visited, TPH tph) { if (returnTypes.contains(tph)) { - return tph; + var res = new HashSet(); + res.add(tph); + return res; } else { for (var pair : input) if (pair instanceof PairLT ptph) { if (ptph.left.equals(tph) && !visited.contains(ptph.right)) { visited.add(ptph.right); var result = findConnectionToReturnType(returnTypes, input, visited, ptph.right); - if (result != null) return result; + if (result.size() > 0) { + result.add(ptph.right); + return result; + }; } } } - return null; + return new HashSet<>(); } void eliminateInfimaConnectedToReturnType(Method method, Set input, Set referenced) { @@ -867,19 +874,22 @@ public abstract class GenerateGenerics { } } if (infima.size() > 1) { + System.out.println(infima); for (var pair : infima) { var returnTypes = findTypeVariables(method.getReturnType()); - var returnType = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left); - if (returnType != null && !returnType.equals(pair.left)) { - System.out.println("Equals now: " + pair.left.resolve() + " " + returnType.resolve()); - addToEquality(pair.left.resolve(), returnType.resolve(), referenced); + var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left); + System.out.println("Find: " + pair.left + " " + chain); + chain.remove(pair.left); + if (chain.size() > 0) { + for (var tph : chain) + addToEquality(pair.left.resolve(), tph.resolve(), referenced); foundInfima = true; } } } } } while (foundInfima); - input.removeIf((i) -> !(i instanceof PairLT lt) || lt.left.equals(lt.right)); + input.removeIf((i) -> (i instanceof PairLT lt) && lt.left.equals(lt.right)); } void eliminateInfima(Set input, Set referenced) { From d05054755c69a141388dc811949435e42f770653 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 3 Jul 2023 10:13:01 +0200 Subject: [PATCH 7/7] Fix bug --- .../target/generate/ASTToTargetAST.java | 4 +-- .../target/generate/GenerateGenerics.java | 30 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 5db79459..bfe353a1 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -240,8 +240,8 @@ public class ASTToTargetAST { ); } - private final Map usedFunN = new HashMap<>(); - private final Set usedFunNSuperTypes = new HashSet<>(); + private static final Map usedFunN = new HashMap<>(); + private static final Set usedFunNSuperTypes = new HashSet<>(); public Map auxiliaries = new HashMap<>(); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java index 8c06b5d6..e966d29d 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java @@ -140,6 +140,7 @@ public abstract class GenerateGenerics { this.astToTargetAST = astToTargetAST; for (var constraint : constraints.results) { if (constraint instanceof PairTPHsmallerTPH p) { + System.out.println(p.left + " " + p.left.getVariance()); simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right))); } else if (constraint instanceof PairTPHEqualTPH p) { equality.put(p.getLeft(), p.getRight()); @@ -213,7 +214,8 @@ public abstract class GenerateGenerics { equality.put(entry.getKey(), to); } } - to.setVariance(from.getVariance()); + System.out.println(from + " -> " + to + " " + from.getVariance()); + //from.setVariance(to.getVariance()); equality.put(from, to); referenced.remove(new TPH(from)); referenced.add(new TPH(to)); @@ -838,19 +840,24 @@ public abstract class GenerateGenerics { } } - TPH findConnectionToReturnType(Set returnTypes, Set input, Set visited, TPH tph) { + Set findConnectionToReturnType(Set returnTypes, Set input, Set visited, TPH tph) { if (returnTypes.contains(tph)) { - return tph; + var res = new HashSet(); + res.add(tph); + return res; } else { for (var pair : input) if (pair instanceof PairLT ptph) { if (ptph.left.equals(tph) && !visited.contains(ptph.right)) { visited.add(ptph.right); var result = findConnectionToReturnType(returnTypes, input, visited, ptph.right); - if (result != null) return result; + if (result.size() > 0) { + result.add(ptph.right); + return result; + }; } } } - return null; + return new HashSet<>(); } void eliminateInfimaConnectedToReturnType(Method method, Set input, Set referenced) { @@ -867,19 +874,22 @@ public abstract class GenerateGenerics { } } if (infima.size() > 1) { + System.out.println(infima); for (var pair : infima) { var returnTypes = findTypeVariables(method.getReturnType()); - var returnType = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left); - if (returnType != null && !returnType.equals(pair.left)) { - System.out.println("Equals now: " + pair.left.resolve() + " " + returnType.resolve()); - addToEquality(pair.left.resolve(), returnType.resolve(), referenced); + var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left); + System.out.println("Find: " + pair.left + " " + chain); + chain.remove(pair.left); + if (chain.size() > 0) { + for (var tph : chain) + addToEquality(pair.left.resolve(), tph.resolve(), referenced); foundInfima = true; } } } } } while (foundInfima); - input.removeIf((i) -> !(i instanceof PairLT lt) || lt.left.equals(lt.right)); + input.removeIf((i) -> (i instanceof PairLT lt) && lt.left.equals(lt.right)); } void eliminateInfima(Set input, Set referenced) {