diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 1fd941fa0c7..fa87fb57e58 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -33981,6 +33981,44 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag } } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/warningsForBreakingChanges") + @TestDataPath("$PROJECT_ROOT") + public class WarningsForBreakingChanges { + @Test + public void testAllFilesPresentInWarningsForBreakingChanges() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/warningsForBreakingChanges"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes") + @TestDataPath("$PROJECT_ROOT") + public class CapturedTypes { + @Test + public void testAllFilesPresentInCapturedTypes() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("incorrectCapturedApproximationForValueParameters.kt") + public void testIncorrectCapturedApproximationForValueParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.kt"); + } + + @Test + @TestMetadata("noWarningAfterSmartcast.kt") + public void testNoWarningAfterSmartcast() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.kt"); + } + + @Test + @TestMetadata("noWarningOnSAMAdaption.kt") + public void testNoWarningOnSAMAdaption() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt"); + } + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/when") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 36811b9a3ec..f804d3416e0 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -33981,6 +33981,44 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti } } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/warningsForBreakingChanges") + @TestDataPath("$PROJECT_ROOT") + public class WarningsForBreakingChanges { + @Test + public void testAllFilesPresentInWarningsForBreakingChanges() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/warningsForBreakingChanges"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes") + @TestDataPath("$PROJECT_ROOT") + public class CapturedTypes { + @Test + public void testAllFilesPresentInCapturedTypes() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("incorrectCapturedApproximationForValueParameters.kt") + public void testIncorrectCapturedApproximationForValueParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.kt"); + } + + @Test + @TestMetadata("noWarningAfterSmartcast.kt") + public void testNoWarningAfterSmartcast() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.kt"); + } + + @Test + @TestMetadata("noWarningOnSAMAdaption.kt") + public void testNoWarningOnSAMAdaption() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt"); + } + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/when") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 90239d0ee7a..65284856917 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -33981,6 +33981,44 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac } } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/warningsForBreakingChanges") + @TestDataPath("$PROJECT_ROOT") + public class WarningsForBreakingChanges { + @Test + public void testAllFilesPresentInWarningsForBreakingChanges() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/warningsForBreakingChanges"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes") + @TestDataPath("$PROJECT_ROOT") + public class CapturedTypes { + @Test + public void testAllFilesPresentInCapturedTypes() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("incorrectCapturedApproximationForValueParameters.kt") + public void testIncorrectCapturedApproximationForValueParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.kt"); + } + + @Test + @TestMetadata("noWarningAfterSmartcast.kt") + public void testNoWarningAfterSmartcast() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.kt"); + } + + @Test + @TestMetadata("noWarningOnSAMAdaption.kt") + public void testNoWarningOnSAMAdaption() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt"); + } + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/when") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 82d0b78fb3e..5ea2df3c2fe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -894,6 +894,9 @@ public interface Errors { DiagnosticFactory0 RESOLUTION_TO_PRIVATE_CONSTRUCTOR_OF_SEALED_CLASS = DiagnosticFactory0.create(WARNING); + DiagnosticFactory2 TYPE_MISMATCH_WARNING_FOR_INCORRECT_CAPTURE_APPROXIMATION = DiagnosticFactory2.create(WARNING); + DiagnosticFactory2 RECEIVER_TYPE_MISMATCH_WARNING_FOR_INCORRECT_CAPTURE_APPROXIMATION = DiagnosticFactory2.create(WARNING); + // Type inference DiagnosticFactory0 CANNOT_INFER_PARAMETER_TYPE = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index ebfa78793d2..da32750f571 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -462,6 +462,16 @@ public class DefaultErrorMessages { MAP.put(RESOLUTION_TO_PRIVATE_CONSTRUCTOR_OF_SEALED_CLASS, "The private constructor of a sealed class will become inaccessible here in future. See https://youtrack.jetbrains.com/issue/KT-44866 for details"); + MAP.put( + TYPE_MISMATCH_WARNING_FOR_INCORRECT_CAPTURE_APPROXIMATION, + "Type mismatch: inferred type is {1} but {0} was expected. This warning will be an error soon. See https://youtrack.jetbrains.com/issue/KT-49404 for details", + RENDER_TYPE, RENDER_TYPE + ); + MAP.put( + RECEIVER_TYPE_MISMATCH_WARNING_FOR_INCORRECT_CAPTURE_APPROXIMATION, + "Extension receiver type mismatch: inferred type is {1} but {0} was expected. This warning will be an error soon. See https://youtrack.jetbrains.com/issue/KT-49404 for details", + RENDER_TYPE, RENDER_TYPE + ); MAP.put(LOCAL_EXTENSION_PROPERTY, "Local extension properties are not allowed"); MAP.put(LOCAL_VARIABLE_WITH_GETTER, "Local variables are not allowed to have getters"); MAP.put(LOCAL_VARIABLE_WITH_SETTER, "Local variables are not allowed to have setters"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt index 9643bb027a0..919569d4048 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt @@ -70,7 +70,7 @@ private val DEFAULT_CALL_CHECKERS = listOf( ReferencingToUnderscoreNamedParameterOfCatchBlockChecker, VarargWrongExecutionOrderChecker, SelfCallInNestedObjectConstructorChecker, NewSchemeOfIntegerOperatorResolutionChecker, EnumEntryVsCompanionPriorityCallChecker, CompanionInParenthesesLHSCallChecker, ResolutionToPrivateConstructorOfSealedClassChecker, EqualityCallChecker, UnsupportedUntilOperatorChecker, - BuilderInferenceAssignmentChecker, + BuilderInferenceAssignmentChecker, IncorrectCapturedApproximationCallChecker, ) private val DEFAULT_TYPE_CHECKERS = emptyList() private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/IncorrectCapturedApproximationCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/IncorrectCapturedApproximationCallChecker.kt new file mode 100644 index 00000000000..669c8e580a1 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/IncorrectCapturedApproximationCallChecker.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2022 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.resolve.calls.checkers + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.isFunctionOrSuspendFunctionType +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.resolve.calls.inference.isCaptured +import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue +import org.jetbrains.kotlin.resolve.calls.util.getEffectiveExpectedType +import org.jetbrains.kotlin.resolve.calls.util.getType +import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForSamType +import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.typeUtil.contains +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf + +object IncorrectCapturedApproximationCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + if (!resolvedCall.isReallySuccess()) return + val dispatchReceiverType = resolvedCall.smartCastDispatchReceiverType ?: resolvedCall.dispatchReceiver?.type ?: return + if (dispatchReceiverType.arguments.all { it.projectionKind == Variance.INVARIANT && !it.type.isCaptured() }) return + + val substitutor = + TypeSubstitutor.create(dispatchReceiverType) + .substitution.wrapWithCapturingSubstitution(needApproximation = false).buildSubstitutor() + + val functionDescriptor = resolvedCall.resultingDescriptor.original as? FunctionDescriptor ?: return + + val capturedSubstituted = functionDescriptor.substitute(substitutor) ?: return + + val indexedArguments = resolvedCall.valueArgumentsByIndex ?: return + for ((index, parameter) in capturedSubstituted.valueParameters.withIndex()) { + for (argument in indexedArguments[index].arguments) { + val expectedType = + getEffectiveExpectedType(parameter, argument, context.resolutionContext) + + val argumentExpression = argument.getArgumentExpression() ?: continue + val expressionType = argumentExpression.getType(context.trace.bindingContext) ?: continue + + val dataFlowValue = + context.dataFlowValueFactory.createDataFlowValue(argumentExpression, expressionType, context.resolutionContext) + if (shouldWarningBeReported(expressionType, expectedType, dataFlowValue, context)) { + context.trace.report( + Errors.TYPE_MISMATCH_WARNING_FOR_INCORRECT_CAPTURE_APPROXIMATION.on( + argumentExpression, expectedType, expressionType + ) + ) + } + } + } + + capturedSubstituted.extensionReceiverParameter?.let { extensionReceiverParameter -> + val extensionReceiver = resolvedCall.extensionReceiver ?: return@let + + val dataFlowValue = + context.dataFlowValueFactory.createDataFlowValue(extensionReceiver, context.resolutionContext) + + if (shouldWarningBeReported(extensionReceiver.type, extensionReceiverParameter.type, dataFlowValue, context)) { + val expression = (extensionReceiver as? ExpressionReceiver)?.expression ?: reportOn + context.trace.report( + Errors.RECEIVER_TYPE_MISMATCH_WARNING_FOR_INCORRECT_CAPTURE_APPROXIMATION.on( + expression, extensionReceiverParameter.type, extensionReceiver.type + ) + ) + } + } + } + + private fun shouldWarningBeReported( + expressionType: KotlinType, + expectedType: KotlinType, + dataFlowValue: DataFlowValue, + context: CallCheckerContext, + ): Boolean { + if (expectedType.arguments.none { arg -> !arg.isStarProjection && arg.type.contains(UnwrappedType::isCaptured) }) return false + if (expressionType.isSubtypeOf(expectedType)) return false + + val samExpectedType = getFunctionTypeForSamType( + expectedType, context.callComponents.samConversionResolver, context.callComponents.samConversionOracle, + ) + + if (expectedType.isFunctionOrSuspendFunctionType || samExpectedType?.isFunctionOrSuspendFunctionType == true) return false + + return context.dataFlowInfo.getCollectedTypes( + dataFlowValue, + context.languageVersionSettings, + ).none { it.isSubtypeOf(expectedType) } + } +} diff --git a/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.fir.kt b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.fir.kt new file mode 100644 index 00000000000..5e731783d1c --- /dev/null +++ b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.fir.kt @@ -0,0 +1,43 @@ +// ISSUE: KT-49404 +// SKIP_TXT + +// FILE: A.java +public class A implements WithExtension { + public void foo(Inv w) {} + public void ext(Inv t) {} +} + +// FILE: main.kt +class Inv(var t: T) + +interface WithExtension { + fun Inv.ext() {} +} + +class B : WithExtension { + fun foo(w: Inv) {} +} + +fun withInvStar(i: Inv<*>.() -> Unit) {} + +fun bar1(a: A, i: Inv<*>) { + a.foo(i) +} + +fun bar2(b: B, i: Inv<*>) { + b.foo(i) +} + +fun A.bar3(i: Inv<*>) { + i.ext() + withInvStar { + ext() + } +} + +fun B.bar4(i: Inv<*>) { + i.ext() + withInvStar { + ext() + } +} diff --git a/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.kt b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.kt new file mode 100644 index 00000000000..9494874b850 --- /dev/null +++ b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.kt @@ -0,0 +1,43 @@ +// ISSUE: KT-49404 +// SKIP_TXT + +// FILE: A.java +public class A implements WithExtension { + public void foo(Inv w) {} + public void ext(Inv t) {} +} + +// FILE: main.kt +class Inv(var t: T) + +interface WithExtension { + fun Inv.ext() {} +} + +class B : WithExtension { + fun foo(w: Inv) {} +} + +fun withInvStar(i: Inv<*>.() -> Unit) {} + +fun bar1(a: A, i: Inv<*>) { + a.foo(i) +} + +fun bar2(b: B, i: Inv<*>) { + b.foo(i) +} + +fun A.bar3(i: Inv<*>) { + i.ext() + withInvStar { + ext() + } +} + +fun B.bar4(i: Inv<*>) { + i.ext() + withInvStar { + ext() + } +} diff --git a/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.fir.kt b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.fir.kt new file mode 100644 index 00000000000..628e3968944 --- /dev/null +++ b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.fir.kt @@ -0,0 +1,9 @@ +// SKIP_TXT +interface Comp { + fun foo(t: T) +} + +fun foo(c: Comp, e: E?) { + if (e == null) return + c.foo(e) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.kt b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.kt new file mode 100644 index 00000000000..5bc900d9f9c --- /dev/null +++ b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.kt @@ -0,0 +1,9 @@ +// SKIP_TXT +interface Comp { + fun foo(t: T) +} + +fun foo(c: Comp, e: E?) { + if (e == null) return + c.foo(e) +} diff --git a/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt new file mode 100644 index 00000000000..c62cb3e9997 --- /dev/null +++ b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt @@ -0,0 +1,17 @@ +// FIR_IDENTICAL +// SKIP_TXT +// FILE: TaskProvider.java +public interface TaskProvider { + void configure(Action a); +} + +// FILE: main.kt +fun interface Action { + fun E.exec() +} + +fun foo(tp: TaskProvider) { + tp.configure { + length + } +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index c9cb294e1df..e8497f93beb 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -34071,6 +34071,44 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { } } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/warningsForBreakingChanges") + @TestDataPath("$PROJECT_ROOT") + public class WarningsForBreakingChanges { + @Test + public void testAllFilesPresentInWarningsForBreakingChanges() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/warningsForBreakingChanges"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes") + @TestDataPath("$PROJECT_ROOT") + public class CapturedTypes { + @Test + public void testAllFilesPresentInCapturedTypes() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("incorrectCapturedApproximationForValueParameters.kt") + public void testIncorrectCapturedApproximationForValueParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/incorrectCapturedApproximationForValueParameters.kt"); + } + + @Test + @TestMetadata("noWarningAfterSmartcast.kt") + public void testNoWarningAfterSmartcast() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningAfterSmartcast.kt"); + } + + @Test + @TestMetadata("noWarningOnSAMAdaption.kt") + public void testNoWarningOnSAMAdaption() throws Exception { + runTest("compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt"); + } + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/when") @TestDataPath("$PROJECT_ROOT")