diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/resolvedCallUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/resolvedCallUtil.kt index e944e95d6f7..44b993cdbe5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/resolvedCallUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/resolvedCallUtil.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.descriptorUtil.getOwnerForEffectiveDispatchReceiverParameter +import org.jetbrains.kotlin.resolve.scopes.receivers.ClassValueReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue @@ -50,6 +51,9 @@ fun ResolvedCall<*>.hasThisOrNoDispatchReceiver( // foo() -- implicit receiver dispatchReceiverDescriptor = dispatchReceiverValue.declarationDescriptor } + else if (dispatchReceiverValue is ClassValueReceiver) { + dispatchReceiverDescriptor = dispatchReceiverValue.classQualifier.descriptor + } else if (dispatchReceiverValue is ExpressionReceiver) { val expression = KtPsiUtil.deparenthesize(dispatchReceiverValue.expression) if (expression is KtThisExpression) { diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/constructorPropertyInterdependence.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/constructorPropertyInterdependence.kt new file mode 100644 index 00000000000..db02e103fe9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/constructorPropertyInterdependence.kt @@ -0,0 +1,8 @@ +// See KT-12809 +open class A(val a: Any) { + override fun toString() = a.toString() +} + +object B : A(B.foo) { // call B.foo should be not-allowed + val foo = 4 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/constructorPropertyInterdependence.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/constructorPropertyInterdependence.txt new file mode 100644 index 00000000000..011af355d20 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/constructorPropertyInterdependence.txt @@ -0,0 +1,18 @@ +package + +public open class A { + public constructor A(/*0*/ a: kotlin.Any) + public final val a: kotlin.Any + 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*/ fun toString(): kotlin.String +} + +public object B : A { + private constructor B() + public final override /*1*/ /*fake_override*/ val a: kotlin.Any + public final val foo: kotlin.Int = 4 + 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/tests/controlFlowAnalysis/enumInterdependence.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/enumInterdependence.kt index bfee3d40374..402b298ae9c 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/enumInterdependence.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/enumInterdependence.kt @@ -29,7 +29,7 @@ enum class D(val x: Int) { } enum class E(val v: Int) { - E1(Nested.COPY); + E1(Nested.COPY); object Nested { val COPY = E1.v diff --git a/compiler/testData/diagnostics/tests/tailRecursionComplex.kt b/compiler/testData/diagnostics/tests/tailRecursionComplex.kt new file mode 100644 index 00000000000..9569b51651c --- /dev/null +++ b/compiler/testData/diagnostics/tests/tailRecursionComplex.kt @@ -0,0 +1,16 @@ +object O { + // This is correct, foo is the same + tailrec fun foo(i: Int): Int = if (i < 0) 0 else O.foo(i - 1) +} + +class A { + tailrec fun foo(i: Int) = if (i < 0) 0 else A.foo(i - 1) + + companion object { + fun foo(i: Int) = 42 + i + } +} + +class B { + tailrec fun foo(i: Int) = if (i < 0) 0 else O.foo(i - 1) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/tailRecursionComplex.txt b/compiler/testData/diagnostics/tests/tailRecursionComplex.txt new file mode 100644 index 00000000000..c0f6f450655 --- /dev/null +++ b/compiler/testData/diagnostics/tests/tailRecursionComplex.txt @@ -0,0 +1,33 @@ +package + +public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final tailrec fun foo(/*0*/ i: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public companion object Companion { + private constructor Companion() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(/*0*/ i: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public final class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final tailrec fun foo(/*0*/ i: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object O { + private constructor O() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final tailrec fun foo(/*0*/ i: kotlin.Int): kotlin.Int + 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 2ccf89542c7..b76ae7cf147 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -685,6 +685,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("tailRecursionComplex.kt") + public void testTailRecursionComplex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/tailRecursionComplex.kt"); + doTest(fileName); + } + @TestMetadata("TraitOverrideObjectMethods.kt") public void testTraitOverrideObjectMethods() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/TraitOverrideObjectMethods.kt"); @@ -3252,6 +3258,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("constructorPropertyInterdependence.kt") + public void testConstructorPropertyInterdependence() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/constructorPropertyInterdependence.kt"); + doTest(fileName); + } + @TestMetadata("definiteReturnInWhen.kt") public void testDefiniteReturnInWhen() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt");