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 b3adf471d4f..c8b89d6c9bd 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 @@ -16979,6 +16979,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt"); } + @Test + @TestMetadata("hideNullableLocalTypeInPublicPosition.kt") + public void testHideNullableLocalTypeInPublicPosition() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.kt"); + } + @Test @TestMetadata("kt32189returnTypeWithTypealiasSubtitution.kt") public void testKt32189returnTypeWithTypealiasSubtitution() 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 95fefeec855..1300366e942 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 @@ -16979,6 +16979,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt"); } + @Test + @TestMetadata("hideNullableLocalTypeInPublicPosition.kt") + public void testHideNullableLocalTypeInPublicPosition() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.kt"); + } + @Test @TestMetadata("kt32189returnTypeWithTypealiasSubtitution.kt") public void testKt32189returnTypeWithTypealiasSubtitution() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index 88c8ca0ee62..2b47145cb41 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -383,11 +383,8 @@ private fun FirTypeRef.hideLocalTypeIfNeeded( ): FirTypeRef { if (!shouldHideLocalType(containingCallableVisibility, isInlineFunction)) return this - val firClass = - (((this as? FirResolvedTypeRef) - ?.type as? ConeClassLikeType) - ?.lookupTag as? ConeClassLookupTagWithFixedSymbol) - ?.symbol?.fir + val coneType = coneTypeSafe() ?: return this + val firClass = (coneType.lookupTag as? ConeClassLookupTagWithFixedSymbol)?.symbol?.fir if (firClass !is FirAnonymousObject) { // NB: local classes are acceptable here, but reported by EXPOSED_* checkers as errors return this @@ -402,6 +399,7 @@ private fun FirTypeRef.hideLocalTypeIfNeeded( var result = superType val resultTypeArguments = result.type.typeArguments + result = result.withReplacedConeType(result.type.withNullability(coneType.nullability, session.typeContext)) if (resultTypeArguments.isNotEmpty() && resultTypeArguments.size == coneType.typeArguments.size) { val substitution = mutableMapOf() for (index in resultTypeArguments.indices) { @@ -410,9 +408,7 @@ private fun FirTypeRef.hideLocalTypeIfNeeded( val symbol = (key as? ConeTypeParameterType)?.lookupTag?.typeParameterSymbol ?: continue substitution[symbol] = value.type!! } - - val substituted = ConeSubstitutorByMap(substitution, session).substituteOrSelf(result.type) - result = substituted.toFirResolvedTypeRef(superType.source, superType.delegatedTypeRef) + result = result.withReplacedConeType(ConeSubstitutorByMap(substitution, session).substituteOrSelf(result.type)) } return if (newKind is KtFakeSourceElementKind) result.copyWithNewSourceKind(newKind) else result diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.fir.kt b/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.fir.kt new file mode 100644 index 00000000000..fbc2c17e3db --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.fir.kt @@ -0,0 +1,18 @@ +// ISSUE: KT-30054 +interface I { + fun foo(): String +} + +fun bar(condition: Boolean) /*: I? */ = + if (condition) + object : I { + override fun foo() = "should check for null first" + fun baz() = "invisible" + } + else null + +fun main() { + bar(false).baz() + bar(false).foo() + bar(false)?.foo() +} diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.kt b/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.kt new file mode 100644 index 00000000000..2e4e5e03f3a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.kt @@ -0,0 +1,18 @@ +// ISSUE: KT-30054 +interface I { + fun foo(): String +} + +fun bar(condition: Boolean) /*: I? */ = + if (condition) + object : I { + override fun foo() = "should check for null first" + fun baz() = "invisible" + } + else null + +fun main() { + bar(false).baz() + bar(false).foo() + bar(false)?.foo() +} diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.txt b/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.txt new file mode 100644 index 00000000000..e619714080d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.txt @@ -0,0 +1,11 @@ +package + +public fun bar(/*0*/ condition: kotlin.Boolean): I +public fun main(): kotlin.Unit + +public interface I { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} 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 ae6d2e6c1ae..46969ac3e13 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 @@ -16985,6 +16985,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt"); } + @Test + @TestMetadata("hideNullableLocalTypeInPublicPosition.kt") + public void testHideNullableLocalTypeInPublicPosition() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideNullableLocalTypeInPublicPosition.kt"); + } + @Test @TestMetadata("kt32189returnTypeWithTypealiasSubtitution.kt") public void testKt32189returnTypeWithTypealiasSubtitution() throws Exception {