| Summary: | [compiler][null] Array initializations not handled | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | shankha banerjee <shankhba> | ||||||||
| Component: | Core | Assignee: | shankha banerjee <shankhba> | ||||||||
| Status: | CLOSED DUPLICATE | QA Contact: | |||||||||
| Severity: | normal | ||||||||||
| Priority: | P3 | CC: | jarthana, shankhba, stephan.herrmann | ||||||||
| Version: | 4.4 | ||||||||||
| Target Milestone: | 4.4 | ||||||||||
| Hardware: | PC | ||||||||||
| OS: | Windows 7 | ||||||||||
| Whiteboard: | |||||||||||
| Attachments: |
|
||||||||||
(In reply to shankha banerjee from comment #0) > import org.eclipse.jdt.annotation.NonNullByDefault; > > @NonNullByDefault > class X { > int a[]; // Error Reported : The @NonNull field may not have been > initialized. > } > > > ----------------------------------------------------------- > > Isn't it misleading. Why misleading? You declare the field to be nonnull (via the default), but there's no nonnull value in it (fields without explicit initialization are implicitly initialized to null). That's an error. > a = new int[3]; // Warning: Null type safety (type annotations): The > expression of type 'int[]' needs unchecked conversion to conform to 'int > @NonNull[]' > [...] > Warning on line 3 also looks incorrect ? Would new return a null value ? Which is your line 3? OK, we seem to have a bug here, probably array initializers aren't yet hooked up to report a nonnull type / nullStatus? Also this looks like a issue:
1. import org.eclipse.jdt.annotation.NonNullByDefault;
2.
3. @NonNullByDefault
4. public class X {
5. int[] a;
6. X() {
7. int [] b;
8. a = new int[0];
9. b = new int[0];
10. foo (b);
11. }
12. private void foo(int [] b) {
13. }
14. }
Line No: 10: foo(b)
Null type safety (type annotations): The expression of type 'int[]' needs unchecked conversion to conform to 'int @NonNull[]'
--------------------------------------------------------------------
As per Comment 1
a = new int[0] (Line No: 8) issues a warning:
Null type safety (type annotations): The expression of type 'int[]' needs unchecked conversion to conform to 'int @NonNull[]'
I am not sure if we could handle this case as a is a field and not a local variable. I could be wrong.
Although something like:
import org.eclipse.jdt.annotation.NonNullByDefault;
@NonNullByDefault
class Y {}
public class X {
Y y1;
void foo() {
Y y;
y = new Y();
bar (y);
y1 = new Y();
}
private void bar(Y y) {
}
}
Does not report any warnings.
Thanks
(In reply to shankha banerjee from comment #2) > Although something like: > import org.eclipse.jdt.annotation.NonNullByDefault; > > > @NonNullByDefault > class Y {} > public class X { > Y y1; > void foo() { > Y y; > y = new Y(); > bar (y); > y1 = new Y(); > } > > private void bar(Y y) { > } > } > > Does not report any warnings. Isn't there an error that y1 is @NonNull but uninitialized? (In reply to Stephan Herrmann from comment #3) > (In reply to shankha banerjee from comment #2) > > Although something like: > > import org.eclipse.jdt.annotation.NonNullByDefault; > > > > > > @NonNullByDefault > > class Y {} > > public class X { > > Y y1; > > void foo() { > > Y y; > > y = new Y(); > > bar (y); > > y1 = new Y(); > > } > > > > private void bar(Y y) { > > } > > } > > > > Does not report any warnings. > > Isn't there an error that y1 is @NonNull but uninitialized? Yes. Sorry. I should have seen it. When you say initialized ? You mean initialization either through constructor or initialization as part of declaration itself. class Y {} public class X { Y y1 = new Y(); ... (In reply to shankha banerjee from comment #4) > When you say initialized ? You mean initialization either through constructor > or initialization as part of declaration itself. > class Y {} > public class X { > Y y1 = new Y(); > ... Right, either one is good (compare to definite assignment of final fields). Currently concentrating on the following test case. Will get to others after that.
Test Case:
import org.eclipse.jdt.annotation.NonNullByDefault;
1. @NonNullByDefault
2. public class X {
3. X() {
4. int[] b;
5. b = new int[0]; // or even int [] b = { 1 };
6. foo(b);
7. }
8. void foo(int [] b) {
9. }
10. }
Warning at line no 6 (foo(b): Null type safety (type annotations): The expression of type 'int[]' needs unchecked conversion to conform to 'int @NonNull[]'
MethodBinding.java#parameterNonNullness
Comment mentions:
public Boolean[] parameterNonNullness; // TRUE means @NonNull declared, FALSE means @Nullable declared, null means nothing declared
is not set.
In my opinion it should be set in one of the below mentioned functions:
createArgumentBindings(Argument[], MethodBinding, MethodScope) : void - org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
createArgumentBindings() : void - org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
resolveType(BlockScope) : TypeBinding - org.eclipse.jdt.internal.compiler.ast.LambdaExpression
If one comes across NonNullByDefault set all the arguments of
parameterNonNullness to true.
Another issue:
1. class Y {}
2. class Z {
3. Y y;
4. void foo() {
5. if (y != null)
6. bar (y);
7. }
8. private void bar(@NonNull Y y) {
9.
10. }
11. }
Warning at line no: 6 Null type safety (type annotations): The expression of type 'Y' needs unchecked conversion to conform to '@NonNull Y'
(In reply to shankha banerjee from comment #7) > Another issue: > > 1. class Y {} > 2. class Z { > 3. Y y; > 4. void foo() { > 5. if (y != null) > 6. bar (y); > 7. } > 8. private void bar(@NonNull Y y) { > 9. > 10. } > 11. } > > Warning at line no: 6 Null type safety (type annotations): The expression of > type 'Y' needs unchecked conversion to conform to '@NonNull Y' This is correct. The var "y" should be read into a local variable. In case of multithreaded programs y could be null even after the check is over. (In reply to shankha banerjee from comment #6) Please ignore Comment 6. The issue is NullAnnotationMatching#analyse. We do not handle case where requiredType -> @NonNULL Type providedType -> Type nullStatus -> NON_NULL. See the elseif part: } else if (requiredType.hasNullTypeAnnotations() || providedType.hasNullTypeAnnotations()) { ... ... Test cases can have following variations: 1) Qualified Array Access. 2) Annotations on different dimensions. 3) Annotations on SuperType. Thanks (In reply to shankha banerjee from comment #6) > Currently concentrating on the following test case. Will get to others after > that. > > Test Case: > > import org.eclipse.jdt.annotation.NonNullByDefault; > 1. @NonNullByDefault > 2. public class X { > 3. X() { > 4. int[] b; > 5. b = new int[0]; // or even int [] b = { 1 }; > 6. foo(b); > 7. } > 8. void foo(int [] b) { > 9. } > 10. } > > Warning at line no 6 (foo(b): Null type safety (type annotations): The > expression of type 'int[]' needs unchecked conversion to conform to 'int > @NonNull[]' > > > MethodBinding.java#parameterNonNullness > > Comment mentions: > public Boolean[] parameterNonNullness; // TRUE means @NonNull declared, > FALSE means @Nullable declared, null means nothing declared > > is not set. Are you testing this at 1.7- or 1.8? The field parameterNonNullness is used only for old declaration annotations, type annotations have that information directly in the type binding. Seeing the error message mentioning "int @NonNull[]" indicates you're indeed in 1.8. In that case not seeing parameterNonNullness is OK. The bug is in how we handle the "new int[]" expression. That part should be fairly easy to fix. Created attachment 241470 [details]
WIP Patch
Patch. All Tests results are green.
(In reply to shankha banerjee from comment #11) > Created attachment 241470 [details] > Patch > > Patch. All Tests results are green. The patch all the issues mentioned in this bug. I will file a separate bug for the test case mentioned in Comment 2 second part and comment 3. (In reply to shankha banerjee from comment #12) > I will file a separate bug for the test case mentioned in Comment 2 second > part and comment 3. Bug 431722. I will upload a new patch. I think I made a mistake.
org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
+ public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ if (this.dimensions.length != 1 && this.annotationsOnDimensions == null)
+ return FlowInfo.POTENTIALLY_NON_NULL;
It should be FlowInfo.POTENTIALLY_NULL.
I will verify.
Created attachment 241501 [details]
Patch
Patch: All test results are green.
Hi Stephan,
Could you please review. Thanks for your help.
Thanks
Created attachment 241505 [details]
Patch
Same patch as the previous. Some formatting errors in the test case were fixed.
(In reply to Stephan Herrmann from comment #10) > Are you testing this at 1.7- or 1.8? The field parameterNonNullness is used > only for old declaration annotations, type annotations have that information > directly in the type binding. > > Seeing the error message mentioning "int @NonNull[]" indicates you're indeed > in 1.8. In that case not seeing parameterNonNullness is OK. The bug is in > how we handle the "new int[]" expression. That part should be fairly easy to > fix. Sorry. I did not reply to this part. This belongs to 1.8. Thanks *** This bug has been marked as a duplicate of bug 431964 *** |
import org.eclipse.jdt.annotation.NonNullByDefault; @NonNullByDefault class X { int a[]; // Error Reported : The @NonNull field may not have been initialized. } ----------------------------------------------------------- Isn't it misleading. I change the code: import org.eclipse.jdt.annotation.NonNullByDefault; @NonNullByDefault class X { int a[]; // Error Reported : The @NonNull field a may not have been initialized. void foo() { a = new int[3]; // Warning: Null type safety (type annotations): The expression of type 'int[]' needs unchecked conversion to conform to 'int @NonNull[]' bar(a); } private void bar(int [] i) {} } Isn't it wrong to report the error in the first case. Warning on line 3 also looks incorrect ? Would new return a null value ?