typetools / typetools/checker-framework
Unsoundness in MustCallChecker (and RLC) for functional interfaces
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 1.1k
- Forks
- 440
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 134
Description
This example creates a Closeable functional interface and makes new instances of it in a few sneaky ways:
- normal inner class
- inline inner class
- anonymous class
- lambda expression
- method reference
// Test that the correct type is assigned to instantiations of functional
// interfaces.
import java.io.Closeable;
import org.checkerframework.checker.mustcall.qual.*;
public abstract class FunctionalInterfaces {
@FunctionalInterface
public interface Actor extends Closeable {
void act();
@Override
default void close() {
}
}
public static class ActorImpl implements Actor {
@Override
public void act() {
}
}
public abstract void run(@MustCall({}) Actor a);
public static void method() {
}
public void normalConstruction() {
// :: error: (assignment)
@MustCall({}) Actor a = new ActorImpl();
}
public void inlineClass() {
class ActorImplInline implements Actor {
@Override
public void act() {
}
}
// :: error: (assignment)
@MustCall({}) Actor a = new ActorImplInline();
}
public void anonymousClass() {
// :: error: (assignment)
@MustCall({}) Actor a = new Actor() {
public void act() {
}
};
}
public void lambda() {
// :: error: (assignment)
@MustCall({}) Actor a = () -> {
};
}
public void methodRef() {
// :: error: (assignment)
@MustCall({}) Actor a = FunctionalInterfaces::method;
}
}
I would expect all 5 cases would report an error, but only the first two do:
checker/tests/mustcall/FunctionalInterfaces.java:32: error: [assignment] incompatible types in assignment.
@MustCall({}) Actor a = new ActorImpl();
^
found : @MustCall("close") ActorImpl
required: @MustCall Actor
checker/tests/mustcall/FunctionalInterfaces.java:45: error: [assignment] incompatible types in assignment.
@MustCall({}) Actor a = new ActorImplInline();
^
found : @MustCall FunctionalInterfaces.@MustCall("close") ActorImplInline
required: @MustCall Actor
2 errors
I did my best to debug this one, but the problem actually seems to be in the "framework" part of the Checker Framework, and not in the Must Call Checker specifically---although I'm not quite knowledgeable enough to know for sure. It seems like new ClassName() is always assigned the correct type @MustCall({"close"}), but other ways of constructing an instance of the class do not get the right inherited annotations.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with checker/tests/mustcall/FunctionalInterfaces.java and run the reproducer, comparing normal, inline, anonymous, lambda, and method-reference construction. Trace how the framework and MustCallChecker/RLC assign inherited annotations; done means all five cases report the expected assignment error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 42/100