From 17d740a3734e6a892124ee2d56c030d9d0ec9b6a Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 6 Nov 2018 15:57:55 +0100 Subject: [PATCH] Do not try computing return type in OverloadChecker Return type is not needed for checking overloads, but querying it may involve resolving function bodies, which usually happens after overload checking (see LazyTopDownAnalyzer.analyzeDeclarations) and at this point can lead to incorrect BACKING_FIELD_REQUIRED value being computed for some properties (see KT-27895) #KT-27895 Fixed --- .../kotlin/resolve/OverloadChecker.kt | 4 +++- .../bytecodeListing/annotations/kt27895.kt | 10 +++++++++ .../bytecodeListing/annotations/kt27895.txt | 21 +++++++++++++++++++ .../codegen/BytecodeListingTestGenerated.java | 5 +++++ .../jetbrains/kotlin/types/ErrorUtils.java | 18 +++++----------- .../idea/codeInliner/CodeToInlineBuilder.kt | 10 +++++++-- 6 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt create mode 100644 compiler/testData/codegen/bytecodeListing/annotations/kt27895.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadChecker.kt index eb0a4381d4f..d6671e13bdc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadChecker.kt @@ -55,7 +55,9 @@ class OverloadChecker(val specificityComparator: TypeSpecificityComparator) { // They can be disambiguated by providing explicit type parameters. if (a.typeParameters.isEmpty() != b.typeParameters.isEmpty()) return true - if (ErrorUtils.containsErrorType(a) || ErrorUtils.containsErrorType(b)) return true + if (a is FunctionDescriptor && ErrorUtils.containsErrorTypeInParameters(a) || + b is FunctionDescriptor && ErrorUtils.containsErrorTypeInParameters(b) + ) return true if (a.varargParameterPosition() != b.varargParameterPosition()) return true val aSignature = FlatSignature.createFromCallableDescriptor(a) diff --git a/compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt b/compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt new file mode 100644 index 00000000000..120785dc2f9 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt @@ -0,0 +1,10 @@ +@Target(AnnotationTarget.FIELD) +annotation class Anno + +data class C(val x: Int) { + @Anno + val json: String = "" + get() = field + + fun copy() = this.also { json } +} diff --git a/compiler/testData/codegen/bytecodeListing/annotations/kt27895.txt b/compiler/testData/codegen/bytecodeListing/annotations/kt27895.txt new file mode 100644 index 00000000000..6bf19f0e55c --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/kt27895.txt @@ -0,0 +1,21 @@ +@kotlin.annotation.Target +@java.lang.annotation.Retention +@java.lang.annotation.Target +@kotlin.Metadata +public annotation class Anno + +@kotlin.Metadata +public final class C { + private final @Anno @org.jetbrains.annotations.NotNull field json: java.lang.String + private final field x: int + public method (p0: int): void + public final method component1(): int + public synthetic static @org.jetbrains.annotations.NotNull method copy$default(p0: C, p1: int, p2: int, p3: java.lang.Object): C + public final @org.jetbrains.annotations.NotNull method copy(): C + public final @org.jetbrains.annotations.NotNull method copy(p0: int): C + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public final @org.jetbrains.annotations.NotNull method getJson(): java.lang.String + public final method getX(): int + public method hashCode(): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 33cee2fe318..f9f22ee0fe3 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -215,6 +215,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/annotations/JvmSynthetic.kt"); } + @TestMetadata("kt27895.kt") + public void testKt27895() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt"); + } + @TestMetadata("kt9320.kt") public void testKt9320() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/annotations/kt9320.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java index 2ac355fe2a9..61eddcc83b7 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java @@ -142,19 +142,11 @@ public class ErrorUtils { }; } - public static boolean containsErrorType(@NotNull CallableDescriptor callableDescriptor) { - if (callableDescriptor instanceof FunctionDescriptor) { - return containsErrorType((FunctionDescriptor) callableDescriptor); - } - else { - return containsErrorType(callableDescriptor.getReturnType()); - } - } - - public static boolean containsErrorType(@NotNull FunctionDescriptor function) { - if (containsErrorType(function.getReturnType())) { - return true; - } + /** + * @return true iff any of the types referenced in parameter types (including type parameters and extension receiver) of the function + * is an error type. Does not check the return type of the function. + */ + public static boolean containsErrorTypeInParameters(@NotNull FunctionDescriptor function) { ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter(); if (receiverParameter != null && containsErrorType(receiverParameter.getType())) { return true; diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt index 4c34881a5c9..b7e886a8f3b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt @@ -16,7 +16,10 @@ package org.jetbrains.kotlin.idea.codeInliner -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.core.asExpression @@ -90,7 +93,10 @@ class CodeToInlineBuilder( private fun getParametersForFunctionLiteral(functionLiteralExpression: KtLambdaExpression, context: BindingContext): String? { val lambdaDescriptor = context.get(BindingContext.FUNCTION, functionLiteralExpression.functionLiteral) - if (lambdaDescriptor == null || ErrorUtils.containsErrorType(lambdaDescriptor)) return null + if (lambdaDescriptor == null || + ErrorUtils.containsErrorTypeInParameters(lambdaDescriptor) || + ErrorUtils.containsErrorType(lambdaDescriptor.returnType) + ) return null return lambdaDescriptor.valueParameters.joinToString { it.name.render() + ": " + IdeDescriptorRenderers.SOURCE_CODE.renderType(it.type) }