Commit 6bba0e5
authored
Add regression test for inner classes inheriting enclosing type arguments (#1703)
## Summary
#1274 reports that NullAway misses a warning when a qualified
inner-class creation is assigned to a
variable whose *enclosing* type argument is incompatible:
```java
class A<X extends @nullable Object> { class B<Y extends @nullable Object> {} }
class C<X extends @nullable Object> extends A<X> { class D<Y extends @nullable Object> extends A<X>.B<Y> {} }
C<@nullable String> c = new C<>();
A<String>.B<@nullable String> unused = c.new D<@nullable String>(); // should warn
```
Rather than assume the issue title described current behavior, I ran the
example verbatim as a test
first. On current `master` NullAway **does** report the expected error:
```
warning: [NullAway] incompatible types: Test.C<@nullable String>.D<@nullable String>
cannot be converted to Test.A<String>.B<@nullable String>
(Test.C<@nullable String>.D<@nullable String> is a subtype of Test.A<@nullable String>.B<@nullable String>)
```
Running the same test against `56bd5ad2` — the commit immediately
preceding #1699 — it reports nothing.
So this false negative was fixed as a side effect of #1699.
That makes sense mechanically. Before #1699, `getTreeType` typed `c.new
D<@nullable String>()` from the
`D<@nullable String>` identifier alone, and
`PreservedAnnotationTreeVisitor` took the enclosing type from
`baseType.getEnclosingType()` — `D`'s statically-declared enclosing type
`C<X>`, with `X` unsubstituted.
Comparing `C<X>.D<@nullable String>` against `A<String>.B<@nullable
String>` surfaces no nullability
conflict, since `X` carries no annotation either way. #1699's
`withEnclosingTypeFromQualifier` types the
qualifier `c` instead, yielding `C<@nullable String>.D<@nullable
String>`; `D`'s supertype then
substitutes to `A<@nullable String>.B<@nullable String>` and the
mismatch against the declared
`A<String>.B<...>` becomes visible.
This PR adds a regression test so the behavior stays fixed. No
production code changes.
## Testing
- Added `innerClassInheritingEnclosingTypeArgs` in `GenericsTests.java`,
covering the reported error case
plus two negative controls: a correctly-typed `@Nullable` enclosing
instance, and a non-`@Nullable` one.
Both must stay silent, so the test also pins down that we don't
over-report here.
- Negative control on the assertion itself: temporarily changed the
erroring line's declared type to the
correct one and confirmed the test fails with `Did not see an error on
line 14 ... There were no errors`,
verifying the expectation is load-bearing and not incidentally
satisfied.
- Confirmed the test fails (reports nothing) at `56bd5ad2` and passes on
`master`.
- `./gradlew :nullaway:test` — 919 tests, 0 failures.
Fixes #1274
## AI usage disclosure
> I used Claude Code for this PR. It ran the issue's repro, bisected to
determine the false negative had
> already been fixed by my earlier PR #1699, explained the mechanism,
and drafted the regression test.
> I asked follow-up questions about the enclosing-type handling in
`getTreeType` and
> `PreservedAnnotationTreeVisitor`, and verified the test is
load-bearing by mutating it locally.
> I have read and understood all the changes in this PR.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Added regression coverage for generic type arguments inherited by
inner classes.
* Verified compatible nullable assignments and detection of incompatible
nullable-to-non-null assignments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->1 parent daa5828 commit 6bba0e5
1 file changed
Lines changed: 29 additions & 0 deletions
Lines changed: 29 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1679 | 1679 | | |
1680 | 1680 | | |
1681 | 1681 | | |
| 1682 | + | |
| 1683 | + | |
| 1684 | + | |
| 1685 | + | |
| 1686 | + | |
| 1687 | + | |
| 1688 | + | |
| 1689 | + | |
| 1690 | + | |
| 1691 | + | |
| 1692 | + | |
| 1693 | + | |
| 1694 | + | |
| 1695 | + | |
| 1696 | + | |
| 1697 | + | |
| 1698 | + | |
| 1699 | + | |
| 1700 | + | |
| 1701 | + | |
| 1702 | + | |
| 1703 | + | |
| 1704 | + | |
| 1705 | + | |
| 1706 | + | |
| 1707 | + | |
| 1708 | + | |
| 1709 | + | |
| 1710 | + | |
1682 | 1711 | | |
1683 | 1712 | | |
1684 | 1713 | | |
| |||
0 commit comments