diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConversionScope.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConversionScope.kt index 00f5729a6b1..88eb65cc9e6 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConversionScope.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConversionScope.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.expressions.FirReturnExpression +import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol @@ -27,6 +28,10 @@ class Fir2IrConversionScope(val configuration: Fir2IrConfiguration) { @PrivateForInline internal val parentStack = mutableListOf() + @PublishedApi + @PrivateForInline + internal val scopeStack = mutableListOf() + @PublishedApi @PrivateForInline internal val containingFirClassStack = mutableListOf() @@ -37,9 +42,15 @@ class Fir2IrConversionScope(val configuration: Fir2IrConfiguration) { inline fun withParent(parent: T, f: T.() -> R): R { parentStack += parent + if (parent is IrDeclaration) { + scopeStack += Scope(parent.symbol) + } try { return parent.f() } finally { + if (parent is IrDeclaration) { + scopeStack.removeAt(scopeStack.size - 1) + } parentStack.removeAt(parentStack.size - 1) } } @@ -69,6 +80,8 @@ class Fir2IrConversionScope(val configuration: Fir2IrConfiguration) { fun parentFromStack(): IrDeclarationParent = parentStack.last() + fun scope(): Scope = scopeStack.last() + fun parentAccessorOfPropertyFromStack(propertySymbol: IrPropertySymbol): IrSimpleFunction { // It is safe to access an owner of property symbol here, because this function may be called // only from property accessor of corresponding property diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 21bf943d2ad..d7d3a8a5296 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.backend import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.* import org.jetbrains.kotlin.contracts.description.LogicOperationKind -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.isObject import org.jetbrains.kotlin.diagnostics.findChildByType @@ -16,8 +15,6 @@ import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.generators.ClassMemberGenerator import org.jetbrains.kotlin.fir.backend.generators.OperatorExpressionGenerator import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.builder.buildProperty -import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.deserialization.toQualifiedPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.* @@ -1150,24 +1147,18 @@ class Fir2IrVisitor( } override fun visitElvisExpression(elvisExpression: FirElvisExpression, data: Any?): IrElement { - val firLhsVariable = buildProperty { - source = elvisExpression.source - moduleData = session.moduleData - origin = FirDeclarationOrigin.Source - returnTypeRef = elvisExpression.lhs.resolvedType.toFirResolvedTypeRef() - name = Name.special("") - initializer = elvisExpression.lhs - symbol = FirPropertySymbol(name) - isVar = false - isLocal = true - status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) - } - val irLhsVariable = firLhsVariable.accept(this, null) as IrVariable return elvisExpression.convertWithOffsets { startOffset, endOffset -> + val irLhsVariable = conversionScope.scope().createTemporaryVariable( + irExpression = elvisExpression.lhs.accept(this, null) as IrExpression, + nameHint = "elvis_lhs", + startOffset = startOffset, + endOffset = endOffset + ) + fun irGetLhsValue(): IrGetValue = IrGetValueImpl(startOffset, endOffset, irLhsVariable.type, irLhsVariable.symbol) - val originalType = firLhsVariable.returnTypeRef.coneType + val originalType = elvisExpression.lhs.resolvedType val notNullType = originalType.withNullability(ConeNullability.NOT_NULL, session.typeContext) val irBranches = listOf( IrBranchImpl( @@ -1188,7 +1179,7 @@ class Fir2IrVisitor( } else { Fir2IrImplicitCastInserter.implicitCastOrExpression( irGetLhsValue(), - firLhsVariable.returnTypeRef.resolvedTypeFromPrototype(notNullType).toIrType() + originalType.toFirResolvedTypeRef().resolvedTypeFromPrototype(notNullType).toIrType() ) } ) diff --git a/compiler/testData/ir/sourceRanges/elvis.fir.txt b/compiler/testData/ir/sourceRanges/elvis.fir.txt deleted file mode 100644 index 9146d366bd1..00000000000 --- a/compiler/testData/ir/sourceRanges/elvis.fir.txt +++ /dev/null @@ -1,20 +0,0 @@ -@0:0..3:0 FILE fqName: fileName:/elvis.kt - @0:0..23 FUN name:intN visibility:public modality:FINAL <> () returnType:kotlin.Int? - @0:19..23 BLOCK_BODY - @0:23..23 RETURN type=kotlin.Nothing from='public final fun intN (): kotlin.Int? declared in ' - @0:19..23 CONST Null type=kotlin.Nothing? value=null - @2:0..24 FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Int - @2:13..24 BLOCK_BODY - @2:24..24 RETURN type=kotlin.Nothing from='public final fun test (): kotlin.Int declared in ' - @2:13..24 BLOCK type=kotlin.Int origin=ELVIS - @2:13..24 VAR IR_TEMPORARY_VARIABLE name: type:kotlin.Int? [val] - @2:13..19 CALL 'public final fun intN (): kotlin.Int? declared in ' type=kotlin.Int? origin=null - @2:13..24 WHEN type=kotlin.Int origin=null - @2:13..24 BRANCH - @2:13..24 CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - @2:13..24 GET_VAR 'val : kotlin.Int? [val] declared in .test' type=kotlin.Int? origin=null - @2:13..24 CONST Null type=kotlin.Nothing? value=null - @2:23..24 CONST Int type=kotlin.Int value=1 - @2:13..24 BRANCH - @2:13..24 CONST Boolean type=kotlin.Boolean value=true - @2:13..24 GET_VAR 'val : kotlin.Int? [val] declared in .test' type=kotlin.Int? origin=null diff --git a/compiler/testData/ir/sourceRanges/elvis.kt b/compiler/testData/ir/sourceRanges/elvis.kt index 1841486b9e3..152872f210f 100644 --- a/compiler/testData/ir/sourceRanges/elvis.kt +++ b/compiler/testData/ir/sourceRanges/elvis.kt @@ -1,3 +1,5 @@ fun intN(): Int? = null fun test() = intN() ?: 1 + +// FIR_IDENTICAL diff --git a/compiler/testData/ir/sourceRanges/elvis.txt b/compiler/testData/ir/sourceRanges/elvis.txt index 2903bffebdb..8b60066f9b3 100644 --- a/compiler/testData/ir/sourceRanges/elvis.txt +++ b/compiler/testData/ir/sourceRanges/elvis.txt @@ -1,4 +1,4 @@ -@0:0..3:0 FILE fqName: fileName:/elvis.kt +@0:0..5:0 FILE fqName: fileName:/elvis.kt @0:0..23 FUN name:intN visibility:public modality:FINAL <> () returnType:kotlin.Int? @0:19..23 BLOCK_BODY @0:23..23 RETURN type=kotlin.Nothing from='public final fun intN (): kotlin.Int? declared in ' diff --git a/js/js.translator/testData/box/jsAstOptimizations/deadCodeElimination.kt b/js/js.translator/testData/box/jsAstOptimizations/deadCodeElimination.kt index d37418cfbb5..10c46322fd5 100644 --- a/js/js.translator/testData/box/jsAstOptimizations/deadCodeElimination.kt +++ b/js/js.translator/testData/box/jsAstOptimizations/deadCodeElimination.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND_K2: JS_IR, JS_IR_ES6 -// FIR works fine, however it generates another names for the temporary variables, therefore ignore it - fun demo(f: () -> String) = f() // EXPECT_GENERATED_JS: function=test$lambda expect=deadCodeEliminationTestLambda.js