Restrict type variable name fallback to subtype narrowing#37082
Open
junhyeong9812 wants to merge 1 commit into
Open
Restrict type variable name fallback to subtype narrowing#37082junhyeong9812 wants to merge 1 commit into
junhyeong9812 wants to merge 1 commit into
Conversation
The name-based fallback in resolveVariable(TypeVariable) matched type variables purely by name once the owner type was null, so for top-level declarations a variable could be resolved against an unrelated declaration that merely shares the same name. The identity-based match introduced in spring-projectsgh-36890 avoids this for nested types (their owner recursion returns before the fallback), but top-level types such as a controller implementing two generic interfaces with identically named type variables still resolved to the wrong argument. Guard the fallback so it only applies when the variable is declared by a class that the resolved type is assignable from, i.e. a genuine subtype narrowing a parameterized supertype (such as ArrayList narrowing List<String>). A name match against a sibling declaration or a method-level type variable is no longer accepted. See spring-projectsgh-36890 Signed-off-by: junhyeong9812 <pickjog@gmail.com>
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.
Overview
Follow-up to gh-36890. That fix resolves same-named type variables against the correct declaration for nested types, but the same scenario is still broken for top-level declarations, which is exactly the shape of the originally reported case (a REST controller implementing two generic interfaces).
Problem
ResolvableType.resolveVariable(TypeVariable)falls back to matching type variables purely by name when the parameterized type has no owner type:For a nested type the owner recursion returns before the fallback is reached, so gh-36890's regression test (which uses nested types) passes. But a top-level type has a
nullowner type and therefore still falls through to the name-only comparison, matching an unrelated declaration that merely shares a variable name.Given:
resolving
TopCreate'sIagainstTopControllerreturnsString(from the siblingTopSearch.I) instead ofLong. The identical structure nested inside a class resolves toLong, so nested and top-level diverge. The same name-only fallback also lets a class-level type argument leak into a shadowing method-level type variable.Fix
Guard the name fallback so it only applies to a genuine subtype narrowing a parameterized supertype (for example
ArrayListnarrowingList<String>), which is the one case where matching differently-declared variables by name is legitimate:A name match against a sibling declaration or a method-level type variable is no longer accepted.
Added three tests in
GenericTypeResolverTests: the top-level sibling-interface case, the method-level shadowing case, and a positive test confirming the legitimate subtype-narrowing path still resolves by name. The existingResolvableTypeTests.narrow()and gh-34386/gh-36890 tests continue to pass.