diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirReturnsImpliesAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirReturnsImpliesAnalyzer.kt index 5b1a821867c..53cc228d7ff 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirReturnsImpliesAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirReturnsImpliesAnalyzer.kt @@ -27,10 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.dfa.cfg.JumpNode import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol import org.jetbrains.kotlin.fir.typeContext -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.coneType -import org.jetbrains.kotlin.fir.types.intersectTypesOrNull -import org.jetbrains.kotlin.fir.types.isNullable +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.utils.addIfNotNull @@ -56,7 +53,7 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() { throw IllegalStateException("Update of all receivers is not possible for this logic system") override fun ConeKotlinType.isAcceptableForSmartcast(): Boolean { - return true + return !isNullableNothing } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt index cb39e86be00..ebe7c9e559f 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt @@ -277,6 +277,14 @@ class Fir2IrImplicitCastInserter( return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef) } + override fun visitExpressionWithSmartcastToNull( + expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, + data: IrElement + ): IrElement { + // We don't want an implicit cast to Nothing?. This expression just encompasses nullability after null check. + return data + } + internal fun implicitCastFromDispatchReceiver( original: IrExpression, originalTypeRef: FirTypeRef, 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 c6c2384e2f1..c62983eff3c 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 @@ -420,6 +420,14 @@ class Fir2IrVisitor( return implicitCastInserter.visitExpressionWithSmartcast(expressionWithSmartcast, value) } + override fun visitExpressionWithSmartcastToNull( + expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, + data: Any? + ): IrElement { + // This should not be materialized. Generate the expression with the original expression. + return convertToIrExpression(expressionWithSmartcastToNull.originalExpression) + } + override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement { val explicitReceiverExpression = convertToIrReceiverExpression( callableReferenceAccess.explicitReceiver, callableReferenceAccess.calleeReference, callableReferenceAccess diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index 98ec4b43de3..e510e28564f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -247,9 +247,35 @@ private fun BodyResolveComponents.typeFromSymbol(symbol: AbstractFirBasedSymbol< } } -fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): FirQualifiedAccessExpression { +fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo( + qualifiedAccessExpression: FirQualifiedAccessExpression +): FirQualifiedAccessExpression { val typesFromSmartCast = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression) ?: return qualifiedAccessExpression val originalType = qualifiedAccessExpression.resultType.coneType + // For example, if (x == null) { ... }, + // we don't want to smartcast to Nothing?, but we want to record the nullability to its own kind of node. + // TODO: should we differentiate x == null v.s. x is Nothing? + if (typesFromSmartCast.any { it.isNullableNothing }) { + val typesFromSmartcastWithoutNullableNothing = + typesFromSmartCast.filterTo(mutableListOf()) { !it.isNullableNothing }.also { + it += originalType + } + val intersectedTypeWithoutNullableNothing = + ConeTypeIntersector.intersectTypes(session.inferenceComponents.ctx, typesFromSmartcastWithoutNullableNothing) + val intersectedTypeRefWithoutNullableNothing = buildResolvedTypeRef { + source = qualifiedAccessExpression.resultType.source?.fakeElement(FirFakeSourceElementKind.SmartCastedTypeRef) + type = intersectedTypeWithoutNullableNothing + annotations += qualifiedAccessExpression.resultType.annotations + delegatedTypeRef = qualifiedAccessExpression.resultType + } + return buildExpressionWithSmartcastToNull { + originalExpression = qualifiedAccessExpression + // TODO: Use Nothing? during resolution? + typeRef = intersectedTypeRefWithoutNullableNothing + // NB: Nothing? in types from smartcast in DFA is recorded here (and the expression kind itself). + this.typesFromSmartCast = typesFromSmartCast + } + } val allTypes = typesFromSmartCast.also { it += originalType } @@ -259,6 +285,7 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAc source = qualifiedAccessExpression.resultType.source?.fakeElement(FirFakeSourceElementKind.SmartCastedTypeRef) type = intersectedType annotations += qualifiedAccessExpression.resultType.annotations + delegatedTypeRef = qualifiedAccessExpression.resultType } return buildExpressionWithSmartcast { originalExpression = qualifiedAccessExpression diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index 7ddc401ef6e..36f0592df6a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -119,9 +119,11 @@ abstract class FirDataFlowAnalyzer( } override fun ConeKotlinType.isAcceptableForSmartcast(): Boolean { + if (this.isNullableNothing) return false return when (this) { is ConeClassLikeType -> { - val symbol = fullyExpandedType(components.session).lookupTag.toSymbol(components.session) ?: return false + val symbol = + fullyExpandedType(components.session).lookupTag.toSymbol(components.session) ?: return false val declaration = symbol.fir as? FirRegularClass ?: return true visibilityChecker.isVisible( declaration, @@ -545,9 +547,12 @@ abstract class FirDataFlowAnalyzer( flow.addImplication((expressionVariable notEq isEq) implies (operandVariable typeEq any)) } -// TODO: design do we need casts to Nothing? -// flow.addImplication((expressionVariable eq !isEq) implies (operandVariable typeEq nullableNothing)) -// flow.addImplication((expressionVariable notEq !isEq) implies (operandVariable typeNotEq nullableNothing)) + if (shouldAddImplicationForStatement(expressionVariable eq !isEq)) { + flow.addImplication((expressionVariable eq !isEq) implies (operandVariable typeNotEq nullableNothing)) + } + if (shouldAddImplicationForStatement(expressionVariable notEq !isEq)) { + flow.addImplication((expressionVariable notEq !isEq) implies (operandVariable typeEq nullableNothing)) + } } node.flow = flow } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt index 7c763a21042..e203d07b79f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt @@ -99,7 +99,10 @@ internal val FirElement.symbol: AbstractFirBasedSymbol<*>? is FirWhenSubjectExpression -> whenRef.value.subject?.symbol is FirSafeCallExpression -> regularQualifiedAccess.symbol else -> null - }?.takeIf { this.unwrapSmartcastExpression() is FirThisReceiverExpression || (it !is FirFunctionSymbol<*> && it !is FirAccessorSymbol) } + }?.takeIf { + (this as? FirExpression)?.unwrapSmartcastExpression() is FirThisReceiverExpression || + (it !is FirFunctionSymbol<*> && it !is FirAccessorSymbol) + } @DfaInternals internal val FirResolvable.symbol: AbstractFirBasedSymbol<*>? @@ -110,4 +113,8 @@ internal val FirResolvable.symbol: AbstractFirBasedSymbol<*>? else -> null } -private fun FirElement.unwrapSmartcastExpression(): FirElement = if (this is FirExpressionWithSmartcast) originalExpression else this +internal fun FirExpression.unwrapSmartcastExpression(): FirExpression = + when (this) { + is FirExpressionWithSmartcast -> originalExpression + else -> this + } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 068b81c8ff8..2224ea86e21 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl +import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor @@ -793,7 +794,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor if (variable.returnTypeRef is FirImplicitTypeRef) { val resultType = when { initializer != null -> { - val unwrappedInitializer = (initializer as? FirExpressionWithSmartcast)?.originalExpression ?: initializer + val unwrappedInitializer = initializer.unwrapSmartcastExpression() unwrappedInitializer.resultType } variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> variable.getter?.returnTypeRef diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/ConeEffectExtractor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/ConeEffectExtractor.kt index 2f97eb2805c..c90d8318c2c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/ConeEffectExtractor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/ConeEffectExtractor.kt @@ -118,6 +118,13 @@ class ConeEffectExtractor( return expressionWithSmartcast.originalExpression.accept(this, data) } + override fun visitExpressionWithSmartcastToNull( + expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, + data: Nothing? + ): ConeContractDescriptionElement? { + return expressionWithSmartcastToNull.originalExpression.accept(this, data) + } + override fun visitQualifiedAccessExpression( qualifiedAccessExpression: FirQualifiedAccessExpression, data: Nothing? @@ -189,4 +196,4 @@ class ConeEffectExtractor( else -> null } } -} \ No newline at end of file +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcastToNull.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcastToNull.kt new file mode 100644 index 00000000000..3e643586063 --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcastToNull.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2021 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.FirElement +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.references.FirReference +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.FirTypeProjection +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.fir.FirImplementationDetail + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +abstract class FirExpressionWithSmartcastToNull : FirExpressionWithSmartcast() { + abstract override val source: FirSourceElement? + abstract override val typeRef: FirTypeRef + abstract override val annotations: List + abstract override val calleeReference: FirReference + abstract override val typeArguments: List + abstract override val explicitReceiver: FirExpression? + abstract override val dispatchReceiver: FirExpression + abstract override val extensionReceiver: FirExpression + abstract override val originalExpression: FirQualifiedAccessExpression + abstract override val typesFromSmartCast: Collection + abstract override val originalType: FirTypeRef + + override fun accept(visitor: FirVisitor, data: D): R = visitor.visitExpressionWithSmartcastToNull(this, data) + + @Suppress("UNCHECKED_CAST") + override fun transform(transformer: FirTransformer, data: D): E = + transformer.transformExpressionWithSmartcastToNull(this, data) as E + + @FirImplementationDetail + abstract override fun replaceSource(newSource: FirSourceElement?) + + abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + + abstract override fun replaceCalleeReference(newCalleeReference: FirReference) + + abstract override fun replaceTypeArguments(newTypeArguments: List) + + abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) + + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull + + abstract override fun transformCalleeReference(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull + + abstract override fun transformTypeArguments(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull + + abstract override fun transformExplicitReceiver(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull + + abstract override fun transformDispatchReceiver(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull + + abstract override fun transformExtensionReceiver(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull +} 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 dd9216418e5..5785f82fda7 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 @@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast +import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject import org.jetbrains.kotlin.fir.expressions.FirGetClassCall @@ -480,6 +481,10 @@ abstract class FirTransformer : FirVisitor() { return transformElement(expressionWithSmartcast, data) } + open fun transformExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): FirStatement { + return transformElement(expressionWithSmartcastToNull, data) + } + open fun transformSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): FirStatement { return transformElement(safeCallExpression, data) } @@ -980,6 +985,10 @@ abstract class FirTransformer : FirVisitor() { return transformExpressionWithSmartcast(expressionWithSmartcast, data) } + final override fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): FirStatement { + return transformExpressionWithSmartcastToNull(expressionWithSmartcastToNull, data) + } + final override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): FirStatement { return transformSafeCallExpression(safeCallExpression, 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 d64174b776c..3749d283c7a 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 @@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast +import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject import org.jetbrains.kotlin.fir.expressions.FirGetClassCall @@ -309,6 +310,8 @@ abstract class FirVisitor { open fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: D): R = visitElement(expressionWithSmartcast, data) + open fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): R = visitElement(expressionWithSmartcastToNull, data) + open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): R = visitElement(safeCallExpression, data) open fun visitCheckedSafeCallSubject(checkedSafeCallSubject: FirCheckedSafeCallSubject, data: D): R = visitElement(checkedSafeCallSubject, 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 7996a04e254..d424151e70d 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 @@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast +import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject import org.jetbrains.kotlin.fir.expressions.FirGetClassCall @@ -479,6 +480,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitElement(expressionWithSmartcast) } + open fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull) { + visitElement(expressionWithSmartcastToNull) + } + open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression) { visitElement(safeCallExpression) } @@ -979,6 +984,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitExpressionWithSmartcast(expressionWithSmartcast) } + final override fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: Nothing?) { + visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull) + } + final override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Nothing?) { visitSafeCallExpression(safeCallExpression) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/builder/FirExpressionWithSmartcastToNullBuilder.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/builder/FirExpressionWithSmartcastToNullBuilder.kt new file mode 100644 index 00000000000..b639f24c92d --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/builder/FirExpressionWithSmartcastToNullBuilder.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2021 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.builder + +import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastToNullImpl +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.FirTypeRef + +class FirExpressionWithSmartcastToNullBuilder { + lateinit var originalExpression: FirQualifiedAccessExpression + lateinit var typeRef: FirTypeRef + lateinit var typesFromSmartCast: Collection + + fun build(): FirExpressionWithSmartcastToNull { + return FirExpressionWithSmartcastToNullImpl(originalExpression, typeRef, typesFromSmartCast) + } +} + +inline fun buildExpressionWithSmartcastToNull(init: FirExpressionWithSmartcastToNullBuilder.() -> Unit): FirExpressionWithSmartcastToNull { + return FirExpressionWithSmartcastToNullBuilder().apply(init).build() +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastToNullImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastToNullImpl.kt new file mode 100644 index 00000000000..117b4c8702b --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastToNullImpl.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2021 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.FirImplementationDetail +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.references.FirReference +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.FirTypeProjection +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.FirVisitor +import org.jetbrains.kotlin.fir.visitors.transformSingle + +class FirExpressionWithSmartcastToNullImpl( + override var originalExpression: FirQualifiedAccessExpression, + override val typeRef: FirTypeRef, + override val typesFromSmartCast: Collection +) : FirExpressionWithSmartcastToNull() { + init { + assert(originalExpression.typeRef is FirResolvedTypeRef) + } + + override val source: FirSourceElement? get() = originalExpression.source + override val annotations: List get() = originalExpression.annotations + override val typeArguments: List get() = originalExpression.typeArguments + override val explicitReceiver: FirExpression? get() = originalExpression.explicitReceiver + override val dispatchReceiver: FirExpression get() = originalExpression.dispatchReceiver + override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver + override val calleeReference: FirReference get() = originalExpression.calleeReference + override val originalType: FirTypeRef get() = originalExpression.typeRef + + override fun transformChildren(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull { + originalExpression = originalExpression.transformSingle(transformer, data) + return this + } + + override fun acceptChildren(visitor: FirVisitor, data: D) { + originalExpression.accept(visitor, data) + } + + override fun transformCalleeReference(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull { + throw IllegalStateException() + } + + override fun transformExplicitReceiver(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull { + throw IllegalStateException() + } + + override fun transformDispatchReceiver(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull { + throw IllegalStateException() + } + + override fun transformExtensionReceiver(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull { + throw IllegalStateException() + } + + override fun transformTypeArguments(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull { + throw IllegalStateException() + } + + override fun transformAnnotations(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull { + throw IllegalStateException() + } + + override fun replaceTypeArguments(newTypeArguments: List) { + throw IllegalStateException() + } + + override fun replaceCalleeReference(newCalleeReference: FirReference) { + throw IllegalStateException() + } + + override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) { + throw IllegalStateException() + } + + override fun replaceTypeRef(newTypeRef: FirTypeRef) {} + + @FirImplementationDetail + override fun replaceSource(newSource: FirSourceElement?) { + } +} 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 33f36619765..7284f5db49d 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 @@ -108,6 +108,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() { val callableReferenceAccess = element("CallableReferenceAccess", Expression, qualifiedAccessExpression) val thisReceiverExpression = element("ThisReceiverExpression", Expression, qualifiedAccessExpression) val expressionWithSmartcast = element("ExpressionWithSmartcast", Expression, qualifiedAccessExpression) + val expressionWithSmartcastToNull = element("ExpressionWithSmartcastToNull", Expression, expressionWithSmartcast) val safeCallExpression = element("SafeCallExpression", Expression, expression) val checkedSafeCallSubject = element("CheckedSafeCallSubject", Expression, expression) val getClassCall = element("GetClassCall", Expression, expression, 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 e0df248bf6a..7681915f965 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 @@ -156,6 +156,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() impl(qualifiedAccessExpression) noImpl(expressionWithSmartcast) + noImpl(expressionWithSmartcastToNull) impl(getClassCall) { default("argument") { diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index f859ef8aab3..4f637700029 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -459,6 +459,12 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +field("originalType", typeRef) } + expressionWithSmartcastToNull.configure { + +field("originalExpression", qualifiedAccessExpression) + +field("typesFromSmartCast", "Collection", null, customType = coneKotlinTypeType) + +field("originalType", typeRef) + } + safeCallExpression.configure { +field("receiver", expression).withTransform() // Special node that might be used as a reference to receiver of a safe call after null check diff --git a/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.fir.kt index 3c61a09af0b..99d461442fa 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.fir.kt @@ -24,6 +24,6 @@ fun g(x: B) { if (y is Nothing?) { f(y) - g(y) + g(y) } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.fir.kt index 219ab26035a..745a7da6705 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.fir.kt @@ -26,7 +26,7 @@ fun testSpilling(x: Any?) { myAssert(x is String) x.length } - x.length + x.length } fun testAssertInIf(x: Any?) { diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt index f5870d06e5f..727ad27b035 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt @@ -20,11 +20,11 @@ fun T?.case_3(value_1: Int?, value_2: Boolean): Boolean { // TESTCASE NUMBER: 4 fun case_4(value_1: Number, block: (() -> Unit)?): Boolean? { - contract { + contract { returns(true) implies (value_1 is Int) returns(false) implies (block == null) returns(null) implies (block != null) - } + } return value_1 == null } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt index 1cfd84548ef..5bd13b398fc 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt @@ -87,7 +87,7 @@ fun case_6(x: EmptyClass?) { // TESTCASE NUMBER: 7 fun case_7() { - if (nullableNumberProperty != null || nullableNumberProperty != null is Boolean) { + if (nullableNumberProperty != null || nullableNumberProperty != null is Boolean) { nullableNumberProperty nullableNumberProperty.equals(null) nullableNumberProperty.propT @@ -262,8 +262,8 @@ fun case_16() { // TESTCASE NUMBER: 17 val case_17 = if (nullableIntProperty == null == true == false) 0 else { - nullableIntProperty - nullableIntProperty.java + nullableIntProperty + nullableIntProperty.java } //TESTCASE NUMBER: 18 @@ -440,18 +440,18 @@ fun case_25(b: Boolean) { // TESTCASE NUMBER: 26 fun case_26(a: ((Float) -> Int?)?, b: Float?) { if (a != null == true == false && b != null == true == false) { - val x = a(b) + val x = a(b) if (x != null == true === false) { - x - x.equals(null) - x.propT - x.propAny - x.propNullableT - x.propNullableAny - x.funT() - x.funAny() - x.funNullableT() - x.funNullableAny() + x + x.equals(null) + x.propT + x.propAny + x.propNullableT + x.propNullableAny + x.funT() + x.funAny() + x.funNullableT() + x.funNullableAny() } } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/16.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/16.fir.kt index a2221158e07..c1789a86e4a 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/16.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/16.fir.kt @@ -18,8 +18,8 @@ fun case_1(x: ClassWithCustomEquals) { // TESTCASE NUMBER: 2 fun case_2(x: ClassWithCustomEquals) { if (x == null) { - x - x.inv() + x + x.inv() } } @@ -76,8 +76,8 @@ fun case_6(x: ClassWithCustomEquals) { // TESTCASE NUMBER: 7 fun case_7(x: ClassWithCustomEquals) { if ((x != null) == false) { - x - x.inv() + x + x.inv() } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/2.fir.kt index e03dfe54da5..39807322f91 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/2.fir.kt @@ -37,8 +37,8 @@ fun case_4(x: Any) { // TESTCASE NUMBER: 5 fun case_5(x: Any?) { if (!(x !is Nothing?)) { - x - x?.inv() + x + x?.inv() } } @@ -61,16 +61,16 @@ fun case_7(x: Any) { // TESTCASE NUMBER: 8 fun case_8(x: Any?) { if (!(x is Nothing?)) else { - x - x?.inv() + x + x?.inv() } } // TESTCASE NUMBER: 9 fun case_9(x: Any?) { if (!!(x !is Nothing?)) else { - x - x?.inv() + x + x?.inv() } } @@ -85,7 +85,7 @@ fun case_10(x: Any?) { // TESTCASE NUMBER: 11 fun case_11(x: Any?) { if (x is Nothing?) { - x - x?.inv() + x + x?.inv() } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/29.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/29.fir.kt index 1f32dd0cb51..13e674b4c5e 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/29.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/29.fir.kt @@ -9,8 +9,8 @@ fun case_1(a: Any?) { if (true) continue } - a - a.equals(10) + a + a.equals(10) } // TESTCASE NUMBER: 2 diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/33.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/33.fir.kt index 0cb3d4cbb07..fa890f0a159 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/33.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/33.fir.kt @@ -12,7 +12,7 @@ fun nullableStringArg(number: String?) {} */ fun case_1(x: Int?) { if (x == null) { - nullableStringArg(x) + nullableStringArg(x) } } @@ -34,7 +34,7 @@ fun case_2(x: Int?, y: Nothing?) { */ fun case_3(x: Int?) { if (x == null) { - nullableStringArg(x) + nullableStringArg(x) } } @@ -45,7 +45,7 @@ fun case_3(x: Int?) { */ fun case_4(x: Int?) { if (x == null) { - nullableStringArg(x) + nullableStringArg(x) } } @@ -57,6 +57,6 @@ fun case_4(x: Int?) { fun case_5(x: Int?) { if (x == null) { var y = x - nullableStringArg(y) + nullableStringArg(y) } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/38.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/38.fir.kt index 310fcb05941..1df5b95afd5 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/38.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/38.fir.kt @@ -15,8 +15,8 @@ fun case_1() { break@outer } } - x - x.length + x + x.length } /* @@ -32,8 +32,8 @@ fun case_2() { break@outer } } - x - x.length + x + x.length } /* @@ -145,8 +145,8 @@ fun case_9() { inner@ do { x = null } while (x != null) - x - x.length + x + x.length } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/39.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/39.fir.kt index 56737b0323d..7a57b8a3cfb 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/39.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/39.fir.kt @@ -151,8 +151,8 @@ fun case_12() { while (true) { y += if (x == null) break else 10 } - x - x.inv() + x + x.inv() } // TESTCASE NUMBER: 13 diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/45.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/45.fir.kt index c2eca5ea7b3..ab7a6254b79 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/45.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/45.fir.kt @@ -17,5 +17,5 @@ fun case_1(x: Number?): Long? { * ISSUES: KT-22997 */ fun case_2(x: Number?): Long? { - if (x == null || x is Long) return x else return 0L + if (x == null || x is Long) return x else return 0L } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/1.fir.kt index 31b1bb2a01f..f3d63fbc9c5 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/1.fir.kt @@ -122,7 +122,7 @@ fun case_6(x: EmptyClass?) { // TESTCASE NUMBER: 7 fun case_7() { - if (nullableNumberProperty != null || nullableNumberProperty != null) { + if (nullableNumberProperty != null || nullableNumberProperty != null) { nullableNumberProperty nullableNumberProperty.equals(null) nullableNumberProperty.propT diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/2.fir.kt index 8f5762dbd85..0817a8c0c67 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/2.fir.kt @@ -288,7 +288,7 @@ fun case_11(b: Boolean) { if (z != null || b) { } else { - ?")!>z + ? & ?")!>z } } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/3.fir.kt index 8ee33236b69..08b2302cb78 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/3.fir.kt @@ -16,14 +16,14 @@ import otherpackage.* // TESTCASE NUMBER: 1 fun case_1(x: Any?) { if (x == null) { - x + x } } // TESTCASE NUMBER: 2 fun case_2(x: Nothing?) { if (x == null) { - x + x } } @@ -38,7 +38,7 @@ fun case_3() { // TESTCASE NUMBER: 4 fun case_4(x: Char?) { if (x == null && true) { - x + x } } @@ -46,7 +46,7 @@ fun case_4(x: Char?) { fun case_5() { val x: Unit? = null - if (x == null) x + if (x == null) x } // TESTCASE NUMBER: 6 @@ -54,7 +54,7 @@ fun case_6(x: EmptyClass?) { val y = true if (x == null && !y) { - x + x } } @@ -67,8 +67,8 @@ fun case_7() { // TESTCASE NUMBER: 8 fun case_8(x: TypealiasNullableString) { - if (x == null && x == null) - x + if (x == null && x == null) + x } /* @@ -105,7 +105,7 @@ fun case_11(x: TypealiasNullableString?, y: TypealiasNullableString) { if (y == null) { if (nullableStringProperty != null) { if (z == null) { - x + x } } } @@ -172,7 +172,7 @@ fun case_14() { // TESTCASE NUMBER: 15 fun case_15(x: TypealiasNullableString) { val t = if (x != null) "" else { - x + x } } @@ -187,13 +187,13 @@ fun case_16() { // TESTCASE NUMBER: 17 val case_17 = if (nullableIntProperty !== null) 0 else { - nullableIntProperty + nullableIntProperty } //TESTCASE NUMBER: 18 fun case_18(a: DeepObject.A.B.C.D.E.F.G.J?) { if (a == null) { - a + a } } @@ -249,15 +249,15 @@ fun case_21() { // TESTCASE NUMBER: 22 fun case_22(a: (() -> Unit)?) { if (a == null) { - ?")!>a + ? & kotlin.Function0?")!>a } } // TESTCASE NUMBER: 23 fun case_23(a: ((Float) -> Int?)?, b: Float?) { if (a == null && b == null) { - ?")!>a - b + ? & kotlin.Function1?")!>a + b if (a != null) { ? & kotlin.Function1")!>a } @@ -290,13 +290,13 @@ fun case_25(b: Boolean) { val z = ?")!>y() if (z == null) { - ?")!>z + ? & ?")!>z } } } // TESTCASE NUMBER: 26 -fun case_26(a: Int?, b: Int? = if (a !== null) 0 else a) { +fun case_26(a: Int?, b: Int? = if (a !== null) 0 else a) { a b } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/4.fir.kt index 9d02e24f57a..d191413dbc5 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/4.fir.kt @@ -19,14 +19,14 @@ import otherpackage.* // TESTCASE NUMBER: 1 fun case_1(x: Any) { if (x === null) { - x + x } } // TESTCASE NUMBER: 2 fun case_2(x: Nothing) { if (x == null) { - x + x } } @@ -41,7 +41,7 @@ fun case_3() { // TESTCASE NUMBER: 4 fun case_4(x: Char) { if (x == null && true) { - x + x } } @@ -49,7 +49,7 @@ fun case_4(x: Char) { fun case_5() { val x: Unit = kotlin.Unit - if (x == null) x + if (x == null) x } // TESTCASE NUMBER: 6 @@ -57,7 +57,7 @@ fun case_6(x: EmptyClass) { val y = true if (x == null && !y) { - x + x } } @@ -70,7 +70,7 @@ fun case_7() { // TESTCASE NUMBER: 8 fun case_8(x: TypealiasString) { - if (x == null && x == null) x + if (x == null && x == null) x } // TESTCASE NUMBER: 9 @@ -78,7 +78,7 @@ fun case_9(x: TypealiasString) { if (x != null) { } else if (false) { - x + x } } @@ -103,7 +103,7 @@ fun case_11(x: TypealiasString, y: TypealiasString) { if (y == null) { if (stringProperty != null) { if (false || false || false || z == null || false) { - x + x } } } @@ -112,14 +112,14 @@ fun case_11(x: TypealiasString, y: TypealiasString) { // TESTCASE NUMBER: 12 fun case_12(x: TypealiasString, y: TypealiasString) = if (x != null) "1" - else if (y !== null) x + else if (y !== null) x else "-1" // TESTCASE NUMBER: 13 fun case_13(x: otherpackage.EmptyClass13) = if (x != null) { 1 - } else x + } else x // TESTCASE NUMBER: 14 class A14 { @@ -179,7 +179,7 @@ fun case_16() { val x: TypealiasNothing = return if (x == null) { - x + x } } @@ -195,7 +195,7 @@ val case_17 = if (true && true && in //TESTCASE NUMBER: 18 fun case_18(a: DeepObject.A.B.C.D.E.F.G.J) { if (a == null) { - a + a } } @@ -256,7 +256,7 @@ fun case_22(a: (() -> Unit)) { // TESTCASE NUMBER: 23 fun case_23(a: ((Float) -> Int), b: Float) { if (a == null && b == null) { - val x = a(b) + val x = a(b) if (x !== null) { x } @@ -276,13 +276,13 @@ fun case_24(a: ((() -> Unit) -> Unit), b: (() -> Unit)) { } // TESTCASE NUMBER: 25 -fun case_25(a: (() -> Unit) -> Unit, b: (() -> Unit) -> Unit = if (a == null) , kotlin.Unit>")!>a else {{}}) { +fun case_25(a: (() -> Unit) -> Unit, b: (() -> Unit) -> Unit = if (a == null) , kotlin.Unit> & kotlin.Function1, kotlin.Unit>")!>a else {{}}) { , kotlin.Unit>")!>a , kotlin.Unit>")!>b } // TESTCASE NUMBER: 26 -fun case_26(a: Int, b: Int = if (a === null) a else 0) { +fun case_26(a: Int, b: Int = if (a === null) a else 0) { a b } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/40.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/40.fir.kt index 30338a08970..89aaeaf3d42 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/40.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/40.fir.kt @@ -133,8 +133,8 @@ fun case_13(x: Any?) { */ fun case_14(x: Any?) { if (x == null) { - x - x?.equals(10) + x + x?.equals(10) x!!.equals(10) x.equals(10) } @@ -147,8 +147,8 @@ fun case_14(x: Any?) { */ fun case_15(x: Any?) { if (x !== null) else { - x - x?.equals(10) + x + x?.equals(10) x!!.equals(10) x.equals(10) } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/68.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/68.fir.kt index 5256453fa6f..09c79cabad4 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/68.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/68.fir.kt @@ -13,8 +13,8 @@ fun case_1(x: Any?) { // TESTCASE NUMBER: 2 fun case_2(x: Any?) { (x as Nothing?)!! - x - x.inv() + x + x.inv() } // TESTCASE NUMBER: 3 @@ -36,8 +36,8 @@ fun case_4(x: Any?) { // TESTCASE NUMBER: 5 fun case_5(x: Any?) { if (x as Nothing? is Nothing) { - x - x.inv() + x + x.inv() } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/7.fir.kt index 63fe7a9a7b9..0b11b0ed40e 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/7.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/7.fir.kt @@ -39,7 +39,7 @@ fun case_1(x: Any?) { */ fun case_2(x: Nothing?) { if (x !== null && x !== null) { - x + x } } @@ -115,7 +115,7 @@ fun case_6(x: Class?) { // TESTCASE NUMBER: 7 fun case_7() { val x: EmptyObject? = null - if (x != null || x != null || x != null) { + if (x != null || x != null || x != null) { x x.equals(null) x.propT diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/70.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/70.fir.kt index d32762d5c7d..46a14698e57 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/70.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/70.fir.kt @@ -25,7 +25,7 @@ fun case_2(): Int? { val x: Int? = null return when (x != null) { false -> { - x + x } else -> null } @@ -53,7 +53,7 @@ fun case_4(): Int? { val x: Int? = null return when (x == null) { true -> { - x + x } else -> null }