Account for non-null assumption when computing dynamic return types.
Bug: 120920488
Change-Id: I7941e51565bb4771a2344ef32d9585fcb0199f79
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index dd45dc5..bcec057 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -1212,10 +1212,20 @@
lattice = aliasedValue.definition.asAssumeDynamicType().getAssumption().getType();
// For precision, verify that the dynamic type is at least as precise as the static type.
- assert lattice.lessThanOrEqualUpToNullability(getTypeLattice(), appView);
+ assert lattice.lessThanOrEqualUpToNullability(typeLattice, appView)
+ : typeLattice + " < " + lattice;
} else {
// Otherwise, simply use the static type.
- lattice = getTypeLattice();
+ lattice = typeLattice;
+ }
+
+ // Account for nullability, which could be flown from non-null assumption in between dynamic
+ // type assumption or simply from array/object creation.
+ if (typeLattice.isDefinitelyNotNull() && lattice.isNullable()) {
+ // Having non-null assumption means it is a reference type.
+ assert lattice.isReference();
+ // Then, we can return the non-null variant of dynamic type if both assumptions are aliased.
+ return lattice.asReferenceTypeLatticeElement().asMeetWithNotNull();
}
return lattice;
}
@@ -1239,7 +1249,11 @@
// Assume<DynamicTypeAssumption>.
Value aliasedValue = getSpecificAliasedValue(value -> value.definition.isAssumeDynamicType());
if (aliasedValue != null) {
- return aliasedValue.definition.asAssumeDynamicType().getAssumption().getLowerBoundType();
+ ClassTypeLatticeElement lattice =
+ aliasedValue.definition.asAssumeDynamicType().getAssumption().getLowerBoundType();
+ return typeLattice.isDefinitelyNotNull() && lattice.isNullable()
+ ? lattice.asMeetWithNotNull().asClassTypeLatticeElement()
+ : lattice;
}
return null;
}