Skip to content

Commit

Permalink
Fix cases where previous valid generic mappings for lambdas would get…
Browse files Browse the repository at this point in the history
… overwritten with subtly incorrect ones
  • Loading branch information
jaskarth committed Sep 6, 2023
1 parent 26088d3 commit 13d4112
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,10 @@ public static boolean doGenericTypesCast(VarType left, VarType right) {
}

if (left.isGeneric() && right.isGeneric()) {
if (shouldGenericTypesCast(left, right)) {
return true;
}

GenericType leftGeneric = (GenericType) left;
GenericType rightGeneric = (GenericType) right;

Expand All @@ -1072,42 +1076,50 @@ public static boolean doGenericTypesCast(VarType left, VarType right) {
}

if (leftType != null) {
if (leftType.isGeneric()) {
if (rightType.isGeneric()) {
if (leftType.isSuperset(rightType)) {
// Casting Clazz<?> to Clazz<T> or Clazz<Concrete>
if ((((GenericType) leftType).getWildcard() == GenericType.WILDCARD_NO || ((GenericType) leftType).getWildcard() == GenericType.WILDCARD_EXTENDS) &&
((GenericType) rightType).getWildcard() == GenericType.WILDCARD_SUPER) {

boolean ok = true;
if (((GenericType) leftType).getWildcard() == GenericType.WILDCARD_EXTENDS) {
// Equals, ignoring wildcards
if (!((GenericType) leftType).getArguments().isEmpty() && !((GenericType) rightType).getArguments().isEmpty() &&
leftType.equals(rightType)) {
ok = false;
}
}
if (shouldGenericTypesCast(leftType, rightType)) {
return true;
}
}
}
}

if (ok) {
return true;
}
}
}
return false;
}

if ((((GenericType) leftType).getWildcard() == GenericType.WILDCARD_NO || ((GenericType) leftType).getWildcard() == GenericType.WILDCARD_SUPER) &&
((GenericType) rightType).getWildcard() == GenericType.WILDCARD_EXTENDS) {
return true;
}
} else {
// Right is not generic
// Check for casting a concrete rightType to a specific left generic
// e.g. (List<T>)list where 'list' is List<Object>
if (((GenericType) leftType).getWildcard() == GenericType.WILDCARD_NO && ((GenericType) leftType).getArguments().isEmpty()) {
return true;
private static boolean shouldGenericTypesCast(VarType leftType, VarType rightType) {
if (leftType.isGeneric()) {
if (rightType.isGeneric()) {
if (leftType.isSuperset(rightType)) {
// Casting Clazz<?> to Clazz<T> or Clazz<Concrete>
if ((((GenericType) leftType).getWildcard() == GenericType.WILDCARD_NO || ((GenericType) leftType).getWildcard() == GenericType.WILDCARD_EXTENDS) &&
((GenericType) rightType).getWildcard() == GenericType.WILDCARD_SUPER) {

boolean ok = true;
if (((GenericType) leftType).getWildcard() == GenericType.WILDCARD_EXTENDS) {
// Equals, ignoring wildcards
if (!((GenericType) leftType).getArguments().isEmpty() && !((GenericType) rightType).getArguments().isEmpty() &&
leftType.equals(rightType)) {
ok = false;
}
}

if (ok) {
return true;
}
}
}

if ((((GenericType) leftType).getWildcard() == GenericType.WILDCARD_NO || ((GenericType) leftType).getWildcard() == GenericType.WILDCARD_SUPER) &&
((GenericType) rightType).getWildcard() == GenericType.WILDCARD_EXTENDS) {
return true;
}
} else {
// Right is not generic
// Check for casting a concrete rightType to a specific left generic
// e.g. (List<T>)list where 'list' is List<Object>
if (((GenericType) leftType).getWildcard() == GenericType.WILDCARD_NO && ((GenericType) leftType).getArguments().isEmpty()) {
return true;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,17 @@ else if (method.getSignature() != null || !desc.ret.equals(VarType.VARTYPE_OBJEC
boolean add = current == null || returnType == null || returnType.isGeneric() ||
(!returnType.equals(genericsMap.get(key)) && (current.type != CodeConstants.TYPE_GENVAR || !named.containsKey(current)));
if (add) {
genericsMap.put(key, returnType);
VarType prior = genericsMap.get(key);
boolean addToMap = true;
if (prior != null) {
if (prior.isGeneric() && !((GenericType)prior).isTypeUnfinished() && DecompilerContext.getStructContext().instanceOf(returnType.value, prior.value)) {
addToMap = false;
}
}

if (addToMap) {
genericsMap.put(key, returnType);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,18 @@ public boolean equalsExact(Object o) {
return this.argumentsEqual(gt);
}

// returns true if there's any genvars abound with empty names
// TODO: this is a hack! check why genvars with empty names are made!
public boolean isTypeUnfinished() {
for (GenericType gv : this.getAllGenericVars()) {
if (gv.value.isEmpty()) {
return true;
}
}

return false;
}

public boolean argumentsEqual(GenericType gt) {
if (arguments.size() != gt.arguments.size()) {
return false;
Expand Down
6 changes: 3 additions & 3 deletions testData/results/pkg/TestGenericsHierarchy.dec
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class TestGenericsHierarchy<T extends Number> {
}

V v1 = list.get(0);// 18
T v2 = list2.get(0);// 19
list3.add(list2.get(0));// 21
T v2 = (T)list2.get(0);// 19
list3.add((T)list2.get(0));// 21
this.field = (T)v;// 23
this.setField((T)v);// 24
}// 25
Expand Down Expand Up @@ -110,4 +110,4 @@ Lines mapping:
24 <-> 21
25 <-> 22
39 <-> 25
40 <-> 26
40 <-> 26

0 comments on commit 13d4112

Please sign in to comment.