typetools / typetools/checker-framework
Incorrect default for inner looping variable in a foreach loop.
@wmdietl is already working on this.
Since Sep 27, 2018.
- Dominant language
- Java
- Stars
- 1.1k
- Forks
- 440
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 134
Description
Normally, local variables (including loop index variables) default to the top type in the qualifier hierarchy and then get type refined to the type of the value they are assigned. The checker framework reveals an unusual behavior where the type of a loop variable doesn't get type refined correctly in the case of nested foreach loops.
Consider the following example to be checked with the nullness checker:
import org.checkerframework.checker.nullness.qual.*;
import java.lang.*;
public class Issue28Nullness {
public static @PolyNull Integer @PolyNull [] makeArr(@PolyNull Integer n) {
return new @PolyNull Integer @PolyNull [] {n};
}
public static void f(@NonNull Integer n) {
for (Integer i : makeArr(n)) {
for (Integer j : makeArr(i)) {
@NonNull Integer m = j;
}
}
}
}
The command javac -processor nullness Issue28Nullness.java produces the following unexpected error:
Issue28Nullness.java:13: error: [assignment.type.incompatible] incompatible types in assignment.
@NonNull Integer m = j;
^
found : @Initialized @Nullable Integer
required: @UnknownInitialization @NonNull Integer
1 error
Since n is @NonNull Integer, the type of makeArr(n) is @NonNull Integer @NonNull[]. As a result, i is of the type @NonNull Integer. Subsequently, the return type of makeArr(i) is also @NonNull Integer @NonNull[] and the type of j should also be @NonNull Integer. But the checker framework incorrectly treats j as @Nullable Integer.
Strangely, the error disappears if the inner loop variable is explicitly annotated as @NonNull Integer j.
The error also disappears if the foreach loops are changed to indexed for loops as follows:
import org.checkerframework.checker.nullness.qual.*;
import java.lang.*;
public class Issue28Nullness {
public static @PolyNull Integer @PolyNull [] makeArr(@PolyNull Integer n) {
return new @PolyNull Integer @PolyNull [] {n};
}
public static void fSimple(@NonNull Integer n) {
@NonNull Integer @NonNull [] local = makeArr(n);
for (Integer i = 0; i < local.length; i++) {
@NonNull Integer @NonNull [] local1 = makeArr(i);
for (Integer j = 0; j < local1.length; j++) {
@NonNull Integer m = j;
}
}
}
}
This shows that this problem pertains to inner loop variables of foreach loops.
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.
Assessment
This issue has not been assessed yet.