[FIR] Hide local type for return type of single expression function ^KT-51418 Fixed

This commit is contained in:
Ivan Kochurkin
2022-04-06 17:48:38 +03:00
committed by teamcity
parent 0ecba0ad0b
commit 05bed8f751
10 changed files with 126 additions and 27 deletions
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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<FirTypeParameterSymbol, ConeKotlinType>()
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 {
@@ -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
}
@@ -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))
}
-2
View File
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
abstract class A<T> {
fun print() = "OK"
}
@@ -0,0 +1,30 @@
// FIR_IDENTICAL
// ISSUE: KT-51418
abstract class A<T>
private fun fPrivate() = test("private")
fun fPublic() = test("public")
private fun <T> test(t: T) = object : A<T>() {
fun bar(): T = t
}
fun main() {
fPrivate().bar()
fPublic().<!UNRESOLVED_REFERENCE!>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()
}
@@ -0,0 +1,25 @@
package
private fun fPrivate(): test.`<no name provided>`<kotlin.String>
public fun fPublic(): A<kotlin.String>
public fun main(): kotlin.Unit
private fun </*0*/ T> test(/*0*/ t: T): test.`<no name provided>`<T>
public abstract class A</*0*/ T> {
public constructor A</*0*/ T>()
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.`<no name provided>`.bar.`<no name provided>`.qux.`<no name provided>`
public final var result: kotlin.String
private final val test: FieldTest.test.`<no name provided>`
private final val ttt: FieldTest.test.`<no name provided>`.bar.`<no name provided>`
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
}
@@ -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 {