File: ArrayCreationNullable.java

package info (click to toggle)
checker-framework-java 3.2.0%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 23,104 kB
  • sloc: java: 145,916; xml: 839; sh: 518; makefile: 404; perl: 26
file content (187 lines) | stat: -rw-r--r-- 6,865 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import org.checkerframework.checker.nullness.qual.*;
import org.checkerframework.framework.qual.DefaultQualifier;

/**
 * The component type of newly created arrays is always @Nullable, also for boxed types. This is an
 * expanded version of the test case for Issue 151:
 * https://github.com/typetools/checker-framework/issues/151
 */
public class ArrayCreationNullable {

    void testObjectArray(@NonNull Object @NonNull [] p) {
        @NonNull Object @NonNull [] objs;
        // :: error: (new.array.type.invalid)
        objs = new Object[10];
        objs[0].toString();
        // :: error: (assignment.type.incompatible)
        objs = new @Nullable Object[10];
        objs[0].toString();
        // :: error: (new.array.type.invalid)
        objs = new @NonNull Object[10];
        objs[0].toString();
        // Allowed.
        objs = p;
        objs[0].toString();
    }

    @DefaultQualifier(NonNull.class)
    void testObjectArray2() {
        Object[] objs;
        // Even if the default qualifier is NonNull, array component
        // types must be Nullable.
        // :: error: (new.array.type.invalid)
        objs = new Object[10];
        objs[0].toString();
    }

    void testInitializers() {
        Object[] objs = {1, 2, 3};
        objs = new Integer[] {1, 2, 3};
        objs = new Object[] {new Object(), "ha"};

        @NonNull Object[] objs2 = {};
        // :: error: (assignment.type.incompatible)
        objs2 = new Integer[] {1, null, 3};
        // :: error: (assignment.type.incompatible)
        objs2 = new Object[] {new Object(), "ha", null};

        @NonNull Object[] objs3 = new Integer[] {1, 2, 3};
        objs3 = new Integer[] {1, 2, 3};
        // :: error: (assignment.type.incompatible)
        objs3 = new Integer[] {1, 2, 3, null};

        (new Integer[] {1, 2, 3})[0].toString();
        // :: error: (dereference.of.nullable)
        (new Integer[] {1, 2, 3, null})[0].toString();

        // The assignment context is used to infer a @Nullable component type.
        @Nullable Object[] objs4 = new Integer[] {1, 2, 3};
        // :: error: (dereference.of.nullable)
        objs4[0].toString();
        objs4 = new Integer[] {1, 2, 3};
    }

    void testStringArray(@NonNull String @NonNull [] p) {
        @NonNull String @NonNull [] strs;
        // :: error: (new.array.type.invalid)
        strs = new String[10];
        strs[0].toString();
        // :: error: (assignment.type.incompatible)
        strs = new @Nullable String[10];
        strs[0].toString();
        // :: error: (new.array.type.invalid)
        strs = new @NonNull String[10];
        strs[0].toString();
        // Allowed.
        strs = p;
        strs[0].toString();
    }

    void testIntegerArray(@NonNull Integer @NonNull [] p) {
        @NonNull Integer @NonNull [] ints;
        // :: error: (new.array.type.invalid)
        ints = new Integer[10];
        ints[0].toString();
        // :: error: (assignment.type.incompatible)
        ints = new @Nullable Integer[10];
        ints[0].toString();
        // :: error: (new.array.type.invalid)
        ints = new @NonNull Integer[10];
        ints[0].toString();
        // Allowed.
        ints = p;
        ints[0].toString();
    }

    // The component type of zero-length arrays can
    // be non-null - they will always generate
    // IndexOutOfBoundsExceptions, but are usually just
    // used for the type, e.g. in List.toArray.
    void testLengthZero() {
        @NonNull Object @NonNull [] objs;
        objs = new Object[0];
    }

    /* Test case for Issue 153.
    // toArray re-uses the passed array, if it is of appropriate size.
    // It is only guaranteed to be non-null, if it is at most the same size.
    void testToArray(java.util.Set<Object> nns) {
        @NonNull Object [] nna = nns.toArray(new Object[nns.size()]);
        // Given array is too small -> new one is created.
        nna = nns.toArray(new Object[nns.size()-2]);
        // Padding elements will be null.
        // TODO:: error: (assignment.type.incompatible)
        nna = nns.toArray(new Object[nns.size() + 2]);
        @Nullable Object [] nbla = nns.toArray(new Object[nns.size() + 2]);
    }
    */

    void testMultiDim() {
        // new double[10][10] has type double @NonNull[] @Nullable[]
        // :: error: (new.array.type.invalid)
        double @NonNull [] @NonNull [] daa = new double[10][10];
        double @NonNull [] @Nullable [] daa2 = new double[10][10];

        // new Object[10][10] has type @Nullable Object @NonNull[] @Nullable[]
        // :: error: (new.array.type.invalid)
        @Nullable Object @NonNull [] @NonNull [] oaa = new Object[10][10];
        @Nullable Object @NonNull [] @Nullable [] oaa2 = new Object[10][10];

        // new Object[10][10] has type @Nullable Object @NonNull[] @Nullable[]
        // :: error: (new.array.type.invalid)
        oaa2 = new Object @NonNull [10] @NonNull [10];

        @MonotonicNonNull Object @NonNull [] @MonotonicNonNull [] oaa3 =
                new @MonotonicNonNull Object @NonNull [10] @MonotonicNonNull [10];
        oaa3[0] = new @MonotonicNonNull Object[4];
        // :: error: (assignment.type.incompatible)
        oaa3[0] = null;
        // :: error: (assignment.type.incompatible) :: error: (accessing.nullable)
        oaa3[0][0] = null;
    }

    @PolyNull Object[] testPolyNull(@PolyNull Object[] in) {
        @PolyNull Object[] out = new @PolyNull Object[in.length];
        for (int i = 0; i < in.length; ++i) {
            if (in[i] == null) {
                out[i] = null;
            } else {
                out[i] = in[i].getClass().toString();
                // :: error: (assignment.type.incompatible)
                out[i] = null;
            }
        }
        return out;
    }

    void testMonotonicNonNull() {
        @MonotonicNonNull Object @NonNull [] loa = new @MonotonicNonNull Object @NonNull [10];
        loa = new Object @NonNull [10];
        loa[0] = new Object();
        @MonotonicNonNull Object @NonNull [] loa2 = new Object @NonNull [10];
        // :: error: (dereference.of.nullable)
        loa2[0].toString();
    }

    @MonotonicNonNull Object @NonNull [] testReturnContext() {
        return new Object[10];
    }

    // :: error: (new.array.type.invalid)
    @NonNull Object @NonNull [] oa0 = new Object[10];

    // OK
    @MonotonicNonNull Object @NonNull [] loa0 = new @MonotonicNonNull Object @NonNull [10];

    Object[] oa1 = new Object[] {new Object()};

    // :: error: (assignment.type.incompatible)
    Object[] oa2 = new Object[] {new Object(), null};

    public static void main(String[] args) {
        ArrayCreationNullable e = new ArrayCreationNullable();
        Integer[] ints = new Integer[] {5, 6};
        // This would result in a NPE, if there were no error.
        e.testIntegerArray(ints);
    }
}