Compensate for more annotations inserted by javac - #1574
Conversation
|
This change is part of the following stack:
Change managed by git-spice. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1574 +/- ##
============================================
- Coverage 88.37% 88.30% -0.07%
- Complexity 2910 2926 +16
============================================
Files 103 104 +1
Lines 9709 9776 +67
Branches 1959 1967 +8
============================================
+ Hits 8580 8633 +53
- Misses 538 543 +5
- Partials 591 600 +9 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
d38b61c to
28a64ab
Compare
51d4506 to
6958035
Compare
28a64ab to
549d2f0
Compare
|
Caution Review failedFailed to post review comments WalkthroughThis PR centralizes TreePath leaf handling via NullabilityUtil.pathWithLeaf, extracts nested generic-method type-variable nullability repair into NestedTypeVarSubstitutionRepairVisitor.repairMethodType (which recursively repairs TypeVar/ClassType/ArrayType substitutions and memoizes results), updates GenericsChecks to delegate to the visitor and make getTreeType package-private, and adds JSpecify tests covering nested generic repair scenarios. Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
549d2f0 to
d4382c4
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@nullaway/src/main/java/com/uber/nullaway/generics/NestedTypeVarSubstitutionRepairVisitor.java`:
- Around line 203-214: The code currently caches the full callSiteType
(including its top-level nullability) into repairedSubstitutions inside
repairTypeVarSubstitution, which causes one occurrence’s direct annotations to
be reused for other occurrences; change repairTypeVarSubstitution to compute and
cache only the nested substitution (the result of
repairNestedTypeVarSubstitutionFromActual or callSiteType without top-level
direct annotations), store that nested substitution in repairedSubstitutions
(instead of callSiteType), and then when returning from visitTypeVar reapply the
current occurrence’s direct/top-level annotations (the callSiteType’s
annotations) to the cached nested substitution before returning (preserve use of
castToNonNull where appropriate). Ensure you update places where
repairedSubstitutions.get(typeVarSymbol) is used so they reapply per-occurrence
annotations rather than reusing a previously annotated type.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 79191c1d-2737-4f75-8b44-f3e840510121
📒 Files selected for processing (4)
nullaway/src/main/java/com/uber/nullaway/NullabilityUtil.javanullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.javanullaway/src/main/java/com/uber/nullaway/generics/NestedTypeVarSubstitutionRepairVisitor.javanullaway/src/test/java/com/uber/nullaway/jspecify/GenericMethodTests.java
3699dd8 to
0510d8e
Compare
47c77d3 to
fe19f94
Compare
lazaroclapp
left a comment
There was a problem hiding this comment.
Did a partial pass on this one, but the truth is I am having trouble following NestedTypeVarSubstitutionRepairVisitor and what exactly it is doing. Wonder if there is a way to make that code more readable that doesn't involve overwhelming it with documentation, but maybe just a high-level picture plus what each visit{x} transform is actually meant to produce?
| * Repairs inferred substitutions for method type variables in a call-site type using nested | ||
| * nullability annotations from the corresponding actual argument type. | ||
| */ | ||
| @SuppressWarnings("ReferenceEquality") |
There was a problem hiding this comment.
I might want a comment on why we want this class-level suppression here
There was a problem hiding this comment.
Switched to narrower suppressions and added comments
| private final Symbol.MethodSymbol methodSymbol; | ||
| private final VisitorState state; | ||
| private final Config config; | ||
| private final Map<Symbol.TypeVariableSymbol, Type> repairedSubstitutions = new HashMap<>(); |
There was a problem hiding this comment.
Do we want to move the comment on the local variable of the old code here as documentation for this field? I know it's private, but the point about preserving the same repaired substitution for all occurrences of the same type variable is worth noting somewhere, no?
| Type actualArgType = | ||
| genericsChecks.getTreeType( | ||
| actualParam, state.withPath(pathWithLeaf(pathToInvocation, actualParam))); | ||
| if (actualArgType != null) { |
There was a problem hiding this comment.
When is actualArgType null? Or is this just defensive?
There was a problem hiding this comment.
No, getTreeType can return null for raw types, and for some other unhandled cases. I've updated the Javadoc of that method
| } | ||
|
|
||
| @Override | ||
| public Type visitClassType(Type.ClassType genericClassType, RepairContext context) { |
There was a problem hiding this comment.
I am losing the plot a bit with what each of these visitors do. Is there a concise way for us to document the semantics here? Like one line that says, given this context, and this type, this is what we would expect the rewrite to look like at this level. Like some pseudo-code incomplete big-step semantics for each visit{...} method?
There was a problem hiding this comment.
I've added significantly more documentation now; hopefully it helps
0510d8e to
9402f1a
Compare
6310b10 to
94a08ab
Compare
97205e2 to
5fed645
Compare
94a08ab to
70b2120
Compare
5fed645 to
89aaeca
Compare
70b2120 to
c2c3046
Compare
msridhar
left a comment
There was a problem hiding this comment.
@lazaroclapp I think this is ready for another look
| * Repairs inferred substitutions for method type variables in a call-site type using nested | ||
| * nullability annotations from the corresponding actual argument type. | ||
| */ | ||
| @SuppressWarnings("ReferenceEquality") |
There was a problem hiding this comment.
Switched to narrower suppressions and added comments
| private final Symbol.MethodSymbol methodSymbol; | ||
| private final VisitorState state; | ||
| private final Config config; | ||
| private final Map<Symbol.TypeVariableSymbol, Type> repairedSubstitutions = new HashMap<>(); |
| Type actualArgType = | ||
| genericsChecks.getTreeType( | ||
| actualParam, state.withPath(pathWithLeaf(pathToInvocation, actualParam))); | ||
| if (actualArgType != null) { |
There was a problem hiding this comment.
No, getTreeType can return null for raw types, and for some other unhandled cases. I've updated the Javadoc of that method
| } | ||
|
|
||
| @Override | ||
| public Type visitClassType(Type.ClassType genericClassType, RepairContext context) { |
There was a problem hiding this comment.
I've added significantly more documentation now; hopefully it helps
lazaroclapp
left a comment
There was a problem hiding this comment.
The docs helped. I think I got it and LGTM. Only a small nit below.
| if (repairedSubstitutions.containsKey(typeVarSymbol)) { | ||
| return castToNonNull(repairedSubstitutions.get(typeVarSymbol)); |
There was a problem hiding this comment.
Why this check instead of:
Type repairedSubstitution = repairedSubstitutions.get(typeVarSymbol);
if (repairedSubstitution != null) {
return repairedSubstitution;
}
?
Seems more nullability idiomatic than this cast
80edec5 to
df5baa3
Compare
This is a fix to an issue similar to that of #1455. See the test case
caffeineNestedArgToGenericMethod(). Basically, #1473 didn't go far enough. Sometimesjavacplaces@Nullabletype annotations in nested positions where they do not belong according to proper JSpecify rules. Now we recurse to discover and remove such annotations.We also refactor to move this repair logic to a separate top-level class, and to use a visitor structure to recurse through types.
With this change, the Caffeine integration test passes again. Other integration test failure are expected and due to new true positive reports.
Summary by CodeRabbit
Bug Fixes
Tests
Refactor