typetools / typetools/checker-framework
Method references and initialization
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 1.1k
- Forks
- 440
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 134
Description
Take this small method reference example:
interface Dump<T> {
void dump(T p);
}
class Demo {
Dump<String> ds = this::print;
void print(String s) {}
}
The Nullness Checker raises an error on the initialization of ds, because this is under initialization:
Error: [methodref.receiver.bound.invalid] @UnderInitialization(java.lang.Object.class) @NonNull Demo is not a valid receiver for @NonNull void print(@Initialized @NonNull Demo this, @Initialized @NonNull String p0) in Demo; attempting to use an incompatible receiver type
found : @UnderInitialization(java.lang.Object.class) @NonNull Demo
required: @Initialized @NonNull Demo
(Note: when using master, I get a Invalid format string error instead. I didn't immediately see what is wrong with the format string or invocation. https://github.com/typetools/checker-framework/commit/dd7bc5917cb2f4d6647eef7cc63ff647715d6f8e touched the key last.)
The error is valid, because if someone extends the class like this:
interface Dump<T> {
void dump(T p);
}
class Demo {
Dump<String> ds = this::print;
void print(String s) {}
Demo() {
ds.dump("init");
}
void bar(String s) {
ds.dump(s);
}
}
public class Sub extends Demo {
Object o = new Object();
void print(String s) {
o.toString();
}
public static void main(String[] args) {
new Sub();
}
}
one will get a NullPointerException:
Exception in thread "main" java.lang.NullPointerException
at Sub.print(Sub.java:20)
at Demo.<init>(Sub.java:10)
at Sub.<init>(Sub.java:17)
at Sub.main(Sub.java:23)
However, lots of code wants to set method references in field initializers, but won't use them until construction is done.
We should see whether we can find a sound way to allow the field initialization and allow the use in methods with fully-initialized receivers, but then forbid the use of that field in the constructor.
In our concrete example, I would want to allow the ds initialization and the use in bar, but forbid the invocation in the Demo constructor.
We would probably need some way to propagate method reference receiver initialization requirements.
Issue #904 is probably related, as we want similar sound but usable behavior for inner/anonymous classes.
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 by reproducing the Java examples with the Nullness Checker and inspect the method-reference receiver handling related to commit dd7bc5917cb2f4d6647eef7cc63ff647715d6f8e. Compare the desired behavior with issue #904 and determine whether receiver initialization requirements can be propagated soundly. Done means field initialization and use in bar are accepted while invocation from the Demo constructor is rejected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100