Bug 413460 - NonNullByDefault is not inherited to Constructors when accessed via Class File
Summary: NonNullByDefault is not inherited to Constructors when accessed via Class File
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.3   Edit
Hardware: All All
: P3 major (vote)
Target Milestone: 4.3.1   Edit
Assignee: Stephan Herrmann CLA
QA Contact:
URL:
Whiteboard: To be verified for 4.4 M2
Keywords: greatbug
Depends on:
Blocks:
 
Reported: 2013-07-22 11:03 EDT by Till Brychcy CLA
Modified: 2013-08-29 06:29 EDT (History)
3 users (show)

See Also:


Attachments
proposed bugfix (4.76 KB, patch)
2013-08-15 16:16 EDT, Till Brychcy CLA
stephan.herrmann: review+
Details | Diff
regression test (2.28 KB, patch)
2013-08-17 04:53 EDT, Stephan Herrmann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Till Brychcy CLA 2013-07-22 11:03:20 EDT
REPRODUCING THE PROBLEM:
Create a workspace with two java projects. In the Java-Compiler "Errors/Warning" -settings turn on "enabled annotation-based null-analysis".

Put the following Class into the first project:

import org.eclipse.jdt.annotation.NonNullByDefault;

@NonNullByDefault
public class Class2 {
	public Class2(String nonNullArg) {
		assert nonNullArg != null;
	}

	public static Class2 create(String nonNullArg) {
		return new Class2(nonNullArg);
	}
}

Now create this class in the other project, configure the build path settings.

public class Class1 {
	public static Class2 works() {
		return Class2.create(null);
	}

	public static Class2 bug() {
		return new Class2(null);
	}
}

Do a clean build.

PROBLEM:
If you open Class1 in the editors, you will see two warnings, but in the problems view, there will be only one warning for "works", but no warning in "bug".

ANALYSIS:
When compiling for the editor, Class2 is accessed via a SourceTypeBinding, and org.eclipse.jdt.internal.compiler.lookup.MethodBinding.parameterNonNullness is initialized in both cases. The compilation for the "problems view" accesses Class2 as BinaryTypeBinding.

In BinaryTypeBinding, there is code to inherit the nullness-settings in  org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.scanFieldForNullAnnotation(IBinaryField, FieldBinding) and org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.scanTypeForNullDefaultAnnotation(IBinaryType, PackageBinding, BinaryTypeBinding), but not for methods in org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.scanMethodForNullAnnotation(IBinaryMethod, MethodBinding).

It still works for the "Class2#create" invocation from "Class1#works", because org.eclipse.jdt.internal.compiler.lookup.MethodBinding.parameterNonNullness is initialized in org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(BlockScope) with ImplicitNullAnnotationVerifier. The corresponding code in org.eclipse.jdt.internal.compiler.ast.AllocationExpression.resolveType(BlockScope) seems to be missing. Adding it like in the following patch makes the warnings appear in the problems view.


diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 2f4b127..5319d9e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -28,6 +28,7 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
@@ -435,6 +436,11 @@
 	if (!isDiamond && this.resolvedType.isParameterizedTypeWithActualArguments()) {
  		checkTypeArgumentRedundancy((ParameterizedTypeBinding) this.resolvedType, null, argumentTypes, scope);
  	}
+	final CompilerOptions compilerOptions = scope.compilerOptions();
+	if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
+		new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations)
+				.checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope);
+	}
 	return allocationType;
 }
Comment 1 Till Brychcy CLA 2013-07-22 11:36:19 EDT
Here is the commit that removed the inheritance code from BinaryTypeBinding:
http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=4ac6f89083748b9c4fc37b738ed82ea1a7c9c63b
Comment 2 Stephan Herrmann CLA 2013-07-22 15:46:46 EDT
Thanks for the report, I can reproduce in HEAD of master.

Thanks also for digging into the implementation. From a quick glance your
analysis hits the nail on the head! Yep, while moving some logic from
BinaryTypeBinding.createMethod() to MessageSend.resolveType() I indeed forgot
about constructors.

This is exactly the kind of bug report we like: small example for reproducing,
clear description and even a proposed patch that fixes the issue.
Comment 3 Dani Megert CLA 2013-08-08 10:44:03 EDT
This is a regression which we should also backport to 4.3.1.
Comment 4 Jay Arthanareeswaran CLA 2013-08-13 09:59:46 EDT
Stephan, are we still looking at getting this into SR1? Thanks for looking into this.
Comment 5 Stephan Herrmann CLA 2013-08-14 13:30:38 EDT
Sorry, I was distracted by other business.

Till, I'd like to mark you as the author of the commit-to-be, so that your
contribution will be given due credit.

To prepare the actual commit I have to ask you a few things, noted below.
Please let me know to which degree you are willing to meet these requests.

For process sake please:

- complete and submit the Contributor License Agreement, see
  http://www.eclipse.org/legal/CLA.php

