diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java index 4ce3e43ddd5..ca28fa19b5c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.KtElement; import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingTrace; +import org.jetbrains.kotlin.resolve.PropertyImportedFromObject; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.ResolvedCallUtilKt; import org.jetbrains.kotlin.types.KotlinType; @@ -98,7 +99,12 @@ public class PseudocodeUtil { ) { if (instruction instanceof AccessValueInstruction) { KtElement element = ((AccessValueInstruction) instruction).getElement(); - return element instanceof KtDeclaration ? null : extractVariableDescriptorIfAny(instruction, bindingContext); + if (element instanceof KtDeclaration) return null; + VariableDescriptor descriptor = extractVariableDescriptorIfAny(instruction, bindingContext); + if (descriptor instanceof PropertyImportedFromObject) { + return ((PropertyImportedFromObject) descriptor).getCallableFromObject(); + } + return descriptor; } return null; } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.kt new file mode 100644 index 00000000000..3ea55b08972 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.kt @@ -0,0 +1,35 @@ +// See KT-15566 + +import DefaultHttpClient.client + +interface HttpClient + +class HttpClientImpl : HttpClient + +// Below we should have initialization error for both (!) delegates + +object DefaultHttpClient : HttpClient by client { + val client = HttpClientImpl() +} + +object DefaultHttpClientWithGetter : HttpClient by client { + val client get() = HttpClientImpl() +} + +object DefaultHttpClientWithFun : HttpClient by fClient() { +} + +private fun fClient() = HttpClientImpl() + +private fun lazy(init: () -> T): kotlin.Lazy { + init() + null!! +} + +object DefaultHttpClientWithBy : HttpClient by client { + val client by lazy { HttpClientImpl() } +} + +object DefaultFqHttpClient : HttpClient by DefaultFqHttpClient.client { + val client = HttpClientImpl() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.txt new file mode 100644 index 00000000000..3a7cf50c0e1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.txt @@ -0,0 +1,56 @@ +package + +private fun fClient(): HttpClientImpl +private fun lazy(/*0*/ init: () -> T): [ERROR : kotlin.Lazy] + +public object DefaultFqHttpClient : HttpClient { + private constructor DefaultFqHttpClient() + public final val client: HttpClientImpl + 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 object DefaultHttpClient : HttpClient { + private constructor DefaultHttpClient() + public final val client: HttpClientImpl + 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 object DefaultHttpClientWithBy : HttpClient { + private constructor DefaultHttpClientWithBy() + public final val client: [ERROR : ] + 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 object DefaultHttpClientWithFun : HttpClient { + private constructor DefaultHttpClientWithFun() + 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 object DefaultHttpClientWithGetter : HttpClient { + private constructor DefaultHttpClientWithGetter() + public final val client: HttpClientImpl + 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 interface HttpClient { + 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 HttpClientImpl : HttpClient { + public constructor HttpClientImpl() + 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 fedd06ed3de..307fe79429c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -3748,6 +3748,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("fieldAsClassDelegate.kt") + public void testFieldAsClassDelegate() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.kt"); + doTest(fileName); + } + @TestMetadata("infiniteLoops.kt") public void testInfiniteLoops() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/infiniteLoops.kt");