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 afc6b762222..244e9466ded 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 @@ -4095,6 +4095,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut2.kt"); } + @Test + @TestMetadata("IsErasedAllowFromOut3.kt") + public void testIsErasedAllowFromOut3() throws Exception { + runTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.kt"); + } + @Test @TestMetadata("IsErasedAllowFromOutAtClass.kt") public void testIsErasedAllowFromOutAtClass() throws Exception { 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 b8510243966..8ee1d405e82 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 @@ -4095,6 +4095,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut2.kt"); } + @Test + @TestMetadata("IsErasedAllowFromOut3.kt") + public void testIsErasedAllowFromOut3() throws Exception { + runTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.kt"); + } + @Test @TestMetadata("IsErasedAllowFromOutAtClass.kt") public void testIsErasedAllowFromOutAtClass() throws Exception { 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 7d292ba95cb..82ea5420cc2 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 @@ -4095,6 +4095,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut2.kt"); } + @Test + @TestMetadata("IsErasedAllowFromOut3.kt") + public void testIsErasedAllowFromOut3() throws Exception { + runTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.kt"); + } + @Test @TestMetadata("IsErasedAllowFromOutAtClass.kt") public void testIsErasedAllowFromOutAtClass() throws Exception { 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 0ee0bd79ec7..3094fea933f 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 @@ -1102,7 +1102,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { } val CASTS_AND_IS_CHECKS by object : DiagnosticGroup("Casts and is-checks") { - val CANNOT_CHECK_FOR_ERASED by warning { + val CANNOT_CHECK_FOR_ERASED by error { parameter("type") } val CAST_NEVER_SUCCEEDS by warning(PositioningStrategy.OPERATOR) 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 fd68629e4cc..2c427713a23 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 @@ -590,7 +590,7 @@ object FirErrors { val USELESS_ELVIS_RIGHT_IS_NULL by warning0(SourceElementPositioningStrategies.USELESS_ELVIS) // Casts and is-checks - val CANNOT_CHECK_FOR_ERASED by warning1() + val CANNOT_CHECK_FOR_ERASED by error1() val CAST_NEVER_SUCCEEDS by warning0(SourceElementPositioningStrategies.OPERATOR) val USELESS_CAST by warning0(SourceElementPositioningStrategies.AS_TYPE) val UNCHECKED_CAST by warning2(SourceElementPositioningStrategies.AS_TYPE) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirCastDiagnosticsHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirCastDiagnosticsHelpers.kt index b45b46fcbe8..ed4bb56fee2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirCastDiagnosticsHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirCastDiagnosticsHelpers.kt @@ -237,17 +237,12 @@ fun findStaticallyKnownSubtype( // If some parameters are not determined by unification, it means that these parameters are lost, // let's put ConeStubType instead, so that we can only cast to something like List<*>, e.g. (a: Any) as List<*> for (variable in variables) { - val value = substitution[variable] - val resultValue = if (value == null) { - if (!resultSubstitution.containsKey(variable)) { - context.session.builtinTypes.nullableAnyType.type - } else { - null + val resultValue = when (val value = substitution[variable]) { + null -> null + is ConeStarProjection -> { + ConeStubTypeForTypeVariableInSubtyping(ConeTypeVariable("", null), ConeNullability.NULLABLE) } - } else if (value is ConeStarProjection) { - ConeStubTypeForTypeVariableInSubtyping(ConeTypeVariable("", variable.toLookupTag()), ConeNullability.NULLABLE) - } else { - value.type + else -> value.type } if (resultValue != null) { resultSubstitution[variable] = resultValue diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 6321e4017a4..2733a5dde33 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -606,7 +606,8 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform private fun FirTypeRef.withTypeArgumentsForBareType(argument: FirExpression, operation: FirOperation): FirTypeRef { val type = coneTypeSafe() ?: return this - if (type.typeArguments.isNotEmpty()) return this + if (type.typeArguments.isNotEmpty()) return this // TODO: Incorrect for local classes. + // TODO: Check equality of size of arguments and parameters? val firClass = type.lookupTag.toSymbol(session)?.fir ?: return this if (firClass.typeParameters.isEmpty()) return this diff --git a/compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.kt b/compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.kt new file mode 100644 index 00000000000..32ec75604f3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.kt @@ -0,0 +1,4 @@ +// FIR_IDENTICAL +open class Base +class Derived : Base() +fun f(entry: Base) = entry is Derived diff --git a/compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.txt b/compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.txt new file mode 100644 index 00000000000..548a826565a --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.txt @@ -0,0 +1,17 @@ +package + +public fun f(/*0*/ entry: Base): kotlin.Boolean + +public open class Base { + public constructor Base() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Derived : Base { + public constructor Derived() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.fir.kt b/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.fir.kt index 6d7618c501e..6b2ad475fd3 100644 --- a/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.fir.kt @@ -6,11 +6,11 @@ fun foo(x: Any, y: Any) : Any { } if (1 == 2) { - x as C + x as C } if (2 == 3) { - x as? C + x as? C } class Outer { @@ -22,7 +22,12 @@ fun foo(x: Any, y: Any) : Any { return y } - y as Outer<*>.Inner + if (y is Outer<*>.Inner) { + return y + } + + y as Outer<*>.Inner + y as Outer.Inner return C() } diff --git a/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.kt b/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.kt index ecdcb99eb61..102c56b2db3 100644 --- a/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.kt +++ b/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.kt @@ -22,7 +22,12 @@ fun foo(x: Any, y: Any) : Any { return y } + if (y is Outer<*>.Inner) { + return y + } + y as Outer<*>.Inner + y as Outer.Inner return C() } diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt10444.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/kt10444.fir.kt index 2f96dbc0e95..8c753c72aed 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/kt10444.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/kt10444.fir.kt @@ -4,7 +4,7 @@ class Base class Qwe(val a: T?) { fun test1(obj: Any) { - obj as Qwe + obj as Qwe check(obj.a) } 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 8979e789739..e9a8e39608a 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 @@ -4101,6 +4101,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut2.kt"); } + @Test + @TestMetadata("IsErasedAllowFromOut3.kt") + public void testIsErasedAllowFromOut3() throws Exception { + runTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut3.kt"); + } + @Test @TestMetadata("IsErasedAllowFromOutAtClass.kt") public void testIsErasedAllowFromOutAtClass() throws Exception {