Skip to content

Commit

Permalink
getLowerBound() should return NULL instead of NONE for variable…
Browse files Browse the repository at this point in the history
…s without a lower bound

Also fix handling of `null` in assignment and subtype tests, and update string representation to match javac.

https://docs.oracle.com/en/java/javase/23/docs/api/java.compiler/javax/lang/model/type/TypeVariable.html#getLowerBound()

PiperOrigin-RevId: 715574037
  • Loading branch information
cushon authored and Javac Team committed Jan 15, 2025
1 parent 370011c commit ee12b9a
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 7 deletions.
2 changes: 1 addition & 1 deletion java/com/google/turbine/model/TurbineConstantTypeKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public enum TurbineConstantTypeKind {
BOOLEAN("boolean"),
BYTE("byte"),
STRING("String"),
NULL("null");
NULL("<nulltype>");

private final String name;

Expand Down
2 changes: 1 addition & 1 deletion java/com/google/turbine/processing/TurbineTypeMirror.java
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ public TypeMirror getUpperBound() {
public TypeMirror getLowerBound() {
return info().lowerBound() != null
? factory.asTypeMirror(info().lowerBound())
: factory.noType();
: factory.nullType();
}

@Override
Expand Down
19 changes: 16 additions & 3 deletions java/com/google/turbine/processing/TurbineTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,8 @@ private boolean isArraySubtype(ArrayTy a, Type b, boolean strict) {
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.10.1
private static boolean isPrimSubtype(PrimTy a, Type other) {
if (other.tyKind() != TyKind.PRIM_TY) {
return false;
// The null reference can always be assigned or cast to any reference type, see JLS 4.1
return a.primkind() == TurbineConstantTypeKind.NULL && isReferenceType(other);
}
PrimTy b = (PrimTy) other;
switch (a.primkind()) {
Expand Down Expand Up @@ -483,7 +484,7 @@ private static boolean isPrimSubtype(PrimTy a, Type other) {
case BOOLEAN:
return a.primkind() == b.primkind();
case NULL:
break;
return isReferenceType(other);
}
throw new AssertionError(a.primkind());
}
Expand Down Expand Up @@ -672,8 +673,12 @@ public boolean isAssignable(TypeMirror a1, TypeMirror a2) {
private boolean isAssignable(Type t1, Type t2) {
switch (t1.tyKind()) {
case PRIM_TY:
TurbineConstantTypeKind primkind = ((PrimTy) t1).primkind();
if (primkind == TurbineConstantTypeKind.NULL) {
return isReferenceType(t2);
}
if (t2.tyKind() == TyKind.CLASS_TY) {
ClassSymbol boxed = boxedClass(((PrimTy) t1).primkind());
ClassSymbol boxed = boxedClass(primkind);
t1 = ClassTy.asNonParametricClassTy(boxed);
}
break;
Expand All @@ -700,6 +705,14 @@ private static boolean isObjectType(Type type) {
return type.tyKind() == TyKind.CLASS_TY && ((ClassTy) type).sym().equals(ClassSymbol.OBJECT);
}

private static boolean isReferenceType(Type type) {
return switch (type.tyKind()) {
case CLASS_TY, ARRAY_TY, TY_VAR, WILD_TY, INTERSECTION_TY, ERROR_TY -> true;
case PRIM_TY -> ((PrimTy) type).primkind() == TurbineConstantTypeKind.NULL;
case NONE_TY, METHOD_TY, VOID_TY -> false;
};
}

@Override
public boolean contains(TypeMirror a, TypeMirror b) {
return contains(asTurbineType(a), asTurbineType(b), /* strict= */ true);
Expand Down
2 changes: 2 additions & 0 deletions java/com/google/turbine/type/Type.java
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ public final String toString() {
}

/** A primitive type. */
// TODO: cushon - consider renaming this, since it models things like String and null that can
// appear as constants and not primitives.
@AutoValue
abstract class PrimTy implements Type {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,9 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) {

/**
* Discover all types contained in the given element, keyed by their immediate enclosing element.
*
* <p>This method is executed for both javac and Turbine and is expected to produce the same
* results in each case.
*/
private static void getTypes(
Types typeUtils, Element element, Multimap<String, TypeMirror> types) {
Expand Down Expand Up @@ -508,6 +511,7 @@ public Void visitTypeVariable(TypeVariable t, Void aVoid) {
if (t.getUpperBound() != null) {
types.put(key(e), t.getUpperBound());
}
types.put(String.format("getLowerBound(%s)", key(e)), t.getLowerBound());
return null;
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ public void tyVar() {
.getTypeParameters())
.asType();
assertThat(t.getKind()).isEqualTo(TypeKind.TYPEVAR);
assertThat(t.getLowerBound().getKind()).isEqualTo(TypeKind.NONE);
assertThat(t.getLowerBound().getKind()).isEqualTo(TypeKind.NULL);
assertThat(t.getUpperBound().toString()).isEqualTo("java.lang.Comparable<? super T>");
}

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<source>8</source>
<source>16</source>
<detectJavaApiLink>false</detectJavaApiLink>
<notimestamp>true</notimestamp>
<doctitle>turbine ${project.version} API</doctitle>
Expand Down

0 comments on commit ee12b9a

Please sign in to comment.