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 c0d6f968906..ba4f6fe12ff 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 @@ -16287,6 +16287,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/inference/substitutions/delegationAndInference.kt"); } + @Test + @TestMetadata("hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt") + public void testHideLocalTypeForReturnTypeOfSingleExpressionFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt"); + } + @Test @TestMetadata("kt32189returnTypeWithTypealiasSubtitution.kt") public void testKt32189returnTypeWithTypealiasSubtitution() 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 385b8520885..c57972d51e8 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 @@ -16287,6 +16287,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/substitutions/delegationAndInference.kt"); } + @Test + @TestMetadata("hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt") + public void testHideLocalTypeForReturnTypeOfSingleExpressionFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.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 777e4cdf34e..aa69332a734 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 @@ -16287,6 +16287,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/substitutions/delegationAndInference.kt"); } + @Test + @TestMetadata("hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt") + public void testHideLocalTypeForReturnTypeOfSingleExpressionFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.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 b472abd6661..b94c3fb7cef 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 @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.copyWithNewSourceKind import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype @@ -22,6 +23,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl @@ -318,13 +320,14 @@ fun FirTypeRef.approximated( fun FirTypeRef.approximatedIfNeededOrSelf( approximator: ConeTypeApproximator, containingCallableVisibility: Visibility?, - isInlineFunction: Boolean = false, + session: FirSession, + isInlineFunction: Boolean = false ): FirTypeRef { val approximated = if (containingCallableVisibility == Visibilities.Public || containingCallableVisibility == Visibilities.Protected) approximatedForPublicPosition(approximator) else this - return approximated.hideLocalTypeIfNeeded(containingCallableVisibility, isInlineFunction).withoutEnhancedNullability() + return approximated.hideLocalTypeIfNeeded(containingCallableVisibility, session, isInlineFunction).withoutEnhancedNullability() } fun FirTypeRef.approximatedForPublicPosition(approximator: ConeTypeApproximator): FirTypeRef = @@ -350,9 +353,11 @@ private fun ConeKotlinType.requiresApproximationInPublicPosition(): Boolean = co */ private fun FirTypeRef.hideLocalTypeIfNeeded( containingCallableVisibility: Visibility?, + session: FirSession, isInlineFunction: Boolean = false ): FirTypeRef { if (!shouldHideLocalType(containingCallableVisibility, isInlineFunction)) return this + val firClass = (((this as? FirResolvedTypeRef) ?.type as? ConeClassLikeType) @@ -369,7 +374,23 @@ private fun FirTypeRef.hideLocalTypeIfNeeded( val superType = firClass.superTypeRefs.single() if (superType is FirResolvedTypeRef) { val newKind = source?.kind - return if (newKind is KtFakeSourceElementKind) superType.copyWithNewSourceKind(newKind) else superType + var result = superType + val resultTypeArguments = result.type.typeArguments + + if (resultTypeArguments.isNotEmpty() && resultTypeArguments.size == coneType.typeArguments.size) { + val substitution = mutableMapOf() + for (index in resultTypeArguments.indices) { + val key = resultTypeArguments[index] + val value = coneType.typeArguments[index] + 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) + } + + return if (newKind is KtFakeSourceElementKind) result.copyWithNewSourceKind(newKind) else result } return this } @@ -383,7 +404,7 @@ fun shouldHideLocalType(containingCallableVisibility: Visibility?, isInlineFunct return containingCallableVisibility == Visibilities.Public || containingCallableVisibility == Visibilities.Protected || containingCallableVisibility == Visibilities.Internal || - (containingCallableVisibility == Visibilities.Private && isInlineFunction) + containingCallableVisibility == Visibilities.Private && isInlineFunction } fun FirDeclaration.visibilityForApproximation(container: FirDeclaration?): Visibility { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index 5c6d6096799..9d29241bc9f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -952,7 +952,7 @@ internal class FirDeclarationCompletionResultsWriter( typeRef.resolvedTypeFromPrototype(it) } ?: typeRef if (data is ApproximationData.ApproximateByStatus) { - return result.approximatedIfNeededOrSelf(typeApproximator, data.visibility, data.isInline) + return result.approximatedIfNeededOrSelf(typeApproximator, data.visibility, this.typeContext.session, data.isInline) } return result } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 50faf646a06..5a2d19e7b5f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -344,7 +344,11 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor typeVariableTypeToStubType, session.typeContext, approximateIntegerLiterals = true ) - val stubTypeSubstituted = substitutor.substituteOrSelf(provideDelegateCandidate.substitutor.substituteOrSelf(components.typeFromCallee(provideDelegateCall).type)) + val stubTypeSubstituted = substitutor.substituteOrSelf( + provideDelegateCandidate.substitutor.substituteOrSelf( + components.typeFromCallee(provideDelegateCall).type + ) + ) provideDelegateCall.replaceTypeRef(provideDelegateCall.typeRef.resolvedTypeFromPrototype(stubTypeSubstituted)) return provideDelegateCall @@ -624,14 +628,15 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor if (result.returnTypeRef is FirImplicitTypeRef) { val simpleFunction = function as? FirSimpleFunction val returnExpression = (body?.statements?.single() as? FirReturnExpression)?.result - if (returnExpression != null && returnExpression.typeRef is FirResolvedTypeRef) { + if (returnExpression?.typeRef is FirResolvedTypeRef) { result.transformReturnTypeRef( transformer, withExpectedType( returnExpression.resultType.approximatedIfNeededOrSelf( session.typeApproximator, simpleFunction?.visibilityForApproximation(), - simpleFunction?.isInline == true + session, + isInlineFunction = simpleFunction?.isInline == true ) ) ) @@ -1009,6 +1014,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor expectedType.approximatedIfNeededOrSelf( session.typeApproximator, backingField.visibilityForApproximation(), + session ) ) ) @@ -1025,28 +1031,23 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> variable.getter?.returnTypeRef else -> null } - if (resultType != null) { - val expectedType = resultType.toExpectedTypeRef() - variable.transformReturnTypeRef( - transformer, - withExpectedType( + + variable.transformReturnTypeRef( + transformer, + withExpectedType( + resultType?.let { + val expectedType = it.toExpectedTypeRef() expectedType.approximatedIfNeededOrSelf( session.typeApproximator, variable.visibilityForApproximation(), + session ) - ) + } ?: buildErrorTypeRef { + diagnostic = ConeLocalVariableNoTypeOrInitializer(variable) + source = variable.source + } ) - } else { - variable.transformReturnTypeRef( - transformer, - withExpectedType( - buildErrorTypeRef { - diagnostic = ConeLocalVariableNoTypeOrInitializer(variable) - source = variable.source - }, - ) - ) - } + ) if (variable.getter?.returnTypeRef is FirImplicitTypeRef) { variable.getter?.transformReturnTypeRef(transformer, withExpectedType(variable.returnTypeRef)) } diff --git a/compiler/testData/codegen/box/objects/kt46136.kt b/compiler/testData/codegen/box/objects/kt46136.kt index 06f64b492aa..748eacab3a4 100644 --- a/compiler/testData/codegen/box/objects/kt46136.kt +++ b/compiler/testData/codegen/box/objects/kt46136.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR - abstract class A { fun print() = "OK" } diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt b/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt new file mode 100644 index 00000000000..765400e1848 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt @@ -0,0 +1,30 @@ +// FIR_IDENTICAL +// ISSUE: KT-51418 + +abstract class A +private fun fPrivate() = test("private") +fun fPublic() = test("public") + +private fun test(t: T) = object : A() { + fun bar(): T = t +} + +fun main() { + fPrivate().bar() + fPublic().bar() + test(1).bar() +} + +class FieldTest { + var result = "" + + private val test = object { + fun bar() = object { + fun qux() = object { + }.also { result += "b" } + }.also { result += "a" } + }.also { result += "!" } + + private val ttt = test.bar() + private val qqq = ttt.qux() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.txt b/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.txt new file mode 100644 index 00000000000..2aac0385567 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.txt @@ -0,0 +1,25 @@ +package + +private fun fPrivate(): test.`` +public fun fPublic(): A +public fun main(): kotlin.Unit +private fun test(/*0*/ t: T): test.`` + +public abstract class A { + public constructor A() + 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 FieldTest { + public constructor FieldTest() + private final val qqq: FieldTest.test.``.bar.``.qux.`` + public final var result: kotlin.String + private final val test: FieldTest.test.`` + private final val ttt: FieldTest.test.``.bar.`` + 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/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 16de95b35f1..e912df9b5d2 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 @@ -16293,6 +16293,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/substitutions/delegationAndInference.kt"); } + @Test + @TestMetadata("hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt") + public void testHideLocalTypeForReturnTypeOfSingleExpressionFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt"); + } + @Test @TestMetadata("kt32189returnTypeWithTypealiasSubtitution.kt") public void testKt32189returnTypeWithTypealiasSubtitution() throws Exception {