Skip to content

Commit

Permalink
Ensure override compatibility with type variables (#171)
Browse files Browse the repository at this point in the history
Co-authored-by: Chris Povirk <cpovirk@google.com>
  • Loading branch information
wmdietl and cpovirk committed Apr 22, 2024
1 parent 2d53314 commit 31279fb
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import static javax.lang.model.type.TypeKind.NULL;
import static javax.lang.model.type.TypeKind.TYPEVAR;
import static javax.lang.model.type.TypeKind.WILDCARD;
import static org.checkerframework.framework.util.AnnotatedTypes.areCorrespondingTypeVariables;
import static org.checkerframework.framework.util.AnnotatedTypes.asSuper;
import static org.checkerframework.javacutil.AnnotationUtils.areSame;
import static org.checkerframework.javacutil.TreePathUtil.enclosingClass;
Expand Down Expand Up @@ -666,6 +667,21 @@ private boolean isNullnessSubtype(AnnotatedTypeMirror subtype, AnnotatedTypeMirr
&& isNullnessSubtype(subtype, ((AnnotatedTypeVariable) supertype).getLowerBound())) {
return true;
}
if (subtype.getKind() == TYPEVAR && supertype.getKind() == TYPEVAR) {
// Work around wonkyness of CF override checks.
AnnotatedTypeVariable subTV = (AnnotatedTypeVariable) subtype;
if (isCapturedTypeVariable(subTV.getUnderlyingType())) {
AnnotatedTypeMirror subTVBnd = subTV.getUpperBound();
if (subTVBnd instanceof AnnotatedTypeVariable) {
subTV = (AnnotatedTypeVariable) subTVBnd;
}
}
AnnotatedTypeVariable superTV = (AnnotatedTypeVariable) supertype;
if (areCorrespondingTypeVariables(elements, subTV, superTV)) {
return isSubtype(subTV.getUpperBound(), superTV.getUpperBound())
&& isSubtype(superTV.getLowerBound(), subTV.getLowerBound());
}
}
return isNullInclusiveUnderEveryParameterization(supertype)
|| isNullExclusiveUnderEveryParameterization(subtype)
|| (nullnessEstablishingPathExists(subtype, supertype)
Expand Down
4 changes: 2 additions & 2 deletions tests/ConformanceTestOnSamples-report.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 73 pass; 500 fail; 573 total; 12.7% score
# 74 pass; 499 fail; 573 total; 12.9% score
FAIL: AnnotatedInnerOfNonParameterized.java: no unexpected facts
FAIL: AnnotatedInnerOfParameterized.java: no unexpected facts
FAIL: AnnotatedReceiver.java: no unexpected facts
Expand Down Expand Up @@ -313,7 +313,7 @@ PASS: OutOfBoundsTypeVariable.java: no unexpected facts
FAIL: OverrideParameters.java:48:jspecify_nullness_mismatch
FAIL: OverrideParameters.java:68:jspecify_nullness_mismatch
FAIL: OverrideParameters.java: no unexpected facts
FAIL: OverrideParametersThatAreTypeVariables.java: no unexpected facts
PASS: OverrideParametersThatAreTypeVariables.java: no unexpected facts
FAIL: OverrideReturns.java:57:jspecify_nullness_mismatch
FAIL: OverrideReturns.java: no unexpected facts
PASS: ParameterizedWithTypeVariableArgumentToSelf.java: no unexpected facts
Expand Down
33 changes: 33 additions & 0 deletions tests/regression/Issue164.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 The JSpecify Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Test case for Issue 164:
// https://github.com/jspecify/jspecify-reference-checker/issues/164

import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
interface Issue164SuperWildcardParent {
<T extends @Nullable Object> void x(Issue164Foo<? super T> foo);
}

@NullMarked
interface Issue164SuperWildcardOverride extends Issue164SuperWildcardParent {
@Override
<U extends @Nullable Object> void x(Issue164Foo<? super U> foo);
}

@NullMarked
interface Issue164Foo<V extends @Nullable Object> {}
32 changes: 32 additions & 0 deletions tests/regression/Issue164More.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2024 The JSpecify Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Test case for Issue 164:
// https://github.com/jspecify/jspecify-reference-checker/issues/164

import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
class Issue164More {
interface Super<T extends @Nullable Object> {
<U extends T> void foo(Lib<? extends U> lib);
}

interface Sub<V extends @Nullable Object> extends Super<V> {
<W extends V> void foo(Lib<? extends W> lib);
}

interface Lib<X extends @Nullable Object> {}
}

0 comments on commit 31279fb

Please sign in to comment.