K2: don't report RETURN_TYPE_MISMATCH on last statement returns
#KT-53198 Fixed
This commit is contained in:
+6
@@ -37734,6 +37734,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nullableUnitLiteral.kt")
|
||||||
|
public void testNullableUnitLiteral() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/functionLiterals/nullableUnitLiteral.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("pseudocodeMemoryOverhead.kt")
|
@TestMetadata("pseudocodeMemoryOverhead.kt")
|
||||||
public void testPseudocodeMemoryOverhead() throws Exception {
|
public void testPseudocodeMemoryOverhead() throws Exception {
|
||||||
|
|||||||
+6
@@ -37734,6 +37734,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nullableUnitLiteral.kt")
|
||||||
|
public void testNullableUnitLiteral() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/functionLiterals/nullableUnitLiteral.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("pseudocodeMemoryOverhead.kt")
|
@TestMetadata("pseudocodeMemoryOverhead.kt")
|
||||||
public void testPseudocodeMemoryOverhead() throws Exception {
|
public void testPseudocodeMemoryOverhead() throws Exception {
|
||||||
|
|||||||
+6
@@ -37734,6 +37734,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nullableUnitLiteral.kt")
|
||||||
|
public void testNullableUnitLiteral() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/functionLiterals/nullableUnitLiteral.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("pseudocodeMemoryOverhead.kt")
|
@TestMetadata("pseudocodeMemoryOverhead.kt")
|
||||||
public void testPseudocodeMemoryOverhead() throws Exception {
|
public void testPseudocodeMemoryOverhead() throws Exception {
|
||||||
|
|||||||
+8
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
@@ -36,6 +37,13 @@ object FirFunctionReturnTypeMismatchChecker : FirReturnExpressionChecker() {
|
|||||||
context.session.builtinTypes.unitType.coneType
|
context.session.builtinTypes.unitType.coneType
|
||||||
else
|
else
|
||||||
targetElement.returnTypeRef.coneType
|
targetElement.returnTypeRef.coneType
|
||||||
|
if (targetElement is FirAnonymousFunction &&
|
||||||
|
expression.source?.kind is KtFakeSourceElementKind.ImplicitReturn.FromLastStatement &&
|
||||||
|
functionReturnType.isUnit
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val typeContext = context.session.typeContext
|
val typeContext = context.session.typeContext
|
||||||
val returnExpressionType = resultExpression.typeRef.coneType
|
val returnExpressionType = resultExpression.typeRef.coneType
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
|||||||
object FirReturnSyntaxAndLabelChecker : FirReturnExpressionChecker() {
|
object FirReturnSyntaxAndLabelChecker : FirReturnExpressionChecker() {
|
||||||
override fun check(expression: FirReturnExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirReturnExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val source = expression.source
|
val source = expression.source
|
||||||
if (source?.kind == KtFakeSourceElementKind.ImplicitReturn) return
|
if (source?.kind is KtFakeSourceElementKind.ImplicitReturn) return
|
||||||
|
|
||||||
val labeledElement = expression.target.labeledElement
|
val labeledElement = expression.target.labeledElement
|
||||||
val targetSymbol = labeledElement.symbol
|
val targetSymbol = labeledElement.symbol
|
||||||
|
|||||||
+2
-1
@@ -40,7 +40,8 @@ object UnreachableCodeChecker : FirControlFlowChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val sourceKindsToSkip = setOf(
|
private val sourceKindsToSkip = setOf(
|
||||||
KtFakeSourceElementKind.ImplicitReturn,
|
KtFakeSourceElementKind.ImplicitReturn.FromExpressionBody,
|
||||||
|
KtFakeSourceElementKind.ImplicitReturn.FromLastStatement,
|
||||||
KtFakeSourceElementKind.DesugaredForLoop
|
KtFakeSourceElementKind.DesugaredForLoop
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ class Fir2IrVisitor(
|
|||||||
return returnExpression.convertWithOffsets { startOffset, endOffset ->
|
return returnExpression.convertWithOffsets { startOffset, endOffset ->
|
||||||
val result = returnExpression.result
|
val result = returnExpression.result
|
||||||
// For implicit returns, use the expression endOffset to generate the expected line number for debugging.
|
// For implicit returns, use the expression endOffset to generate the expected line number for debugging.
|
||||||
val returnStartOffset = if (returnExpression.source?.kind == KtFakeSourceElementKind.ImplicitReturn) endOffset else startOffset
|
val returnStartOffset = if (returnExpression.source?.kind is KtFakeSourceElementKind.ImplicitReturn) endOffset else startOffset
|
||||||
IrReturnImpl(
|
IrReturnImpl(
|
||||||
returnStartOffset, endOffset, irBuiltIns.nothingType,
|
returnStartOffset, endOffset, irBuiltIns.nothingType,
|
||||||
when (irTarget) {
|
when (irTarget) {
|
||||||
|
|||||||
+1
-1
@@ -195,7 +195,7 @@ class ExpressionsConverter(
|
|||||||
if (statements.isEmpty()) {
|
if (statements.isEmpty()) {
|
||||||
statements.add(
|
statements.add(
|
||||||
buildReturnExpression {
|
buildReturnExpression {
|
||||||
source = expressionSource.fakeElement(KtFakeSourceElementKind.ImplicitReturn)
|
source = expressionSource.fakeElement(KtFakeSourceElementKind.ImplicitReturn.FromExpressionBody)
|
||||||
this.target = target
|
this.target = target
|
||||||
result = buildUnitExpression {
|
result = buildUnitExpression {
|
||||||
source = expressionSource.fakeElement(KtFakeSourceElementKind.ImplicitUnit)
|
source = expressionSource.fakeElement(KtFakeSourceElementKind.ImplicitUnit)
|
||||||
|
|||||||
@@ -1435,7 +1435,7 @@ open class RawFirBuilder(
|
|||||||
if (statements.isEmpty()) {
|
if (statements.isEmpty()) {
|
||||||
statements.add(
|
statements.add(
|
||||||
buildReturnExpression {
|
buildReturnExpression {
|
||||||
source = expressionSource.fakeElement(KtFakeSourceElementKind.ImplicitReturn)
|
source = expressionSource.fakeElement(KtFakeSourceElementKind.ImplicitReturn.FromExpressionBody)
|
||||||
this.target = target
|
this.target = target
|
||||||
result = buildUnitExpression {
|
result = buildUnitExpression {
|
||||||
source = expressionSource.fakeElement(KtFakeSourceElementKind.ImplicitUnit)
|
source = expressionSource.fakeElement(KtFakeSourceElementKind.ImplicitUnit)
|
||||||
|
|||||||
+1
-1
@@ -192,7 +192,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
|||||||
|
|
||||||
source =
|
source =
|
||||||
if (fromKtReturnExpression) baseSource?.realElement()
|
if (fromKtReturnExpression) baseSource?.realElement()
|
||||||
else baseSource?.fakeElement(KtFakeSourceElementKind.ImplicitReturn)
|
else baseSource?.fakeElement(KtFakeSourceElementKind.ImplicitReturn.FromExpressionBody)
|
||||||
result = this@toReturn
|
result = this@toReturn
|
||||||
if (labelName == null) {
|
if (labelName == null) {
|
||||||
target = context.firFunctionTargets.lastOrNull { !it.isLambda } ?: FirFunctionTarget(labelName, isLambda = false).apply {
|
target = context.firFunctionTargets.lastOrNull { !it.isLambda } ?: FirFunctionTarget(labelName, isLambda = false).apply {
|
||||||
|
|||||||
+1
-1
@@ -944,7 +944,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
override fun <E : FirElement> transformElement(element: E, data: FirExpression): E {
|
override fun <E : FirElement> transformElement(element: E, data: FirExpression): E {
|
||||||
if (element == lastStatement) {
|
if (element == lastStatement) {
|
||||||
val returnExpression = buildReturnExpression {
|
val returnExpression = buildReturnExpression {
|
||||||
source = element.source?.fakeElement(KtFakeSourceElementKind.ImplicitReturn)
|
source = element.source?.fakeElement(KtFakeSourceElementKind.ImplicitReturn.FromLastStatement)
|
||||||
result = lastStatement
|
result = lastStatement
|
||||||
target = FirFunctionTarget(null, isLambda = this@addReturn.isLambda).also {
|
target = FirFunctionTarget(null, isLambda = this@addReturn.isLambda).also {
|
||||||
it.bind(this@addReturn)
|
it.bind(this@addReturn)
|
||||||
|
|||||||
@@ -59,7 +59,11 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() {
|
|||||||
|
|
||||||
// for lambdas & functions with expression bodies the return statement is added
|
// for lambdas & functions with expression bodies the return statement is added
|
||||||
// with a fake sources which refers to the return target
|
// with a fake sources which refers to the return target
|
||||||
object ImplicitReturn : KtFakeSourceElementKind()
|
sealed class ImplicitReturn : KtFakeSourceElementKind() {
|
||||||
|
object FromExpressionBody : ImplicitReturn()
|
||||||
|
|
||||||
|
object FromLastStatement : ImplicitReturn()
|
||||||
|
}
|
||||||
|
|
||||||
// return expression in procedures -> return Unit
|
// return expression in procedures -> return Unit
|
||||||
// with a fake sources which refers to the return statement
|
// with a fake sources which refers to the return statement
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val closeable: java.io.Closeable? = null
|
||||||
|
val closeF = fun() { closeable?.close() }
|
||||||
|
val closeFB = fun(): Unit = <!RETURN_TYPE_MISMATCH!>closeable?.close()<!>
|
||||||
|
val closeFR = fun() { return <!RETURN_TYPE_MISMATCH!>closeable?.close()<!> }
|
||||||
|
val closeL = { closeable?.close() }
|
||||||
|
val closeLR = label@ { return@label closeable?.close() }
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val closeable: java.io.Closeable? = null
|
||||||
|
val closeF = fun() { closeable?.close() }
|
||||||
|
val closeFB = fun(): Unit = <!TYPE_MISMATCH!>closeable?.close()<!>
|
||||||
|
val closeFR = fun() { return <!TYPE_MISMATCH!>closeable?.close()<!> }
|
||||||
|
val closeL = { closeable?.close() }
|
||||||
|
val closeLR = label@ { return@label closeable?.close() }
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
Generated
+6
@@ -37824,6 +37824,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nullableUnitLiteral.kt")
|
||||||
|
public void testNullableUnitLiteral() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/functionLiterals/nullableUnitLiteral.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("pseudocodeMemoryOverhead.kt")
|
@TestMetadata("pseudocodeMemoryOverhead.kt")
|
||||||
public void testPseudocodeMemoryOverhead() throws Exception {
|
public void testPseudocodeMemoryOverhead() throws Exception {
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ abstract class AbstractKtDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
|
|||||||
val sourceElement = element.source ?: return null
|
val sourceElement = element.source ?: return null
|
||||||
val sourceKind = sourceElement.kind
|
val sourceKind = sourceElement.kind
|
||||||
if (sourceKind !in allowedKindsForDebugInfo) {
|
if (sourceKind !in allowedKindsForDebugInfo) {
|
||||||
if (sourceKind != KtFakeSourceElementKind.ImplicitReturn || sourceElement.elementType != KtNodeTypes.RETURN) {
|
if (sourceKind !is KtFakeSourceElementKind.ImplicitReturn || sourceElement.elementType != KtNodeTypes.RETURN) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user