- submit the next version of your patch as an attachment to this bug
  - before creating the patch, add your name and a reference to this bug to
    the header comment of each source file touched by you.
    Please see the existing headers.

- after that, please "sign-off" your patch by a comment in this bug like
  "This contribution complies with http://www.eclipse.org/legal/CoO.php"


Technically I'd like to ask you to

- check whether class QualifiedAllocationExpression needs the same fix.


Ideally, the patch should also contain corresponding unit tests. These would
be added to org.eclipse.jdt.core.tests.compiler.regression.NullAnnotationTest
from where you may take inspiration how to write such a test.
Feel free to either ask for some hints on writing the tests or pass this
part on to me.


To get this into Kepler SR1 as requested, we should try to get this ready
within approx. 10 days.


So, Till, do you want to give it a try as outlined above?
Thanks!
Comment 6 Till Brychcy CLA 2013-08-15 13:45:00 EDT
(In reply to comment #5)
> Sorry, I was distracted by other business.
> 
> Till, I'd like to mark you as the author of the commit-to-be, so that your
> contribution will be given due credit.
> 
> To prepare the actual commit I have to ask you a few things, noted below.
> Please let me know to which degree you are willing to meet these requests.
> 
> For process sake please:
> 
> - complete and submit the Contributor License Agreement, see
>   http://www.eclipse.org/legal/CLA.php
> 
> - submit the next version of your patch as an attachment to this bug
>   - before creating the patch, add your name and a reference to this bug to
>     the header comment of each source file touched by you.
>     Please see the existing headers.
> 
> - after that, please "sign-off" your patch by a comment in this bug like
>   "This contribution complies with http://www.eclipse.org/legal/CoO.php"
> 
> 
> Technically I'd like to ask you to
> 
> - check whether class QualifiedAllocationExpression needs the same fix.

I think I can do all of this.

> 
> 
> Ideally, the patch should also contain corresponding unit tests. These would
> be added to org.eclipse.jdt.core.tests.compiler.regression.NullAnnotationTest
> from where you may take inspiration how to write such a test.
> Feel free to either ask for some hints on writing the tests or pass this
> part on to me.

I would be great if you would do that because I couldn't find an existing multi-project test scenario in there that can be easily adapted.

> 
> 
> To get this into Kepler SR1 as requested, we should try to get this ready
> within approx. 10 days.

Sounds possible

> 
> 
> So, Till, do you want to give it a try as outlined above?
> Thanks!
Comment 7 Till Brychcy CLA 2013-08-15 16:16:42 EDT
Created attachment 234469 [details]
proposed bugfix
Comment 8 Till Brychcy CLA 2013-08-15 16:17:55 EDT
This contribution complies with http://www.eclipse.org/legal/CoO.php
Comment 9 Till Brychcy CLA 2013-08-15 16:29:43 EDT
> - complete and submit the Contributor License Agreement, see
>   http://www.eclipse.org/legal/CLA.php
DONE

> 
> - submit the next version of your patch as an attachment to this bug
>   - before creating the patch, add your name and a reference to this bug to
>     the header comment of each source file touched by you.
>     Please see the existing headers.
DONE

> 
> - after that, please "sign-off" your patch by a comment in this bug like
>   "This contribution complies with http://www.eclipse.org/legal/CoO.php"
DONE

> 
> 
> Technically I'd like to ask you to
> 
> - check whether class QualifiedAllocationExpression needs the same fix.
You were right, it needed the same fix.

> 
> 
> Ideally, the patch should also contain corresponding unit tests. These would
> be added to org.eclipse.jdt.core.tests.compiler.regression.NullAnnotationTest
> from where you may take inspiration how to write such a test.
> Feel free to either ask for some hints on writing the tests or pass this
> part on to me.
As i wrote in my previous response, I would appreciate if you could do that,
because i couldn't find an existing multi-project test example in a reasonable amount of time).
maybe you can base it on my extended test example:
import org.eclipse.jdt.annotation.NonNullByDefault;

@NonNullByDefault
public class Class2 {
	public class Class3 {
		public Class3(String nonNullArg) {
			assert nonNullArg != null;
		}
	}

	public Class2(String nonNullArg) {
		assert nonNullArg != null;
	}

	public static Class2 create(String nonNullArg) {
		return new Class2(nonNullArg);
	}
}

public class Class1 {
	public static Class2 works() {
		return Class2.create(null);
	}

	public static Class2 bug() {
		return new Class2(null);
	}

	public static Class2.Class3 qualifiedbug() {
		return new Class2("").new Class3(null);
	}
}

> 
> 
> To get this into Kepler SR1 as requested, we should try to get this ready
> within approx. 10 days.
DONE except for new unit tests (but i successfully ran the existing tests with RunJDTCoreTests)
Comment 10 Stephan Herrmann CLA 2013-08-15 16:50:16 EDT
Thanks, Till!

I will take this forward from here.
Comment 11 Till Brychcy CLA 2013-08-16 19:25:25 EDT
Stephan, 

I have found another problem related to the inheritance of NonNullByDefault and have prepared a proposed fix in bug 415269. Maybe you want to consider that for the Kepler SR1, too.

Anyway, thank you for your great work.
Comment 12 Stephan Herrmann CLA 2013-08-17 04:53:38 EDT
Created attachment 234507 [details]
regression test

Here's a test that fails without the fix from this bug and passes after
applying attachment 234469 [details]
Comment 13 Stephan Herrmann CLA 2013-08-17 05:15:12 EDT
I noticed a slight difference between how the fix is applied to both classes.
The difference does no harm for now, it is obviously motivated by existing
differences between both classes. 
I raised bug 415275 for cleanup to improve maintainability for the future.
Till, maybe you want to comment in that bug about the difference how you
integrated the fix into both classes?

The patch looks good to me. 
Dani, Jay, may I count your previous comments as the required +1 for release 
to R4_3_mainteance?
Comment 14 Jay Arthanareeswaran CLA 2013-08-19 00:15:36 EDT
(In reply to comment #13)
> The patch looks good to me. 
> Dani, Jay, may I count your previous comments as the required +1 for release 
> to R4_3_mainteance?

Sure.
Comment 15 Dani Megert CLA 2013-08-19 04:35:01 EDT
(In reply to comment #13)
> I noticed a slight difference between how the fix is applied to both classes.
> The difference does no harm for now, it is obviously motivated by existing
> differences between both classes. 
> I raised bug 415275 for cleanup to improve maintainability for the future.
> Till, maybe you want to comment in that bug about the difference how you
> integrated the fix into both classes?
> 
> The patch looks good to me. 

In that case, please set the review+ flag.

> Dani, Jay, may I count your previous comments as the required +1 for release 
> to R4_3_mainteance?

Yes.
Comment 16 Stephan Herrmann CLA 2013-08-19 09:06:33 EDT
Released for 4.3.1 via 
  commit 71fa684d4e8a76828182f4efcbe41eab655d0299 (test)
  commit c005efbda8be0db83712eb14294777155c3ab919 (fix)
Comment 17 Jay Arthanareeswaran CLA 2013-08-21 01:48:30 EDT
Stephan, this needs to be released for Luna as well, right? I am removing the whiteboard content as the target already points to 4.3.1. But when we decide to release it in master, we need to set the whiteboard content appropriately.
Comment 18 Dani Megert CLA 2013-08-21 03:31:46 EDT
(In reply to comment #17)
> But when we
> decide to release it in master, we need to set the whiteboard content
> appropriately.

NOTE: The normal process is
1. commit to 'master'
2. wait that it works (at least one good build without test failures)
3. backport
Comment 19 Stephan Herrmann CLA 2013-08-21 07:08:37 EDT
I'm aware I didn't follow the normal process, but considering the tight schedule for
the next SR1 candidate and given release for 4.3.1 has been approved I did this first.

As I didn't have the time to run all tests against Luna immediately after, I
- changed the target to 4.4 M2
- added the whiteboard note "to be verified for 4.3.1"

Next I was going to ask Dani why he reverted these two changes :)
Comment 20 Dani Megert CLA 2013-08-21 07:12:50 EDT
(In reply to comment #19)
> I'm aware I didn't follow the normal process, but considering the tight
> schedule for
> the next SR1 candidate and given release for 4.3.1 has been approved I did
> this first.
> 
> As I didn't have the time to run all tests against Luna immediately after, I
> - changed the target to 4.4 M2
> - added the whiteboard note "to be verified for 4.3.1"
> 
> Next I was going to ask Dani why he reverted these two changes :)

The target milestone reflects the oldest build where the fix is present - unless you want to have a bug report for each release where you backport.

I see the time pressure in this case and assume you did run the tests against 4.3.1 before committing.
Comment 21 Stephan Herrmann CLA 2013-08-21 07:55:01 EDT
(In reply to comment #20)
> The target milestone reflects the oldest build where the fix is present -
> unless you want to have a bug report for each release where you backport.

Thanks. So, when I release to Luna I will set resolved and set the whiteboard flag
"to be verified for 4.4 M2"?
 
> I see the time pressure in this case and assume you did run the tests
> against 4.3.1 before committing.

Yes, I did.
Comment 22 Dani Megert CLA 2013-08-21 08:11:30 EDT
(In reply to comment #21)
> Thanks. So, when I release to Luna I will set resolved and set the
> whiteboard flag
> "to be verified for 4.4 M2"?

Yes.
Comment 23 Stephan Herrmann CLA 2013-08-21 15:42:06 EDT
Released for 4.4 M2
  commit f5be514287a14c34eaf46764a8f15d56d8087272 (test)
  commit e2e97eb1ed318448b72d60aca6f0daa8c5b48408 (fix)
Comment 24 Jay Arthanareeswaran CLA 2013-08-29 05:35:34 EDT
Verified for 4.3.1 with build M20130828-0800