| Summary: | [1.8][null] help the type inference to find a nullness-annotated type if possible | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Stephan Herrmann <stephan.herrmann> |
| Component: | Core | Assignee: | Stephan Herrmann <stephan.herrmann> |
| Status: | VERIFIED FIXED | QA Contact: | |
| Severity: | enhancement | ||
| Priority: | P3 | CC: | noopur_gupta, shankhba |
| Version: | 4.4 | ||
| Target Milestone: | BETA J8 | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | |||
(In reply to Stephan Herrmann from comment #0) > Another option would be to add nullness hints to TypeBounds during > incorporation. This proves to be quite easy and is probably even more consistent than the previous proposal. I have a patch under test that implements this strategy: - whenever during incorporation two TypeBounds are combined into a new ConstraintTypeFormula, we inspect if the types in that new formula have null tagBits. If so, we collect & accumulate these bits back into the originating type bounds. E.g. from T#0 <: @NonNull String T#0 :> String we collect the tagBit for nonnull and add it as a hint to both shown TypeBounds - later when the BoundSet is asked for the lower or upper bounds for a given InferenceVariable, we collect the nullHints of all relevant TypeBounds. If these specify exactly one of @NonNull or @Nullable, we add the corresponding AnnotationBinding to all types in the resp. lower/upper bound. This suffices to steer inference into producing a solution with the desired null annotation. We don't influence type inference if both @NonNull and @Nullable are seen in different TypeBounds affecting the same InferenceVariable. In that case we simply refrain from adding null annotations to the result. This solution is lean, as during inference it only merges a few bits into a new field nullHints. In the final phase of resolution any useful hints collected until then are used to create an annotated type binding of the same naked type. For easier review I've again split the change into a preparatory refactoring in http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=f700051affab74804180d3a8bb296f6cabd751a0 the test & actual fix in http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=745840be480d4e43f22d0c4f40c198cdee6926a4 More tests and a bit more hinting released via http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=b16af955ad096598d372b7b23da79db705ddee11 (Here the connection is made during substituting an inference variable, so no TypeBound directly involved). Verified as working for Eclipse + Java 8 RC2 using Kepler SR2 + Eclipse Java Development Tools Patch for Java 8 Support (BETA) 1.0.0.v20140306-1935 |
Consider examples like this: //--- import org.eclipse.jdt.annotation.*; interface Func<T> { T a(T i); } public class PolyNull { <X> X extract(Func<X> f, X s) { return f.a(s); } @NonNull String test() { return extract(i -> i, "hallo"); } //--- Type inference will infer X to String, fine. But the target type is actually '@NonNull String'. While null analysis should not affect the basic outcome of type inference, we actually have sufficient leeway to improve the exact inferred type: Inference comes up with X#0 :> String X#0 <: @NonNull String knowing that both bounds are compatible since incorporation didn't fail. During resolution X#0 is instantiated just from the lower bound, which has no null annotation. If we add to this result just the nullness findings from the upper bounds we can indeed produces the result '@NonNull String'. I'll look for more tests, to see this is already makes for a consistent solution. Another option would be to add nullness hints to TypeBounds during incorporation. Obviously, any such magic will be controlled by the option to enable null annotations in the first place.