Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method call for testing RD class substitution #1032

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
import org.checkerframework.framework.qual.Unused;
import org.checkerframework.framework.source.DiagMessage;
import org.checkerframework.framework.source.SourceVisitor;
import org.checkerframework.framework.type.AbstractViewpointAdapter;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeFactory.ParameterizedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
Expand Down Expand Up @@ -5073,9 +5074,18 @@ public boolean isValidUse(
AnnotationMirrorSet tops = qualHierarchy.getTopAnnotations();
TypeMirror declarationTM = declarationType.getUnderlyingType();
AnnotationMirrorSet upperBounds = atypeFactory.getTypeDeclarationBounds(declarationTM);
AbstractViewpointAdapter vpa =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The visitor should not adapt types. I think we should change atypeFactory.getTypeDeclarationBounds to take what it needs to determine the correct bounds for a particular use.
Then the factory that has a viewpoint adaptor can add the adaptation logic.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, let me try to move the adaptation over.

(AbstractViewpointAdapter) atypeFactory.getViewpointAdapter();

for (AnnotationMirror top : tops) {
AnnotationMirror upperBound = qualHierarchy.findAnnotationInHierarchy(upperBounds, top);
if (!typeHierarchy.isSubtypeShallowEffective(useType, upperBound)) {
if (vpa != null) {
AnnotatedDeclaredType adaptedBound =
(AnnotatedDeclaredType) vpa.combineAnnotationWithType(upperBound, useType);
if (!typeHierarchy.isSubtypeShallowEffective(useType, adaptedBound)) {
return false;
}
} else if (!typeHierarchy.isSubtypeShallowEffective(useType, upperBound)) {
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ protected AnnotatedTypeMirror combineTypeWithType(
* @param declared declared type
* @return {@link AnnotatedTypeMirror} after viewpoint adaptation
*/
protected AnnotatedTypeMirror combineAnnotationWithType(
public AnnotatedTypeMirror combineAnnotationWithType(
AnnotationMirror receiverAnnotation, AnnotatedTypeMirror declared) {
if (declared.getKind().isPrimitive()) {
AnnotatedPrimitiveType apt = (AnnotatedPrimitiveType) declared.shallowCopy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5689,6 +5689,15 @@ public Trees getTreeUtils() {
return this.trees;
}

/**
* Accessor for the viewpoint adapter.
*
* @return the viewpoint adapter
*/
public ViewpointAdapter getViewpointAdapter() {
return this.viewpointAdapter;
}

/**
* Accessor for the processing environment.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ public class ViewpointTestCheckerTest extends CheckerFrameworkPerDirectoryTest {
* @param testFiles the files containing test code, which will be type-checked
*/
public ViewpointTestCheckerTest(List<File> testFiles) {
super(testFiles, viewpointtest.ViewpointTestChecker.class, "viewpointtest");
super(
testFiles,
viewpointtest.ViewpointTestChecker.class,
"viewpointtest",
"-Astubs=src/test/java/viewpointtest/jdk.astub");
}

@Parameterized.Parameters
Expand Down
7 changes: 7 additions & 0 deletions framework/src/test/java/viewpointtest/jdk.astub
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import viewpointtest.quals.ReceiverDependentQual;

package java.lang;

@ReceiverDependentQual class Object {
@ReceiverDependentQual Object() {}
}
11 changes: 5 additions & 6 deletions framework/tests/viewpointtest/LostNonReflexive.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import viewpointtest.quals.*;

public class LostNonReflexive {
@ReceiverDependentQual public class LostNonReflexive {
@ReceiverDependentQual Object f;

@SuppressWarnings({"inconsistent.constructor.type", "super.invocation.invalid"})
Expand All @@ -17,16 +17,15 @@ void test(@Top LostNonReflexive obj, @Bottom Object bottomObj) {
this.f = obj.f;
this.f = bottomObj;

// :: error: (assignment.type.incompatible)
// :: error: (assignment.type.incompatible) :: error: (method.invocation.invalid)
@A Object aObj = obj.get();
// :: error: (assignment.type.incompatible)
// :: error: (assignment.type.incompatible) :: error: (method.invocation.invalid)
@B Object bObj = obj.get();
// :: error: (assignment.type.incompatible)
// :: error: (assignment.type.incompatible) :: error: (method.invocation.invalid)
@Bottom Object botObj = obj.get();

// :: error: (argument.type.incompatible) :: error: (new.class.type.invalid)
// :: error: (argument.type.incompatible)
new LostNonReflexive(obj.f);
// :: error: (new.class.type.invalid)
new LostNonReflexive(bottomObj);

// :: error: (argument.type.incompatible)
Expand Down
2 changes: 1 addition & 1 deletion framework/tests/viewpointtest/PolyConstructor.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
public class PolyConstructor {

static class MyClass {
// :: error: (super.invocation.invalid) :: warning: (inconsistent.constructor.type)
// :: warning: (inconsistent.constructor.type)
@PolyVP MyClass(@PolyVP Object o) {
// :: error: (new.class.type.invalid)
throw new RuntimeException(" * You are filled with DETERMINATION."); // stub
Expand Down
10 changes: 6 additions & 4 deletions framework/tests/viewpointtest/SuperConstructorCalls.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@
// https://github.com/eisop/checker-framework/issues/782
import viewpointtest.quals.*;

public class SuperConstructorCalls {

@ReceiverDependentQual public class SuperConstructorCalls {
@SuppressWarnings("inconsistent.constructor.type")
public SuperConstructorCalls() {}

@SuppressWarnings("inconsistent.constructor.type")
public SuperConstructorCalls(@ReceiverDependentQual Object obj) {}

@SuppressWarnings({"inconsistent.constructor.type", "super.invocation.invalid"})
public @ReceiverDependentQual SuperConstructorCalls(
@ReceiverDependentQual Object obj, int dummy) {}

class Inner extends SuperConstructorCalls {
@ReceiverDependentQual class Inner extends SuperConstructorCalls {
@SuppressWarnings("inconsistent.constructor.type")
public Inner() {
super();
}

// The constructor's return type is implicitly @Top by default.
// When calling the super constructor, @Top becomes @Lost in the super constructor's
// signature, causing a type mismatch with the expected @ReceiverDependentQual parameter.
@SuppressWarnings("inconsistent.constructor.type")
public Inner(@Top Object objTop) {
// :: error: (argument.type.incompatible)
super(objTop);
Expand All @@ -32,7 +35,6 @@ public Inner(@Top Object objTop) {

@SuppressWarnings("inconsistent.constructor.type")
public @A Inner(@A Object objA, @B Object objB) {
// :: error: (super.invocation.invalid)
super(objA);
}

Expand Down
18 changes: 18 additions & 0 deletions framework/tests/viewpointtest/TestGetAnnotatedLhs.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,27 @@
this.f = new @ReceiverDependentQual Object();
}

// This method could be called by both @A and @B instances.
void recieverDependentMethod(@ReceiverDependentQual TestGetAnnotatedLhs this) {}

// This method could only be called by @A instances.
void aMethod(@A TestGetAnnotatedLhs this) {}

// This method could only be called by @B instances.
void bMethod(@B TestGetAnnotatedLhs this) {}

@SuppressWarnings({"cast.unsafe.constructor.invocation"})
void topWithRefinement() {
TestGetAnnotatedLhs a = new @A TestGetAnnotatedLhs();
TestGetAnnotatedLhs b = new @B TestGetAnnotatedLhs();
a.recieverDependentMethod();
b.recieverDependentMethod();
a.aMethod();
// :: error: (method.invocation.invalid)
a.bMethod();
// :: error: (method.invocation.invalid)
b.aMethod();
b.bMethod();
// :: error: (new.class.type.invalid)
TestGetAnnotatedLhs top = new @Top TestGetAnnotatedLhs();
top = a;
Expand Down
5 changes: 3 additions & 2 deletions framework/tests/viewpointtest/ThisConstructorCalls.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

// Test case for EISOP issue #782:
// https://github.com/eisop/checker-framework/issues/782
public class ThisConstructorCalls {
@ReceiverDependentQual public class ThisConstructorCalls {
@SuppressWarnings("inconsistent.constructor.type")
public ThisConstructorCalls() {}

@SuppressWarnings("inconsistent.constructor.type")
public ThisConstructorCalls(@ReceiverDependentQual Object obj) {}

@SuppressWarnings({"inconsistent.constructor.type", "super.invocation.invalid"})
Expand All @@ -24,7 +26,6 @@ public ThisConstructorCalls(@ReceiverDependentQual Object obj) {}

@SuppressWarnings("inconsistent.constructor.type")
public @A ThisConstructorCalls(@A Object objA, @B Object objB) {
// :: error: (this.invocation.invalid)
this(objA);
}
}
3 changes: 2 additions & 1 deletion framework/tests/viewpointtest/VPAExamples.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import viewpointtest.quals.*;

public class VPAExamples {
@SuppressWarnings("inconsistent.constructor.type")
@ReceiverDependentQual public class VPAExamples {

static class RDContainer {
@ReceiverDependentQual Object get() {
Expand Down
16 changes: 5 additions & 11 deletions framework/tests/viewpointtest/VarargsConstructor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
// https://github.com/eisop/checker-framework/issues/777
import viewpointtest.quals.*;

public class VarargsConstructor {

@ReceiverDependentQual public class VarargsConstructor {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be two variants of the test? Why is it enough to add RDQ here? Some comments would be helpful to understand these tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think right now viewpoint test checker has a lot suppress warnings and errors because of we default everything to Top. Since we also forbid Top object creation, I would like to make viewpoint test checker more PICO like system, i.e. default Object to RDQ and make A as the default qualifier.

@SuppressWarnings("inconsistent.constructor.type")
VarargsConstructor(String str, Object... args) {}

@SuppressWarnings({"inconsistent.constructor.type", "super.invocation.invalid"})
@SuppressWarnings("inconsistent.constructor.type")
@ReceiverDependentQual VarargsConstructor(@ReceiverDependentQual Object... args) {}

void foo() {
// :: warning: (cast.unsafe.constructor.invocation)
VarargsConstructor a = new @A VarargsConstructor("testStr", new @A Object());
}

Expand All @@ -25,17 +24,14 @@ void invokeConstructor(@A Object aObj, @B Object bObj, @Top Object topObj) {
new @B VarargsConstructor(aObj);
}

class Inner {
// :: warning: (inconsistent.constructor.type) :: error:(super.invocation.invalid)
@ReceiverDependentQual class Inner {
@SuppressWarnings("inconsistent.constructor.type")
@ReceiverDependentQual Inner(@ReceiverDependentQual Object... args) {}

void foo() {
// :: error: (new.class.type.invalid)
Inner a = new Inner();
// :: warning: (cast.unsafe.constructor.invocation)
Inner b = new @A Inner(new @A Object());
Inner c = VarargsConstructor.this.new @A Inner();
// :: warning: (cast.unsafe.constructor.invocation)
Inner d = VarargsConstructor.this.new @A Inner(new @A Object());
}

Expand All @@ -53,11 +49,9 @@ void invokeConstructor(@A Object aObj, @B Object bObj, @Top Object topObj) {

void testAnonymousClass(@A Object aObj, @B Object bObj, @Top Object topObj) {
Object o =
// :: warning: (cast.unsafe.constructor.invocation)
new @A VarargsConstructor("testStr", new @A Object()) {
void foo() {
VarargsConstructor a =
// :: warning: (cast.unsafe.constructor.invocation)
new @A VarargsConstructor("testStr", new @A Object());
}
};
Expand Down
Loading