JSpecify: preserve explicit nullability annotations on type variables when performing substitutions#1143
JSpecify: preserve explicit nullability annotations on type variables when performing substitutions#1143
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1143 +/- ##
============================================
- Coverage 88.25% 88.12% -0.13%
- Complexity 2264 2265 +1
============================================
Files 85 86 +1
Lines 7320 7427 +107
Branches 1463 1483 +20
============================================
+ Hits 6460 6545 +85
- Misses 432 445 +13
- Partials 428 437 +9 ☔ View full report in Codecov by Sentry. |
| @@ -1,9 +1,18 @@ | |||
| package com.uber.nullaway.generics; | |||
There was a problem hiding this comment.
What kind of substitution are we referring to here exactly (is it for generic types?)? And why are nullability annotations from type variables lost after performing a substitution - Could you clarify more in the diff description?
There was a problem hiding this comment.
PR description is updated
| if (enclosingType != null) { | ||
| invokedMethodType = | ||
| TypeSubstitutionUtils.memberType(state.getTypes(), enclosingType, methodSymbol); | ||
| TypeSubstitutionUtils.memberType(state.getTypes(), enclosingType, methodSymbol, config); |
There was a problem hiding this comment.
Is the passing around of the config variable everywhere required for this bug fix? I don't see it being used anywhere.
Or is it an unrelated change which has been combined with this PR? If so, can we clarify this in the PR description?
There was a problem hiding this comment.
The Config object is required for this bug fix. It is stored in an instance field of RestoreNullnessAnnotationsVisitor and used to check whether an annotation should be treated as @Nullable or @NonNull here:
Fixes #1091
Consider the following code:
The call to
fooshould not type check. Since the type of its parameterfisFunction<@Nullable V, @Nullable V>, with explicit@Nullableannotations on the type variables, anyFunctionpassed tofoomust have@Nullabletype arguments. In typechecking this code, NullAway previously substituted the type arguments for the type variables infoojust using built-injavacroutines. But, this would yield a formal parameter typeFunction<String, String>, as thejavacroutine would not retain the explicit type arguments in the right places. So we would miss reporting an error. This PR fixes the substitutions and re-introduces the annotations on type variables, so we get the typeFunction<@Nullable String, @Nullable String>for the formal parameter at the call, and report an error correctly. Substitutions were broken in other cases as well; substituting@Nullable Vfor@Nullable V(whereVis a type variable) yielded justV, which led to false positives (like #1091).The main logic changes are in
TypeSubstitutionUtils. We add a newRestoreNullnessAnnotationsVisitorand use it to restore nullability annotations from type variables after performing a substitution.We also extract the
TypeMetadataBuilderlogic to a top-level source file, and add new methods as needed for this PR. Some of this could have been split into a separate PR but it's a bit of a pain to extract it now.