diff --git a/compiler/fir/analysis-tests/testData/resolve/covariantArrayAsReceiver.kt b/compiler/fir/analysis-tests/testData/resolve/covariantArrayAsReceiver.kt index 15af25df94b..214c087e801 100644 --- a/compiler/fir/analysis-tests/testData/resolve/covariantArrayAsReceiver.kt +++ b/compiler/fir/analysis-tests/testData/resolve/covariantArrayAsReceiver.kt @@ -11,7 +11,7 @@ interface KtLightMethod : PsiElement // With covariant array here we do not visit lambda (it.usage is KtLightMethod) below // Problem disappears if 'out' is removed fun Array.filterNot(f: (T) -> Boolean): List { - return this + return this } fun Array.toList(): List? = null diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt index 5e9975af944..4c5ae15c767 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt @@ -57,7 +57,7 @@ open class J() : S() { } open class Base { - open fun kek(): Z = Z() + open fun kek(): Z = Z() } open class GoodDerrived : Base() { diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/invoke/explicitReceiver2.kt b/compiler/fir/analysis-tests/testData/resolve/expresssions/invoke/explicitReceiver2.kt index 501707e377a..92ae0ce7704 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/invoke/explicitReceiver2.kt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/invoke/explicitReceiver2.kt @@ -1,6 +1,6 @@ class Bar { - operator fun invoke(): Foo { return this } // (1) + operator fun invoke(): Foo { return this } // (1) } @@ -11,7 +11,7 @@ fun x() { class Foo { - operator fun Bar.invoke(): Foo { return this } // (2) + operator fun Bar.invoke(): Foo { return this } // (2) val x: Bar = Bar() diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/invoke/threeReceivers.kt b/compiler/fir/analysis-tests/testData/resolve/expresssions/invoke/threeReceivers.kt index e5081adbb98..d5cde4eebb1 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/invoke/threeReceivers.kt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/invoke/threeReceivers.kt @@ -1,7 +1,7 @@ class Bar { - fun FooBar.invoke(): Bar = this + fun FooBar.invoke(): Bar = this } class Buz diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/callableReferences/beyoundCalls.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/callableReferences/beyoundCalls.kt index a024636d858..755616f109a 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/callableReferences/beyoundCalls.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/callableReferences/beyoundCalls.kt @@ -1,5 +1,5 @@ fun bar(x: String): Int = 1 -fun bar(x: String): Double = 1 +fun bar(x: String): Double = 1 fun baz(x: String): Int = 1 fun foobaz(x: T): R = TODO() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt index e0aa879b4a3..2e81aa6712d 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt @@ -5,7 +5,7 @@ fun checkNotNull(x: Any?) { returns(true) implies (x != null) returns(false) implies (x == null) } - return x != null + return x != null } fun trickyRequireNotNull(x: Any?) { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.kt index 817489339b2..ae92d5b2f23 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.kt @@ -5,7 +5,7 @@ fun checkIsString(x: Any) { returns(true) implies (x is String) returns(false) implies (x !is String) } - return x is String + return x is String } fun test(x: Any) { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker/basic.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker/basic.fir.txt new file mode 100644 index 00000000000..438b5ffeca3 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker/basic.fir.txt @@ -0,0 +1,77 @@ +FILE: basic.kt + public final fun illegalReturnIf(): R|kotlin/Char| { + ^illegalReturnIf when () { + CMP(<, Int(1).R|kotlin/Int.compareTo|(Int(2))) -> { + Char(a) + } + else -> { + Int(1) + } + } + + } + public final fun foo(): R|kotlin/String| { + ^foo Int(1) + } + public final fun ok(): R|kotlin/Int| { + ^ok Int(1) + } + public final fun okOneLineFunction(): R|kotlin/Int| { + ^okOneLineFunction Int(10).R|kotlin/Int.plus|(Int(1)) + } + public final fun errorOneLineFunction(): R|kotlin/String| { + ^errorOneLineFunction Int(10).R|kotlin/Int.plus|(Int(1)) + } + public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final fun bar(): R|kotlin/Unit| { + } + + } + public final infix fun R|() -> kotlin/Unit|.foo(x: R|A.() -> kotlin/Unit|): R|kotlin/Unit| { + } + public final fun okWithLambda(): R|kotlin/String| { + foo@fun (): R|kotlin/Unit| { + ^@foo Unit + } + .R|/foo|(foo@fun R|A|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|/A.bar|() + ^@foo Unit + } + ) + ^okWithLambda String() + } + public final fun errorWithLambda(): R|kotlin/String| { + foo@fun (): R|kotlin/Unit| { + ^@foo Unit + } + .R|/foo|(foo@fun R|A|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|/A.bar|() + ^@foo Int(10) + } + ) + ^errorWithLambda String() + } + public final fun blockReturnValueTypeMatch1(): R|kotlin/Int| { + when () { + CMP(>, Int(1).R|kotlin/Int.compareTo|(Int(2))) -> { + ^blockReturnValueTypeMatch1 Double(1.0) + } + } + + ^blockReturnValueTypeMatch1 Double(2.0) + } + public final fun blockReturnValueTypeMatch2(): R|kotlin/Int| { + when () { + CMP(>, Int(1).R|kotlin/Int.compareTo|(Int(2))) -> { + } + else -> { + ^blockReturnValueTypeMatch2 Double(1.0) + } + } + + ^blockReturnValueTypeMatch2 Double(2.0) + } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker/basic.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker/basic.kt new file mode 100644 index 00000000000..112c3a321d2 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker/basic.kt @@ -0,0 +1,55 @@ +// bug: type of the expression in return statement is Char +fun illegalReturnIf(): Char { + return if (1 < 2) 'a' else { 1 } +} + +fun foo(): String { + return 1 +} + +fun ok(): Int { + return 1 +} + +fun okOneLineFunction(): Int = 10 + 1 +fun errorOneLineFunction(): String = 10 + 1 + +class A { + fun bar() {} +} + +infix fun (() -> Unit).foo(x: A.() -> Unit) {} + +fun okWithLambda(): String { + { + return@foo + } foo { + bar() + return@foo + } + + return "" +} + +// no report due bad returns in lambda +fun errorWithLambda(): String { + { + return@foo + } foo { + bar() + return@foo 10 + } + + return "" +} + +fun blockReturnValueTypeMatch1() : Int { + if (1 > 2) + return 1.0 + return 2.0 +} +fun blockReturnValueTypeMatch2() : Int { + if (1 > 2) + else return 1.0 + return 2.0 +} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 412c427ff92..c930247617f 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -4781,6 +4781,22 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker") + @TestDataPath("$PROJECT_ROOT") + public class FunctionReturnTypeMismatchChecker { + @Test + public void testAllFilesPresentInFunctionReturnTypeMismatchChecker() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker/basic.kt"); + } + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/initializerTypeMismatchChecker") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index efbac27d9e4..0169f69bb4b 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -4851,6 +4851,23 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker") + @TestDataPath("$PROJECT_ROOT") + @Execution(ExecutionMode.SAME_THREAD) + public class FunctionReturnTypeMismatchChecker { + @Test + public void testAllFilesPresentInFunctionReturnTypeMismatchChecker() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker/basic.kt"); + } + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/initializerTypeMismatchChecker") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt index aabaafccb25..b2d10a309a6 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt @@ -57,6 +57,7 @@ enum class PositioningStrategy(private val strategy: String? = null) { SUPERTYPES_LIST, RETURN_WITH_LABEL, ASSIGNMENT_VALUE, + WHOLE_ELEMENT, INT_LITERAL_OUT_OF_RANGE, FLOAT_LITERAL_OUT_OF_RANGE, LONG_LITERAL_SUFFIX, diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 837a57352d5..29fbda69899 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -317,6 +317,11 @@ object DIAGNOSTICS_LIST : DiagnosticList() { parameter("typeParameterName") parameter("typeParametersOwner") } + + val RETURN_TYPE_MISMATCH by error(PositioningStrategy.WHOLE_ELEMENT) { + parameter("expected") + parameter("actual") + } } val REFLECTION by object : DiagnosticGroup("Reflection") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 15a0d5e33eb..a31d87df42a 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -235,6 +235,7 @@ object FirErrors { val REPEATED_BOUND by error0() val CONFLICTING_UPPER_BOUNDS by error1() val NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER by error2() + val RETURN_TYPE_MISMATCH by error2(SourceElementPositioningStrategies.WHOLE_ELEMENT) // Reflection val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 18be2c6c75e..f8b62d00539 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -16,11 +16,14 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier import org.jetbrains.kotlin.fir.analysis.getChild import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.FirComponentCall +import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike @@ -416,3 +419,38 @@ private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinTy } fun FirMemberDeclaration.isInlineOnly(): Boolean = isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_CLASS_ID) + +val FirProperty.isDestructuringDeclaration + get() = name.asString() == "" + +val FirExpression.isComponentCall + get() = this is FirComponentCall + +fun isSubtypeForTypeMismatch(context: ConeInferenceContext, subtype: ConeKotlinType, supertype: ConeKotlinType): Boolean { + return AbstractTypeChecker.isSubtypeOf(context, subtype, supertype) + || isSubtypeOfForFunctionalTypeReturningUnit(context.session.typeContext, subtype, supertype) +} + +fun isSubtypeOfForFunctionalTypeReturningUnit(context: ConeInferenceContext, subtype: ConeKotlinType, supertype: ConeKotlinType): Boolean { + if (!supertype.isBuiltinFunctionalType(context.session)) return false + val functionalTypeReturnType = supertype.typeArguments.lastOrNull() + if ((functionalTypeReturnType as? ConeClassLikeType)?.isUnit == true) { + // We don't try to match return type for this case + // Dropping the return type (getting only the lambda args) + val superTypeArgs = supertype.typeArguments.dropLast(1) + val subTypeArgs = subtype.typeArguments.dropLast(1) + if (superTypeArgs.size != subTypeArgs.size) return false + + for (i in superTypeArgs.indices) { + val subTypeArg = subTypeArgs[i].type ?: return false + val superTypeArg = superTypeArgs[i].type ?: return false + + if (!AbstractTypeChecker.isSubtypeOf(context.session.typeContext, subTypeArg, superTypeArg)) { + return false + } + } + + return true + } + return false +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInitializerTypeMismatchChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInitializerTypeMismatchChecker.kt index 73b5a1ccee0..5b3ce2835a4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInitializerTypeMismatchChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInitializerTypeMismatchChecker.kt @@ -6,67 +6,28 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.isComponentCall +import org.jetbrains.kotlin.fir.analysis.checkers.isDestructuringDeclaration +import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_TYPE_MISMATCH import org.jetbrains.kotlin.fir.declarations.FirProperty -import org.jetbrains.kotlin.fir.expressions.FirComponentCall -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.resolve.inference.isFunctionalType import org.jetbrains.kotlin.fir.typeContext -import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.coneTypeSafe object FirInitializerTypeMismatchChecker : FirPropertyChecker() { override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { val initializer = declaration.initializer ?: return if (declaration.isDestructuringDeclaration) return - if (initializer.isComponent) return + if (initializer.isComponentCall) return val propertyType = declaration.returnTypeRef.coneTypeSafe() ?: return val expressionType = initializer.typeRef.coneTypeSafe() ?: return val typeContext = context.session.typeContext - // hack: if property's type is (args) -> Unit, and lambda returns non-Unit value, the type of the lambda - // will be non-unit, but it's OK - if (propertyType.isFunctionalType(context.session)) { - // getting property's expected return type - val expectedType = propertyType.typeArguments.lastOrNull() - if ((expectedType as? ConeClassLikeType)?.isUnit == true) { - // dropping the return type (getting only the lambda args) - val expectedArgs = propertyType.typeArguments.dropLast(1) - val actualArgs = expressionType.typeArguments.dropLast(1) - if (compareTypesList(actualArgs, expectedArgs, typeContext)) { - return - } - } - } - - if (!AbstractTypeChecker.isSubtypeOf(typeContext, expressionType, propertyType)) { + if (!isSubtypeForTypeMismatch(typeContext, subtype = expressionType, supertype = propertyType)) { val source = declaration.source ?: return reporter.report(INITIALIZER_TYPE_MISMATCH.on(source, propertyType, expressionType), context) } } - - private val FirProperty.isDestructuringDeclaration - get() = name.asString() == "" - private val FirExpression.isComponent - get() = this is FirComponentCall - - private fun compareTypesList( - expressionTypes: List, - propertyTypes: List, - context: ConeInferenceContext - ): Boolean { - if (expressionTypes.size != propertyTypes.size) return false - - for (i in expressionTypes.indices) { - val expressionType = expressionTypes[i].type ?: return false - val propertyType = propertyTypes[i].type ?: return false - - if (!AbstractTypeChecker.isSubtypeOf(context.session.typeContext, expressionType, propertyType)) { - return false - } - } - - return true - } } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirFunctionReturnTypeMismatchChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirFunctionReturnTypeMismatchChecker.kt new file mode 100644 index 00000000000..71a705ec373 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirFunctionReturnTypeMismatchChecker.kt @@ -0,0 +1,37 @@ +/* + * 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.analysis.checkers.expression + +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.expressions.FirReturnExpression +import org.jetbrains.kotlin.fir.expressions.FirWhenExpression +import org.jetbrains.kotlin.fir.expressions.isExhaustive +import org.jetbrains.kotlin.fir.typeContext +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.coneTypeSafe + +object FirFunctionReturnTypeMismatchChecker : FirReturnExpressionChecker() { + override fun check(expression: FirReturnExpression, context: CheckerContext, reporter: DiagnosticReporter) { + if (expression.source == null) return + val targetElement = expression.target.labeledElement + if (targetElement !is FirSimpleFunction) return + val resultExpression = expression.result + if (resultExpression is FirWhenExpression && !resultExpression.isExhaustive) return + + val functionReturnType = targetElement.returnTypeRef.coneTypeSafe() ?: return + val typeContext = context.session.typeContext + val returnExpressionType = resultExpression.typeRef.coneTypeSafe() ?: return + + if (!isSubtypeForTypeMismatch(typeContext, subtype = returnExpressionType, supertype = functionReturnType)) { + val returnExpressionSource = resultExpression.source ?: return + reporter.report(RETURN_TYPE_MISMATCH.on(returnExpressionSource, functionReturnType, returnExpressionType), context) + } + } +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt index 1c2e9dd43f5..abb0101571a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt @@ -102,7 +102,7 @@ class ExpressionCheckersDiagnosticComponent( } override fun visitReturnExpression(returnExpression: FirReturnExpression, data: CheckerContext) { - checkers.returnExpressionCheckers.check(returnExpression, data, reporter) + checkers.allReturnExpressionCheckers.check(returnExpression, data, reporter) } private fun Collection>.check( diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index e4c7fb88aa8..19af32f4bc0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -196,6 +196,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_MODIFIER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESERVED_MEMBER_INSIDE_INLINE_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_NOT_ALLOWED +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH_ON_OVERRIDE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_CLASS_CONSTRUCTOR_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE @@ -488,6 +489,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { NAME ) + map.put(RETURN_TYPE_MISMATCH, "Return type mismatch: expected {0}, actual {1}", RENDER_TYPE, RENDER_TYPE) + // Reflection map.put( EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index 18610c9cf75..a04d3e543d9 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -12,6 +12,7 @@ import com.intellij.psi.impl.source.tree.ElementType import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.TokenSet import com.intellij.util.diff.FlyweightCapableTreeStructure +import org.jetbrains.kotlin.KtNodeType import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.getChildren @@ -242,7 +243,7 @@ object LightTreePositioningStrategies { } } - val ASSIGNMENT_VALUE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { + val LAST_CHILD: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { override fun mark( node: LighterASTNode, startOffset: Int, @@ -537,6 +538,8 @@ object LightTreePositioningStrategies { } } + val WHOLE_ELEMENT = object : LightTreePositioningStrategy() { } + val LONG_LITERAL_SUFFIX = object : LightTreePositioningStrategy() { } } @@ -739,5 +742,5 @@ private fun FlyweightCapableTreeStructure.firstChild(node: Light private fun FlyweightCapableTreeStructure.lastChild(node: LighterASTNode): LighterASTNode? { val childrenRef = Ref>() getChildren(node, childrenRef) - return childrenRef.get()?.lastOrNull() + return childrenRef.get().lastOrNull() } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt index 5e35811c92a..16369d20bb0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt @@ -179,10 +179,15 @@ object SourceElementPositioningStrategies { ) val ASSIGNMENT_VALUE = SourceElementPositioningStrategy( - LightTreePositioningStrategies.ASSIGNMENT_VALUE, + LightTreePositioningStrategies.LAST_CHILD, PositioningStrategies.ASSIGNMENT_VALUE ) + val WHOLE_ELEMENT = SourceElementPositioningStrategy( + LightTreePositioningStrategies.WHOLE_ELEMENT, + PositioningStrategies.WHOLE_ELEMENT + ) + val LONG_LITERAL_SUFFIX = SourceElementPositioningStrategy( LightTreePositioningStrategies.LONG_LITERAL_SUFFIX, PositioningStrategies.LONG_LITERAL_SUFFIX diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt index a8fc29a2f63..f6b5fbff93e 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt @@ -48,6 +48,7 @@ object CommonExpressionCheckers : ExpressionCheckers() { ) override val returnExpressionCheckers: Set = setOf( - FirReturnAllowedChecker + FirReturnAllowedChecker, + FirFunctionReturnTypeMismatchChecker ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index f8d059c0915..4e920d6b5d0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -782,23 +782,12 @@ object PositioningStrategies { val ASSIGNMENT_VALUE: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: PsiElement): List { - return if (element is KtProperty) { - mark(element.initializer ?: element) - } else { - super.mark(element) - } + return markElement(if (element is KtProperty) element.initializer ?: element else element) } } - val RETURN_EXPRESSION: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: PsiElement): List { - return if (element is KtReturnExpression) { - markElement(element.returnedExpression ?: element) - } else { - markElement(element) - } - } - } + val WHOLE_ELEMENT: PositioningStrategy = object : PositioningStrategy() {} + /** * @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt index 9005fd18d90..f93d087d8af 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt @@ -6,7 +6,7 @@ fun none() {} fun unitEmptyInfer() {} fun unitEmpty() : Unit {} fun unitEmptyReturn() : Unit {return} -fun unitIntReturn() : Unit {return 1} +fun unitIntReturn() : Unit {return 1} fun unitUnitReturn() : Unit {return Unit} fun test1() : Any = {return} fun test2() : Any = a@ {return@a 1} @@ -16,7 +16,7 @@ fun test5(): Any = l@{ return@l } fun test6(): Any = {return 1} fun bbb() { - return 1 + return 1 } fun foo(expr: StringBuilder): Int { @@ -29,8 +29,8 @@ fun foo(expr: StringBuilder): Int { fun unitShort() : Unit = Unit -fun unitShortConv() : Unit = 1 -fun unitShortNull() : Unit = null +fun unitShortConv() : Unit = 1 +fun unitShortNull() : Unit = null fun intEmpty() : Int {} fun intShortInfer() = 1 @@ -39,56 +39,56 @@ fun intShort() : Int = 1 fun intBlock() : Int {return 1} fun intBlock1() : Int {1} -fun intString(): Int = "s" -fun intFunctionLiteral(): Int = { 10 } +fun intString(): Int = "s" +fun intFunctionLiteral(): Int = { 10 } -fun blockReturnUnitMismatch() : Int {return} -fun blockReturnValueTypeMismatch() : Int {return 3.4} +fun blockReturnUnitMismatch() : Int {return} +fun blockReturnValueTypeMismatch() : Int {return 3.4} fun blockReturnValueTypeMatch() : Int {return 1} -fun blockReturnValueTypeMismatchUnit() : Int {return Unit} +fun blockReturnValueTypeMismatchUnit() : Int {return Unit} fun blockAndAndMismatch() : Int { true && false } fun blockAndAndMismatch1() : Int { - return true && false + return true && false } fun blockAndAndMismatch2() : Int { - (return true) && (return false) + (return true) && (return false) } fun blockAndAndMismatch3() : Int { true || false } fun blockAndAndMismatch4() : Int { - return true || false + return true || false } fun blockAndAndMismatch5() : Int { - (return true) || (return false) + (return true) || (return false) } fun blockReturnValueTypeMatch1() : Int { - return if (1 > 2) 1.0 else 2.0 + return if (1 > 2) 1.0 else 2.0 } fun blockReturnValueTypeMatch2() : Int { return if (1 > 2) 1 } fun blockReturnValueTypeMatch3() : Int { - return if (1 > 2) else 1 + return if (1 > 2) else 1 } fun blockReturnValueTypeMatch4() : Int { if (1 > 2) - return 1.0 - else return 2.0 + return 1.0 + else return 2.0 } fun blockReturnValueTypeMatch5() : Int { if (1 > 2) - return 1.0 - return 2.0 + return 1.0 + return 2.0 } fun blockReturnValueTypeMatch6() : Int { if (1 > 2) - else return 1.0 - return 2.0 + else return 1.0 + return 2.0 } fun blockReturnValueTypeMatch7() : Int { if (1 > 2) @@ -116,7 +116,7 @@ fun blockReturnValueTypeMatch11() : Int { fun blockReturnValueTypeMatch12() : Int { if (1 > 2) return 1 - else return 1.0 + else return 1.0 } fun blockNoReturnIfValDeclaration(): Int { val x = 1 @@ -134,23 +134,23 @@ fun blockNoReturnIfUnitInOneBranch(): Int { } } } -fun nonBlockReturnIfEmptyIf(): Int = if (1 < 2) {} else {} -fun nonBlockNoReturnIfUnitInOneBranch(): Int = if (1 < 2) {} else 2 +fun nonBlockReturnIfEmptyIf(): Int = if (1 < 2) {} else {} +fun nonBlockNoReturnIfUnitInOneBranch(): Int = if (1 < 2) {} else 2 val a = return 1 class A() { } -fun illegalConstantBody(): Int = "s" +fun illegalConstantBody(): Int = "s" fun illegalConstantBlock(): String { - return 1 + return 1 } fun illegalIfBody(): Int = - if (1 < 2) 'a' else { 1.0 } + if (1 < 2) 'a' else { 1.0 } fun illegalIfBlock(): Boolean { if (1 < 2) return false - else { return 1 } + else { return 1 } } fun illegalReturnIf(): Char { return if (1 < 2) 'a' else { 1 } diff --git a/compiler/testData/diagnostics/tests/callableReference/generic/expectedFunctionType.fir.kt b/compiler/testData/diagnostics/tests/callableReference/generic/expectedFunctionType.fir.kt index f4b473683e0..e75ef5af6fa 100644 --- a/compiler/testData/diagnostics/tests/callableReference/generic/expectedFunctionType.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/generic/expectedFunctionType.fir.kt @@ -19,6 +19,6 @@ class A3 { fun test2(): (T) -> Unit = A3()::a3 fun test3(): (Int) -> String = A3()::a3 - fun test4(): (R) -> Unit = this::a3 + fun test4(): (R) -> Unit = this::a3 fun test5(): (T) -> R = this::a3 } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/unitAdaptationForReferenceCompatibility.fir.kt b/compiler/testData/diagnostics/tests/callableReference/unitAdaptationForReferenceCompatibility.fir.kt index 4f96216a149..1e441058319 100644 --- a/compiler/testData/diagnostics/tests/callableReference/unitAdaptationForReferenceCompatibility.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/unitAdaptationForReferenceCompatibility.fir.kt @@ -20,6 +20,6 @@ public interface Executor { fun f(): String = "test" class A { - fun schedule1(e: Executor): Future = e.submit(::f) - fun schedule2(e: Executor): Future = e.submit { f() } + fun schedule1(e: Executor): Future = e.submit(::f) + fun schedule2(e: Executor): Future = e.submit { f() } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.fir.kt b/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.fir.kt index 87afc9c3581..c0d39d65d21 100644 --- a/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.fir.kt +++ b/compiler/testData/diagnostics/tests/cast/AsInBinaryUnary.fir.kt @@ -20,12 +20,12 @@ operator fun Impl2.unaryMinus() = Impl2() // See also KT-10384: in non-error functions, as is necessary! fun add1(x: Impl2, y: Base): Impl1 = x as Base + y -fun error1(x: Impl2, y: Base): Impl1 = x + y +fun error1(x: Impl2, y: Base): Impl1 = x + y fun add2(x: Base, y: Impl2): Impl1 = x + y as Base -fun error2(x: Base, y: Impl2): Impl1 = x + y +fun error2(x: Base, y: Impl2): Impl1 = x + y fun minus3(x: Impl2): Impl1 = -(x as Base) -fun error3(x: Impl2): Impl1 = -x +fun error3(x: Impl2): Impl1 = -x diff --git a/compiler/testData/diagnostics/tests/classLiteral/genericArrays.fir.kt b/compiler/testData/diagnostics/tests/classLiteral/genericArrays.fir.kt index 2a1e83866cc..5d1d7303176 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/genericArrays.fir.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/genericArrays.fir.kt @@ -4,7 +4,7 @@ fun f1(): KClass> = Array::clas fun f2(): KClass>> = Array>::class inline fun f3() = Array::class inline fun f4() = Array>::class -fun f5(): KClass> = Array<*>::class +fun f5(): KClass> = Array<*>::class fun f6(): KClass> = Array::class fun f7() = Array>::class fun f8() = Array?>::class diff --git a/compiler/testData/diagnostics/tests/classLiteral/smartCast.fir.kt b/compiler/testData/diagnostics/tests/classLiteral/smartCast.fir.kt new file mode 100644 index 00000000000..7ab9924cefa --- /dev/null +++ b/compiler/testData/diagnostics/tests/classLiteral/smartCast.fir.kt @@ -0,0 +1,23 @@ +// KT-16291 Smart cast doesn't work when getting class of instance + +import kotlin.reflect.KClass + +class Foo { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other === null || other::class != this::class) return false + + return true + } +} + +fun test(f: Foo?): KClass? = if (f != null) f::class else null + +fun test2(): KClass? { + var f: Foo? = null + if (f != null) { + run { f = null } + return f::class + } + return null +} diff --git a/compiler/testData/diagnostics/tests/classLiteral/smartCast.kt b/compiler/testData/diagnostics/tests/classLiteral/smartCast.kt index dd50fd47ea5..0bae9c28f6d 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/smartCast.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/smartCast.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // KT-16291 Smart cast doesn't work when getting class of instance import kotlin.reflect.KClass diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeDifferentExamples.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeDifferentExamples.fir.kt index 5d076cdc2e1..6cae426de24 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeDifferentExamples.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeDifferentExamples.fir.kt @@ -6,7 +6,7 @@ fun t1() : Int{ } fun t1a() : Int { - return + return return 1 1 } @@ -19,7 +19,7 @@ fun t1b() : Int { fun t1c() : Int { return 1 - return + return 1 } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/elvisNotProcessed.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/elvisNotProcessed.fir.kt index 3709119f6f3..9ff535e2ed0 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/elvisNotProcessed.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/elvisNotProcessed.fir.kt @@ -35,5 +35,5 @@ val bbbb = ( l() ?: null) ?: ( l() ?: null) fun f(x : Long?): Long { var a = x ?: (fun() {} ?: fun() {}) - return a + return a } diff --git a/compiler/testData/diagnostics/tests/controlStructures/ifToAnyDiscriminatingUsages.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/ifToAnyDiscriminatingUsages.fir.kt index 83926c282f8..d5d7466d071 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/ifToAnyDiscriminatingUsages.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/ifToAnyDiscriminatingUsages.fir.kt @@ -33,15 +33,15 @@ fun testReturnFromAnonFun() = fun testReturn1() = run { - return if (true) 42 - else println() + return if (true) 42 + else println() } fun testReturn2() = run { - return if (true) 42 + return if (true) 42 else if (true) 42 - else println() + else println() } fun testUsage1() = diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt10717.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/kt10717.fir.kt index 1389d9e036d..ad95a36e687 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/kt10717.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/kt10717.fir.kt @@ -1,21 +1,21 @@ // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNREACHABLE_CODE -UNUSED_PARAMETER -RETURN_NOT_ALLOWED fun test1() = run { - return "OK" + return "OK" } fun test2() = run { fun local(): String { return "" } - return "" + return "" } inline fun Iterable.map(transform: (T) -> R): List = null!! fun test3(a: List, b: List) = a.map { - if (it.length == 3) return null - if (it.length == 4) return "" - if (it.length == 4) return 5 + if (it.length == 3) return null + if (it.length == 4) return "" + if (it.length == 4) return 5 if (it.length == 4) return b 1 } @@ -24,14 +24,14 @@ fun test4() = run { fun test5() { return - return@test4 + return@test4 - return return@test4 + return return@test4 - return fun() { return; return@test4 "" } + return fun() { return; return@test4 "" } } - return + return 3 } @@ -43,5 +43,5 @@ val foo: Int } fun test(): Int = run { - return "" + return "" } diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt4310.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/kt4310.fir.kt index 257f5363802..e2818f7c57a 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/kt4310.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/kt4310.fir.kt @@ -2,11 +2,11 @@ package f fun test(a: Boolean, b: Boolean): Int { - return if(a) { + return if(a) { 1 } else { if (b) { 3 } - } + } } diff --git a/compiler/testData/diagnostics/tests/controlStructures/localReturnInsidePropertyAccessor.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/localReturnInsidePropertyAccessor.fir.kt index 5e7e19ac22c..0feead4f920 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/localReturnInsidePropertyAccessor.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/localReturnInsidePropertyAccessor.fir.kt @@ -10,7 +10,7 @@ fun f() = object : ClassData { fun g() = object : ClassData { init { if (true) { - return 0 + return 0 } } diff --git a/compiler/testData/diagnostics/tests/controlStructures/localReturnInsidePropertyAccessor.kt b/compiler/testData/diagnostics/tests/controlStructures/localReturnInsidePropertyAccessor.kt index ce50695c506..a7f685798ed 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/localReturnInsidePropertyAccessor.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/localReturnInsidePropertyAccessor.kt @@ -17,4 +17,4 @@ fun g() = object : ClassData { fun some(): Int { return 6 } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/controlStructures/tryReturnType.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/tryReturnType.fir.kt index 77b157a446e..0b61cce53ab 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/tryReturnType.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/tryReturnType.fir.kt @@ -6,15 +6,15 @@ fun foo() : Int { doSmth() } catch (e: Exception) { - return "" + return "" } finally { - return "" + return "" } } fun bar() : Int = - try { + try { doSmth() } catch (e: Exception) { @@ -22,7 +22,7 @@ fun bar() : Int = } finally { "" - } + } fun doSmth() {} diff --git a/compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.fir.kt index 96c68ac62d8..3f15aab9809 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.fir.kt @@ -26,22 +26,22 @@ fun testResultOfLambda2() = fun testReturn1() = run { - return when { + return when { true -> 42 else -> println() - } + } } fun testReturn2() = run { - return when { + return when { true -> 42 else -> when { true -> 42 else -> println() } - } + } } fun testUsage1() = diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Return.fir.kt b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Return.fir.kt index 36b0d153106..636fe46bec9 100644 --- a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Return.fir.kt +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Return.fir.kt @@ -14,5 +14,5 @@ fun foo(): Int { val z: Int? = null if (z != null) return if (z == null) z else z - return z + return z } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/ScalaLikeNamedFun.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/ScalaLikeNamedFun.fir.kt index 0ad9f653f61..14967f7b962 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/ScalaLikeNamedFun.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/ScalaLikeNamedFun.fir.kt @@ -1,36 +1,36 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE // KT-5068 Add special error for scala-like syntax 'fun foo(): Int = { 1 }' -fun test1(): Int = { return 1 } -fun test2(): Int = { 1 } +fun test1(): Int = { return 1 } +fun test2(): Int = { 1 } val test3: () -> Int = fun (): Int = { return 1 } val test4: () -> Int = fun (): Int = { 1 } -fun test5(): Int { return { 1 } } -fun test6(): Int = fun (): Int = 1 +fun test5(): Int { return { 1 } } +fun test6(): Int = fun (): Int = 1 fun outer() { - fun test1(): Int = { return 1 } - fun test2(): Int = { 1 } + fun test1(): Int = { return 1 } + fun test2(): Int = { 1 } val test3: () -> Int = fun (): Int = { return 1 } val test4: () -> Int = fun (): Int = { 1 } - fun test5(): Int { return { 1 } } - fun test6(): Int = fun (): Int = 1 + fun test5(): Int { return { 1 } } + fun test6(): Int = fun (): Int = 1 } class Outer { - fun test1(): Int = { return 1 } - fun test2(): Int = { 1 } + fun test1(): Int = { return 1 } + fun test2(): Int = { 1 } val test3: () -> Int = fun (): Int = { return 1 } val test4: () -> Int = fun (): Int = { 1 } - fun test5(): Int { return { 1 } } - fun test6(): Int = fun (): Int = 1 + fun test5(): Int { return { 1 } } + fun test6(): Int = fun (): Int = 1 class Nested { - fun test1(): Int = { return 1 } - fun test2(): Int = { 1 } + fun test1(): Int = { return 1 } + fun test2(): Int = { 1 } val test3: () -> Int = fun (): Int = { return 1 } val test4: () -> Int = fun (): Int = { 1 } - fun test5(): Int { return { 1 } } - fun test6(): Int = fun (): Int = 1 + fun test5(): Int { return { 1 } } + fun test6(): Int = fun (): Int = 1 } } diff --git a/compiler/testData/diagnostics/tests/generics/nullability/nullToGeneric.fir.kt b/compiler/testData/diagnostics/tests/generics/nullability/nullToGeneric.fir.kt index a09000b76c9..2eb58cc71eb 100644 --- a/compiler/testData/diagnostics/tests/generics/nullability/nullToGeneric.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/nullability/nullToGeneric.fir.kt @@ -9,12 +9,12 @@ fun foo(): T { bar(null) bar(null) - return null + return null } fun baz(): T? = null -fun foobar(): T = null +fun foobar(): T = null class A { fun xyz(x: F) {} @@ -26,10 +26,10 @@ class A { xyz(null) bar(null) - return null + return null } fun baz(): F? = null - fun foobar(): F = null + fun foobar(): F = null } diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt new file mode 100644 index 00000000000..ca0d9acc14c --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt @@ -0,0 +1,11 @@ +class Foo(val baz: Baz) + +class Bar { + val foo: Foo<*> = TODO() + + fun bar(): Baz { + return foo.baz + } +} + +typealias Baz = (@UnsafeVariance T) -> Unit diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt index 67afde5e957..05ad642e149 100644 --- a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt @@ -1,5 +1,3 @@ -// FIR_IDENTICAL - class Foo(val baz: Baz) class Bar { @@ -10,4 +8,4 @@ class Bar { } } -typealias Baz = (@UnsafeVariance T) -> Unit \ No newline at end of file +typealias Baz = (@UnsafeVariance T) -> Unit diff --git a/compiler/testData/diagnostics/tests/implicitNothing.fir.kt b/compiler/testData/diagnostics/tests/implicitNothing.fir.kt index c11e3e59082..75018f55018 100644 --- a/compiler/testData/diagnostics/tests/implicitNothing.fir.kt +++ b/compiler/testData/diagnostics/tests/implicitNothing.fir.kt @@ -17,7 +17,7 @@ fun check() { val x = null!! } -fun nonLocalReturn() = run { return } +fun nonLocalReturn() = run { return } class Klass { fun bar() = null!! diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionToUnitForIfAsLastExpressionInLambda.fir.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionToUnitForIfAsLastExpressionInLambda.fir.kt index f911a70bde1..55ca5294eeb 100644 --- a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionToUnitForIfAsLastExpressionInLambda.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionToUnitForIfAsLastExpressionInLambda.fir.kt @@ -12,7 +12,7 @@ fun foo(): String? { run { if (true) return@run - if (true) return Obj() // correct error, type check against return type of function "foo" + if (true) return Obj() // correct error, type check against return type of function "foo" } run { diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/noCoercion.fir.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/noCoercion.fir.kt index 94f1cba028c..789e35678ba 100644 --- a/compiler/testData/diagnostics/tests/inference/coercionToUnit/noCoercion.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/noCoercion.fir.kt @@ -23,4 +23,4 @@ fun noCoercionBlockHasExplicitReturn() { } } -fun noCoercionInExpressionBody(): Unit = "hello" \ No newline at end of file +fun noCoercionInExpressionBody(): Unit = "hello" diff --git a/compiler/testData/diagnostics/tests/inference/kt28654.fir.kt b/compiler/testData/diagnostics/tests/inference/kt28654.fir.kt index 0aaeeb85abf..b5c63b66f0c 100644 --- a/compiler/testData/diagnostics/tests/inference/kt28654.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/kt28654.fir.kt @@ -2,7 +2,7 @@ // !DIAGNOSTICS: -UNUSED_VARIABLE // Related issue: KT-28654 -fun select(): K = run { } +fun select(): K = run { } fun test() { val x: Int = select() diff --git a/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt b/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt index 1e0631d1dc3..7aeffc88755 100644 --- a/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt +++ b/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt @@ -149,7 +149,7 @@ fun illegalWhenBody(a: Any): Int = when(a) { fun illegalWhenBlock(a: Any): Int { when(a) { is Int -> return a - is String -> return a + is String -> return a } } fun declarations(a: Any?) { @@ -222,7 +222,7 @@ fun f(): String { fun foo(aa: Any?): Int { var a = aa if (a is Int?) { - return a + return a } return 1 } diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.fir.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.fir.kt index 13d904a5615..073ed8d2ca2 100644 --- a/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.fir.kt +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.fir.kt @@ -30,5 +30,5 @@ import p2.* fun test2(): Int { val r = foo(42) - return r + return r } diff --git a/compiler/testData/diagnostics/tests/objects/objectLiteralExpressionTypeMismatch.fir.kt b/compiler/testData/diagnostics/tests/objects/objectLiteralExpressionTypeMismatch.fir.kt index 1c9378ffee8..70c5dab5623 100644 --- a/compiler/testData/diagnostics/tests/objects/objectLiteralExpressionTypeMismatch.fir.kt +++ b/compiler/testData/diagnostics/tests/objects/objectLiteralExpressionTypeMismatch.fir.kt @@ -2,8 +2,8 @@ interface A interface B -fun test1(): B = object : A { -} +fun test1(): B = object : A { +} -fun test2(): B = object { -} \ No newline at end of file +fun test2(): B = object { +} diff --git a/compiler/testData/diagnostics/tests/override/kt12482.fir.kt b/compiler/testData/diagnostics/tests/override/kt12482.fir.kt index 1ae130d6152..76b8b916fc7 100644 --- a/compiler/testData/diagnostics/tests/override/kt12482.fir.kt +++ b/compiler/testData/diagnostics/tests/override/kt12482.fir.kt @@ -3,7 +3,7 @@ interface A { } interface B : A { - override fun test(): Unit = "B" + override fun test(): Unit = "B" } open class C : A diff --git a/compiler/testData/diagnostics/tests/regressions/OutProjections.fir.kt b/compiler/testData/diagnostics/tests/regressions/OutProjections.fir.kt index 8b50c0fe6b8..1544579fc22 100644 --- a/compiler/testData/diagnostics/tests/regressions/OutProjections.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/OutProjections.fir.kt @@ -9,7 +9,7 @@ fun f(expression : T) : G = G() fun foo() : G { val p = Point() - return f(p) + return f(p) } class Out() {} diff --git a/compiler/testData/diagnostics/tests/regressions/kt411.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt411.fir.kt index d7a776f7cb5..665fe2c907e 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt411.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt411.fir.kt @@ -35,7 +35,7 @@ fun t3() : String { return@t3 "1" } else { - return 2 + return 2 } return@l 0 } diff --git a/compiler/testData/diagnostics/tests/resolve/newLineLambda.fir.kt b/compiler/testData/diagnostics/tests/resolve/newLineLambda.fir.kt index 364d1d77525..ce6a7af112c 100644 --- a/compiler/testData/diagnostics/tests/resolve/newLineLambda.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/newLineLambda.fir.kt @@ -111,8 +111,8 @@ fun testTwoLambdas() { } fun f1(): (() -> Unit) -> (() -> Unit) -> Unit { - return { l1 -> + return { l1 -> l1() { l2 -> l2() } - } + } } diff --git a/compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.fir.kt b/compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.fir.kt index 9c8e2764d6e..0638f9ccb7b 100644 --- a/compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.fir.kt +++ b/compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.fir.kt @@ -16,7 +16,7 @@ fun LiveData.observe(a: Any, observer: (T) -> Unit): Observer { } // FILE: test.kt -fun test1(r: Runnable, l: LiveData): Observer = l.observe(r) { } // partial conversion +fun test1(r: Runnable, l: LiveData): Observer = l.observe(r) { } // partial conversion fun test2(r: Runnable, o: Observer, l: LiveData) { val a = l.observe(r, o) // no conversion diff --git a/compiler/testData/diagnostics/tests/smartCasts/elvisExprNotNull.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/elvisExprNotNull.fir.kt index 4a86b04553d..be351d4825c 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/elvisExprNotNull.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/elvisExprNotNull.fir.kt @@ -33,5 +33,5 @@ fun baz(s: String?, r: String?): String { fun withNull(s: String?): String { val t = s ?: null // Error: nullable - return t + return t } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/propertyToNotNull.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/propertyToNotNull.fir.kt index 7b54582ba92..a7f7a154349 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/propertyToNotNull.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/propertyToNotNull.fir.kt @@ -8,7 +8,7 @@ class Immutable(val x: String?) { class Mutable(var y: String?) { fun foo(): String { - if (y != null) return y + if (y != null) return y return "" } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/safecalls/falseSecondArgument.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/safecalls/falseSecondArgument.fir.kt index 91ac2daecbd..f86d085ad71 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/safecalls/falseSecondArgument.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/safecalls/falseSecondArgument.fir.kt @@ -3,5 +3,5 @@ fun calc(x: List?, y: Int?): Int { x?.subList(y!! - 1, y) // y!! above should not provide smart cast here - return y + return y } diff --git a/compiler/testData/diagnostics/tests/smartCasts/safecalls/receiverAndChainFalse.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/safecalls/receiverAndChainFalse.fir.kt index 347cb784791..149459a15ca 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/safecalls/receiverAndChainFalse.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/safecalls/receiverAndChainFalse.fir.kt @@ -6,5 +6,5 @@ fun calc(x: String?, y: Int?): Int { // Smart cast because of x!! in receiver foo(x!!)?.subSequence(y!!, x.length)?.length // No smart cast possible - return y + return y } diff --git a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEach.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEach.fir.kt index db4f2975016..e3f6e3cce53 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEach.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEach.fir.kt @@ -13,5 +13,5 @@ fun list(start: SomeObject): SomeObject { e = e.next() } // Smart cast is not possible here due to next() - return e + return e } diff --git a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEachWithBreak.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEachWithBreak.fir.kt index dd368ad85c8..21b0471ef68 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEachWithBreak.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEachWithBreak.fir.kt @@ -14,5 +14,5 @@ fun list(start: SomeObject): SomeObject { e.doSomething() e = e.next() } - return e + return e } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEachWithContinue.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEachWithContinue.fir.kt index 67fec6fb985..81441d3d79c 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEachWithContinue.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/forEachWithContinue.fir.kt @@ -14,5 +14,5 @@ fun list(start: SomeObject): SomeObject { e.doSomething() e = e.next() } - return e + return e } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/InnerClassInGeneric.fir.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/InnerClassInGeneric.fir.kt index 4aed075a786..2b796b31498 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/InnerClassInGeneric.fir.kt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/InnerClassInGeneric.fir.kt @@ -2,7 +2,7 @@ // FILE: KotlinFile.kt fun foo(javaClass: JavaClass): Int { val inner = javaClass.createInner() - return inner.doSomething(1, "") { } + return inner.doSomething(1, "") { } } // FILE: JavaClass.java diff --git a/compiler/testData/diagnostics/tests/typeParameters/implicitNothingInReturnPosition.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/implicitNothingInReturnPosition.fir.kt index cfe7e786efc..3c98b57eacf 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/implicitNothingInReturnPosition.fir.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/implicitNothingInReturnPosition.fir.kt @@ -40,7 +40,7 @@ class Context fun Any.decodeIn(typeFrom: Context): T = something() fun Any?.decodeOut1(typeFrom: Context): T { - return this?.decodeIn(typeFrom) ?: kotlin.Unit + return this?.decodeIn(typeFrom) ?: kotlin.Unit } fun Any.decodeOut2(typeFrom: Context): T { diff --git a/compiler/testData/diagnostics/tests/unsignedTypes/varargTypeToArrayTypeCheck.fir.kt b/compiler/testData/diagnostics/tests/unsignedTypes/varargTypeToArrayTypeCheck.fir.kt index 9a96a3978f9..ece5be15fb7 100644 --- a/compiler/testData/diagnostics/tests/unsignedTypes/varargTypeToArrayTypeCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/unsignedTypes/varargTypeToArrayTypeCheck.fir.kt @@ -4,4 +4,4 @@ fun ushort(vararg a: UShort): UShortArray = a fun uint(vararg a: UInt): UIntArray = a fun ulong(vararg a: ULong): ULongArray = a -fun rawUInt(vararg a: UInt): IntArray = a +fun rawUInt(vararg a: UInt): IntArray = a diff --git a/compiler/testData/diagnostics/tests/when/BranchBypassVal.fir.kt b/compiler/testData/diagnostics/tests/when/BranchBypassVal.fir.kt index cda408221da..a2d147b56da 100644 --- a/compiler/testData/diagnostics/tests/when/BranchBypassVal.fir.kt +++ b/compiler/testData/diagnostics/tests/when/BranchBypassVal.fir.kt @@ -18,5 +18,5 @@ fun test(a: Any): String { is A -> q!! } // When is not exhaustive - return q + return q } diff --git a/compiler/testData/diagnostics/tests/when/BranchBypassVar.fir.kt b/compiler/testData/diagnostics/tests/when/BranchBypassVar.fir.kt index 90053fe80f2..b082ea2311e 100644 --- a/compiler/testData/diagnostics/tests/when/BranchBypassVar.fir.kt +++ b/compiler/testData/diagnostics/tests/when/BranchBypassVar.fir.kt @@ -18,5 +18,5 @@ fun test(a: Any) { is A -> q = "1" } // When is not exhaustive - return q + return q } diff --git a/compiler/testData/diagnostics/tests/when/kt4434.fir.kt b/compiler/testData/diagnostics/tests/when/kt4434.fir.kt index 8a378378379..88b4514dbeb 100644 --- a/compiler/testData/diagnostics/tests/when/kt4434.fir.kt +++ b/compiler/testData/diagnostics/tests/when/kt4434.fir.kt @@ -14,14 +14,14 @@ package test fun foo(): Int { val a = "a" - return if (a.length > 0) { + return if (a.length > 0) { when (a) { "a" -> 1 } } else { 3 - } + } } fun bar(): Int { diff --git a/compiler/testData/diagnostics/testsWithStdLib/elvisOnJavaList.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/elvisOnJavaList.fir.kt index 646570072b9..6fb9ad31f41 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/elvisOnJavaList.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/elvisOnJavaList.fir.kt @@ -15,5 +15,5 @@ public class P { fun foo(c: P): MutableList { // Error should be here: see KT-8168 Typechecker fails for platform collection type - return c.getList() ?: listOf() + return c.getList() ?: listOf() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/when/kt10807.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/when/kt10807.fir.kt index 20ea3211028..cc0827a7554 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/when/kt10807.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/when/kt10807.fir.kt @@ -5,9 +5,9 @@ import kotlin.comparisons.nullsLast class Foo(val a: String, val b: Int) fun getComp(): Comparator = - when { + when { else -> nullsLast(compareBy({ it.a }, { it.b })) - } + } fun getCompInverted(): Comparator = nullsLast( diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/jump-expressions/return-expressions/p-4/neg/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/jump-expressions/return-expressions/p-4/neg/1.1.fir.kt index e1d619972eb..0fe93689183 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/jump-expressions/return-expressions/p-4/neg/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/jump-expressions/return-expressions/p-4/neg/1.1.fir.kt @@ -5,7 +5,7 @@ // TESTCASE NUMBER: 1 // UNEXPECTED BEHAVIOUR // ISSUES : KT-35545 -fun case1(a: Boolean) = run { println("d"); return true } +fun case1(a: Boolean) = run { println("d"); return true } // TESTCASE NUMBER: 2 val case2 diff --git a/compiler/tests-spec/testData/diagnostics/linked/type-system/introduction-1/p-6/neg/2.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/type-system/introduction-1/p-6/neg/2.2.fir.kt index 942e2cd5b8e..ca21cdde700 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/type-system/introduction-1/p-6/neg/2.2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/type-system/introduction-1/p-6/neg/2.2.fir.kt @@ -43,13 +43,13 @@ class Case8 { } // TESTCASE NUMBER: 9 -fun case_9(): Any = null +fun case_9(): Any = null // TESTCASE NUMBER: 10 -fun case_10(x: Int, y: Boolean): Any = if (y) x else null +fun case_10(x: Int, y: Boolean): Any = if (y) x else null // TESTCASE NUMBER: 11 -fun case_11(x: Int, y: Boolean): Any = if (y) x else null +fun case_11(x: Int, y: Boolean): Any = if (y) x else null // TESTCASE NUMBER: 12 class Case12 { 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 ab7a6254b79..c2eca5ea7b3 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/64.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/64.fir.kt index f24a90f7e97..babf675b651 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/64.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/64.fir.kt @@ -17,7 +17,7 @@ class Case1 { x = getT() } x - return x + return x } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 4820e812538..1c469a623f3 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -986,6 +986,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.RETURN_TYPE_MISMATCH) { firDiagnostic -> + ReturnTypeMismatchImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic -> ExtensionInClassReferenceNotAllowedImpl( firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration), diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 506e88683c9..d83386cfd87 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -701,6 +701,12 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val typeParametersOwner: KtSymbol } + abstract class ReturnTypeMismatch : KtFirDiagnostic() { + override val diagnosticClass get() = ReturnTypeMismatch::class + abstract val expected: KtType + abstract val actual: KtType + } + abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic() { override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class abstract val referencedDeclaration: KtCallableSymbol diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index d537c8b0a45..ce988e34c0a 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1131,6 +1131,15 @@ internal class NameInConstraintIsNotATypeParameterImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class ReturnTypeMismatchImpl( + override val expected: KtType, + override val actual: KtType, + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.ReturnTypeMismatch(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ExtensionInClassReferenceNotAllowedImpl( override val referencedDeclaration: KtCallableSymbol, firDiagnostic: FirPsiDiagnostic<*>, diff --git a/idea/testData/checker/FunctionReturnTypes.fir.kt b/idea/testData/checker/FunctionReturnTypes.fir.kt index 41ffd65f4af..ab4aa1f6db5 100644 --- a/idea/testData/checker/FunctionReturnTypes.fir.kt +++ b/idea/testData/checker/FunctionReturnTypes.fir.kt @@ -6,14 +6,14 @@ fun none() {} fun unitEmptyInfer() {} fun unitEmpty() : Unit {} fun unitEmptyReturn() : Unit {return} -fun unitIntReturn() : Unit {return 1} +fun unitIntReturn() : Unit {return 1} fun unitUnitReturn() : Unit {return Unit} fun test1() : Any = { return } fun test2() : Any = a@ {return@a 1} fun test3() : Any { return } fun bbb() { - return 1 + return 1 } fun foo(expr: StringBuilder): Int { @@ -26,8 +26,8 @@ fun foo(expr: StringBuilder): Int { fun unitShort() : Unit = Unit -fun unitShortConv() : Unit = 1 -fun unitShortNull() : Unit = null +fun unitShortConv() : Unit = 1 +fun unitShortNull() : Unit = null fun intEmpty() : Int {} fun intShortInfer() = 1 @@ -36,56 +36,56 @@ fun intShort() : Int = 1 fun intBlock() : Int {return 1} fun intBlock1() : Int {1} -fun intString(): Int = "s" -fun intFunctionLiteral(): Int = { 10 } +fun intString(): Int = "s" +fun intFunctionLiteral(): Int = { 10 } -fun blockReturnUnitMismatch() : Int {return} -fun blockReturnValueTypeMismatch() : Int {return 3.4} +fun blockReturnUnitMismatch() : Int {return} +fun blockReturnValueTypeMismatch() : Int {return 3.4} fun blockReturnValueTypeMatch() : Int {return 1} -fun blockReturnValueTypeMismatchUnit() : Int {return Unit} +fun blockReturnValueTypeMismatchUnit() : Int {return Unit} fun blockAndAndMismatch() : Int { true && false } fun blockAndAndMismatch1() : Int { - return true && false + return true && false } fun blockAndAndMismatch2() : Int { - (return true) && (return false) + (return true) && (return false) } fun blockAndAndMismatch3() : Int { true || false } fun blockAndAndMismatch4() : Int { - return true || false + return true || false } fun blockAndAndMismatch5() : Int { - (return true) || (return false) + (return true) || (return false) } fun blockReturnValueTypeMatch1() : Int { - return if (1 > 2) 1.0 else 2.0 + return if (1 > 2) 1.0 else 2.0 } fun blockReturnValueTypeMatch2() : Int { return if (1 > 2) 1 } fun blockReturnValueTypeMatch3() : Int { - return if (1 > 2) else 1 + return if (1 > 2) else 1 } fun blockReturnValueTypeMatch4() : Int { if (1 > 2) - return 1.0 - else return 2.0 + return 1.0 + else return 2.0 } fun blockReturnValueTypeMatch5() : Int { if (1 > 2) - return 1.0 - return 2.0 + return 1.0 + return 2.0 } fun blockReturnValueTypeMatch6() : Int { if (1 > 2) - else return 1.0 - return 2.0 + else return 1.0 + return 2.0 } fun blockReturnValueTypeMatch7() : Int { if (1 > 2) @@ -112,7 +112,7 @@ fun blockReturnValueTypeMatch11() : Int { fun blockReturnValueTypeMatch12() : Int { if (1 > 2) return 1 - else return 1.0 + else return 1.0 } fun blockNoReturnIfValDeclaration(): Int { val x = 1 @@ -130,23 +130,23 @@ fun blockNoReturnIfUnitInOneBranch(): Int { } } } -fun nonBlockReturnIfEmptyIf(): Int = if (1 < 2) {} else {} -fun nonBlockNoReturnIfUnitInOneBranch(): Int = if (1 < 2) {} else 2 +fun nonBlockReturnIfEmptyIf(): Int = if (1 < 2) {} else {} +fun nonBlockNoReturnIfUnitInOneBranch(): Int = if (1 < 2) {} else 2 val a = return 1 class A() { } -fun illegalConstantBody(): Int = "s" +fun illegalConstantBody(): Int = "s" fun illegalConstantBlock(): String { - return 1 + return 1 } fun illegalIfBody(): Int = - if (1 < 2) 'a' else { 1.0 } + if (1 < 2) 'a' else { 1.0 } fun illegalIfBlock(): Boolean { if (1 < 2) return false - else { return 1 } + else { return 1 } } fun illegalReturnIf(): Char { return if (1 < 2) 'a' else { 1 } diff --git a/idea/testData/checker/infos/SmartCasts.fir.kt b/idea/testData/checker/infos/SmartCasts.fir.kt index e7875925b4d..2fe868ece94 100644 --- a/idea/testData/checker/infos/SmartCasts.fir.kt +++ b/idea/testData/checker/infos/SmartCasts.fir.kt @@ -161,7 +161,7 @@ fun illegalWhenBody(a: Any): Int = when(a) { fun illegalWhenBlock(a: Any): Int { when(a) { is Int -> return a - is String -> return a + is String -> return a else -> return 1 } } @@ -218,11 +218,11 @@ fun f(): String { if (a is String) { val i: String = a a.compareTo("f") - val f: Function0 = { + val f: Function0 = { a = 42 a - } - return a + } + return a } return "" } @@ -234,13 +234,13 @@ class Mutable(var x: String?) { fun foo(): String { if (x is String) { - return x + return x } if (x != null) { - return x + return x } if (xx is String) { - return xx + return xx } return "" } @@ -248,7 +248,7 @@ class Mutable(var x: String?) { fun bar(other: Mutable): String { var y = other if (y.x is String) { - return y.x + return y.x } return "" }