Skip to content

Don't bound a fresh capture type variable by unresolved inference variables - #8299

Merged
smillst merged 1 commit into
typetools:masterfrom
smillst:issue8298
Oct 1, 2026
Merged

smillst merged 1 commit into
typetools:masterfrom
smillst:issue8298

Conversation

@smillst

@smillst smillst commented Sep 29, 2026

Copy link
Copy Markdown
Member

Fixes #8298.

When Resolution.resolveWithCapture instantiates a variable with a fresh type variable, it used the glb of all of the variable's upper bounds. For takeExtends(wildcardBox(box)), the capture variable γ for the return type Box<? extends T> has upper bounds U (via T) and α, the inference variable for takeExtends's X, from γ <: α. α depends on the resolution of γ, so it is still unresolved, and the fresh type variable was bounded by α instead of U. Incorporation then needed α <: U, which was false: a type.arguments.not.inferred error, or a crash when U is F-bounded or the argument is Box<String>.

javac records γ <: α only as a lower bound of α, so the capture's bounds are all proper when it is resolved. Now the fresh type variable's upper bound uses only the upper bounds whose inference variables are all being resolved together with it. Bounds that mention those variables are still needed, since the substitution replaces them. The omitted bounds stay in the bound set and are checked during incorporation.

…iables

Fixes typetools#8298.

When `Resolution.resolveWithCapture` instantiates a variable with a fresh
type variable, it used the glb of all of the variable's upper bounds.  For
`takeExtends(wildcardBox(box))`, the capture variable `γ` for the return type
`Box<? extends T>` has upper bounds `U` (via `T`) and `α`, the inference
variable for `takeExtends`'s `X`, from `γ <: α`.  `α` depends on the
resolution of `γ`, so it is still unresolved, and the fresh type variable was
bounded by `α` instead of `U`.  Incorporation then needed `α <: U`, which was
false: a `type.arguments.not.inferred` error, or a crash when `U` is
F-bounded or the argument is `Box<String>`.

javac records `γ <: α` only as a lower bound of `α`, so the capture's bounds
are all proper when it is resolved.  Now the fresh type variable's upper bound
uses only the upper bounds whose inference variables are all being resolved
together with it.  Bounds that mention those variables are still needed, since
the substitution replaces them.  The omitted bounds stay in the bound set and
are checked during incorporation.
@smillst smillst self-assigned this Sep 29, 2026
@coderabbitai

coderabbitai Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: typetools/checker-framework/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: f8fbac9e-dd85-48fd-a53a-1dc3952822ea

📥 Commits

Reviewing files that changed from the base of the PR and between 9139362 and 8d16e31.

📒 Files selected for processing (3)
  • checker/tests/nullness/Issue8298Nullness.java
  • framework/src/main/java/org/checkerframework/framework/util/typeinference8/util/Resolution.java
  • framework/tests/all-systems/Issue8298.java

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The capture-based type-inference resolver now filters upper bounds whose inference variables are not all among the variables being resolved before computing a greatest lower bound. Regression tests cover unconstrained, F-bounded, String, and List<String> cases, as well as nullness behavior and expected diagnostics.

Fixed issue severity: <fixed_issue_severity>Low</fixed_issue_severity>

Priority: ➖ Normal

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 8d16e

This fixes a type-inference crash involving wildcard capture. No concrete merge-blocking risk was found, and regression tests were added for the reported scenarios.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 8d16e

The change affects a shared type-inference rule, but the inspected code keeps excluded bounds for later checking and does not introduce a new public entrypoint. No security issue was established. Some downstream coverage remains incomplete.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The plausible security-relevant reach is through existing consumers of framework type-inference results, not through a newly exposed service or privileged sink. The reported high fanout belongs to a regression-test range and does not establish production fanout.

Resilience and Maintainability Implications

  • observed — The original upper bounds remain available for later incorporation, limiting the risk that the filter silently deletes a constraint. This establishes the local state transition, not the correctness of every possible inference case.
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation addresses #8298 in Resolution.resolveWithCapture by excluding upper bounds that mention inference variables outside the variables resolved together. This prevents a fresh capture …
Out of Scope Changes check ✅ Passed The changes are limited to the capture-resolution fix and regression tests for #8298. The all-systems and nullness tests exercise the affected inference behavior and annotation results. No unrelated p…
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@smillst smillst assigned mernst and unassigned smillst Sep 30, 2026
@smillst
smillst merged commit 3c6e930 into typetools:master Oct 1, 2026
27 checks passed
@smillst
smillst deleted the issue8298 branch October 1, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash on capture of wildcard return type

2 participants