From b25a67a50ecf7836c68d2c5e5dc0c4d8f5746e80 Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Fri, 11 Aug 2023 14:56:02 +0300 Subject: [PATCH] [FIR] Prohibit statement-like expressions in expression context ^KT-61067 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 6 +++ ...sticCompilerFE10TestDataTestGenerated.java | 6 +++ ...eeOldFrontendDiagnosticsTestGenerated.java | 6 +++ ...siOldFrontendDiagnosticsTestGenerated.java | 6 +++ .../LightTreeRawFirDeclarationBuilder.kt | 4 +- .../LightTreeRawFirExpressionBuilder.kt | 53 +++++++++++++++---- .../kotlin/fir/builder/PsiRawFirBuilder.kt | 44 ++++++++------- .../kotlin/fir/builder/ConversionUtils.kt | 9 ++++ .../kotlin/fir/resolve/ResolveUtils.kt | 9 +--- .../src/org/jetbrains/kotlin/fir/Utils.kt | 19 +++++++ .../tests/assigningAssignments.fir.kt | 12 +++++ .../diagnostics/tests/assigningAssignments.kt | 12 +++++ .../ParenthesizedVariable.fir.kt | 2 +- .../NameDeprecation.fir.kt | 8 +-- .../tests/regressions/kt629.fir.kt | 23 -------- .../diagnostics/tests/regressions/kt629.kt | 1 + .../deprecatedSyntaxInConditions_after.fir.kt | 24 ++++----- ...deprecatedSyntaxInConditions_before.fir.kt | 24 ++++----- .../test/runners/DiagnosticTestGenerated.java | 6 +++ 19 files changed, 183 insertions(+), 91 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/assigningAssignments.fir.kt create mode 100644 compiler/testData/diagnostics/tests/assigningAssignments.kt delete mode 100644 compiler/testData/diagnostics/tests/regressions/kt629.fir.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 217e996040f..3653922cf1f 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -93,6 +93,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/AssignToArrayElement.kt"); } + @Test + @TestMetadata("assigningAssignments.kt") + public void testAssigningAssignments() throws Exception { + runTest("compiler/testData/diagnostics/tests/assigningAssignments.kt"); + } + @Test @TestMetadata("AutoCreatedIt.kt") public void testAutoCreatedIt() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 1f01fb687a4..84afc5eea62 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -93,6 +93,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/AssignToArrayElement.kt"); } + @Test + @TestMetadata("assigningAssignments.kt") + public void testAssigningAssignments() throws Exception { + runTest("compiler/testData/diagnostics/tests/assigningAssignments.kt"); + } + @Test @TestMetadata("AutoCreatedIt.kt") public void testAutoCreatedIt() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 3f67771313d..9a8bc0977ae 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -93,6 +93,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/AssignToArrayElement.kt"); } + @Test + @TestMetadata("assigningAssignments.kt") + public void testAssigningAssignments() throws Exception { + runTest("compiler/testData/diagnostics/tests/assigningAssignments.kt"); + } + @Test @TestMetadata("AutoCreatedIt.kt") public void testAutoCreatedIt() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index e1fab79970c..4b07b108fc8 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -93,6 +93,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/AssignToArrayElement.kt"); } + @Test + @TestMetadata("assigningAssignments.kt") + public void testAssigningAssignments() throws Exception { + runTest("compiler/testData/diagnostics/tests/assigningAssignments.kt"); + } + @Test @TestMetadata("AutoCreatedIt.kt") public void testAutoCreatedIt() throws Exception { diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt index 40486c3b5cc..79d0d1e4e78 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt @@ -143,7 +143,7 @@ class LightTreeRawFirDeclarationBuilder( DESTRUCTURING_DECLARATION -> container += convertDestructingDeclaration(node).toFirDestructingDeclaration(baseModuleData) TYPEALIAS -> container += convertTypeAlias(node) as FirStatement CLASS_INITIALIZER -> container += convertAnonymousInitializer(node) as FirStatement - else -> if (node.isExpression()) container += expressionConverter.getAsFirExpression(node) + else -> if (node.isExpression()) container += expressionConverter.getAsFirStatement(node) } } return FirBlockBuilder().apply { @@ -1839,7 +1839,7 @@ class LightTreeRawFirDeclarationBuilder( if (block == null) return buildEmptyExpressionBlock() if (block.tokenType != BLOCK) { return FirSingleExpressionBlock( - expressionConverter.getAsFirExpression(block) + expressionConverter.getAsFirStatement(block) ) } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt index ab7617b5e21..f62c31a7110 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt @@ -60,15 +60,41 @@ class LightTreeRawFirExpressionBuilder( context: Context = Context(), ) : AbstractLightTreeRawFirBuilder(session, tree, context) { - inline fun getAsFirExpression(expression: LighterASTNode?, errorReason: String = ""): R { + inline fun getAsFirExpression( + expression: LighterASTNode?, + errorReason: String = "", + sourceWhenInvalidExpression: LighterASTNode? = expression, + isValidExpression: (R) -> Boolean = { !it.isStatementLikeExpression }, + ): R { val converted = expression?.let { convertExpression(it, errorReason) } - return converted as? R - ?: buildErrorExpression( - expression?.toFirSourceElement(), + + return when { + converted is R -> when { + isValidExpression(converted) -> converted + else -> buildErrorExpression( + sourceWhenInvalidExpression?.toFirSourceElement(), + ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionExpected), + converted, + ) + } + else -> buildErrorExpression( + converted?.source?.withForcedKindFrom(context) ?: expression?.toFirSourceElement(), if (expression == null) ConeSyntaxDiagnostic(errorReason) else ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionExpected), converted, - ) as R + ) + } as R + } + + fun getAsFirStatement(expression: LighterASTNode, errorReason: String = ""): FirStatement { + return when (val converted = convertExpression(expression, errorReason)) { + is FirStatement -> converted + else -> buildErrorExpression( + expression.toFirSourceElement(), + ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionExpected), + converted, + ) + } } /***** EXPRESSIONS *****/ @@ -316,7 +342,14 @@ class LightTreeRawFirExpressionBuilder( firOperation, leftArgAsFir.annotations, rightArg, - ) { getAsFirExpression(this) } + ) { + getAsFirExpression( + this, + "Incorrect expression in assignment: ${binaryExpression.asText}", + sourceWhenInvalidExpression = binaryExpression, + isValidExpression = { !it.isStatementLikeExpression || it.isArraySet }, + ) + } } else { buildEqualityOperatorCall { source = binaryExpression.toFirSourceElement() @@ -379,7 +412,7 @@ class LightTreeRawFirExpressionBuilder( } BLOCK -> firExpression = declarationBuilder.convertBlock(it) PROPERTY -> firExpression = declarationBuilder.convertPropertyDeclaration(it) - else -> if (it.isExpression()) firExpression = getAsFirExpression(it) + else -> if (it.isExpression()) firExpression = getAsFirStatement(it) } } @@ -457,7 +490,7 @@ class LightTreeRawFirExpressionBuilder( BLOCK -> firExpression = declarationBuilder.convertBlockExpression(it) else -> if (it.isExpression()) { context.forwardLabelUsagePermission(annotatedExpression, it) - firExpression = getAsFirExpression(it) + firExpression = getAsFirStatement(it) } } } @@ -1209,10 +1242,10 @@ class LightTreeRawFirExpressionBuilder( if (it.getChildNodeByType(BLOCK) != null) { firBlock = getAsFirExpression(it) } else { - firStatement = getAsFirExpression(it) + firStatement = getAsFirStatement(it) } } - else -> if (it.isExpression()) firStatement = getAsFirExpression(it) + else -> if (it.isExpression()) firStatement = getAsFirStatement(it) } } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt index a7324dffbfd..0bac56305e3 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt @@ -47,10 +47,7 @@ import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -import org.jetbrains.kotlin.utils.addToStdlib.runIf -import org.jetbrains.kotlin.utils.addToStdlib.runUnless -import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled +import org.jetbrains.kotlin.utils.addToStdlib.* import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment import org.jetbrains.kotlin.utils.exceptions.withPsiEntry @@ -297,28 +294,33 @@ open class PsiRawFirBuilder( ): FirExpression = toFirExpression { ConeSimpleDiagnostic(errorReason, kind) } private inline fun KtElement?.toFirExpression( - sourceWhenThisIsNull: PsiElement? = null, + sourceWhenThisIsNull: KtElement? = null, + sourceWhenInvalidExpression: KtElement? = this, + isValidExpression: (FirExpression) -> Boolean = { !it.isStatementLikeExpression }, diagnosticFn: () -> ConeDiagnostic, ): FirExpression { if (this == null) { return buildErrorExpression(source = sourceWhenThisIsNull?.toFirSourceElement(), diagnosticFn()) } - val result = when (val fir = convertElement(this, null)) { - is FirExpression -> fir - else -> { - return buildErrorExpression { + return when (val fir = convertElement(this, null)) { + is FirExpression -> when { + isValidExpression(fir) -> checkSelectorInvariant(fir) + else -> buildErrorExpression { nonExpressionElement = fir diagnostic = diagnosticFn() - source = toFirSourceElement() + source = sourceWhenInvalidExpression?.toFirSourceElement() } } + else -> buildErrorExpression { + nonExpressionElement = fir + diagnostic = diagnosticFn() + source = fir?.source?.withForcedKindFrom(this@PsiRawFirBuilder.context) ?: toFirSourceElement() + } } - - return toFirExpression(result) } - private fun KtElement.toFirExpression(result: FirExpression): FirExpression { + private fun KtElement.checkSelectorInvariant(result: FirExpression): FirExpression { val callExpressionCallee = (this as? KtCallExpression)?.calleeExpression?.unwrapParenthesesLabelsAndAnnotations() if (this is KtNameReferenceExpression || @@ -2700,7 +2702,15 @@ open class PsiRawFirBuilder( leftArgument.annotations, expression.right, ) { - (this as KtExpression).toFirExpression("Incorrect expression in assignment: ${expression.text}") + (this as KtExpression).toFirExpression( + sourceWhenInvalidExpression = expression, + isValidExpression = { !it.isStatementLikeExpression || it.isArraySet }, + ) { + ConeSimpleDiagnostic( + "Incorrect expression in assignment: ${expression.text}", + DiagnosticKind.ExpressionExpected + ) + } } } else { buildEqualityOperatorCall { @@ -2926,11 +2936,7 @@ open class PsiRawFirBuilder( override fun visitParenthesizedExpression(expression: KtParenthesizedExpression, data: FirElement?): FirElement { context.forwardLabelUsagePermission(expression, expression.expression) - return expression.expression?.accept(this, data) - ?: buildErrorExpression( - expression.toFirSourceElement(), - ConeSyntaxDiagnostic("Empty parentheses") - ) + return expression.expression.toFirExpression("Empty parentheses") } override fun visitLabeledExpression(expression: KtLabeledExpression, data: FirElement?): FirElement { diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 1c4754a7739..bc741cb9de4 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -51,6 +51,7 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.realElement import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.expressions.OperatorConventions @@ -696,3 +697,11 @@ fun AnnotationUseSiteTarget?.appliesToPrimaryConstructorParameter() = this == nu this == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER || this == AnnotationUseSiteTarget.RECEIVER || this == AnnotationUseSiteTarget.FILE + +fun KtSourceElement.withForcedKindFrom(context: Context<*>): KtSourceElement { + return when (val forcedKind = context.forcedElementSourceKind) { + kind -> this + is KtFakeSourceElementKind -> fakeElement(forcedKind) + else -> this.realElement() + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index eb9f25acecb..c260091edf4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -47,7 +47,6 @@ import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.types.SmartcastStability import org.jetbrains.kotlin.types.model.safeSubstitute -import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import kotlin.contracts.ExperimentalContracts @@ -490,7 +489,7 @@ fun FirSafeCallExpression.propagateTypeFromQualifiedAccessAfterNullCheck( val selector = selector val resultingType = when { - selector is FirExpression && !selector.isCallToStatementLikeFunction -> { + selector is FirExpression && !selector.isStatementLikeExpression -> { val type = selector.coneTypeSafe() ?: return type.withNullability(ConeNullability.NULLABLE, session.typeContext) } @@ -506,12 +505,6 @@ fun FirSafeCallExpression.propagateTypeFromQualifiedAccessAfterNullCheck( session.lookupTracker?.recordTypeResolveAsLookup(independentInstance, source, file.source) } -private val FirExpression.isCallToStatementLikeFunction: Boolean - get() { - val symbol = (this as? FirFunctionCall)?.calleeReference?.toResolvedNamedFunctionSymbol() ?: return false - return origin == FirFunctionCallOrigin.Operator && symbol.name in OperatorNameConventions.STATEMENT_LIKE_OPERATORS - } - fun FirAnnotation.getCorrespondingClassSymbolOrNull(session: FirSession): FirRegularClassSymbol? { return annotationTypeRef.coneType.fullyExpandedType(session).toRegularClassSymbol(session) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt index 8b4fe4412ac..5cd2bbea8f2 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt @@ -17,12 +17,16 @@ import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass import org.jetbrains.kotlin.fir.declarations.utils.isStatic import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.expressions.FirFunctionCallOrigin import org.jetbrains.kotlin.fir.renderer.FirRenderer import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.* import org.jetbrains.kotlin.fir.types.impl.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.util.OperatorNameConventions.STATEMENT_LIKE_OPERATORS import org.jetbrains.kotlin.util.wrapIntoFileAnalysisExceptionIfNeeded import org.jetbrains.kotlin.util.wrapIntoSourceCodeAnalysisExceptionIfNeeded @@ -254,3 +258,18 @@ fun List.smartPlus(other: List): List = when { // Source element may be missing if the class came from a library fun FirVariable.isEnumEntries(containingClass: FirClass) = isStatic && name == StandardNames.ENUM_ENTRIES && containingClass.isEnumClass + +val FirExpression.isArraySet: Boolean + get() { + val name = (this as? FirFunctionCall)?.calleeReference?.name ?: return false + return origin == FirFunctionCallOrigin.Operator && name == OperatorNameConventions.SET + } + +val FirExpression.isStatementLikeExpression: Boolean + get() = when (this) { + is FirFunctionCall -> origin == FirFunctionCallOrigin.Operator && calleeReference.name in STATEMENT_LIKE_OPERATORS + else -> isIndexedAssignment + } + +private val FirExpression.isIndexedAssignment: Boolean + get() = this is FirBlock && statements.lastOrNull()?.source?.kind == KtFakeSourceElementKind.ImplicitUnit.IndexedAssignmentCoercion diff --git a/compiler/testData/diagnostics/tests/assigningAssignments.fir.kt b/compiler/testData/diagnostics/tests/assigningAssignments.fir.kt new file mode 100644 index 00000000000..4c1b46a433f --- /dev/null +++ b/compiler/testData/diagnostics/tests/assigningAssignments.fir.kt @@ -0,0 +1,12 @@ +// ISSUE: KT-61067 +// DIAGNOSTICS: -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE + +fun main() { + val storages: HashMap = HashMap() + val a = storages["4"] = "" //K1 compile error - Kotlin: Assignments are not expressions, and only expressions are allowed in this context + storages["4"] = "" + + var nonStorages: Int = 10 + val b = nonStorages = 20 + nonStorages = 20 +} diff --git a/compiler/testData/diagnostics/tests/assigningAssignments.kt b/compiler/testData/diagnostics/tests/assigningAssignments.kt new file mode 100644 index 00000000000..e742ecb016b --- /dev/null +++ b/compiler/testData/diagnostics/tests/assigningAssignments.kt @@ -0,0 +1,12 @@ +// ISSUE: KT-61067 +// DIAGNOSTICS: -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE + +fun main() { + val storages: HashMap = HashMap() + val a = storages["4"] = "" //K1 compile error - Kotlin: Assignments are not expressions, and only expressions are allowed in this context + storages["4"] = "" + + var nonStorages: Int = 10 + val b = nonStorages = 20 + nonStorages = 20 +} diff --git a/compiler/testData/diagnostics/tests/deparenthesize/ParenthesizedVariable.fir.kt b/compiler/testData/diagnostics/tests/deparenthesize/ParenthesizedVariable.fir.kt index f8950a03263..f27bb3f653b 100644 --- a/compiler/testData/diagnostics/tests/deparenthesize/ParenthesizedVariable.fir.kt +++ b/compiler/testData/diagnostics/tests/deparenthesize/ParenthesizedVariable.fir.kt @@ -1,3 +1,3 @@ fun test() { - (d@ val bar = 2) + (d@ val bar = 2) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/NameDeprecation.fir.kt b/compiler/testData/diagnostics/tests/functionAsExpression/NameDeprecation.fir.kt index 651dd1ec9b4..d0b36c0648c 100644 --- a/compiler/testData/diagnostics/tests/functionAsExpression/NameDeprecation.fir.kt +++ b/compiler/testData/diagnostics/tests/functionAsExpression/NameDeprecation.fir.kt @@ -1,9 +1,9 @@ fun foo() { class A - fun bar() {} - (fun bar() {}) - fun A.foo() {} - (fun A.foo() {}) + fun bar() {} + (fun bar() {}) + fun A.foo() {} + (fun A.foo() {}) run(fun foo() {}) } diff --git a/compiler/testData/diagnostics/tests/regressions/kt629.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt629.fir.kt deleted file mode 100644 index 607c074789b..00000000000 --- a/compiler/testData/diagnostics/tests/regressions/kt629.fir.kt +++ /dev/null @@ -1,23 +0,0 @@ -//KT-629 Assignments are parsed as expressions. - -package kt629 - -class A() { - var p = "yeah" - operator fun rem(other : A) : A { - return A(); - } -} - -fun box() : Boolean { - var c = A() - val d = c; - c %= A(); - return (c != d) && (c.p = "yeah") -} - - -fun box2() : Boolean { - var c = A() - return (c.p = "yeah") && true -} diff --git a/compiler/testData/diagnostics/tests/regressions/kt629.kt b/compiler/testData/diagnostics/tests/regressions/kt629.kt index 026b69bf6d6..e7d298c9bba 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt629.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt629.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL //KT-629 Assignments are parsed as expressions. package kt629 diff --git a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.fir.kt b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.fir.kt index 4fc2e19920a..15370671f62 100644 --- a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.fir.kt +++ b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.fir.kt @@ -122,12 +122,12 @@ fun testWithSubject_bad_4(b: B) { } // also bad when (b) { - (x = b) -> {} - (b += b) -> {} - (b -= b) -> {} - (b *= b) -> {} - (b /= b) -> {} - (b %= b) -> {} + (x = b) -> {} + (b += b) -> {} + (b -= b) -> {} + (b *= b) -> {} + (b /= b) -> {} + (b %= b) -> {} } } @@ -226,11 +226,11 @@ fun testWithRange_bad_4(b: B) { } // also bad when (b) { - in (x = b) -> {} - in (b += b) -> {} - in (b -= b) -> {} - in (b *= b) -> {} - in (b /= b) -> {} - in (b %= b) -> {} + in (x = b) -> {} + in (b += b) -> {} + in (b -= b) -> {} + in (b *= b) -> {} + in (b /= b) -> {} + in (b %= b) -> {} } } diff --git a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.fir.kt b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.fir.kt index 55e539f034b..40f5a5069dc 100644 --- a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.fir.kt +++ b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.fir.kt @@ -122,12 +122,12 @@ fun testWithSubject_bad_4(b: B) { } // also bad when (b) { - (x = b) -> {} - (b += b) -> {} - (b -= b) -> {} - (b *= b) -> {} - (b /= b) -> {} - (b %= b) -> {} + (x = b) -> {} + (b += b) -> {} + (b -= b) -> {} + (b *= b) -> {} + (b /= b) -> {} + (b %= b) -> {} } } @@ -226,11 +226,11 @@ fun testWithRange_bad_4(b: B) { } // also bad when (b) { - in (x = b) -> {} - in (b += b) -> {} - in (b -= b) -> {} - in (b *= b) -> {} - in (b /= b) -> {} - in (b %= b) -> {} + in (x = b) -> {} + in (b += b) -> {} + in (b -= b) -> {} + in (b *= b) -> {} + in (b /= b) -> {} + in (b %= b) -> {} } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index b87e24c4f00..d01a7c05699 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -93,6 +93,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/AssignToArrayElement.kt"); } + @Test + @TestMetadata("assigningAssignments.kt") + public void testAssigningAssignments() throws Exception { + runTest("compiler/testData/diagnostics/tests/assigningAssignments.kt"); + } + @Test @TestMetadata("AutoCreatedIt.kt") public void testAutoCreatedIt() throws Exception {