Skip to content

Move PICO to EISOP - #1013

Open
aosen-xiong wants to merge 267 commits into
eisop:masterfrom
aosen-xiong:pico-move
Open

aosen-xiong wants to merge 267 commits into
eisop:masterfrom
aosen-xiong:pico-move

Conversation

@aosen-xiong

@aosen-xiong aosen-xiong commented Dec 9, 2024 •

Copy link
Copy Markdown
Collaborator

Original code repo: https://github.com/opprop/immutability
Some of commits are presented in: https://github.com/Ao-senXiong/immutability/tree/pico-cf-only
Merge with: eisop/jdk#106
As discussed before, I will try to move PICO here gradually. Hopefully adding test cases and Javadoc with more discussion as well.

@wmdietl wmdietl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A quick round of initial comments.

Comment thread checker-qual/src/main/java/org/checkerframework/checker/pico/qual/Bottom.java Outdated
Comment thread checker-qual/src/main/java/org/checkerframework/checker/pico/qual/Lost.java Outdated
Comment thread checker/src/main/java/org/checkerframework/checker/pico/jdk.astub Outdated
Comment thread checker/src/main/java/org/checkerframework/checker/pico/jdk.astub Outdated
Comment thread checker/src/main/java/org/checkerframework/checker/pico/jdk.astub Outdated
Comment thread checker/src/main/java/org/checkerframework/checker/pico/jdk.astub Outdated
Comment thread checker/src/main/java/org/checkerframework/checker/pico/jdk.astub Outdated

this.assignableReadonlyField = rdmObject;
// :: error: (assignment.type.incompatible) :: error: (illegal.field.write)
this.rdmField = rdmObject; // Field is adpated to immutable but method parameters are not?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is wrong, method parameter should also be adapted. #1037

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

visitMethod is getting its oracle in AnnotatedExecutableType methodType = atypeFactory.getAnnotatedType(tree).deepCopy();. It should get adapated version of the original method signature.

@aosen-xiong

aosen-xiong commented Dec 31, 2024 •

Copy link
Copy Markdown
Collaborator Author

Ah, looks like it can not find the branch again.
Fixed

Comment thread framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java Outdated
aosen-xiong and others added 26 commits August 4, 2026 13:51
Replace TypesUtils.isAnonymous(TreeUtils.typeOf(...)) with
TreeUtils.isAnonymousClass(ClassTree) in MutabilityNoInitVisitor and
MutabilityValidator, following the API unification in eisop#1909
which fixes a JDK 11 anonymous class detection bug.
Java enums can have mutable fields, so @mutable on enum declarations
is a valid use case. The existing defaulting (MutabilityEnumDefaultAnnotator)
already handles this correctly via addMissingAnnotations. Added a Counter
enum test case demonstrating mutable enum with mutable state.
Replace actionable TODO with descriptive comment explaining that the
modern builder pattern (mutating target via setters) correctly reports
illegal.field.write and would require uniqueness tracking to support.
No custom poly.invocation.error key needed — the generic
assignment.type.incompatible is correct for poly return constrained
by receiver mutability. Chained poly calls (test5) correctly error
since each poly return resolves based on the receiver's mutability.
In @immutable ObjectMethods2, annotate clone() return type as
@immutable Object instead of using SuppressWarnings workaround.
The override.return.invalid remains (consistent with all three
test classes) due to how Object.clone() is annotated in stubs.
Replace the TODO with a descriptive comment explaining that varargs
type inference with @PolyMutable (e.g. Arrays.asList) does not
correctly adapt to the required mutability context, causing a false
positive that requires @SuppressWarnings.
Convert actionable TODOs into a descriptive note explaining that the
test is skipped because PICO lacks postcondition qualifiers (like
@EnsuresAssigned), preventing it from verifying initialization via
helper methods.
Add method calls with assertions to LocalVariableRefinement.java foo()
to test that local variable mutability flow refinement is correctly
applied after reassignment.
Update MutabilityNoInitVisitor to strictly check that constructors
can only initialize fields declared in their own class. Reassigning
inherited fields is now forbidden since the superclass constructor
has already completed and its state should not be mutated.
Added illegal.field.write expectation to SuperClassTest.java.
Update MemoizedRectangle.java to replace the TODO with a comment
explaining why no override error is emitted: mutating an @Assignable
field does not require a @mutable receiver. Also explicitly annotated
the receiver of size() as @readonly to make it clear why it validly
overrides the superclass method.
Make inner classes static in ImplicitMutable.java. In Java 11,
non-static inner classes cannot declare static fields, which was
causing a compilation error in the test suite.
The test was skipped because the Initialization Checker had no postcondition
qualifier, so a constructor that delegates field initialization to helper
methods reported initialization.fields.uninitialized.  eisop#1918 added
@EnsuresInitialized; annotate the three helpers with it and un-skip the test.

The field writes also need an immutable value: `new Object()` yields a
@mutable instance, which cannot be assigned to a field of an @immutable class.

The test now type-checks with no expected diagnostics at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…method

Calling a @ReceiverDependentMutable method through a @readonly receiver adapts
the method's type parameter bound to @MutabilityLost, which is already reported
as mutability.lost.in.bounds.  When the call also passes an argument and the
type parameter is not instantiated explicitly, the parameter's type is the
uninstantiated type variable, so the same lost bound is reported a second time
as mutability.lost.parameter.

The neighboring calls show the two errors share that one cause: methodWithNoArgs
has no parameter and reports only the bound error, and an explicit
<@mutable Object> type argument instantiates the variable away from the lost
bound and reports type.argument.type.incompatible instead.

Record the current behavior.  Whether the parameter check should skip a type
variable whose only lost qualifier comes from its bound is a separate question.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The test reads on its own; the history records why it was skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Merging master broke compilation of the Mutability Checker:
`DefaultQualifierForUseTypeAnnotator.getDefaultAnnosForUses` is now
public, and `AbstractViewpointAdapter` gained the abstract
`extractAnnotationMirror(AnnotationMirrorSet)`.

Widen the override to public, and implement the new method by finding
the qualifier in the mutability hierarchy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Master moved the Spotless configuration from build.gradle into
buildSrc/src/main/groovy/cf-spotless.gradle; carry the branch's extra
formatAnnotations type annotations over to it. Master also dropped the
TEX_FILES list from docs/manual/Makefile, so the branch's entry for
mutability-checker.tex is no longer needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The override skipped super.postDirectSuperTypes because viewpoint
adaptation of direct supertypes recursed infinitely on raw recursive
types. eisop#2255 stopped viewpoint adaptation from searching supertypes of
an already-substituted type, so the framework's implementation now
works for the Mutability Checker and the copied superclass tail can go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants