diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java
index 9b95f7e2f28..bb94a0905f2 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java
@@ -349,6 +349,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
KtExpression receiver = ((KtQualifiedExpression) parent).getReceiverExpression();
return PsiTreeUtil.isAncestor(receiver, expression, false);
}
+ // in binary expression, left argument can be a receiver and right an argument
+ // in unary expression, left argument can be a receiver
+ if (parent instanceof KtBinaryExpression || parent instanceof KtUnaryExpression) {
+ return true;
+ }
return false;
}
diff --git a/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.kt b/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.kt
new file mode 100644
index 00000000000..766d7ffb719
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.kt
@@ -0,0 +1,30 @@
+// !DIAGNOSTICS: -UNUSED_PARAMETER
+
+interface Base
+
+class Impl1 : Base
+
+class Impl2 : Base
+
+operator fun Base.plus(arg: Base) = Impl1()
+
+operator fun Impl2.plus(arg: Base) = Impl2()
+
+operator fun Base.plus(arg: Impl2) = Impl2()
+
+operator fun Base.unaryMinus() = Impl1()
+
+operator fun Impl2.unaryMinus() = Impl2()
+
+// See also KT-10384: in non-error functions, as is necessary!
+fun add1(x: Impl2, y: Base): Impl1 = x as Base + y
+
+fun error1(x: Impl2, y: Base): Impl1 = x + y
+
+fun add2(x: Base, y: Impl2): Impl1 = x + y as Base
+
+fun error2(x: Base, y: Impl2): Impl1 = x + y
+
+fun minus3(x: Impl2): Impl1 = -(x as Base)
+
+fun error3(x: Impl2): Impl1 = -x
diff --git a/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.txt b/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.txt
new file mode 100644
index 00000000000..540eedf77fd
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.txt
@@ -0,0 +1,33 @@
+package
+
+public fun add1(/*0*/ x: Impl2, /*1*/ y: Base): Impl1
+public fun add2(/*0*/ x: Base, /*1*/ y: Impl2): Impl1
+public fun error1(/*0*/ x: Impl2, /*1*/ y: Base): Impl1
+public fun error2(/*0*/ x: Base, /*1*/ y: Impl2): Impl1
+public fun error3(/*0*/ x: Impl2): Impl1
+public fun minus3(/*0*/ x: Impl2): Impl1
+public operator fun Base.plus(/*0*/ arg: Base): Impl1
+public operator fun Base.plus(/*0*/ arg: Impl2): Impl2
+public operator fun Impl2.plus(/*0*/ arg: Base): Impl2
+public operator fun Base.unaryMinus(): Impl1
+public operator fun Impl2.unaryMinus(): Impl2
+
+public interface Base {
+ 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
+}
+
+public final class Impl1 : Base {
+ public constructor Impl1()
+ 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
+}
+
+public final class Impl2 : Base {
+ public constructor Impl2()
+ 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/testData/diagnostics/testsWithStdLib/cast/AsInsideIn.kt b/compiler/testData/diagnostics/testsWithStdLib/cast/AsInsideIn.kt
new file mode 100644
index 00000000000..83f41e31eec
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/cast/AsInsideIn.kt
@@ -0,0 +1,20 @@
+// See also KT-10386
+interface A
+class B : A
+fun foo1(list: List, arg: B?): Boolean {
+ // contains(T): Boolean is deprecated
+ return arg in list
+}
+fun foo2(list: List, arg: B?): Boolean {
+ // FAKE: no cast needed
+ return arg as A? in list
+}
+fun foo3(list: List, arg: B?): Boolean {
+ // No warning but KNPE risk
+ return arg!! in list
+}
+// But
+fun foo4(list: List, arg: B): Boolean {
+ // Ok
+ return arg in list
+}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/testsWithStdLib/cast/AsInsideIn.txt b/compiler/testData/diagnostics/testsWithStdLib/cast/AsInsideIn.txt
new file mode 100644
index 00000000000..40c95db45b7
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/cast/AsInsideIn.txt
@@ -0,0 +1,19 @@
+package
+
+public fun foo1(/*0*/ list: kotlin.List, /*1*/ arg: B?): kotlin.Boolean
+public fun foo2(/*0*/ list: kotlin.List, /*1*/ arg: B?): kotlin.Boolean
+public fun foo3(/*0*/ list: kotlin.List, /*1*/ arg: B?): kotlin.Boolean
+public fun foo4(/*0*/ list: kotlin.List, /*1*/ arg: B): kotlin.Boolean
+
+public interface A {
+ 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
+}
+
+public final class B : A {
+ public constructor B()
+ 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 bac1973e037..53174091738 100644
--- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java
@@ -2157,6 +2157,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
+ @TestMetadata("AsInBinaryUnary.kt")
+ public void testAsInBinaryUnary() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("constants.kt")
public void testConstants() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cast/constants.kt");
diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java
index ef57788e999..6ca79d2990a 100644
--- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java
@@ -568,6 +568,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/cast"), Pattern.compile("^(.+)\\.kt$"), true);
}
+ @TestMetadata("AsInsideIn.kt")
+ public void testAsInsideIn() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/cast/AsInsideIn.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("IsArray.kt")
public void testIsArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/cast/IsArray.kt");