From 38a719cb22a99d117fc1ce7985ff240a5d312a8c Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 24 Mar 2020 02:44:00 +0300 Subject: [PATCH] [NI] Fix trace manipulations for builder inference and ::-expressions For a class literal Type::class we are resolving Type as a constructor, getting all diagnostics (about missing arguments, for example) and then just not committing this trace with errors #KT-37626 Fixed --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../inference/CoroutineInferenceSession.kt | 29 +++++++++++-- .../kotlin/psi/KtDoubleColonExpression.kt | 5 ++- ...ExpressionsGenerationInBuilderInference.kt | 32 +++++++++++++++ ...bleColonExpressionToClassWithParameters.kt | 38 +++++++++++++++++ ...leColonExpressionToClassWithParameters.txt | 41 +++++++++++++++++++ .../DiagnosticsTestWithStdLibGenerated.java | 5 +++ ...ticsTestWithStdLibUsingJavacGenerated.java | 5 +++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ 13 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.txt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 2d873460aa9..e8e2cc5224f 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -6140,6 +6140,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines"); } + @TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt") + public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt"); + } + @TestMetadata("emptyClosure.kt") public void testEmptyClosure_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt index ab14a9c5522..59b10a6067f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt @@ -9,7 +9,13 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor +import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import org.jetbrains.kotlin.psi.KtDoubleColonExpression +import org.jetbrains.kotlin.psi.KtReferenceExpression +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.MissingSupertypesResolver import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver @@ -25,7 +31,10 @@ import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver -import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.StubType +import org.jetbrains.kotlin.types.TypeApproximator +import org.jetbrains.kotlin.types.TypeConstructor +import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.typeUtil.contains @@ -110,10 +119,24 @@ class CoroutineInferenceSession( } private fun skipCall(callInfo: SingleCallResolutionResult): Boolean { + val descriptor = callInfo.resultCallAtom.candidateDescriptor + // FakeCallableDescriptorForObject can't introduce new information for inference, // so it's safe to complete it fully - val descriptor = callInfo.resultCallAtom.candidateDescriptor - return descriptor is FakeCallableDescriptorForObject + if (descriptor is FakeCallableDescriptorForObject) return true + + // In this case temporary trace isn't committed during resolve of expressions like A::class, see resolveDoubleColonLHS + if (!DescriptorUtils.isObject(descriptor) && isInLHSOfDoubleColonExpression(callInfo)) return true + + return false + } + + private fun isInLHSOfDoubleColonExpression(callInfo: SingleCallResolutionResult): Boolean { + val callElement = callInfo.resultCallAtom.atom.psiKotlinCall.psiCall.callElement + val lhs = callElement.getParentOfType(strict = false)?.lhs + if (lhs !is KtReferenceExpression && lhs !is KtDotQualifiedExpression) return false + + return lhs.isAncestor(callElement) } override fun currentConstraintSystem(): ConstraintStorage { diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtDoubleColonExpression.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtDoubleColonExpression.kt index a3a4eede6a2..c9c3f96e930 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtDoubleColonExpression.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtDoubleColonExpression.kt @@ -38,13 +38,16 @@ abstract class KtDoubleColonExpression(node: ASTNode) : KtExpressionImpl(node) { val doubleColonTokenReference: PsiElement get() = findChildByType(KtTokens.COLONCOLON)!! + val lhs: PsiElement? + get() = doubleColonTokenReference.prevSibling + fun setReceiverExpression(newReceiverExpression: KtExpression) { val oldReceiverExpression = this.receiverExpression oldReceiverExpression?.replace(newReceiverExpression) ?: addBefore(newReceiverExpression, doubleColonTokenReference) } val isEmptyLHS: Boolean - get() = doubleColonTokenReference.prevSibling == null + get() = lhs == null override fun accept(visitor: KtVisitor, data: D): R { return visitor.visitDoubleColonExpression(this, data) diff --git a/compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt b/compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt new file mode 100644 index 00000000000..990eb0f100b --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt @@ -0,0 +1,32 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// IGNORE_BACKEND: JS, JS_IR +// WITH_RUNTIME +// KJS_WITH_FULL_RUNTIME + +package a.b + +class BatchInfo1(val batchSize: Int) +class BatchInfo2(val data: T) + +object Obj + +fun test() { + val a: Sequence = sequence { + val x = BatchInfo1::class + val y = a.b.BatchInfo1::class + val z = Obj::class + + val x1 = BatchInfo1::batchSize + val y1 = a.b.BatchInfo1::class + + yieldAll(listOf(x, y, z, x1, y1).map { it.toString() }) + } + + val size = a.toList().size + assert(size == 5) { "actual size: $size"} +} + +fun box(): String { + test() + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.kt new file mode 100644 index 00000000000..0521de6290a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.kt @@ -0,0 +1,38 @@ +// !USE_EXPERIMENTAL: kotlin.RequiresOptIn +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNUSED_EXPRESSION + +@file:OptIn(ExperimentalTypeInference::class) + +package a.b + +import kotlin.experimental.ExperimentalTypeInference + +class BatchInfo1(val batchSize: Int) +class BatchInfo2(val data: T) + +object Obj + +fun test1() { + val a: Sequence = sequence { + val x = BatchInfo1::class + val y = a.b.BatchInfo1::class + val z = Obj::class + + val x1 = BatchInfo1::batchSize + val y1 = a.b.BatchInfo1::class + } +} + +interface Scope { + fun yield(t: T) {} +} + +fun generate(@BuilderInference g: Scope.() -> Unit): S = TODO() + +val test2 = generate { + { yield("foo") }::class +} + +val test3 = generate { + ({ yield("foo") })::class +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.txt new file mode 100644 index 00000000000..7d0e993043d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.txt @@ -0,0 +1,41 @@ +package + +package a { + + package a.b { + public val test2: kotlin.String + public val test3: kotlin.String + public fun generate(/*0*/ @kotlin.BuilderInference g: a.b.Scope.() -> kotlin.Unit): S + public fun test1(): kotlin.Unit + + public final class BatchInfo1 { + public constructor BatchInfo1(/*0*/ batchSize: kotlin.Int) + public final val batchSize: kotlin.Int + 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 BatchInfo2 { + public constructor BatchInfo2(/*0*/ data: T) + public final val data: T + 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 Obj { + private constructor Obj() + 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 Scope { + 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 open fun yield(/*0*/ t: T): kotlin.Unit + } + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 17d6efbca6d..9d860625b65 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -1922,6 +1922,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/correctMember.kt"); } + @TestMetadata("doubleColonExpressionToClassWithParameters.kt") + public void testDoubleColonExpressionToClassWithParameters() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.kt"); + } + @TestMetadata("elvisOperatorAgainstFlexibleType.kt") public void testElvisOperatorAgainstFlexibleType() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/elvisOperatorAgainstFlexibleType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index a7f28ecb09d..749d2511aeb 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -1922,6 +1922,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/correctMember.kt"); } + @TestMetadata("doubleColonExpressionToClassWithParameters.kt") + public void testDoubleColonExpressionToClassWithParameters() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.kt"); + } + @TestMetadata("elvisOperatorAgainstFlexibleType.kt") public void testElvisOperatorAgainstFlexibleType() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/elvisOperatorAgainstFlexibleType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 8417ccde734..f031d8a9ec4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -6260,6 +6260,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines"); } + @TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt") + public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt"); + } + @TestMetadata("emptyClosure.kt") public void testEmptyClosure_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 84680c830c6..da624ed0516 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -6260,6 +6260,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines"); } + @TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt") + public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt"); + } + @TestMetadata("emptyClosure.kt") public void testEmptyClosure_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 0df28d658d9..29379a2f6ac 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -6140,6 +6140,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines"); } + @TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt") + public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt"); + } + @TestMetadata("emptyClosure.kt") public void testEmptyClosure_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index c4ed607700e..9201c3af6cb 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -5160,6 +5160,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines"); } + @TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt") + public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt"); + } + @TestMetadata("emptyClosure.kt") public void testEmptyClosure_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index c313e7a18d6..562a712515a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -5160,6 +5160,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines"); } + @TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt") + public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt"); + } + @TestMetadata("emptyClosure.kt") public void testEmptyClosure_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines");