Skip to content

Conversation

@jsjeon
Copy link
Contributor

@jsjeon jsjeon commented Jan 6, 2026

PsiNewExpression#multiResolve uses super type's implementation of
multiResolve---PsiPolyVariantCachingReference---by treating itself as
a fake reference to a constructor. That super implementation may return
ResolveResult[], including ResolveResult.EMPTY_ARRAY (if not resolved
for some reason, like Lint CLI w/ different JDK, etc.), and the current
direct cast to JavaResolveResult[] raised the class cast exception.

A reproduction, however, failed in ToT Java UAST with a different error:
recursive resolution attempts while resolving the lambda expression used
in the constructor. The type of the lambda's parameter depends on the
chosen method overload, but choosing the correct overload depends on the
lambda's type, hence recursion. We can break the cycle by adding a guard
to the process of resolving lambda parameter type.

^IDEA-383770 fixed

…tructor

PsiNewExpression#multiResolve uses super type's implementation of
multiResolve---PsiPolyVariantCachingReference---by treating itself as
a fake reference to a constructor. That super implementation may return
ResolveResult[], including ResolveResult.EMPTY_ARRAY (if not resolved
for some reason, like Lint CLI w/ different JDK, etc.), and the current
direct cast to JavaResolveResult[] raised the class cast exception.

A reproduction, however, failed in ToT Java UAST with a different error:
recursive resolution attempts while resolving the lambda expression used
in the constructor. The type of the lambda's parameter depends on the
chosen method overload, but choosing the correct overload depends on the
lambda's type, hence recursion. We can break the cycle by adding a guard
to the process of resolving lambda parameter type.

^IDEA-383770 fixed
@jsjeon
Copy link
Contributor Author

jsjeon commented Jan 6, 2026

cc @BartvHelvert @amaembo

public JavaResolveResult @NotNull [] multiResolve(boolean incompleteCode) {
return (JavaResolveResult[])getConstructorFakeReference().multiResolve(incompleteCode);
ResolveResult[] results = getConstructorFakeReference().multiResolve(incompleteCode);
return results instanceof JavaResolveResult[] ? (JavaResolveResult[])results : JavaResolveResult.EMPTY_ARRAY;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that we will silently replace non-empty ResolveResult[] array with an empty array. If there's a bug and non-JavaResolveResult appears, we should report it. I'll modify this code to:

    ResolveResult[] results = getConstructorFakeReference().multiResolve(incompleteCode);
    if (results instanceof JavaResolveResult[]) return (JavaResolveResult[])results;
    return ContainerUtil.map2Array(results, JavaResolveResult.EMPTY_ARRAY, result -> (JavaResolveResult)result);

@amaembo
Copy link
Contributor

amaembo commented Jan 9, 2026

Merged: 3e87a8c

@amaembo amaembo closed this Jan 9, 2026
@jsjeon jsjeon deleted the prr/jsjeon/idea-383770 branch January 9, 2026 17:26
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.

2 participants