diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt index f5523e29483..9646e101df9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -180,12 +180,25 @@ class GenericCandidateResolver( private fun getBinaryWithTypeParent(calleeExpression: KtExpression?): KtBinaryExpressionWithTypeRHS? { val callExpression = calleeExpression?.parent.safeAs() ?: return null - val parent = callExpression.parent - return when (parent) { - is KtBinaryExpressionWithTypeRHS -> parent - is KtQualifiedExpression -> parent.parent.safeAs().takeIf { parent.selectorExpression == callExpression } - else -> null + val possibleQualifiedExpression = callExpression.parent + + val targetExpression = if (possibleQualifiedExpression is KtQualifiedExpression) { + if (possibleQualifiedExpression.selectorExpression != callExpression) return null + possibleQualifiedExpression } + else { + callExpression + } + + return targetExpression.topParenthesizedParentOrMe().parent.safeAs() + } + + private fun KtExpression.topParenthesizedParentOrMe(): KtExpression { + var result: KtExpression = this + while (KtPsiUtil.deparenthesizeOnce(result.parent.safeAs()) == result) { + result = result.parent.safeAs() ?: break + } + return result } private fun addValidityConstraintsForConstituentTypes(builder: ConstraintSystem.Builder, type: KotlinType) { diff --git a/compiler/testData/diagnostics/tests/inference/expectedTypeFromCastParenthesized.kt b/compiler/testData/diagnostics/tests/inference/expectedTypeFromCastParenthesized.kt new file mode 100644 index 00000000000..fe50339913c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/expectedTypeFromCastParenthesized.kt @@ -0,0 +1,21 @@ +// !LANGUAGE: +ExpectedTypeFromCast + +@Target(AnnotationTarget.EXPRESSION) +annotation class bar + +fun foo(): T = TODO() + +fun id(value: V) = value + +val par1 = (foo()) as String +val par2 = ((foo())) as String + +val par3 = (dd@ (foo())) as String + +val par4 = ( @bar() (foo())) as String + +object X { + fun foo(): T = TODO() +} + +val par5 = ( @bar() X.foo()) as String \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/expectedTypeFromCastParenthesized.txt b/compiler/testData/diagnostics/tests/inference/expectedTypeFromCastParenthesized.txt new file mode 100644 index 00000000000..9965fa808ce --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/expectedTypeFromCastParenthesized.txt @@ -0,0 +1,24 @@ +package + +public val par1: kotlin.String +public val par2: kotlin.String +public val par3: kotlin.String +public val par4: kotlin.String +public val par5: kotlin.String +public fun foo(): T +public fun id(/*0*/ value: V): V + +public object X { + private constructor X() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(): T + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.EXPRESSION}) public final annotation class bar : kotlin.Annotation { + public constructor bar() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index ade99189a63..67d0e9cbca2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10240,6 +10240,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("expectedTypeFromCastParenthesized.kt") + public void testExpectedTypeFromCastParenthesized() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/expectedTypeFromCastParenthesized.kt"); + doTest(fileName); + } + @TestMetadata("expectedTypeWithGenerics.kt") public void testExpectedTypeWithGenerics() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index cf26eb2294e..7be96c12339 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10240,6 +10240,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("expectedTypeFromCastParenthesized.kt") + public void testExpectedTypeFromCastParenthesized() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/expectedTypeFromCastParenthesized.kt"); + doTest(fileName); + } + @TestMetadata("expectedTypeWithGenerics.kt") public void testExpectedTypeWithGenerics() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");