Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 429906

Summary: [compiler][null] Array initializations not handled
Product: [Eclipse Project] JDT Reporter: shankha banerjee <shankhba>
Component: CoreAssignee: 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:
Description Flags
WIP Patch
none
Patch
none
Patch none

Description shankha banerjee CLA 2014-03-07 14:12:07 EST
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 ?
Comment 1 Stephan Herrmann CLA 2014-03-08 18:17:55 EST
(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?
Comment 2 shankha banerjee CLA 2014-03-12 05:06:48 EDT
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
Comment 3 Stephan Herrmann CLA 2014-03-12 08:12:56 EDT
(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?
Comment 4 shankha banerjee CLA 2014-03-12 08:57:27 EDT
(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();
...
Comment 5 Stephan Herrmann CLA 2014-03-12 09:08:35 EDT
(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).
Comment 6 shankha banerjee CLA 2014-03-14 10:35:58 EDT
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.
Comment 7 shankha banerjee CLA 2014-03-15 08:02:10 EDT
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'
Comment 8 shankha banerjee CLA 2014-03-18 00:01:16 EDT
(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.
Comment 9 shankha banerjee CLA 2014-03-19 09:00:56 EDT
(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
Comment 10 Stephan Herrmann CLA 2014-03-29 19:10:22 EDT
(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.
Comment 11 shankha banerjee CLA 2014-04-01 10:46:22 EDT
Created attachment 241470 [details]
WIP Patch

Patch. All Tests results are green.
Comment 12 shankha banerjee CLA 2014-04-01 10:47:53 EDT
(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.
Comment 13 shankha banerjee CLA 2014-04-01 11:22:06 EDT
(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.
Comment 14 shankha banerjee CLA 2014-04-01 21:01:53 EDT
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.
Comment 15 shankha banerjee CLA 2014-04-02 06:03:47 EDT
Created attachment 241501 [details]
Patch

Patch: All test results are green.

Hi Stephan,
Could you please review. Thanks for your help.

Thanks
Comment 16 shankha banerjee CLA 2014-04-02 08:42:24 EDT
Created attachment 241505 [details]
Patch

Same patch as the previous. Some formatting errors in the test case were fixed.
Comment 17 shankha banerjee CLA 2014-04-03 10:52:16 EDT
(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
Comment 18 shankha banerjee CLA 2014-04-03 23:40:10 EDT

*** This bug has been marked as a duplicate of bug 431964 ***