Repository navigation
Conversation
JavaTypeInternalNameVisitor mapped every `out X` wildcard to java/lang/Object, so values typed `out Parent` were checkcast to Object and calling Parent's methods on them failed bytecode verification. JavaTypeDescriptorVisitor recursed into itself instead of the bound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A raw class reference (e.g. a `GenClass` parameter) was translated by looking up the class's own type variables in the current context, which only works when the class refers to itself. From anywhere else this threw "Could not find type variable T". Raw types are now erased the way Java does it: each type argument becomes `out <erasure of its first bound>`, so a raw `Something<T extends Parent>` exposes Parent's members. As in JavaRuntimeClass.translateTypeParameters, the type variables are put into a child TypeVariableContext before their bounds are resolved, so a bound leading back to the class being loaded (e.g. `T extends Node<T>`) is detected and becomes Object. Fixes RawTypeInHeaderTest; adds RawBoundedTypeInHeaderTest and RawRecursiveBoundTypeInHeaderTest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kindlich
force-pushed
the
fix/raw-types-in-headers
branch
from
October 18, 2026 12:36
86b7e35 to
e303d2e
Compare
kindlich
marked this pull request as ready for review
October 18, 2026 12:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GenClassparameter used to crash withCould not find type variable T. The converter looked up the class's own type variables, which are only in scope when the class refers to itself. Raw types are now erased the way Java does it: each type argument becomesout <erasure of its first bound>. So a rawSomething<T extends Parent>exposesParent's members, and an unboundedTbecomesout Object. Bounds that lead back to the class being loaded (e.g.T extends Node<T>) becomeObject. LikeJavaRuntimeClass.translateTypeParameters, this uses theTypeVariableContextas the guard: the type variables are put into a child context before their bounds are resolved.JavaTypeInternalNameVisitormapped everyout Xwildcard tojava/lang/Object, so values typedout Parentwere checkcast toObject, and callingParentmethods on them failed bytecode verification (VerifyError). This also affected explicit? extends Parentparameters, not just raw types.JavaTypeDescriptorVisitor.visitWildcardOutalso called itself instead of the bound. Both now use the upper bound. Both fixes are needed for bounded raw types to work end-to-end, so they're in one PR.Testing
RawTypeInHeaderTest.testRawTypeErrors1/2(added in e0851bc as a known failure) now pass.RawBoundedTypeInHeaderTestcovers a raw bounded parameter acceptingBoundedGenClass<Child>and a raw bounded return type exposing the bound's members at runtime.RawRecursiveBoundTypeInHeaderTestround-trips a raw self-bounded type. It's a separate class so that a failure points only at the recursion guard. Mutation-checked: with the guard disabled, only this test fails../gradlew test --rerun-tasks: 1,043 tests, 0 failures.Limitation: only the first bound is used, so
T extends A & Bbecomesout A, matching Java's erasure.Stacked on #190 (which is stacked on #191).
🤖 Generated with Claude Code