From 0a57eb8ea4e4712808b9d3c7319bb2f151330949 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Tue, 16 Aug 2016 15:43:23 +0300 Subject: [PATCH] IR: - smart casts handling separated from expression generation - improved infrastructure for desugaring --- .../org/jetbrains/kotlin/psi2ir/IrUtils.kt | 42 ++++++++ .../kotlin/psi2ir/generators/AssignmentLHS.kt | 61 ------------ .../psi2ir/generators/IrCallGenerator.kt | 99 +++++++++++-------- .../psi2ir/generators/IrDeclarationFactory.kt | 4 - .../generators/IrDeclarationGenerator.kt | 4 +- .../kotlin/psi2ir/generators/IrGenerator.kt | 3 - .../IrOperatorExpressionGenerator.kt | 58 +++++++++-- .../psi2ir/generators/IrStatementGenerator.kt | 53 ++++------ .../kotlin/psi2ir/generators/IrValue.kt | 83 ++++++++++++++++ .../kotlin/ir/expressions/IrOperator.kt | 76 +++++++------- .../expressions/IrPropertyAccessExpression.kt | 9 +- .../expressions/IrTypeOperatorExpression.kt | 10 +- .../expressions/IrVariableAccessExpression.kt | 14 +-- .../ir/irText/augmentedAssignment1.kt | 6 ++ .../ir/irText/augmentedAssignment1.txt | 12 +++ .../ir/irText/augmentedAssignment2.kt | 8 ++ .../ir/irText/augmentedAssignment2.txt | 8 ++ compiler/testData/ir/irText/dotQualified.txt | 2 +- compiler/testData/ir/irText/smartCasts.txt | 12 +-- .../ir/irText/smartCastsWithDestructuring.txt | 2 +- .../kotlin/ir/IrTextTestCaseGenerated.java | 12 +++ 21 files changed, 363 insertions(+), 215 deletions(-) create mode 100644 compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrUtils.kt delete mode 100644 compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentLHS.kt create mode 100644 compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrValue.kt create mode 100644 compiler/testData/ir/irText/augmentedAssignment1.kt create mode 100644 compiler/testData/ir/irText/augmentedAssignment1.txt create mode 100644 compiler/testData/ir/irText/augmentedAssignment2.kt create mode 100644 compiler/testData/ir/irText/augmentedAssignment2.txt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrUtils.kt new file mode 100644 index 00000000000..e7c718af98f --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrUtils.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.psi2ir + +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetVariableExpressionImpl +import org.jetbrains.kotlin.ir.expressions.IrTypeOperator +import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorExpressionImpl +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.checker.KotlinTypeChecker + +fun IrExpression.toExpectedType(expectedType: KotlinType?): IrExpression { + if (expectedType == null) return this + val valueType = type ?: throw AssertionError("expectedType != null, valueType == null: $this") + if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) { + return this + } + + return IrTypeOperatorExpressionImpl( + startOffset, endOffset, expectedType, + IrTypeOperator.IMPLICIT_CAST, expectedType, + this + ) +} + +fun IrVariable.implicitGetExpression(): IrExpression = + IrGetVariableExpressionImpl(startOffset, endOffset, descriptor) \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentLHS.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentLHS.kt deleted file mode 100644 index 9abccf57f48..00000000000 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentLHS.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.psi2ir.generators - -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrOperator -import org.jetbrains.kotlin.ir.expressions.IrSetPropertyExpressionImpl -import org.jetbrains.kotlin.ir.expressions.IrSetVariableExpressionImpl -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.psiUtil.endOffset -import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.types.KotlinType - -interface AssignmentLHS { - val type: KotlinType? - - fun generateAssignment(ktOperation: KtBinaryExpression, irOperator: IrOperator, irRight: IrExpression): IrExpression -} - -class VariableLHS( - val descriptor: VariableDescriptor -) : AssignmentLHS { - override val type: KotlinType? = descriptor.type - - override fun generateAssignment(ktOperation: KtBinaryExpression, irOperator: IrOperator, irRight: IrExpression) = - IrSetVariableExpressionImpl(ktOperation.startOffset, ktOperation.endOffset, descriptor, irRight, irOperator) -} - -class PropertyLHS( - val descriptor: PropertyDescriptor, - val dispatchReceiver: IrExpression?, - val extensionReceiver: IrExpression?, - val isSafe: Boolean -) : AssignmentLHS { - override val type: KotlinType? = descriptor.type - - override fun generateAssignment(ktOperation: KtBinaryExpression, irOperator: IrOperator, irRight: IrExpression): IrExpression = - IrSetPropertyExpressionImpl(ktOperation.startOffset, ktOperation.endOffset, isSafe, descriptor, irOperator).apply { - dispatchReceiver = this@PropertyLHS.dispatchReceiver - extensionReceiver = this@PropertyLHS.extensionReceiver - value = irRight - } -} - - diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrCallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrCallGenerator.kt index 663e7639c12..205030083e3 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrCallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrCallGenerator.kt @@ -21,31 +21,32 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.psi2ir.toExpectedType import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize import java.util.* -class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenerator { +class IrCallGenerator( + private val irStatementGenerator: IrStatementGenerator +) : IrGenerator { override val context: IrGeneratorContext get() = irStatementGenerator.context - private val temporaries = newHashMapWithExpectedSize(3) + private val expressionValues = HashMap() + private val receiverValues = HashMap() + private val valueArgumentValues = HashMap() - fun putTemporary(ktExpression: KtExpression, temporaryVariableDescriptor: VariableDescriptor) { - temporaries[ktExpression] = temporaryVariableDescriptor + fun putValue(ktExpression: KtExpression, irValue: IrValue) { + expressionValues[ktExpression] = irValue } - private fun generateExpressionOrTemporary(ktExpression: KtExpression, expectedType: KotlinType?): IrExpression { - val temporary = temporaries[ktExpression] - return if (temporary != null) - irStatementGenerator.smartCastTo( - IrGetVariableExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, temporary.type, temporary), - expectedType - ) - else - irStatementGenerator.generateExpression(ktExpression, expectedType) + fun putValue(receiver: ReceiverValue, irValue: IrValue) { + receiverValues[receiver] = irValue + } + + fun putValue(valueArgument: ResolvedValueArgument, irValue: IrValue) { + valueArgumentValues[valueArgument] = irValue } fun generateCall( @@ -64,10 +65,8 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera returnType, resolvedCall.call.isSafeCall(), descriptor ).apply { - dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, - descriptor.dispatchReceiverParameter?.type) - extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, - descriptor.extensionReceiverParameter?.type) + dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter) + extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter) } is FunctionDescriptor -> generateFunctionCall(descriptor, ktExpression, returnType, operator, resolvedCall, superQualifier) @@ -102,10 +101,8 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera ktExpression.startOffset, ktExpression.endOffset, resultType, descriptor, resolvedCall.call.isSafeCall(), operator, superQualifier ) - irCall.dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, - descriptor.dispatchReceiverParameter?.type) - irCall.extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, - descriptor.extensionReceiverParameter?.type) + irCall.dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter) + irCall.extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter) return if (resolvedCall.requiresArgumentReordering()) { generateCallWithArgumentReordering(irCall, ktExpression, resolvedCall, resultType) @@ -116,10 +113,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera for (index in valueArguments!!.indices) { val valueArgument = valueArguments[index] val valueParameter = descriptor.valueParameters[index] - val irArgument = generateValueArgument( - valueArgument, - valueParameter.varargElementType ?: valueParameter.type - ) ?: continue + val irArgument = generateValueArgument(valueArgument, valueParameter) ?: continue irCall.putArgument(index, irArgument) } } @@ -140,21 +134,19 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera hasResult = isUsedAsExpression(ktExpression), isDesugared = true) - val temporaryVariablesForValueArguments = HashMap>() + val temporariesForValueArguments = HashMap>() for (valueArgument in valueArgumentsInEvaluationOrder) { - val irArgument = generateValueArgument(valueArgument, null) ?: continue + val irArgument = generateValueArgument(valueArgument) ?: continue val irTemporary = irStatementGenerator.declarationFactory.createTemporaryVariable(irArgument) + temporariesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument) irBlock.addStatement(irTemporary) - - temporaryVariablesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument) } for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) { - val (temporaryDescriptor, irArgument) = temporaryVariablesForValueArguments[valueArgument]!! + val (temporaryDescriptor, irArgument) = temporariesForValueArguments[valueArgument]!! val valueParameter = resolvedCall.resultingDescriptor.valueParameters[index] - val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset, irArgument.type, - temporaryDescriptor) - irCall.putArgument(index, irStatementGenerator.smartCastTo(irGetTemporary, valueParameter.type)) + val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset, temporaryDescriptor) + irCall.putArgument(index, irGetTemporary.toExpectedType(valueParameter.type)) } irBlock.addStatement(irCall) @@ -162,8 +154,16 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera return irBlock } - // TODO smart casts on implicit receivers - fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?, expectedType: KotlinType?): IrExpression? = + fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?, receiverParameterDescriptor: ReceiverParameterDescriptor?) = + generateReceiver(ktExpression, receiver)?.toExpectedType(receiverParameterDescriptor?.type) + + fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? = + if (receiver == null) + null + else + receiverValues[receiver]?.load() ?: doGenerateReceiver(ktExpression, receiver) + + fun doGenerateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? = when (receiver) { is ImplicitClassReceiver -> IrThisExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, receiver.classDescriptor) @@ -172,7 +172,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor) } ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver") is ExpressionReceiver -> - generateExpressionOrTemporary(receiver.expression, expectedType) + generateExpression(receiver.expression) is ClassValueReceiver -> IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type, receiver.classQualifier.descriptor) @@ -185,15 +185,32 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera TODO("Receiver: ${receiver.javaClass.simpleName}") } - fun generateValueArgument(valueArgument: ResolvedValueArgument, expectedType: KotlinType?) = + fun generateValueArgument(valueArgument: ResolvedValueArgument, valueParameterDescriptor: ValueParameterDescriptor): IrExpression? = + if (valueParameterDescriptor.varargElementType != null) { + generateValueArgument(valueArgument) + } + else { + generateValueArgument(valueArgument)?.toExpectedType(valueParameterDescriptor.type) + } + + fun generateValueArgument(valueArgument: ResolvedValueArgument): IrExpression? = + if (valueArgument is DefaultValueArgument) + null + else + valueArgumentValues[valueArgument]?.load() ?: doGenerateValueArgument(valueArgument) + + + private fun doGenerateValueArgument(valueArgument: ResolvedValueArgument): IrExpression? = when (valueArgument) { - is DefaultValueArgument -> - null is ExpressionValueArgument -> - generateExpressionOrTemporary(valueArgument.valueArgument!!.getArgumentExpression()!!, expectedType) + generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!) is VarargValueArgument -> TODO("vararg") else -> TODO("Unexpected valueArgument: ${valueArgument.javaClass.simpleName}") } + + private fun generateExpression(ktExpression: KtExpression): IrExpression = + expressionValues[ktExpression]?.load() ?: irStatementGenerator.generateExpression(ktExpression) + } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrDeclarationFactory.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrDeclarationFactory.kt index 40b4e8d80a7..4483d57a399 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrDeclarationFactory.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrDeclarationFactory.kt @@ -70,10 +70,6 @@ class IrLocalDeclarationsFactory(val scopeOwner: DeclarationDescriptor) : IrDecl fun createDescriptorForTemporaryVariable(type: KotlinType): IrTemporaryVariableDescriptor = IrTemporaryVariableDescriptorImpl(scopeOwner, Name.identifier("tmp${nextTemporaryIndex()}"), type) - fun createTemporaryVariable(ktElement: KtElement, type: KotlinType): IrVariable = - IrVariableImpl(ktElement.startOffset, ktElement.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE, - createDescriptorForTemporaryVariable(type)) - fun createTemporaryVariable(irExpression: IrExpression): IrVariable = IrVariableImpl(irExpression.startOffset, irExpression.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE, createDescriptorForTemporaryVariable( diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrDeclarationGenerator.kt index dbb93f78e08..d7bde6eeee6 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrDeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrDeclarationGenerator.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.psi2ir.toExpectedType import org.jetbrains.kotlin.resolve.BindingContext interface IrDeclarationGenerator : IrGenerator @@ -94,7 +95,8 @@ abstract class IrDeclarationGeneratorBase( private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression = IrStatementGenerator(context, scopeOwner, IrLocalDeclarationsFactory(scopeOwner)) - .generateExpression(ktExpression, getExpectedTypeForLastInferredCall(ktExpression)) + .generateExpression(ktExpression) + .toExpectedType(getExpectedTypeForLastInferredCall(ktExpression)) private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody { val irRhs = generateExpressionWithinContext(ktBody, scopeOwner) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrGenerator.kt index 6ca73283894..45a8b5b62fa 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrGenerator.kt @@ -45,9 +45,6 @@ fun IrGenerator.getOrFail(slice: ReadOnlySlice, key: K): V = inline fun IrGenerator.getOrFail(slice: ReadOnlySlice, key: K, message: (K) -> String): V = context.bindingContext[slice, key] ?: throw RuntimeException(message(key)) -inline fun IrGenerator.getOrElse(slice: ReadOnlySlice, key: K, otherwise: (K) -> V): V = - context.bindingContext[slice, key] ?: otherwise(key) - fun IrGenerator.getInferredTypeWithSmartcasts(key: KtExpression): KotlinType? = context.bindingContext.getType(key) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrOperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrOperatorExpressionGenerator.kt index 95490bb905a..e492523f21b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrOperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrOperatorExpressionGenerator.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.psi2ir.generators +import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -23,7 +24,18 @@ import org.jetbrains.kotlin.ir.expressions.IrOperator import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.types.KotlinType + +val KT_OPERATOR_TO_IR_OPERATOR = hashMapOf( + KtTokens.PLUSEQ to IrOperator.PLUSEQ, + KtTokens.MINUSEQ to IrOperator.MINUSEQ, + KtTokens.MULTEQ to IrOperator.MULTEQ, + KtTokens.DIVEQ to IrOperator.DIVEQ, + KtTokens.PERCEQ to IrOperator.PERCEQ +) class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerator): IrGenerator { override val context: IrGeneratorContext get() = irStatementGenerator.context @@ -33,18 +45,46 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat return when (ktOperator) { KtTokens.EQ -> generateAssignment(expression) + in KtTokens.AUGMENTED_ASSIGNMENTS -> generateAugmentedAssignment(expression, ktOperator) else -> createDummyExpression(expression, ktOperator.toString()) } } + private fun generateAugmentedAssignment(expression: KtBinaryExpression, ktOperator: IElementType): IrExpression { + val ktLeft = expression.left!! + + val irOperator = getIrOperator(ktOperator) + val lhs = generateReferenceForAssignmentLhs(ktLeft, irOperator) + + val isSimpleAssignment = get(BindingContext.VARIABLE_REASSIGNMENT, expression) ?: false + + val operatorCall = getResolvedCall(expression)!! + + val opCallGenerator = IrCallGenerator(irStatementGenerator).apply { putValue(ktLeft, lhs) } + val irOpCall = opCallGenerator.generateCall(expression, operatorCall, irOperator) + + return if (isSimpleAssignment) { + // Set( Op( Get(), RHS ) ) + lhs.store(irOpCall) + } + else { + // Op( Get(), RHS ) + irOpCall + } + } + + private fun getIrOperator(ktOperator: IElementType): IrOperator { + return KT_OPERATOR_TO_IR_OPERATOR[ktOperator] ?: TODO("Operator: $ktOperator") + } + private fun generateAssignment(expression: KtBinaryExpression): IrExpression { val ktLeft = expression.left!! val ktRight = expression.right!! - val lhs = generateAssignmentLHS(ktLeft) - return lhs.generateAssignment(expression, IrOperator.EQ, irStatementGenerator.generateExpression(ktRight, lhs.type)) + val lhsReference = generateReferenceForAssignmentLhs(ktLeft, IrOperator.EQ) + return lhsReference.store(irStatementGenerator.generateExpression(ktRight)) } - private fun generateAssignmentLHS(ktLeft: KtExpression): AssignmentLHS { + private fun generateReferenceForAssignmentLhs(ktLeft: KtExpression, irOperator: IrOperator?): IrReference { val resolvedCall = getResolvedCall(ktLeft) ?: TODO("no resolved call for LHS") val descriptor = resolvedCall.candidateDescriptor @@ -53,15 +93,13 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat if (descriptor.isDelegated) TODO("Delegated local variable") else - VariableLHS(descriptor) + IrVariableReferenceValue(ktLeft, irOperator, descriptor) is PropertyDescriptor -> IrCallGenerator(irStatementGenerator).run { - PropertyLHS( - descriptor, - generateReceiver(ktLeft, resolvedCall.dispatchReceiver, - descriptor.dispatchReceiverParameter?.type), - generateReceiver(ktLeft, resolvedCall.extensionReceiver, - descriptor.extensionReceiverParameter?.type), + IrPropertyReferenceValue( + ktLeft, irOperator, descriptor, + generateReceiver(ktLeft, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter), + generateReceiver(ktLeft, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter), resolvedCall.call.isSafeCall() ) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrStatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrStatementGenerator.kt index 118c999a2c4..3582ce663f2 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrStatementGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrStatementGenerator.kt @@ -24,6 +24,8 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.deparenthesize +import org.jetbrains.kotlin.psi2ir.implicitGetExpression +import org.jetbrains.kotlin.psi2ir.toExpectedType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContextUtils import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -32,8 +34,6 @@ import org.jetbrains.kotlin.resolve.constants.IntValue import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils class IrStatementGenerator( @@ -42,32 +42,14 @@ class IrStatementGenerator( val declarationFactory: IrLocalDeclarationsFactory ) : KtVisitor(), IrGenerator { - fun generateExpression(ktExpression: KtExpression, expectedType: KotlinType?): IrExpression = - ktExpression.genExpr(expectedType) + fun generateExpression(ktExpression: KtExpression): IrExpression = + ktExpression.genExpr() - private fun KtElement.genStmt(expectedType: KotlinType?): IrStatement { - val irStatement = deparenthesize().accept(this@IrStatementGenerator, null) - if (irStatement is IrExpression) { - return smartCastTo(irStatement, expectedType) - } - return irStatement - } - - private fun KtElement.genExpr(expectedType: KotlinType?): IrExpression = - genStmt(expectedType).assertCast() - - fun smartCastTo(irExpression: IrExpression, expectedType: KotlinType?): IrExpression { - val actualType = irExpression.type - if (expectedType != null && actualType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType)) { - return IrTypeOperatorExpressionImpl( - irExpression.startOffset, irExpression.endOffset, expectedType, - IrTypeOperator.SMART_AS, expectedType, - irExpression - ) - } - return irExpression - } + private fun KtElement.genStmt(): IrStatement = + deparenthesize().accept(this@IrStatementGenerator, null) + private fun KtElement.genExpr(): IrExpression = + genStmt().assertCast() override fun visitExpression(expression: KtExpression, data: Nothing?): IrStatement = createDummyExpression(expression, expression.javaClass.simpleName) @@ -78,7 +60,9 @@ class IrStatementGenerator( val variableDescriptor = getOrFail(BindingContext.VARIABLE, property) val irLocalVariable = declarationFactory.createLocalVariable(property, variableDescriptor) - irLocalVariable.initializer = property.initializer?.genExpr(variableDescriptor.type) + irLocalVariable.initializer = property.initializer?.let { + it.genExpr().toExpectedType(variableDescriptor.type) + } return irLocalVariable } @@ -89,10 +73,11 @@ class IrStatementGenerator( val irBlock = IrBlockExpressionImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null, hasResult = false, isDesugared = true) val ktInitializer = multiDeclaration.initializer!! - val irInitializer = declarationFactory.createTemporaryVariable(ktInitializer.genExpr(null)) - irBlock.addStatement(irInitializer) + val irInitializerVal = declarationFactory.createTemporaryVariable(ktInitializer.genExpr()) + irBlock.addStatement(irInitializerVal) - val irCallGenerator = IrCallGenerator(this).apply { putTemporary(ktInitializer, irInitializer.descriptor) } + val irCallGenerator = IrCallGenerator(this) + irCallGenerator.putValue(ktInitializer, justExpressionValue { irInitializerVal.implicitGetExpression() }) for ((index, ktEntry) in multiDeclaration.entries.withIndex()) { val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry) @@ -108,7 +93,7 @@ class IrStatementGenerator( override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement { val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, getReturnType(expression), hasResult = isUsedAsExpression(expression), isDesugared = false) - expression.statements.forEach { irBlock.addStatement(it.genStmt(null)) } + expression.statements.forEach { irBlock.addStatement(it.genStmt()) } return irBlock } @@ -117,7 +102,7 @@ class IrStatementGenerator( return IrReturnExpressionImpl( expression.startOffset, expression.endOffset, returnTarget, - expression.returnedExpression?.let { it.genExpr(returnTarget.returnType) } + expression.returnedExpression?.let { it.genExpr().toExpectedType(returnTarget.returnType) } ) } @@ -160,7 +145,7 @@ class IrStatementGenerator( if (expression.entries.size == 1) { val entry0 = expression.entries[0] if (entry0 is KtLiteralStringTemplateEntry) { - return entry0.genExpr(null) + return entry0.genExpr() } } @@ -200,7 +185,7 @@ class IrStatementGenerator( IrCallGenerator(this).generateCall(expression, resolvedCall) } is VariableDescriptor -> - IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor.type, descriptor) + IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor) else -> IrDummyExpression( expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression), diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrValue.kt new file mode 100644 index 00000000000..add58644e30 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrValue.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.psi2ir.toExpectedType + +interface IrValue { + fun load(): IrExpression +} + +inline fun justExpressionValue(crossinline makeExpression: () -> IrExpression) = + object : IrValue { + override fun load() = makeExpression() + } + +interface IrReference : IrValue { + fun store(value: IrExpression): IrExpression +} + +class IrVariableReferenceValue( + val ktElement: KtElement, + val irOperator: IrOperator?, + val descriptor: VariableDescriptor +) : IrReference { + override fun load(): IrExpression = + IrGetVariableExpressionImpl( + ktElement.startOffset, ktElement.endOffset, + descriptor, irOperator + ) + + override fun store(value: IrExpression): IrExpression = + IrSetVariableExpressionImpl( + ktElement.startOffset, ktElement.endOffset, + descriptor, value.toExpectedType(descriptor.type), irOperator + ) +} + +class IrPropertyReferenceValue( + val ktElement: KtElement, + val irOperator: IrOperator?, + val descriptor: PropertyDescriptor, + val dispatchReceiver: IrExpression?, + val extensionReceiver: IrExpression?, + val isSafe: Boolean +) : IrReference { + private fun IrPropertyAccessExpression.setReceivers() = + apply { + dispatchReceiver = this@IrPropertyReferenceValue.dispatchReceiver + extensionReceiver = this@IrPropertyReferenceValue.extensionReceiver + } + + override fun load(): IrExpression = + IrGetPropertyExpressionImpl( + ktElement.startOffset, ktElement.endOffset, + descriptor.type, isSafe, descriptor, irOperator + ).setReceivers() + + override fun store(value: IrExpression): IrExpression = + IrSetPropertyExpressionImpl( + ktElement.startOffset, ktElement.endOffset, + isSafe, descriptor, value.toExpectedType(descriptor.type), irOperator + ).setReceivers() +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt index 24a7e8d9767..0bbb374eaae 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt @@ -16,52 +16,54 @@ package org.jetbrains.kotlin.ir.expressions -sealed class IrOperator { - object INVOKE : IrOperator() - object PREFIX_INCR : IrOperator() - object PREFIX_DECR : IrOperator() - object POSTFIX_INCR : IrOperator() - object POSTFIX_DECR : IrOperator() - object UMINUS : IrOperator() - object EXCL : IrOperator() - object EXCLEXCL : IrOperator() - object ELVIS : IrOperator() +sealed class IrOperator(val debugName: String) { + override fun toString(): String = debugName + + object INVOKE : IrOperator("INVOKE") + object PREFIX_INCR : IrOperator("PREFIX_INCR") + object PREFIX_DECR : IrOperator("PREFIX_DECR") + object POSTFIX_INCR : IrOperator("POSTFIX_INCR") + object POSTFIX_DECR : IrOperator("POSTFIX_DECR") + object UMINUS : IrOperator("UMINUS") + object EXCL : IrOperator("EXCL") + object EXCLEXCL : IrOperator("EXCLEXCL") + object ELVIS : IrOperator("ELVIS") - object LT : IrOperator() - object GT : IrOperator() - object LTEQ : IrOperator() - object GTEQ : IrOperator() + object LT : IrOperator("LT") + object GT : IrOperator("GT") + object LTEQ : IrOperator("LTEQ") + object GTEQ : IrOperator("GTEQ") - object EQEQ : IrOperator() - object EQEQEQ : IrOperator() - object EXCLEQ : IrOperator() - object EXCLEQEQ : IrOperator() - object IN : IrOperator() - object NOT_IN : IrOperator() - object ANDAND : IrOperator() - object OROR : IrOperator() - object RANGE : IrOperator() + object EQEQ : IrOperator("EQEQ") + object EQEQEQ : IrOperator("EQEQEQ") + object EXCLEQ : IrOperator("EXCLEQ") + object EXCLEQEQ : IrOperator("EXCLEQEQ") + object IN : IrOperator("IN") + object NOT_IN : IrOperator("NOT_IN") + object ANDAND : IrOperator("ANDAND") + object OROR : IrOperator("OROR") + object RANGE : IrOperator("RANGE") - object PLUS : IrOperator() - object MINUS : IrOperator() - object MUL : IrOperator() - object DIV : IrOperator() - object MOD : IrOperator() + object PLUS : IrOperator("PLUS") + object MINUS : IrOperator("MINUS") + object MUL : IrOperator("MUL") + object DIV : IrOperator("DIV") + object MOD : IrOperator("MOD") - object EQ : IrOperator() - object PLUSEQ : IrOperator() - object MINUSEQ : IrOperator() - object MULEQ : IrOperator() - object DIVEQ : IrOperator() - object MODEQ : IrOperator() + object EQ : IrOperator("EQ") + object PLUSEQ : IrOperator("PLUSEQ") + object MINUSEQ : IrOperator("MINUSEQ") + object MULTEQ : IrOperator("MULTEQ") + object DIVEQ : IrOperator("DIVEQ") + object PERCEQ : IrOperator("PERCEQ") - data class COMPONENT_N private constructor(val index: Int) : IrOperator() { + data class COMPONENT_N private constructor(val index: Int) : IrOperator("COMPONENT_$index") { companion object { - private val precreatedComponents = Array(32, ::COMPONENT_N) + private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) } fun withIndex(index: Int) = if (index < precreatedComponents.size) - precreatedComponents[index] + precreatedComponents[index - 1] else COMPONENT_N(index) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessExpression.kt index 113a55f6741..20407e643bc 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessExpression.kt @@ -23,13 +23,13 @@ import org.jetbrains.kotlin.types.KotlinType interface IrPropertyAccessExpression : IrMemberAccessExpression { override val descriptor: PropertyDescriptor + val operator: IrOperator? } interface IrGetPropertyExpression : IrPropertyAccessExpression interface IrSetPropertyExpression : IrPropertyAccessExpression { var value: IrExpression - val operator: IrOperator } class IrGetPropertyExpressionImpl( @@ -37,7 +37,8 @@ class IrGetPropertyExpressionImpl( endOffset: Int, type: KotlinType?, isSafe: Boolean, - override val descriptor: PropertyDescriptor + override val descriptor: PropertyDescriptor, + override val operator: IrOperator? = null ) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrGetPropertyExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetProperty(this, data) @@ -48,7 +49,7 @@ class IrSetPropertyExpressionImpl( endOffset: Int, isSafe: Boolean, override val descriptor: PropertyDescriptor, - override val operator: IrOperator = IrOperator.EQ + override val operator: IrOperator? = null ) : IrMemberAccessExpressionBase(startOffset, endOffset, null, isSafe), IrSetPropertyExpression { constructor( startOffset: Int, @@ -56,7 +57,7 @@ class IrSetPropertyExpressionImpl( isSafe: Boolean, descriptor: PropertyDescriptor, value: IrExpression, - operator: IrOperator = IrOperator.EQ + operator: IrOperator? = null ) : this(startOffset, endOffset, isSafe, descriptor, operator) { this.value = value } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt index f60a3d664ef..6c27298d293 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt @@ -21,11 +21,11 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType enum class IrTypeOperator { - AS, - SMART_AS, - SAFE_AS, - IS, - NOT_IS; + CAST, + IMPLICIT_CAST, + SAFE_CAST, + INSTANCEOF, + NOT_INSTANCEOF; } interface IrTypeOperatorExpression : IrExpression { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrVariableAccessExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrVariableAccessExpression.kt index 0f4ab0184f3..d3a2986bd7c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrVariableAccessExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrVariableAccessExpression.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.ir.expressions -import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -24,21 +23,22 @@ import org.jetbrains.kotlin.types.KotlinType interface IrVariableAccessExpression : IrDeclarationReference { override val descriptor: VariableDescriptor + val operator: IrOperator? } interface IrGetVariableExpression : IrVariableAccessExpression interface IrSetVariableExpression : IrVariableAccessExpression { val value: IrExpression - val operator: IrOperator? + } class IrGetVariableExpressionImpl( startOffset: Int, endOffset: Int, - type: KotlinType?, - descriptor: VariableDescriptor -) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetVariableExpression { + descriptor: VariableDescriptor, + override val operator: IrOperator? = null +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, descriptor.type, descriptor), IrGetVariableExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetVariable(this, data) } @@ -47,14 +47,14 @@ class IrSetVariableExpressionImpl( startOffset: Int, endOffset: Int, override val descriptor: VariableDescriptor, - override val operator: IrOperator = IrOperator.EQ + override val operator: IrOperator? ) : IrExpressionBase(startOffset, endOffset, null), IrSetVariableExpression { constructor( startOffset: Int, endOffset: Int, descriptor: VariableDescriptor, value: IrExpression, - operator: IrOperator = IrOperator.EQ + operator: IrOperator? ) : this(startOffset, endOffset, descriptor, operator) { this.value = value } diff --git a/compiler/testData/ir/irText/augmentedAssignment1.kt b/compiler/testData/ir/irText/augmentedAssignment1.kt new file mode 100644 index 00000000000..27015b59f50 --- /dev/null +++ b/compiler/testData/ir/irText/augmentedAssignment1.kt @@ -0,0 +1,6 @@ +// <<< augmentedAssignment1.txt +fun test(): Int { + var x = 0 + x += 10 + return x +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/augmentedAssignment1.txt b/compiler/testData/ir/irText/augmentedAssignment1.txt new file mode 100644 index 00000000000..66990e40178 --- /dev/null +++ b/compiler/testData/ir/irText/augmentedAssignment1.txt @@ -0,0 +1,12 @@ +IrFile /augmentedAssignment1.kt + IrFunction public fun test(): kotlin.Int + IrExpressionBody + BLOCK type= hasResult=false isDesugared=false + VAR var x: kotlin.Int + LITERAL Int type=kotlin.Int value='0' + SET_VAR x type= + CALL .plus type=kotlin.Int operator=PLUSEQ + $this: GET_VAR x type=kotlin.Int + other: LITERAL Int type=kotlin.Int value='10' + RETURN type= + GET_VAR x type=kotlin.Int diff --git a/compiler/testData/ir/irText/augmentedAssignment2.kt b/compiler/testData/ir/irText/augmentedAssignment2.kt new file mode 100644 index 00000000000..f2d9c377f3d --- /dev/null +++ b/compiler/testData/ir/irText/augmentedAssignment2.kt @@ -0,0 +1,8 @@ +class A + +operator fun A.plusAssign(s: String) {} + +fun test() { // <<< augmentedAssignment2.txt + val a = A() + a += "" +} diff --git a/compiler/testData/ir/irText/augmentedAssignment2.txt b/compiler/testData/ir/irText/augmentedAssignment2.txt new file mode 100644 index 00000000000..422340b5fef --- /dev/null +++ b/compiler/testData/ir/irText/augmentedAssignment2.txt @@ -0,0 +1,8 @@ +IrFunction public fun test(): kotlin.Unit + IrExpressionBody + BLOCK type= hasResult=false isDesugared=false + VAR val a: A + CALL . type=A operator= + CALL .plusAssign type=kotlin.Unit operator=PLUSEQ + $receiver: GET_VAR a type=A + s: ? IrStringConcatenationExpressionImpl type=kotlin.String diff --git a/compiler/testData/ir/irText/dotQualified.txt b/compiler/testData/ir/irText/dotQualified.txt index fa1334b706a..e091af323fc 100644 --- a/compiler/testData/ir/irText/dotQualified.txt +++ b/compiler/testData/ir/irText/dotQualified.txt @@ -10,5 +10,5 @@ IrFile /dotQualified.kt BLOCK type= hasResult=false isDesugared=true RETURN type= GET_PROPERTY ?.length type=kotlin.Int? - $this: TYPE_OP operator=SMART_AS typeOperand=kotlin.String + $this: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String GET_VAR s type=kotlin.String? diff --git a/compiler/testData/ir/irText/smartCasts.txt b/compiler/testData/ir/irText/smartCasts.txt index 37435d35de5..0f415f27023 100644 --- a/compiler/testData/ir/irText/smartCasts.txt +++ b/compiler/testData/ir/irText/smartCasts.txt @@ -21,18 +21,18 @@ IrFile /smartCasts.kt DUMMY KtIfExpression type=kotlin.Unit CALL .println type=kotlin.Unit operator= message: GET_PROPERTY .length type=kotlin.Int - $this: TYPE_OP operator=SMART_AS typeOperand=kotlin.String + $this: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String GET_VAR x type=kotlin.Any CALL .expectsString type=kotlin.Unit operator= - s: TYPE_OP operator=SMART_AS typeOperand=kotlin.String + s: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String GET_VAR x type=kotlin.Any CALL .expectsInt type=kotlin.Unit operator= i: GET_PROPERTY .length type=kotlin.Int - $this: TYPE_OP operator=SMART_AS typeOperand=kotlin.String + $this: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String GET_VAR x type=kotlin.Any CALL .expectsString type=kotlin.Unit operator= s: CALL .overloaded type=kotlin.String operator= - s: TYPE_OP operator=SMART_AS typeOperand=kotlin.String + s: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String GET_VAR x type=kotlin.Any IrFunction public fun test2(/*0*/ x: kotlin.Any): kotlin.String IrExpressionBody @@ -40,12 +40,12 @@ IrFile /smartCasts.kt DUMMY KtIfExpression type=kotlin.Unit RETURN type= CALL .overloaded type=kotlin.String operator= - s: TYPE_OP operator=SMART_AS typeOperand=kotlin.String + s: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String GET_VAR x type=kotlin.Any IrFunction public fun test3(/*0*/ x: kotlin.Any): kotlin.String IrExpressionBody BLOCK type= hasResult=false isDesugared=false DUMMY KtIfExpression type=kotlin.Unit RETURN type= - TYPE_OP operator=SMART_AS typeOperand=kotlin.String + TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String GET_VAR x type=kotlin.Any diff --git a/compiler/testData/ir/irText/smartCastsWithDestructuring.txt b/compiler/testData/ir/irText/smartCastsWithDestructuring.txt index 804337b2b47..0747d8047c8 100644 --- a/compiler/testData/ir/irText/smartCastsWithDestructuring.txt +++ b/compiler/testData/ir/irText/smartCastsWithDestructuring.txt @@ -22,5 +22,5 @@ IrFile /smartCastsWithDestructuring.kt $receiver: GET_VAR tmp0 type=I1 VAR val c2: kotlin.String CALL .component2 type=kotlin.String operator=COMPONENT_N(index=2) - $receiver: TYPE_OP operator=SMART_AS typeOperand=I2 + $receiver: TYPE_OP operator=IMPLICIT_CAST typeOperand=I2 GET_VAR tmp0 type=I1 diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index abca1380949..c63935daaef 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -41,6 +41,18 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("augmentedAssignment1.kt") + public void testAugmentedAssignment1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/augmentedAssignment1.kt"); + doTest(fileName); + } + + @TestMetadata("augmentedAssignment2.kt") + public void testAugmentedAssignment2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/augmentedAssignment2.kt"); + doTest(fileName); + } + @TestMetadata("boxOk.kt") public void testBoxOk() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/boxOk.kt");