From 692a83f7bbf33f84bfa00ce2edea662bd0e9a8c5 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Mon, 2 Dec 2019 22:57:24 -0800 Subject: [PATCH] [FIR] Add FirCheckNotNullCall converted to CHECK_NOT_NULL intrinsic function call. --- .../kotlin/fir/symbols/SyntheticCallableId.kt | 4 + .../kotlin/fir/backend/Fir2IrVisitor.kt | 19 +++- .../converter/ExpressionsConverter.kt | 43 ++++++---- .../kotlin/fir/builder/BaseFirBuilder.kt | 12 --- .../kotlin/fir/builder/RawFirBuilder.kt | 43 ++++++---- .../rawBuilder/expressions/nullability.txt | 10 +-- .../src/org/jetbrains/kotlin/fir/CopyUtils.kt | 12 +++ .../kotlin/fir/resolve/calls/Arguments.kt | 2 +- .../fir/resolve/calls/CandidateFactory.kt | 2 +- .../fir/resolve/calls/InferenceCompletion.kt | 5 ++ ...rCallCompletionResultsWriterTransformer.kt | 53 +++++------- .../transformers/FirSyntheticCallGenerator.kt | 64 ++++++++++++-- .../body/resolve/FirBodyResolveTransformer.kt | 7 ++ .../FirExpressionsResolveTransformer.kt | 25 ++++++ .../arguments/lambdaInUnresolvedCall.kt | 2 +- .../arguments/lambdaInUnresolvedCall.txt | 10 +-- .../resolve/delegatingConstructorCall.kt | 2 +- .../resolve/delegatingConstructorCall.txt | 10 +-- .../testData/resolve/nestedClassNameClash.kt | 4 +- .../testData/resolve/nestedClassNameClash.txt | 20 +---- .../inferenceFromCallableReferenceType.txt | 20 +---- .../inferenceFromExpectedType.txt | 20 +---- .../stdlib/factoryFunctionOverloads.txt | 10 +-- .../testData/resolve/stdlib/hashSet.txt | 10 +-- .../testData/resolve/whenAsReceiver.kt | 2 +- .../testData/resolve/whenAsReceiver.txt | 10 +-- .../fir/expressions/FirCheckNotNullCall.kt | 31 +++++++ .../impl/FirCheckNotNullCallImpl.kt | 60 +++++++++++++ .../kotlin/fir/visitors/FirTransformer.kt | 9 ++ .../kotlin/fir/visitors/FirVisitor.kt | 3 + .../kotlin/fir/visitors/FirVisitorVoid.kt | 9 ++ .../org/jetbrains/kotlin/fir/FirRenderer.kt | 5 ++ .../fir/expressions/FirExpressionUtil.kt | 2 +- .../fir/tree/generator/FirTreeBuilder.kt | 1 + .../generator/ImplementationConfigurator.kt | 5 ++ .../codegen/box/binaryOp/callNullable.kt | 1 - .../codegen/box/binaryOp/intrinsicNullable.kt | 1 - .../testData/codegen/box/classes/kt725.kt | 1 - .../codegen/box/controlStructures/kt2147.kt | 1 - .../codegen/box/controlStructures/kt628.kt | 1 - .../returnsNothing/ifElse.kt | 1 - .../returnsNothing/inlineMethod.kt | 1 - .../returnsNothing/propertyGetter.kt | 1 - .../returnsNothing/tryCatch.kt | 1 - .../controlStructures/returnsNothing/when.kt | 1 - .../codegen/box/exclExcl/genericNull.kt | 1 - .../testData/codegen/box/fullJdk/ifInWhile.kt | 1 - .../box/ieee754/explicitCompareCall.kt | 1 - .../codegen/box/ieee754/explicitEqualsCall.kt | 1 - .../greaterDouble_properIeeeComparisons.kt | 1 - .../greaterFloat_properIeeeComparisons.kt | 1 - .../lessDouble_properIeeeComparisons.kt | 1 - .../lessFloat_properIeeeComparisons.kt | 1 - .../testData/codegen/box/ieee754/safeCall.kt | 1 - .../codegen/box/intrinsics/throwable.kt | 1 - .../optimizations/negateObjectComp.kt | 1 - .../optimizations/negateObjectComp2.kt | 1 - .../codegen/box/lazyCodegen/safeAssign.kt | 1 - .../codegen/box/primitiveTypes/kt3613.kt | 1 - .../codegen/box/primitiveTypes/kt4098.kt | 1 - .../codegen/box/primitiveTypes/kt4210.kt | 1 - .../codegen/box/primitiveTypes/kt753.kt | 1 - .../codegen/box/primitiveTypes/kt756.kt | 1 - .../codegen/box/primitiveTypes/kt757.kt | 1 - .../primitiveTypes/nullAsNullableIntIsNull.kt | 1 - .../box/primitiveTypes/nullableCharBoolean.kt | 1 - .../codegen/box/specialBuiltins/throwable.kt | 1 - .../codegen/box/unaryOp/callNullable.kt | 1 - .../codegen/box/unaryOp/intrinsicNullable.kt | 1 - .../ir/irText/expressions/bangbang.fir.txt | 86 ++++--------------- ...eqRhsConditionPossiblyAffectingLhs.fir.txt | 16 +--- .../ir/irText/expressions/kt30020.fir.txt | 36 ++------ 72 files changed, 363 insertions(+), 355 deletions(-) create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCheckNotNullCall.kt create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCheckNotNullCallImpl.kt diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/SyntheticCallableId.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/SyntheticCallableId.kt index 2339af4cecd..b455f2e083e 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/SyntheticCallableId.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/SyntheticCallableId.kt @@ -17,6 +17,10 @@ object SyntheticCallableId { FqName("_synthetic"), Name.identifier("TRY_CALL") ) + val CHECK_NOT_NULL = CallableId( + FqName("_synthetic"), + Name.identifier("CHECK_NOT_NULL_CALL") + ) val ID = CallableId( FqName("_synthetic"), Name.identifier("ID_CALL") 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 3a0c0e52890..f5a5064fa30 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 @@ -45,11 +45,8 @@ import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.classifierOrFail -import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl -import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.ClassId @@ -1289,6 +1286,20 @@ class Fir2IrVisitor( } } + override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: Any?): IrElement { + return checkNotNullCall.convertWithOffsets { startOffset, endOffset -> + IrCallImpl( + startOffset, endOffset, + checkNotNullCall.typeRef.toIrType(session, declarationStorage), + irBuiltIns.checkNotNullSymbol, + IrStatementOrigin.EXCLEXCL + ).apply { + putTypeArgument(0, checkNotNullCall.argument.typeRef.toIrType(session, declarationStorage).makeNotNull()) + putValueArgument(0, checkNotNullCall.argument.toIrExpression()) + } + } + } + override fun visitGetClassCall(getClassCall: FirGetClassCall, data: Any?): IrElement { return getClassCall.convertWithOffsets { startOffset, endOffset -> IrGetClassImpl( diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index f700e8fbe82..cb8b02d57d9 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -306,28 +306,33 @@ class ExpressionsConverter( } val operationToken = operationTokenName.getOperationSymbol() - if (operationToken == EXCLEXCL) { - return argument.bangBangToWhen(null) { getAsFirExpression(this, it) } - } - val conventionCallName = operationToken.toUnaryName() - return if (conventionCallName != null) { - if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) { - return generateIncrementOrDecrementBlock( - null, - argument, - callName = conventionCallName, - prefix = unaryExpression.tokenType == PREFIX_EXPRESSION - ) { getAsFirExpression(this) } + return when { + operationToken == EXCLEXCL -> { + FirCheckNotNullCallImpl(null).apply { + arguments += getAsFirExpression(argument, "No operand") + } + } - FirFunctionCallImpl(null).apply { - calleeReference = FirSimpleNamedReference(null, conventionCallName, null) - explicitReceiver = getAsFirExpression(argument, "No operand") + conventionCallName != null -> { + if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) { + return generateIncrementOrDecrementBlock( + null, + argument, + callName = conventionCallName, + prefix = unaryExpression.tokenType == PREFIX_EXPRESSION + ) { getAsFirExpression(this) } + } + FirFunctionCallImpl(null).apply { + calleeReference = FirSimpleNamedReference(null, conventionCallName, null) + explicitReceiver = getAsFirExpression(argument, "No operand") + } } - } else { - val firOperation = operationToken.toFirOperation() - FirOperatorCallImpl(null, firOperation).apply { - arguments += getAsFirExpression(argument, "No operand") + else -> { + val firOperation = operationToken.toFirOperation() + FirOperatorCallImpl(null, firOperation).apply { + arguments += getAsFirExpression(argument, "No operand") + } } } } diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index 80d21688a4f..6ccb52cbf8c 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -167,18 +167,6 @@ abstract class BaseFirBuilder(val session: FirSession, val context: Context = ?: emptyList() } - fun T?.bangBangToWhen(parent: KtUnaryExpression?, convert: T?.(String) -> FirExpression): FirWhenExpression { - val source = parent.getSourceOrNull() - return this.convert("No operand").generateNotNullOrOther( - session, - FirThrowExpressionImpl( - source, FirFunctionCallImpl(source).apply { - calleeReference = FirSimpleNamedReference(source, KNPE, null) - } - ), "bangbang", source - ) - } - fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop { label = context.firLabels.pop() context.firLoops += this diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index cb991565c35..87274f22c7e 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -1222,28 +1222,33 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder override fun visitUnaryExpression(expression: KtUnaryExpression, data: Unit): FirElement { val operationToken = expression.operationToken val argument = expression.baseExpression - if (operationToken == EXCLEXCL) { - return expression.baseExpression.bangBangToWhen(expression) { (this as KtExpression).toFirExpression(it) } - } val conventionCallName = operationToken.toUnaryName() - return if (conventionCallName != null) { - if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) { - return generateIncrementOrDecrementBlock( - expression, argument, - callName = conventionCallName, - prefix = expression is KtPrefixExpression - ) { (this as KtExpression).toFirExpression("Incorrect expression inside inc/dec") } + return when { + operationToken == EXCLEXCL -> { + FirCheckNotNullCallImpl(expression.toFirSourceElement()).apply { + arguments += argument.toFirExpression("No operand") + } } - FirFunctionCallImpl(expression.toFirSourceElement()).apply { - calleeReference = FirSimpleNamedReference( - expression.operationReference.toFirSourceElement(), conventionCallName, null - ) - explicitReceiver = argument.toFirExpression("No operand") + conventionCallName != null -> { + if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) { + return generateIncrementOrDecrementBlock( + expression, argument, + callName = conventionCallName, + prefix = expression is KtPrefixExpression + ) { (this as KtExpression).toFirExpression("Incorrect expression inside inc/dec") } + } + FirFunctionCallImpl(expression.toFirSourceElement()).apply { + calleeReference = FirSimpleNamedReference( + expression.operationReference.toFirSourceElement(), conventionCallName, null + ) + explicitReceiver = argument.toFirExpression("No operand") + } } - } else { - val firOperation = operationToken.toFirOperation() - FirOperatorCallImpl(expression.toFirSourceElement(), firOperation).apply { - arguments += argument.toFirExpression("No operand") + else -> { + val firOperation = operationToken.toFirOperation() + FirOperatorCallImpl(expression.toFirSourceElement(), firOperation).apply { + arguments += argument.toFirExpression("No operand") + } } } } diff --git a/compiler/fir/psi2fir/testData/rawBuilder/expressions/nullability.txt b/compiler/fir/psi2fir/testData/rawBuilder/expressions/nullability.txt index 0a86e2ffa67..1221c05701c 100644 --- a/compiler/fir/psi2fir/testData/rawBuilder/expressions/nullability.txt +++ b/compiler/fir/psi2fir/testData/rawBuilder/expressions/nullability.txt @@ -11,13 +11,5 @@ FILE: nullability.kt } public? final? fun bang(arg: Int?): { - ^bang when (lval : = arg#) { - ==($subj$, Null(null)) -> { - throw KotlinNullPointerException#() - } - else -> { - R|/| - } - } - + ^bang arg#!! } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt index 24f3765f694..b2f71780840 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.FirCheckNotNullCallImpl import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl import org.jetbrains.kotlin.fir.expressions.impl.FirTryExpressionImpl import org.jetbrains.kotlin.fir.expressions.impl.FirWhenExpressionImpl @@ -119,4 +120,15 @@ fun FirTryExpression.copy( this@apply.catches.addAll(this@copy.catches) this.typeRef = resultType this.annotations += annotations +} + +fun FirCheckNotNullCall.copy( + resultType: FirTypeRef = this.typeRef, + calleeReference: FirReference = this.calleeReference, + annotations: List = this.annotations +): FirCheckNotNullCallImpl = FirCheckNotNullCallImpl(source).apply { + this.calleeReference = calleeReference + this@apply.arguments.addAll(this@copy.arguments) + this.typeRef = resultType + this.annotations += annotations } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index a07671c91f7..d9ff352906c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -44,7 +44,7 @@ fun Candidate.resolveArgumentExpression( typeProvider: (FirExpression) -> FirTypeRef? ) { return when (argument) { - is FirFunctionCall, is FirWhenExpression, is FirTryExpression -> resolveSubCallArgument( + is FirFunctionCall, is FirWhenExpression, is FirTryExpression, is FirCheckNotNullCall -> resolveSubCallArgument( csBuilder, argument as FirResolvable, expectedType, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt index a8293af538c..f04f3c7f0b8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt @@ -44,7 +44,7 @@ class CandidateFactory( fun PostponedArgumentsAnalyzer.Context.addSubsystemFromExpression(statement: FirStatement) { when (statement) { - is FirFunctionCall, is FirQualifiedAccessExpression, is FirWhenExpression, is FirTryExpression, is FirCallableReferenceAccess -> + is FirFunctionCall, is FirQualifiedAccessExpression, is FirWhenExpression, is FirTryExpression, is FirCheckNotNullCall, is FirCallableReferenceAccess -> (statement as FirResolvable).candidate()?.let { addOtherSystem(it.system.asReadOnlyStorage()) } is FirWrappedArgumentExpression -> addSubsystemFromExpression(statement.expression) is FirBlock -> statement.returnExpressions().forEach { addSubsystemFromExpression(it) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt index 9553c1bce0c..aa534122143 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt @@ -246,6 +246,11 @@ class ConstraintSystemCompleter(val components: InferenceComponents) { catches.forEach { it.block.processAllContainingCallCandidates(processBlocks, processor) } } + is FirCheckNotNullCall -> { + processCandidateIfApplicable(processor) + this.arguments.forEach { it.processAllContainingCallCandidates(processBlocks, processor) } + } + is FirQualifiedAccessExpression -> { processCandidateIfApplicable(processor) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index deaf5ae5b43..a7513cb77c9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.references.impl.FirResolvedNamedReferenceImpl import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate -import org.jetbrains.kotlin.fir.resolve.calls.candidate import org.jetbrains.kotlin.fir.resolve.calls.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor @@ -52,7 +51,6 @@ class FirCallCompletionResultsWriterTransformer( ): CompositeTransformResult { val calleeReference = qualifiedAccessExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return qualifiedAccessExpression.compose() - calleeReference.candidate.substitutor val candidateFir = calleeReference.candidateSymbol.phasedFir val typeRef = (candidateFir as? FirTypedDeclaration)?.let { @@ -276,49 +274,38 @@ class FirCallCompletionResultsWriterTransformer( return transformElement(block, data) } - override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ExpectedArgumentType?): CompositeTransformResult { - val calleeReference = whenExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return whenExpression.compose() + // Transformations for synthetic calls generated by FirSyntheticCallGenerator - val whenExpression = whenExpression.transformChildren(this, data?.getExpectedType(whenExpression)?.toExpectedType()) as FirWhenExpression + override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ExpectedArgumentType?) = + transformSyntheticCall(whenExpression, data) - val declaration = whenExpression.candidate()?.symbol?.fir as? FirMemberFunction<*> ?: return whenExpression.compose() + override fun transformTryExpression(tryExpression: FirTryExpression, data: ExpectedArgumentType?) = + transformSyntheticCall(tryExpression, data) - val subCandidate = calleeReference.candidate + override fun transformCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: ExpectedArgumentType?) = + transformSyntheticCall(checkNotNullCall, data) + + private inline fun transformSyntheticCall( + syntheticCall: D, + data: ExpectedArgumentType? + ): CompositeTransformResult + where D : FirResolvable, D : FirExpression { + val syntheticCall = syntheticCall.transformChildren(this, data?.getExpectedType(syntheticCall)?.toExpectedType()) as D + val calleeReference = syntheticCall.calleeReference as? FirNamedReferenceWithCandidate ?: return syntheticCall.compose() + + val declaration = calleeReference.candidate.symbol.fir as? FirMemberFunction<*> ?: return syntheticCall.compose() val typeRef = typeCalculator.tryCalculateReturnType(declaration) + syntheticCall.replaceTypeRefWithSubstituted(calleeReference, typeRef) - whenExpression.resultType = typeRef.substituteTypeRef(subCandidate) - - return whenExpression.transformCalleeReference( + return (syntheticCall.transformCalleeReference( StoreCalleeReference, FirResolvedNamedReferenceImpl( calleeReference.source, calleeReference.name, calleeReference.candidateSymbol ) - ).compose() - } - - override fun transformTryExpression(tryExpression: FirTryExpression, data: ExpectedArgumentType?): CompositeTransformResult { - val calleeReference = tryExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return tryExpression.compose() - - val tryExpression = tryExpression.transformChildren(this, data) as FirTryExpression - - val declaration = tryExpression.candidate()?.symbol?.fir as? FirMemberFunction<*> ?: return tryExpression.compose() - - val subCandidate = calleeReference.candidate - - val typeRef = typeCalculator.tryCalculateReturnType(declaration) - - tryExpression.resultType = typeRef.substituteTypeRef(subCandidate) - return tryExpression.transformCalleeReference( - StoreCalleeReference, - FirResolvedNamedReferenceImpl( - calleeReference.source, - calleeReference.name, - calleeReference.candidateSymbol - ) - ).compose() + ) as D).compose() } override fun transformConstExpression( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt index 712535331b1..f63c0b377c4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt @@ -16,10 +16,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl -import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirTryExpression -import org.jetbrains.kotlin.fir.expressions.FirWhenExpression +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.impl.FirStubReference @@ -28,6 +25,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType +import org.jetbrains.kotlin.fir.resolve.withNullability import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.SyntheticCallableId import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol @@ -51,6 +49,7 @@ class FirSyntheticCallGenerator( private val whenSelectFunction: FirSimpleFunctionImpl = generateSyntheticSelectFunction(SyntheticCallableId.WHEN) private val trySelectFunction: FirSimpleFunctionImpl = generateSyntheticSelectFunction(SyntheticCallableId.TRY) private val idFunction: FirSimpleFunctionImpl = generateSyntheticSelectFunction(SyntheticCallableId.ID) + private val checkNotNullFunction: FirSimpleFunctionImpl = generateSyntheticCheckNotNullFunction() fun generateCalleeForWhenExpression(whenExpression: FirWhenExpression): FirWhenExpression? { val stubReference = whenExpression.calleeReference @@ -90,6 +89,19 @@ class FirSyntheticCallGenerator( return tryExpression.transformCalleeReference(UpdateReference, reference) } + fun generateCalleeForCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall): FirCheckNotNullCall? { + val stubReference = checkNotNullCall.calleeReference + if (stubReference !is FirStubReference) return null + + val reference = generateCalleeReferenceWithCandidate( + checkNotNullFunction, + checkNotNullCall.arguments, + SyntheticCallableId.CHECK_NOT_NULL.callableName + ) ?: return null // TODO + + return checkNotNullCall.transformCalleeReference(UpdateReference, reference) + } + fun resolveCallableReferenceWithSyntheticOuterCall( callableReferenceAccess: FirCallableReferenceAccess, expectedTypeRef: FirTypeRef? @@ -140,12 +152,15 @@ class FirSyntheticCallGenerator( implicitReceiverStack = implicitReceiverStack ) { it.resultType } - private fun generateSyntheticSelectFunction(callableId: CallableId, isVararg: Boolean = true): FirSimpleFunctionImpl { + private fun generateSyntheticSelectFunction(callableId: CallableId): FirSimpleFunctionImpl { + // Synthetic function signature: + // fun select(vararg values: K): K val functionSymbol = FirSyntheticFunctionSymbol(callableId) val typeParameterSymbol = FirTypeParameterSymbol() - val typeParameter = FirTypeParameterImpl(null, session, Name.identifier("K"), typeParameterSymbol, Variance.INVARIANT, false).apply { - addDefaultBoundIfNecessary() - } + val typeParameter = + FirTypeParameterImpl(null, session, Name.identifier("K"), typeParameterSymbol, Variance.INVARIANT, false).apply { + addDefaultBoundIfNecessary() + } val returnType = FirResolvedTypeRefImpl(null, ConeTypeParameterTypeImpl(typeParameterSymbol.toLookupTag(), false)) @@ -154,7 +169,38 @@ class FirSyntheticCallGenerator( return generateMemberFunction(session, functionSymbol, callableId.callableName, typeArgument.typeRef).apply { typeParameters += typeParameter - valueParameters += argumentType.toValueParameter(session, "branches", isVararg) + valueParameters += argumentType.toValueParameter(session, "branches", isVararg = true) + } + } + + private fun generateSyntheticCheckNotNullFunction(): FirSimpleFunctionImpl { + // Synthetic function signature: + // fun checkNotNull(arg: K?): K + // + // Note: The upper bound of `K` cannot be `Any` because of the following case: + // fun test(a: X) = a!! + // `X` is not a subtype of `Any` and hence cannot satisfy `K` if it had an upper bound of `Any`. + val functionSymbol = FirSyntheticFunctionSymbol(SyntheticCallableId.CHECK_NOT_NULL) + val typeParameterSymbol = FirTypeParameterSymbol() + val typeParameter = + FirTypeParameterImpl(null, session, Name.identifier("K"), typeParameterSymbol, Variance.INVARIANT, false).apply { + addDefaultBoundIfNecessary() + } + + val returnType = FirResolvedTypeRefImpl(null, ConeTypeParameterTypeImpl(typeParameterSymbol.toLookupTag(), false)) + + val argumentType = + FirResolvedTypeRefImpl(null, returnType.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE)) + val typeArgument = FirTypeProjectionWithVarianceImpl(null, returnType, Variance.INVARIANT) + + return generateMemberFunction( + session, + functionSymbol, + SyntheticCallableId.CHECK_NOT_NULL.callableName, + typeArgument.typeRef + ).apply { + typeParameters += typeParameter + valueParameters += argumentType.toValueParameter(session, "arg") } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt index ac4c9fe9c0a..3a9631bf06c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt @@ -113,6 +113,13 @@ open class FirBodyResolveTransformer( return expressionsTransformer.transformTypeOperatorCall(typeOperatorCall, data) } + override fun transformCheckNotNullCall( + checkNotNullCall: FirCheckNotNullCall, + data: ResolutionMode + ): CompositeTransformResult { + return expressionsTransformer.transformCheckNotNullCall(checkNotNullCall, data) + } + override fun transformBinaryLogicExpression( binaryLogicExpression: FirBinaryLogicExpression, data: ResolutionMode diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 3236a067d2e..e948ecb8cb6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -287,6 +287,31 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : return resolved.transform(integerLiteralTypeApproximator, null) } + override fun transformCheckNotNullCall( + checkNotNullCall: FirCheckNotNullCall, + data: ResolutionMode + ): CompositeTransformResult { + // Resolve the return type of a call to the synthetic function with signature: + // fun checkNotNull(arg: K?): K + // ...in order to get the not-nullable type of the argument. + + if (checkNotNullCall.calleeReference is FirResolvedNamedReference && checkNotNullCall.resultType !is FirImplicitTypeRef) { + return checkNotNullCall.compose() + } + + checkNotNullCall.transformArguments(transformer, ResolutionMode.ContextDependent) + + val result = components.syntheticCallGenerator.generateCalleeForCheckNotNullCall(checkNotNullCall)?.let { + callCompleter.completeCall(it, data.expectedType) + } ?: run { + checkNotNullCall.resultType = + FirErrorTypeRefImpl(null, FirSimpleDiagnostic("Can't resolve !! operator call", DiagnosticKind.InferenceError)) + checkNotNullCall + } + // TODO: Data flow analysis + return result.compose() + } + override fun transformBinaryLogicExpression( binaryLogicExpression: FirBinaryLogicExpression, data: ResolutionMode diff --git a/compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.kt b/compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.kt index 449a5f75509..26f6d8f3b0d 100644 --- a/compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.kt +++ b/compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.kt @@ -1,4 +1,4 @@ -fun materialize(): R = null!! +fun materialize(): R = null!! fun test_1() { myRun { diff --git a/compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.txt b/compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.txt index b91a7dc1207..92f5c9d2b31 100644 --- a/compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.txt +++ b/compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.txt @@ -1,14 +1,6 @@ FILE: lambdaInUnresolvedCall.kt public final fun materialize(): R|R| { - ^materialize when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw #() - } - else -> { - R|/| - } - } - + ^materialize Null(null)!! } public final fun test_1(): R|kotlin/Unit| { #( = myRun@fun (): R|kotlin/Int| { diff --git a/compiler/fir/resolve/testData/resolve/delegatingConstructorCall.kt b/compiler/fir/resolve/testData/resolve/delegatingConstructorCall.kt index 572fe555b15..0150e5633e3 100644 --- a/compiler/fir/resolve/testData/resolve/delegatingConstructorCall.kt +++ b/compiler/fir/resolve/testData/resolve/delegatingConstructorCall.kt @@ -1,4 +1,4 @@ -fun materialize(): K = null!! +fun materialize(): K = null!! open class A1(val x: String) class B1 : A1(materialize()) diff --git a/compiler/fir/resolve/testData/resolve/delegatingConstructorCall.txt b/compiler/fir/resolve/testData/resolve/delegatingConstructorCall.txt index 710189d1fbf..c78301b6fc7 100644 --- a/compiler/fir/resolve/testData/resolve/delegatingConstructorCall.txt +++ b/compiler/fir/resolve/testData/resolve/delegatingConstructorCall.txt @@ -1,14 +1,6 @@ FILE: delegatingConstructorCall.kt public final fun materialize(): R|K| { - ^materialize when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw #() - } - else -> { - R|/| - } - } - + ^materialize Null(null)!! } public open class A1 : R|kotlin/Any| { public constructor(x: R|kotlin/String|): R|A1| { diff --git a/compiler/fir/resolve/testData/resolve/nestedClassNameClash.kt b/compiler/fir/resolve/testData/resolve/nestedClassNameClash.kt index 02430f4c70b..b1df40b3da8 100644 --- a/compiler/fir/resolve/testData/resolve/nestedClassNameClash.kt +++ b/compiler/fir/resolve/testData/resolve/nestedClassNameClash.kt @@ -1,6 +1,6 @@ -fun listOf(): List = null!! +fun listOf(): List = null!! -fun materialize(): T = null!! +fun materialize(): T = null!! class Result diff --git a/compiler/fir/resolve/testData/resolve/nestedClassNameClash.txt b/compiler/fir/resolve/testData/resolve/nestedClassNameClash.txt index bb5e6f31cfb..53fdcb8cdae 100644 --- a/compiler/fir/resolve/testData/resolve/nestedClassNameClash.txt +++ b/compiler/fir/resolve/testData/resolve/nestedClassNameClash.txt @@ -1,25 +1,9 @@ FILE: nestedClassNameClash.kt public final fun listOf(): R|kotlin/collections/List| { - ^listOf when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw #() - } - else -> { - R|/| - } - } - + ^listOf Null(null)!! } public final fun materialize(): R|T| { - ^materialize when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw #() - } - else -> { - R|/| - } - } - + ^materialize Null(null)!! } public final class Result : R|kotlin/Any| { public constructor(): R|Result| { diff --git a/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/inferenceFromCallableReferenceType.txt b/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/inferenceFromCallableReferenceType.txt index bcfe9d226e2..8d886adbacd 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/inferenceFromCallableReferenceType.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/inferenceFromCallableReferenceType.txt @@ -9,28 +9,12 @@ FILE: inferenceFromCallableReferenceType.kt } public final fun baz(x: R|kotlin/String|): R|kotlin/Int| { - ^baz when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|() - } - else -> { - R|/| - } - } - + ^baz Null(null)!! } } public final fun bar(x: R|kotlin/String|): R|kotlin/Int| { - ^bar when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|() - } - else -> { - R|/| - } - } - + ^bar Null(null)!! } public final fun main(): R|kotlin/Unit| { R|/foo|(::R|/bar|) diff --git a/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/inferenceFromExpectedType.txt b/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/inferenceFromExpectedType.txt index 817138b31e0..f4a74451b32 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/inferenceFromExpectedType.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/inferenceFromExpectedType.txt @@ -9,28 +9,12 @@ FILE: inferenceFromExpectedType.kt } public final fun baz(x: R|T|): R|E| { - ^baz when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|() - } - else -> { - R|/| - } - } - + ^baz Null(null)!! } } public final fun bar(x: R|T|): R|E| { - ^bar when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|() - } - else -> { - R|/| - } - } - + ^bar Null(null)!! } public final fun main(): R|kotlin/Unit| { R|/foo|(::R|/bar|) diff --git a/compiler/fir/resolve/testData/resolve/stdlib/factoryFunctionOverloads.txt b/compiler/fir/resolve/testData/resolve/stdlib/factoryFunctionOverloads.txt index 961eed0460f..a57900b4a25 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/factoryFunctionOverloads.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/factoryFunctionOverloads.txt @@ -7,15 +7,7 @@ FILE: factoryFunctionOverloads.kt } public final fun A(b: R|B?|, flag: R|kotlin/Boolean| = Boolean(true)): R|A| { - ^A R|/A.A|(when (lval : R|B?| = R|/b|) { - ==($subj$, Null(null)) -> { - throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|() - } - else -> { - R|/| - } - } - , R|/flag|) + ^A R|/A.A|(R|/b|!!, R|/flag|) } public final fun A(c: R|C|, flag: R|kotlin/Boolean| = Boolean(true)): R|A| { ^A R|/A.A|(R|/c|.R|/C.b|, R|/flag|) diff --git a/compiler/fir/resolve/testData/resolve/stdlib/hashSet.txt b/compiler/fir/resolve/testData/resolve/stdlib/hashSet.txt index 4b7abb20640..33457b9721d 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/hashSet.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/hashSet.txt @@ -18,13 +18,5 @@ FILE: hashSet.kt public final fun foo(): R|kotlin/Unit| { lvar c: R|kotlin/collections/MutableSet?| = Null(null) R|/c| = R|java/util/HashSet.HashSet|() - when (lval : R|java/util/HashSet| = R|/c|) { - ==($subj$, Null(null)) -> { - throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|() - } - else -> { - R|/| - } - } - .R|/d| = R|/produce|() + R|/c|!!.R|/d| = R|/produce|() } diff --git a/compiler/fir/resolve/testData/resolve/whenAsReceiver.kt b/compiler/fir/resolve/testData/resolve/whenAsReceiver.kt index 96199d335c3..f6078dd1139 100644 --- a/compiler/fir/resolve/testData/resolve/whenAsReceiver.kt +++ b/compiler/fir/resolve/testData/resolve/whenAsReceiver.kt @@ -1,5 +1,5 @@ fun T.also(block: () -> R): R { - return null!! + return null!! } fun foo(b: Boolean, a: Int) { diff --git a/compiler/fir/resolve/testData/resolve/whenAsReceiver.txt b/compiler/fir/resolve/testData/resolve/whenAsReceiver.txt index 60bddc99304..95b97b8db58 100644 --- a/compiler/fir/resolve/testData/resolve/whenAsReceiver.txt +++ b/compiler/fir/resolve/testData/resolve/whenAsReceiver.txt @@ -1,14 +1,6 @@ FILE: whenAsReceiver.kt public final fun R|T|.also(block: R|() -> R|): R|R| { - ^also when (lval : R|kotlin/Nothing?| = Null(null)) { - ==($subj$, Null(null)) -> { - throw #() - } - else -> { - R|/| - } - } - + ^also Null(null)!! } public final fun foo(b: R|kotlin/Boolean|, a: R|kotlin/Int|): R|kotlin/Unit| { lval x: R|kotlin/Int?| = when (R|/b|) { diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCheckNotNullCall.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCheckNotNullCall.kt new file mode 100644 index 00000000000..dc0360d22ba --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCheckNotNullCall.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.expressions + +import org.jetbrains.kotlin.fir.FirPureAbstractElement +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.references.FirReference +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.* + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +abstract class FirCheckNotNullCall : FirPureAbstractElement(), FirExpression, FirCall, FirResolvable { + abstract override val source: FirSourceElement? + abstract override val typeRef: FirTypeRef + abstract override val annotations: List + abstract override val arguments: List + abstract override val calleeReference: FirReference + + override fun accept(visitor: FirVisitor, data: D): R = visitor.visitCheckNotNullCall(this, data) + + abstract override fun transformArguments(transformer: FirTransformer, data: D): FirCheckNotNullCall + + abstract override fun transformCalleeReference(transformer: FirTransformer, data: D): FirCheckNotNullCall +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCheckNotNullCallImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCheckNotNullCallImpl.kt new file mode 100644 index 00000000000..3c9473517bc --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCheckNotNullCallImpl.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.expressions.impl + +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall +import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.impl.FirAbstractAnnotatedElement +import org.jetbrains.kotlin.fir.references.FirReference +import org.jetbrains.kotlin.fir.references.impl.FirStubReference +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl +import org.jetbrains.kotlin.fir.visitors.* + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +class FirCheckNotNullCallImpl( + override val source: FirSourceElement? +) : FirCheckNotNullCall(), FirAbstractAnnotatedElement { + override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) + override val annotations: MutableList = mutableListOf() + override val arguments: MutableList = mutableListOf() + override var calleeReference: FirReference = FirStubReference() + + override fun acceptChildren(visitor: FirVisitor, data: D) { + typeRef.accept(visitor, data) + annotations.forEach { it.accept(visitor, data) } + arguments.forEach { it.accept(visitor, data) } + calleeReference.accept(visitor, data) + } + + override fun transformChildren(transformer: FirTransformer, data: D): FirCheckNotNullCallImpl { + typeRef = typeRef.transformSingle(transformer, data) + annotations.transformInplace(transformer, data) + transformArguments(transformer, data) + transformCalleeReference(transformer, data) + return this + } + + override fun transformArguments(transformer: FirTransformer, data: D): FirCheckNotNullCallImpl { + arguments.transformInplace(transformer, data) + return this + } + + override fun transformCalleeReference(transformer: FirTransformer, data: D): FirCheckNotNullCallImpl { + calleeReference = calleeReference.transformSingle(transformer, data) + return this + } + + override fun replaceTypeRef(newTypeRef: FirTypeRef) { + typeRef = newTypeRef + } +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt index 3fe1ef34c2e..f234a524824 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt @@ -73,6 +73,7 @@ import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessWithoutCallee import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess +import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall import org.jetbrains.kotlin.fir.expressions.FirArraySetCall import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression @@ -396,6 +397,10 @@ abstract class FirTransformer : FirVisitor { + return transformElement(checkNotNullCall, data) + } + open fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: D): CompositeTransformResult { return transformElement(arrayOfCall, data) } @@ -844,6 +849,10 @@ abstract class FirTransformer : FirVisitor { + return transformCheckNotNullCall(checkNotNullCall, data) + } + final override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: D): CompositeTransformResult { return transformArrayOfCall(arrayOfCall, data) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt index ae2363f8880..a8e8080a005 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt @@ -73,6 +73,7 @@ import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessWithoutCallee import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess +import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall import org.jetbrains.kotlin.fir.expressions.FirArraySetCall import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression @@ -260,6 +261,8 @@ abstract class FirVisitor { open fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: D): R = visitElement(qualifiedAccess, data) + open fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: D): R = visitElement(checkNotNullCall, data) + open fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: D): R = visitElement(arrayOfCall, data) open fun visitArraySetCall(arraySetCall: FirArraySetCall, data: D): R = visitElement(arraySetCall, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt index a94802349b3..6c9e3721b3e 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt @@ -73,6 +73,7 @@ import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessWithoutCallee import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess +import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall import org.jetbrains.kotlin.fir.expressions.FirArraySetCall import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression @@ -394,6 +395,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitElement(qualifiedAccess) } + open fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall) { + visitElement(checkNotNullCall) + } + open fun visitArrayOfCall(arrayOfCall: FirArrayOfCall) { visitElement(arrayOfCall) } @@ -842,6 +847,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitQualifiedAccess(qualifiedAccess) } + final override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: Nothing?) { + visitCheckNotNullCall(checkNotNullCall) + } + final override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: Nothing?) { visitArrayOfCall(arrayOfCall) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index 9c0a094815f..c9c19729c55 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -923,6 +923,11 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() { } } + override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall) { + checkNotNullCall.argument.accept(this) + print("!!") + } + override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess) { callableReferenceAccess.annotations.renderAnnotations() callableReferenceAccess.explicitReceiver?.accept(this) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt index 1a463e1c9f3..6d9b6b322a3 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt @@ -26,7 +26,7 @@ inline val FirAnnotationCall.classId: ClassId? fun FirConstExpressionImpl(source: FirSourceElement?, kind: FirConstKind, value: T?, diagnostic: FirDiagnostic): FirExpression = value?.let { FirConstExpressionImpl(source, kind, it) } ?: FirErrorExpressionImpl(source, diagnostic) -inline val FirTypeOperatorCall.argument: FirExpression get() = arguments.first() +inline val FirCall.argument: FirExpression get() = arguments.first() fun FirExpression.toResolvedCallableReference(): FirResolvedNamedReference? { return (this as? FirQualifiedAccess)?.calleeReference as? FirResolvedNamedReference diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt index fba4eb9d768..1ec448b94c5 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt @@ -86,6 +86,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() { val whenBranch = element("WhenBranch", Expression) val qualifiedAccessWithoutCallee = element("QualifiedAccessWithoutCallee", Expression, statement) val qualifiedAccess = element("QualifiedAccess", Expression, qualifiedAccessWithoutCallee, resolvable) + val checkNotNullCall = element("CheckNotNullCall", Expression, expression, call, resolvable) val arrayOfCall = element("ArrayOfCall", Expression, expression, call) val arraySetCall = element("ArraySetCall", Expression, qualifiedAccess, call) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index 8d079324377..65f2f9e9550 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -245,6 +245,11 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() defaultNoReceivers() } + impl(checkNotNullCall) { + default("calleeReference", "FirStubReference()") + useTypes(stubReferenceType) + } + noImpl(expressionWithSmartcast) impl(getClassCall) { diff --git a/compiler/testData/codegen/box/binaryOp/callNullable.kt b/compiler/testData/codegen/box/binaryOp/callNullable.kt index f5b12319ac8..0167a38ed04 100644 --- a/compiler/testData/codegen/box/binaryOp/callNullable.kt +++ b/compiler/testData/codegen/box/binaryOp/callNullable.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { val a1: Byte? = 1.plus(1) val a2: Short? = 1.plus(1) diff --git a/compiler/testData/codegen/box/binaryOp/intrinsicNullable.kt b/compiler/testData/codegen/box/binaryOp/intrinsicNullable.kt index a42b6bc8d40..fdfc98f3bb4 100644 --- a/compiler/testData/codegen/box/binaryOp/intrinsicNullable.kt +++ b/compiler/testData/codegen/box/binaryOp/intrinsicNullable.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { val a1: Byte? = 1 + 1 val a2: Short? = 1 + 1 diff --git a/compiler/testData/codegen/box/classes/kt725.kt b/compiler/testData/codegen/box/classes/kt725.kt index d37c758a743..3aea020f890 100644 --- a/compiler/testData/codegen/box/classes/kt725.kt +++ b/compiler/testData/codegen/box/classes/kt725.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR operator fun Int?.inc() = this!!.inc() public fun box() : String { diff --git a/compiler/testData/codegen/box/controlStructures/kt2147.kt b/compiler/testData/codegen/box/controlStructures/kt2147.kt index 11e467e4e20..df664fb16ef 100644 --- a/compiler/testData/codegen/box/controlStructures/kt2147.kt +++ b/compiler/testData/codegen/box/controlStructures/kt2147.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR class Foo { fun isOk() = true } diff --git a/compiler/testData/codegen/box/controlStructures/kt628.kt b/compiler/testData/codegen/box/controlStructures/kt628.kt index 12348233fcd..234e336e5a7 100644 --- a/compiler/testData/codegen/box/controlStructures/kt628.kt +++ b/compiler/testData/codegen/box/controlStructures/kt628.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR class A() { fun action() = "OK" diff --git a/compiler/testData/codegen/box/controlStructures/returnsNothing/ifElse.kt b/compiler/testData/codegen/box/controlStructures/returnsNothing/ifElse.kt index 522ac25759b..98d5401d12e 100644 --- a/compiler/testData/codegen/box/controlStructures/returnsNothing/ifElse.kt +++ b/compiler/testData/codegen/box/controlStructures/returnsNothing/ifElse.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR var flag = true fun exit(): Nothing = null!! diff --git a/compiler/testData/codegen/box/controlStructures/returnsNothing/inlineMethod.kt b/compiler/testData/codegen/box/controlStructures/returnsNothing/inlineMethod.kt index 417e9265778..5ec5f8feff2 100644 --- a/compiler/testData/codegen/box/controlStructures/returnsNothing/inlineMethod.kt +++ b/compiler/testData/codegen/box/controlStructures/returnsNothing/inlineMethod.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR inline fun exit(): Nothing = null!! fun box(): String { diff --git a/compiler/testData/codegen/box/controlStructures/returnsNothing/propertyGetter.kt b/compiler/testData/codegen/box/controlStructures/returnsNothing/propertyGetter.kt index 499a2ac187d..1b69f5b1b66 100644 --- a/compiler/testData/codegen/box/controlStructures/returnsNothing/propertyGetter.kt +++ b/compiler/testData/codegen/box/controlStructures/returnsNothing/propertyGetter.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR var flag = true object Test { diff --git a/compiler/testData/codegen/box/controlStructures/returnsNothing/tryCatch.kt b/compiler/testData/codegen/box/controlStructures/returnsNothing/tryCatch.kt index c58a163744f..bc23f5cb748 100644 --- a/compiler/testData/codegen/box/controlStructures/returnsNothing/tryCatch.kt +++ b/compiler/testData/codegen/box/controlStructures/returnsNothing/tryCatch.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun exit(): Nothing = null!! fun box(): String { diff --git a/compiler/testData/codegen/box/controlStructures/returnsNothing/when.kt b/compiler/testData/codegen/box/controlStructures/returnsNothing/when.kt index 3df1609982a..e4953bb6e3c 100644 --- a/compiler/testData/codegen/box/controlStructures/returnsNothing/when.kt +++ b/compiler/testData/codegen/box/controlStructures/returnsNothing/when.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun exit(): Nothing = null!! var x = 0 diff --git a/compiler/testData/codegen/box/exclExcl/genericNull.kt b/compiler/testData/codegen/box/exclExcl/genericNull.kt index 9b8fc8adeaa..0d4f831dfb7 100644 --- a/compiler/testData/codegen/box/exclExcl/genericNull.kt +++ b/compiler/testData/codegen/box/exclExcl/genericNull.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun foo(t: T) { t!! } diff --git a/compiler/testData/codegen/box/fullJdk/ifInWhile.kt b/compiler/testData/codegen/box/fullJdk/ifInWhile.kt index 8490636566f..8831f244021 100644 --- a/compiler/testData/codegen/box/fullJdk/ifInWhile.kt +++ b/compiler/testData/codegen/box/fullJdk/ifInWhile.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // FULL_JDK diff --git a/compiler/testData/codegen/box/ieee754/explicitCompareCall.kt b/compiler/testData/codegen/box/ieee754/explicitCompareCall.kt index 62cd3f7a216..57d0b06328d 100644 --- a/compiler/testData/codegen/box/ieee754/explicitCompareCall.kt +++ b/compiler/testData/codegen/box/ieee754/explicitCompareCall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun less1(a: Double, b: Double) = a.compareTo(b) == -1 fun less2(a: Double?, b: Double?) = a!!.compareTo(b!!) == -1 diff --git a/compiler/testData/codegen/box/ieee754/explicitEqualsCall.kt b/compiler/testData/codegen/box/ieee754/explicitEqualsCall.kt index 0ee1a4c550b..51dfd696f72 100644 --- a/compiler/testData/codegen/box/ieee754/explicitEqualsCall.kt +++ b/compiler/testData/codegen/box/ieee754/explicitEqualsCall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun equals1(a: Double, b: Double) = a.equals(b) fun equals2(a: Double?, b: Double?) = a!!.equals(b!!) diff --git a/compiler/testData/codegen/box/ieee754/greaterDouble_properIeeeComparisons.kt b/compiler/testData/codegen/box/ieee754/greaterDouble_properIeeeComparisons.kt index 18b56cf3681..27740d7c318 100644 --- a/compiler/testData/codegen/box/ieee754/greaterDouble_properIeeeComparisons.kt +++ b/compiler/testData/codegen/box/ieee754/greaterDouble_properIeeeComparisons.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +ProperIeee754Comparisons -// IGNORE_BACKEND_FIR: JVM_IR fun greater1(a: Double, b: Double) = a > b diff --git a/compiler/testData/codegen/box/ieee754/greaterFloat_properIeeeComparisons.kt b/compiler/testData/codegen/box/ieee754/greaterFloat_properIeeeComparisons.kt index 5f9a3ecfe59..baa388c59bf 100644 --- a/compiler/testData/codegen/box/ieee754/greaterFloat_properIeeeComparisons.kt +++ b/compiler/testData/codegen/box/ieee754/greaterFloat_properIeeeComparisons.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +ProperIeee754Comparisons -// IGNORE_BACKEND_FIR: JVM_IR fun greater1(a: Float, b: Float) = a > b diff --git a/compiler/testData/codegen/box/ieee754/lessDouble_properIeeeComparisons.kt b/compiler/testData/codegen/box/ieee754/lessDouble_properIeeeComparisons.kt index 707c79e13b1..c12061d393b 100644 --- a/compiler/testData/codegen/box/ieee754/lessDouble_properIeeeComparisons.kt +++ b/compiler/testData/codegen/box/ieee754/lessDouble_properIeeeComparisons.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +ProperIeee754Comparisons -// IGNORE_BACKEND_FIR: JVM_IR fun less1(a: Double, b: Double) = a < b diff --git a/compiler/testData/codegen/box/ieee754/lessFloat_properIeeeComparisons.kt b/compiler/testData/codegen/box/ieee754/lessFloat_properIeeeComparisons.kt index 04c1eb67894..03307553086 100644 --- a/compiler/testData/codegen/box/ieee754/lessFloat_properIeeeComparisons.kt +++ b/compiler/testData/codegen/box/ieee754/lessFloat_properIeeeComparisons.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +ProperIeee754Comparisons -// IGNORE_BACKEND_FIR: JVM_IR fun less1(a: Float, b: Float) = a < b diff --git a/compiler/testData/codegen/box/ieee754/safeCall.kt b/compiler/testData/codegen/box/ieee754/safeCall.kt index ba82f682dbc..690b6168935 100644 --- a/compiler/testData/codegen/box/ieee754/safeCall.kt +++ b/compiler/testData/codegen/box/ieee754/safeCall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { val plusZero: Double? = 0.0 val minusZero: Double = -0.0 diff --git a/compiler/testData/codegen/box/intrinsics/throwable.kt b/compiler/testData/codegen/box/intrinsics/throwable.kt index 33bde10d04f..b0ddd265abc 100644 --- a/compiler/testData/codegen/box/intrinsics/throwable.kt +++ b/compiler/testData/codegen/box/intrinsics/throwable.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS, NATIVE diff --git a/compiler/testData/codegen/box/lazyCodegen/optimizations/negateObjectComp.kt b/compiler/testData/codegen/box/lazyCodegen/optimizations/negateObjectComp.kt index aa5de10a64c..58e15f4de93 100644 --- a/compiler/testData/codegen/box/lazyCodegen/optimizations/negateObjectComp.kt +++ b/compiler/testData/codegen/box/lazyCodegen/optimizations/negateObjectComp.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR val p: Int? = 1; val z: Int? = 2; diff --git a/compiler/testData/codegen/box/lazyCodegen/optimizations/negateObjectComp2.kt b/compiler/testData/codegen/box/lazyCodegen/optimizations/negateObjectComp2.kt index ea6fa11cabf..e1a13f17cc9 100644 --- a/compiler/testData/codegen/box/lazyCodegen/optimizations/negateObjectComp2.kt +++ b/compiler/testData/codegen/box/lazyCodegen/optimizations/negateObjectComp2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR val p: Int? = 1; val z: Int? = 2; diff --git a/compiler/testData/codegen/box/lazyCodegen/safeAssign.kt b/compiler/testData/codegen/box/lazyCodegen/safeAssign.kt index a5aab7d9f46..8019455b3da 100644 --- a/compiler/testData/codegen/box/lazyCodegen/safeAssign.kt +++ b/compiler/testData/codegen/box/lazyCodegen/safeAssign.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR class Shape(var result: String) { } diff --git a/compiler/testData/codegen/box/primitiveTypes/kt3613.kt b/compiler/testData/codegen/box/primitiveTypes/kt3613.kt index df4c7f43745..c578f93fb7e 100644 --- a/compiler/testData/codegen/box/primitiveTypes/kt3613.kt +++ b/compiler/testData/codegen/box/primitiveTypes/kt3613.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun foo(): Int? = 42 fun box(): String { diff --git a/compiler/testData/codegen/box/primitiveTypes/kt4098.kt b/compiler/testData/codegen/box/primitiveTypes/kt4098.kt index ae4af9e5eab..a74f18feeac 100644 --- a/compiler/testData/codegen/box/primitiveTypes/kt4098.kt +++ b/compiler/testData/codegen/box/primitiveTypes/kt4098.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { val c: Char? = '0' c!!.toInt() diff --git a/compiler/testData/codegen/box/primitiveTypes/kt4210.kt b/compiler/testData/codegen/box/primitiveTypes/kt4210.kt index 17484d4a12b..4f3b16d0e6e 100644 --- a/compiler/testData/codegen/box/primitiveTypes/kt4210.kt +++ b/compiler/testData/codegen/box/primitiveTypes/kt4210.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { val s: String? = "abc" val c = s?.get(0)!! - 'b' diff --git a/compiler/testData/codegen/box/primitiveTypes/kt753.kt b/compiler/testData/codegen/box/primitiveTypes/kt753.kt index 5b342329bfc..1b02e46ee54 100644 --- a/compiler/testData/codegen/box/primitiveTypes/kt753.kt +++ b/compiler/testData/codegen/box/primitiveTypes/kt753.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS, NATIVE diff --git a/compiler/testData/codegen/box/primitiveTypes/kt756.kt b/compiler/testData/codegen/box/primitiveTypes/kt756.kt index a9490866a7f..b201b52f467 100644 --- a/compiler/testData/codegen/box/primitiveTypes/kt756.kt +++ b/compiler/testData/codegen/box/primitiveTypes/kt756.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS, NATIVE diff --git a/compiler/testData/codegen/box/primitiveTypes/kt757.kt b/compiler/testData/codegen/box/primitiveTypes/kt757.kt index 1dc9446de06..037df703423 100644 --- a/compiler/testData/codegen/box/primitiveTypes/kt757.kt +++ b/compiler/testData/codegen/box/primitiveTypes/kt757.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS, NATIVE diff --git a/compiler/testData/codegen/box/primitiveTypes/nullAsNullableIntIsNull.kt b/compiler/testData/codegen/box/primitiveTypes/nullAsNullableIntIsNull.kt index 9ec0f1653af..a9273088e10 100644 --- a/compiler/testData/codegen/box/primitiveTypes/nullAsNullableIntIsNull.kt +++ b/compiler/testData/codegen/box/primitiveTypes/nullAsNullableIntIsNull.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { try { if ((null as Int?)!! == 10) return "Fail #1" diff --git a/compiler/testData/codegen/box/primitiveTypes/nullableCharBoolean.kt b/compiler/testData/codegen/box/primitiveTypes/nullableCharBoolean.kt index 65bf080a44b..ddc86b85777 100644 --- a/compiler/testData/codegen/box/primitiveTypes/nullableCharBoolean.kt +++ b/compiler/testData/codegen/box/primitiveTypes/nullableCharBoolean.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { val c: Char? = 'a' if (c!! - 'a' != 0) return "Fail c" diff --git a/compiler/testData/codegen/box/specialBuiltins/throwable.kt b/compiler/testData/codegen/box/specialBuiltins/throwable.kt index f8fb7f6fc9f..e4040a63794 100644 --- a/compiler/testData/codegen/box/specialBuiltins/throwable.kt +++ b/compiler/testData/codegen/box/specialBuiltins/throwable.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { try { throw Throwable("OK", null) diff --git a/compiler/testData/codegen/box/unaryOp/callNullable.kt b/compiler/testData/codegen/box/unaryOp/callNullable.kt index 7fc7c8c4740..f3ff7db949a 100644 --- a/compiler/testData/codegen/box/unaryOp/callNullable.kt +++ b/compiler/testData/codegen/box/unaryOp/callNullable.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { val a1: Byte? = 1.unaryMinus() val a2: Short? = 1.unaryMinus() diff --git a/compiler/testData/codegen/box/unaryOp/intrinsicNullable.kt b/compiler/testData/codegen/box/unaryOp/intrinsicNullable.kt index 5edb9718d52..0463bcddba9 100644 --- a/compiler/testData/codegen/box/unaryOp/intrinsicNullable.kt +++ b/compiler/testData/codegen/box/unaryOp/intrinsicNullable.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { val a1: Byte? = -1 val a2: Short? = -1 diff --git a/compiler/testData/ir/irText/expressions/bangbang.fir.txt b/compiler/testData/ir/irText/expressions/bangbang.fir.txt index bfcd73465df..dcb24876968 100644 --- a/compiler/testData/ir/irText/expressions/bangbang.fir.txt +++ b/compiler/testData/ir/irText/expressions/bangbang.fir.txt @@ -3,55 +3,25 @@ FILE fqName: fileName:/bangbang.kt VALUE_PARAMETER name:a index:0 type:kotlin.Any? BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test1 (a: kotlin.Any?): kotlin.Any declared in ' - BLOCK type=kotlin.Any origin=EXCLEXCL - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Any? [val] - GET_VAR 'a: kotlin.Any? declared in .test1' type=kotlin.Any? origin=null - WHEN type=kotlin.Any origin=EXCLEXCL - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_0: kotlin.Any? [val] declared in .test1' type=kotlin.Any? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: THROW type=kotlin.Nothing - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_0: kotlin.Any? [val] declared in .test1' type=kotlin.Any origin=null + CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.Any origin=EXCLEXCL + : kotlin.Any + arg0: GET_VAR 'a: kotlin.Any? declared in .test1' type=kotlin.Any? origin=null FUN name:test2 visibility:public modality:FINAL <> (a:kotlin.Any?) returnType:kotlin.Int VALUE_PARAMETER name:a index:0 type:kotlin.Any? BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test2 (a: kotlin.Any?): kotlin.Int declared in ' - BLOCK type=kotlin.Int origin=EXCLEXCL - VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int? [val] - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int? origin=null - $this: GET_VAR 'a: kotlin.Any? declared in .test2' type=kotlin.Any? origin=null - WHEN type=kotlin.Int origin=EXCLEXCL - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_1: kotlin.Int? [val] declared in .test2' type=kotlin.Int? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: THROW type=kotlin.Nothing - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_1: kotlin.Int? [val] declared in .test2' type=kotlin.Int origin=null - FUN name:test3 visibility:public modality:FINAL (a:X of .test3) returnType:kotlin.Any + CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.Int origin=EXCLEXCL + : kotlin.Int + arg0: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int? origin=null + $this: GET_VAR 'a: kotlin.Any? declared in .test2' type=kotlin.Any? origin=null + FUN name:test3 visibility:public modality:FINAL (a:X of .test3) returnType:X of .test3 TYPE_PARAMETER name:X index:0 variance: superTypes:[kotlin.Any?] VALUE_PARAMETER name:a index:0 type:X of .test3 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test3 (a: X of .test3): kotlin.Any declared in ' - BLOCK type=kotlin.Any origin=EXCLEXCL - VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:X of .test3 [val] - GET_VAR 'a: X of .test3 declared in .test3' type=X of .test3 origin=null - WHEN type=kotlin.Any origin=EXCLEXCL - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_2: X of .test3 [val] declared in .test3' type=X of .test3 origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: THROW type=kotlin.Nothing - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_2: X of .test3 [val] declared in .test3' type=kotlin.Any origin=null + RETURN type=kotlin.Nothing from='public final fun test3 (a: X of .test3): X of .test3 declared in ' + CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=X of .test3 origin=EXCLEXCL + : X of .test3 + arg0: GET_VAR 'a: X of .test3 declared in .test3' type=X of .test3 origin=null FUN name:useString visibility:public modality:FINAL <> (s:kotlin.String) returnType:kotlin.Unit VALUE_PARAMETER name:s index:0 type:kotlin.String BLOCK_BODY @@ -63,34 +33,14 @@ FILE fqName: fileName:/bangbang.kt BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String? GET_VAR 'a: X of .test4 declared in .test4' type=X of .test4 origin=null - then: BLOCK type=kotlin.String origin=EXCLEXCL - VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.String? [val] - GET_VAR 'a: X of .test4 declared in .test4' type=kotlin.String? origin=null - WHEN type=kotlin.String origin=EXCLEXCL - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_3: kotlin.String? [val] declared in .test4' type=kotlin.String? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: THROW type=kotlin.Nothing - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_3: kotlin.String? [val] declared in .test4' type=kotlin.String origin=null + then: CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.String? origin=EXCLEXCL + : kotlin.String + arg0: GET_VAR 'a: X of .test4 declared in .test4' type=kotlin.String? origin=null WHEN type=kotlin.Unit origin=IF BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String? GET_VAR 'a: X of .test4 declared in .test4' type=X of .test4 origin=null then: CALL 'public final fun useString (s: kotlin.String): kotlin.Unit declared in ' type=kotlin.Unit origin=null - s: BLOCK type=kotlin.String origin=EXCLEXCL - VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.String? [val] - GET_VAR 'a: X of .test4 declared in .test4' type=kotlin.String? origin=null - WHEN type=kotlin.String origin=EXCLEXCL - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_4: kotlin.String? [val] declared in .test4' type=kotlin.String? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: THROW type=kotlin.Nothing - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_4: kotlin.String? [val] declared in .test4' type=kotlin.String origin=null + s: CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.String? origin=EXCLEXCL + : kotlin.String + arg0: GET_VAR 'a: X of .test4 declared in .test4' type=kotlin.String? origin=null diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/eqeqRhsConditionPossiblyAffectingLhs.fir.txt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/eqeqRhsConditionPossiblyAffectingLhs.fir.txt index deb53faa298..479d79ca02c 100644 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/eqeqRhsConditionPossiblyAffectingLhs.fir.txt +++ b/compiler/testData/ir/irText/expressions/floatingPointComparisons/eqeqRhsConditionPossiblyAffectingLhs.fir.txt @@ -9,19 +9,9 @@ FILE fqName: fileName:/eqeqRhsConditionPossiblyAffectingLhs.kt BRANCH if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=kotlin.Double GET_VAR 'x: kotlin.Any declared in .test' type=kotlin.Any origin=null - then: BLOCK type=kotlin.Nothing origin=EXCLEXCL - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Nothing? [val] - CONST Null type=kotlin.Nothing? value=null - WHEN type=kotlin.Nothing origin=EXCLEXCL - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_0: kotlin.Nothing? [val] declared in .test' type=kotlin.Nothing? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: THROW type=kotlin.Nothing - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_0: kotlin.Nothing? [val] declared in .test' type=kotlin.Nothing origin=null + then: CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.Nothing origin=EXCLEXCL + : kotlin.Nothing + arg0: CONST Null type=kotlin.Nothing? value=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true then: GET_VAR 'x: kotlin.Any declared in .test' type=kotlin.Double origin=null diff --git a/compiler/testData/ir/irText/expressions/kt30020.fir.txt b/compiler/testData/ir/irText/expressions/kt30020.fir.txt index 021c9130b67..472e436d59e 100644 --- a/compiler/testData/ir/irText/expressions/kt30020.fir.txt +++ b/compiler/testData/ir/irText/expressions/kt30020.fir.txt @@ -48,37 +48,17 @@ FILE fqName: fileName:/kt30020.kt element: CONST Int type=kotlin.Int value=4 CALL 'public final fun plusAssign (element: T of kotlin.collections.plusAssign): kotlin.Unit [inline,operator] declared in kotlin.collections' type=kotlin.Unit origin=null : kotlin.Int - $receiver: BLOCK type=kotlin.collections.MutableList origin=EXCLEXCL - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.collections.MutableList [val] - CALL 'public abstract fun (): kotlin.collections.MutableList declared in .X' type=kotlin.collections.MutableList origin=null - $this: GET_VAR 'nx: .X? declared in .test' type=.X? origin=null - WHEN type=kotlin.collections.MutableList origin=EXCLEXCL - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_0: kotlin.collections.MutableList [val] declared in .test' type=kotlin.collections.MutableList origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: THROW type=kotlin.Nothing - CONSTRUCTOR_CALL 'public constructor () declared in kotlin.KotlinNullPointerException' type=kotlin.KotlinNullPointerException origin=null - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_0: kotlin.collections.MutableList [val] declared in .test' type=kotlin.collections.MutableList origin=null + $receiver: CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.collections.MutableList origin=EXCLEXCL + : kotlin.collections.MutableList + arg0: CALL 'public abstract fun (): kotlin.collections.MutableList declared in .X' type=kotlin.collections.MutableList origin=null + $this: GET_VAR 'nx: .X? declared in .test' type=.X? origin=null element: CONST Int type=kotlin.Int value=5 CALL 'public final fun plusAssign (element: T of kotlin.collections.plusAssign): kotlin.Unit [inline,operator] declared in kotlin.collections' type=kotlin.Unit origin=null : kotlin.Int - $receiver: BLOCK type=kotlin.collections.MutableList origin=EXCLEXCL - VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.collections.MutableList? [val] - CALL 'public abstract fun f (): kotlin.collections.MutableList declared in .X' type=kotlin.collections.MutableList? origin=null - $this: GET_VAR 'nx: .X? declared in .test' type=.X origin=null - WHEN type=kotlin.collections.MutableList origin=EXCLEXCL - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_1: kotlin.collections.MutableList? [val] declared in .test' type=kotlin.collections.MutableList? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: THROW type=kotlin.Nothing - CONSTRUCTOR_CALL 'public constructor () declared in kotlin.KotlinNullPointerException' type=kotlin.KotlinNullPointerException origin=null - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_1: kotlin.collections.MutableList? [val] declared in .test' type=kotlin.collections.MutableList origin=null + $receiver: CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.collections.MutableList origin=EXCLEXCL + : kotlin.collections.MutableList + arg0: CALL 'public abstract fun f (): kotlin.collections.MutableList declared in .X' type=kotlin.collections.MutableList? origin=null + $this: GET_VAR 'nx: .X? declared in .test' type=.X? origin=null element: CONST Int type=kotlin.Int value=6 FUN name:testExtensionReceiver visibility:public modality:FINAL <> ($receiver:kotlin.collections.MutableList) returnType:kotlin.Unit $receiver: VALUE_PARAMETER name: type:kotlin.collections.MutableList