Repository navigation
Better handling of method references passed to generic methods in JSpecify mode - #1499
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #1499 +/- ##
============================================
+ Coverage 88.43% 88.45% +0.01%
- Complexity 2813 2823 +10
============================================
Files 99 100 +1
Lines 9410 9446 +36
Branches 1888 1893 +5
============================================
+ Hits 8322 8355 +33
- Misses 529 530 +1
- Partials 559 561 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughAdds method-reference support to generic-method inference and assignment-compatibility checks by treating MemberReferenceTree as a poly-expression, generalizing target-type caching, and delegating method-reference return/parameter relation generation to a new utility class 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@nullaway/src/main/java/com/uber/nullaway/generics/GenericsUtils.java`:
- Around line 66-69: The code currently force-casts the result of
genericsChecks.getMemberReferenceMethodType(...) via castToNonNull into
referencedMethodType, which can be null outside JSpecify mode; update the logic
in GenericsUtils to first call
genericsChecks.getMemberReferenceMethodType(memberReferenceTree,
referencedMethod, state), check for null and return early (or handle the null
case appropriately) before calling castToNonNull, so castToNonNull is only
invoked on a guaranteed non-null value.
🪄 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: f9889036-37ff-4dbb-addc-87c86891f3d1
📒 Files selected for processing (3)
nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.javanullaway/src/main/java/com/uber/nullaway/generics/GenericsUtils.javanullaway/src/test/java/com/uber/nullaway/jspecify/GenericMethodLambdaOrMethodRefArgTests.java
| if (typeArgumentTrees != null | ||
| && !typeArgumentTrees.isEmpty() | ||
| && overridingMethod.asType() instanceof Type.ForAll forAllType) { | ||
| // handle explicit type arguments in method reference, e.g., x::<Foo>method |
There was a problem hiding this comment.
The other changes in this PR exposed this issue; apparently we weren't doing the appropriate substitution before when a method reference has explicit type arguments
There was a problem hiding this comment.
Is there a case where a method reference has some type arguments given explicitly and some inferred? (Not sure if this is possible in Java, just checking)
There was a problem hiding this comment.
No, it either needs to be all explicit or all inferred
lazaroclapp
left a comment
There was a problem hiding this comment.
Did my best to check this. LGMT. Biggest thing bothering me is the location of the annotation in the error messages, but I think that's just our existing pretty-printing logic instead?
| return; | ||
| } | ||
| Type.MethodType referencedMethodType = | ||
| castToNonNull( |
There was a problem hiding this comment.
Why is this cast safe? And why is it preferred to an if check and return? I suspect it might be both, just noting that it might benefit from a comment as to why :)
Edit: There was a null check and an alternative default for referencedMethodType in the non-refactored version, no?
There was a problem hiding this comment.
You're right. A null check does no harm here (though I don't think we should ever see null). Will add.
|
|
||
| private final NullAway analysis; | ||
| private final Config config; | ||
| /* package-private */ final Config config; |
There was a problem hiding this comment.
Why? Can't get pass it around or create a package-private accessor?
There was a problem hiding this comment.
Good catch, added a package-private getter
| solver.addSubtypeConstraint(fiParamTypes.get(fiStartIndex + i), varargsElementType, false); | ||
| } | ||
| state, | ||
| (subtype, supertype, relationKind) -> { |
There was a problem hiding this comment.
I guess relationKind is used only for reporting and then only when checking call-sites, right?
Does java support something like: (subtype, supertype, _) -> { here for clarity?
There was a problem hiding this comment.
Java does support _ but only in a more recent version than we are using. I renamed to unused here; you're right this is only used in the other case for error reporting.
| if (typeArgumentTrees != null | ||
| && !typeArgumentTrees.isEmpty() | ||
| && overridingMethod.asType() instanceof Type.ForAll forAllType) { | ||
| // handle explicit type arguments in method reference, e.g., x::<Foo>method |
There was a problem hiding this comment.
Is there a case where a method reference has some type arguments given explicitly and some inferred? (Not sure if this is possible in Java, just checking)
See #1499 (comment). This should make our error messages more consistent and less confusing. We now only include `@Nullable` type use annotations. Eventually, we may want to adopt [JSpecify shorthand](https://github.com/jspecify/jspecify/wiki/notation#shorthand-notation) when printing types, but we'd have to think more carefully about that. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Diagnostic type annotations are printed more concisely: most inline annotations (e.g., @nonnull) are suppressed while @nullable remains visible once; array spacing normalized for clearer output. * **Tests** * Updated expected diagnostic texts in several tests to match the slimmer annotation formatting. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…ks.java Co-authored-by: Lázaro Clapp <lazaro@uber.com>
Fixes #1431
Fixes #1474
We make two key changes. First, we store the inferred types of method reference expressions in the
inferredPolyExpressionTypescache, similar to what we did for lambdas, so that some later checks that require the type of the method reference get the inferred type.Second, when a method reference is passed to a generic method, sometimes the type for the method reference computed by
javacdoes not include nullability annotations on nested types (see #1474 and a new test case here). So, we need to do explicit checks using the return and parameter types of the referenced method, to see if nested nullability annotations are consistent with the target functional-interface method type.For code reuse and clarity, we extract a utility method for doing type checks related to method references to a new class
GenericsUtils, and rewrite one use of the original logic to use the new utility.Summary by CodeRabbit
New Features
Improvements
Tests