barry-m / checker-framework

Automatically exported from code.google.com/p/checker-framework
Other
0 stars 0 forks source link

Limitation of nullness checker flow analysis with inner classes #266

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
# What steps will reproduce the problem?

Run the nullness checker on the attached file.

# What is the expected output? What do you see instead?

I expected the nullness checker to recognize that the deference of 'tmp' in the 
inner class will always succeed. Instead, I got the error:

FinalNullable.java:16: error: dereference of possibly-null reference tmp
        return tmp.toString();
               ^

#What version of the product are you using? On what operating system?

javac 1.8.0-jsr308-1.6.7 (7102:18502dce6db5)

Original issue reported on code.google.com by cus...@google.com on 16 Oct 2013 at 4:45

Attachments:

GoogleCodeExporter commented 9 years ago
The Checker Framework currently does type refinement on a final variable based 
on the initializer expression, but not based on subsequent conditional 
expressions.

I have committed a test case as 
checker-framework/checkers/tests/nullness/FinalVar2.java

Original comment by michael.ernst@gmail.com on 16 Oct 2013 at 9:59

GoogleCodeExporter commented 9 years ago
I find comment #1 misleading.
The following example:

  static Object method1(@Nullable Object arg) {
    final Object tmp = arg;
    if (tmp == null) {
      return "hello";
    }
    tmp.hashCode();
    return "bye";
  }

passes the Nullness Checker without an error.

I think we correctly type refine the final variable in the outer class, but 
when we initialize the store for the anonymous inner class, we only use the 
declared types of the final variables. We should take the refined values of the 
final variables at the point where the anonymous class is instantiated.

Stefan recently worked on anonymous inner classes, maybe he can have a quick 
look.

Original comment by wdi...@gmail.com on 17 Oct 2013 at 3:23

GoogleCodeExporter commented 9 years ago
We do remember the refined value of final variables and use it to initialize 
the store in the anonymous inner class.  However, the refinement is only based 
on the initializer of the final variable;  future refinements based on 
comparing the final variable with other values are not used.  This has the 
advantage, that only a single value per final variable needs to be remembered, 
rather than (potentially) a value for every program point.

I'm sure it would be possible to remember more information, but it also does 
not seem like a high-priority issue.  It can easily be worked around by doing 
the check what value the final variable holds earlier.  For the example given, 
one could change it as follows:

    if (arg == null) {
      return null;
    }
    final Object tmp = arg;
    return new Inner() {
      String getThing() {
        return tmp.toString();
      }
    };

I changed the priority to low for now.

Original comment by stefanheule@gmail.com on 17 Oct 2013 at 5:16

GoogleCodeExporter commented 9 years ago

Original comment by michael.ernst@gmail.com on 25 May 2014 at 4:25

GoogleCodeExporter commented 9 years ago

Original comment by michael.ernst@gmail.com on 29 May 2014 at 4:04

GoogleCodeExporter commented 9 years ago
Issue 411 has been merged into this issue.

Original comment by wdi...@gmail.com on 16 Mar 2015 at 8:54

GoogleCodeExporter commented 9 years ago
Issue 411 has been merged into this issue.

Original comment by wdi...@gmail.com on 16 Mar 2015 at 8:54