From ab506c1579baa65dbce74f08231e1af50d19fabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Thu, 31 Oct 2019 13:11:48 +0100 Subject: [PATCH] Frontend: Avoid retypechecking the right hand side of assignment operators --- .../kotlin/fir/FirDiagnosticsSmokeTestGenerated.java | 5 +++++ .../ExpressionTypingVisitorForStatements.java | 9 ++++++++- .../tests/inference/genericAssignmentOperator.kt | 9 +++++++++ .../tests/inference/genericAssignmentOperator.txt | 12 ++++++++++++ .../kotlin/checkers/DiagnosticsTestGenerated.java | 5 +++++ .../javac/DiagnosticsUsingJavacTestGenerated.java | 5 +++++ 6 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.kt create mode 100644 compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.txt diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index 12f79a0f339..141bed3fdfc 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -9763,6 +9763,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/inference/functionPlaceholderError.kt"); } + @TestMetadata("genericAssignmentOperator.kt") + public void testGenericAssignmentOperator() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.kt"); + } + @TestMetadata("hasErrorInConstrainingTypes.kt") public void testHasErrorInConstrainingTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/hasErrorInConstrainingTypes.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java index 76f4cce3d03..891bdd51472 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java @@ -29,7 +29,9 @@ import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContextUtils; import org.jetbrains.kotlin.resolve.TemporaryBindingTrace; +import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver; import org.jetbrains.kotlin.resolve.calls.context.CallPosition; +import org.jetbrains.kotlin.resolve.calls.context.ContextDependency; import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults; @@ -37,7 +39,6 @@ import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl; import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue; -import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory; import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil; import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope; import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; @@ -213,6 +214,12 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito context.trace.report(UNRESOLVED_REFERENCE.on(operationSign, operationSign)); temporary.commit(); return rightInfo.clearType(); + } else if (ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(right, context) == null && + ArgumentTypeResolver.getCallableReferenceExpressionIfAny(right, context) == null) { + // Cache the type info for the right hand side so that we don't evaluate it twice if there is no valid plusAssign. + // We skip over function literals and references, since ArgumentTypeResolver will only resolve the shape of the + // function type before attempting to resolve the call. + facade.getTypeInfo(right, context.replaceContextDependency(ContextDependency.DEPENDENT)); } ExpressionReceiver receiver = ExpressionReceiver.Companion.create(left, leftType, context.trace.getBindingContext()); diff --git a/compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.kt b/compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.kt new file mode 100644 index 00000000000..dc8a1ddf655 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.kt @@ -0,0 +1,9 @@ +class R + +fun f(): R = R() + +operator fun Int.plusAssign(y: R) {} + +fun box() { + 1 += f() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.txt b/compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.txt new file mode 100644 index 00000000000..87c12a3f5e5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.txt @@ -0,0 +1,12 @@ +package + +public fun box(): kotlin.Unit +public fun f(): R +public operator fun kotlin.Int.plusAssign(/*0*/ y: R): kotlin.Unit + +public final class R { + public constructor R() + 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 c6eacd1f618..1627acc3038 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -9770,6 +9770,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/functionPlaceholderError.kt"); } + @TestMetadata("genericAssignmentOperator.kt") + public void testGenericAssignmentOperator() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.kt"); + } + @TestMetadata("hasErrorInConstrainingTypes.kt") public void testHasErrorInConstrainingTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/hasErrorInConstrainingTypes.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 73c1c692e44..a784f0cc0f2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -9765,6 +9765,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/functionPlaceholderError.kt"); } + @TestMetadata("genericAssignmentOperator.kt") + public void testGenericAssignmentOperator() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/genericAssignmentOperator.kt"); + } + @TestMetadata("hasErrorInConstrainingTypes.kt") public void testHasErrorInConstrainingTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/hasErrorInConstrainingTypes.kt");