FIR: migrate type-related utils to relevant file

This commit is contained in:
Jinseong Jeon
2020-09-16 01:05:16 +03:00
committed by Mikhail Glukhikh
parent 0436a555d5
commit 721248f883
10 changed files with 125 additions and 138 deletions
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.serialization.FirElementSerializer
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.fir.types.*
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.providers.*
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -15,13 +15,9 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.scopes.scope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.Name
private operator fun <T> Pair<T, *>?.component1() = this?.first
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.remapArguments
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.writeResultType
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.declarations.FirTypedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.*
@@ -14,12 +14,8 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildVarargArgumentsExpression
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.arrayElementType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import kotlin.math.min
@@ -6,11 +6,6 @@
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities.Internal
import org.jetbrains.kotlin.descriptors.Visibilities.Private
import org.jetbrains.kotlin.descriptors.Visibilities.Protected
import org.jetbrains.kotlin.descriptors.Visibilities.Public
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
@@ -34,9 +29,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
@@ -44,7 +37,6 @@ import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
@@ -511,7 +503,9 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
result.transformReturnTypeRef(
transformer,
withExpectedType(
body.resultType.approximateTypeIfNeeded(simpleFunction?.visibility, simpleFunction?.isInline == true)
body.resultType.approximatedIfNeededOrSelf(
inferenceComponents.approximator, simpleFunction?.visibility, simpleFunction?.isInline == true
)
)
)
} else {
@@ -923,7 +917,9 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
}
variable.transformReturnTypeRef(
transformer,
withExpectedType(expectedType.approximateTypeIfNeeded((variable as? FirProperty)?.visibility))
withExpectedType(
expectedType.approximatedIfNeededOrSelf(inferenceComponents.approximator, (variable as? FirProperty)?.visibility)
)
)
}
variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> {
@@ -945,7 +941,9 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
}
variable.transformReturnTypeRef(
transformer,
withExpectedType(expectedType?.approximateTypeIfNeeded((variable as? FirProperty)?.visibility))
withExpectedType(
expectedType?.approximatedIfNeededOrSelf(inferenceComponents.approximator, (variable as? FirProperty)?.visibility)
)
)
}
else -> {
@@ -968,87 +966,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
}
}
private fun ConeKotlinType.requiresApproximationInPublicPosition(): Boolean {
return when (this) {
is ConeIntegerLiteralType,
is ConeCapturedType,
is ConeDefinitelyNotNullType,
is ConeIntersectionType -> true
is ConeClassLikeType -> typeArguments.any {
it is ConeKotlinTypeProjection && it.type.requiresApproximationInPublicPosition()
}
else -> false
}
}
private fun FirTypeRef.approximateTypeIfNeeded(
containingCallableVisibility: Visibility?,
isInlineFunction: Boolean = false
): FirTypeRef {
val approximatedType = if (this is FirResolvedTypeRef &&
(containingCallableVisibility == Public || containingCallableVisibility == Protected)
) {
if (type.requiresApproximationInPublicPosition()) {
this.withReplacedConeType(
inferenceComponents.approximator.approximateToSuperType(
this.type, TypeApproximatorConfiguration.PublicDeclaration
) as? ConeKotlinType
)
} else {
this
}
} else {
this
}
return approximatedType.hideLocalTypeIfNeeded(containingCallableVisibility, isInlineFunction)
}
/*
* Suppose a function without an explicit return type just returns an anonymous object:
*
* fun foo(...) = object : ObjectSuperType {
* override fun ...
* }
*
* Without unwrapping, the return type ended up with that anonymous object (<no name provided>), while the resolved super type, which
* acts like an implementing interface, is a better fit. In fact, exposing an anonymous object types is prohibited for certain cases,
* e.g., KT-33917. We can also apply this to any local types.
*/
private fun FirTypeRef.hideLocalTypeIfNeeded(
containingCallableVisibility: Visibility?,
isInlineFunction: Boolean = false
): FirTypeRef {
if (containingCallableVisibility == null) {
return this
}
// Approximate types for non-private (all but package private or private) members.
// Also private inline functions, as per KT-33917.
if (containingCallableVisibility == Public ||
containingCallableVisibility == Protected ||
containingCallableVisibility == Internal ||
(containingCallableVisibility == Private && isInlineFunction)
) {
val firClass =
(((this as? FirResolvedTypeRef)
?.type as? ConeClassLikeType)
?.lookupTag as? ConeClassLookupTagWithFixedSymbol)
?.symbol?.fir
if (firClass?.classId?.isLocal != true) {
return this
}
if (firClass.superTypeRefs.size > 1) {
return buildErrorTypeRef {
diagnostic = ConeSimpleDiagnostic("Cannot hide local type ${firClass.render()}")
}
}
val superType = firClass.superTypeRefs.single()
if (superType is FirResolvedTypeRef && !superType.isAny) {
return superType
}
}
return this
}
private object ImplicitToErrorTypeTransformer : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose()
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.fir.resolve.inference.FirStubInferenceSession
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.*
@@ -626,33 +626,3 @@ class FirClassSubstitutionScope(
return useSiteMemberScope.getClassifierNames()
}
}
// Unlike other cases, return types may be implicit, i.e. unresolved
// But in that cases newType should also be `null`
fun FirTypeRef.withReplacedReturnType(newType: ConeKotlinType?): FirTypeRef {
require(this is FirResolvedTypeRef || newType == null)
if (newType == null) return this
return buildResolvedTypeRef {
source = this@withReplacedReturnType.source
type = newType
annotations += this@withReplacedReturnType.annotations
}
}
fun FirTypeRef.withReplacedConeType(
newType: ConeKotlinType?,
firFakeSourceElementKind: FirFakeSourceElementKind? = null
): FirResolvedTypeRef {
require(this is FirResolvedTypeRef)
if (newType == null) return this
return buildResolvedTypeRef {
source = if (firFakeSourceElementKind != null)
this@withReplacedConeType.source?.fakeElement(firFakeSourceElementKind)
else
this@withReplacedConeType.source
type = newType
annotations += this@withReplacedConeType.annotations
}
}
@@ -5,9 +5,18 @@
package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.classId
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.fakeElement
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
@@ -174,6 +183,36 @@ fun FirTypeRef.isUnsafeVarianceType(session: FirSession): Boolean {
return coneTypeSafe<ConeKotlinType>()?.isUnsafeVarianceType(session) == true
}
// Unlike other cases, return types may be implicit, i.e. unresolved
// But in that cases newType should also be `null`
fun FirTypeRef.withReplacedReturnType(newType: ConeKotlinType?): FirTypeRef {
require(this is FirResolvedTypeRef || newType == null)
if (newType == null) return this
return buildResolvedTypeRef {
source = this@withReplacedReturnType.source
type = newType
annotations += this@withReplacedReturnType.annotations
}
}
fun FirTypeRef.withReplacedConeType(
newType: ConeKotlinType?,
firFakeSourceElementKind: FirFakeSourceElementKind? = null
): FirResolvedTypeRef {
require(this is FirResolvedTypeRef)
if (newType == null) return this
return buildResolvedTypeRef {
source = if (firFakeSourceElementKind != null)
this@withReplacedConeType.source?.fakeElement(firFakeSourceElementKind)
else
this@withReplacedConeType.source
type = newType
annotations += this@withReplacedConeType.annotations
}
}
fun FirTypeRef.approximated(
typeApproximator: AbstractTypeApproximator,
toSuper: Boolean,
@@ -186,3 +225,77 @@ fun FirTypeRef.approximated(
return withReplacedConeType(approximatedType as? ConeKotlinType)
}
fun FirTypeRef.approximatedIfNeededOrSelf(
approximator: AbstractTypeApproximator,
containingCallableVisibility: Visibility?,
isInlineFunction: Boolean = false
): FirTypeRef {
val approximatedType = if (this is FirResolvedTypeRef &&
(containingCallableVisibility == Visibilities.Public || containingCallableVisibility == Visibilities.Protected)
) {
if (type.requiresApproximationInPublicPosition()) this.approximated(approximator, toSuper = true) else this
} else {
this
}
return approximatedType.hideLocalTypeIfNeeded(containingCallableVisibility, isInlineFunction)
}
private fun ConeKotlinType.requiresApproximationInPublicPosition(): Boolean {
return when (this) {
is ConeIntegerLiteralType,
is ConeCapturedType,
is ConeDefinitelyNotNullType,
is ConeIntersectionType -> true
is ConeClassLikeType -> typeArguments.any {
it is ConeKotlinTypeProjection && it.type.requiresApproximationInPublicPosition()
}
else -> false
}
}
/*
* Suppose a function without an explicit return type just returns an anonymous object:
*
* fun foo(...) = object : ObjectSuperType {
* override fun ...
* }
*
* Without unwrapping, the return type ended up with that anonymous object (<no name provided>), while the resolved super type, which
* acts like an implementing interface, is a better fit. In fact, exposing an anonymous object types is prohibited for certain cases,
* e.g., KT-33917. We can also apply this to any local types.
*/
private fun FirTypeRef.hideLocalTypeIfNeeded(
containingCallableVisibility: Visibility?,
isInlineFunction: Boolean = false
): FirTypeRef {
if (containingCallableVisibility == null) {
return this
}
// Approximate types for non-private (all but package private or private) members.
// Also private inline functions, as per KT-33917.
if (containingCallableVisibility == Visibilities.Public ||
containingCallableVisibility == Visibilities.Protected ||
containingCallableVisibility == Visibilities.Internal ||
(containingCallableVisibility == Visibilities.Private && isInlineFunction)
) {
val firClass =
(((this as? FirResolvedTypeRef)
?.type as? ConeClassLikeType)
?.lookupTag as? ConeClassLookupTagWithFixedSymbol)
?.symbol?.fir
if (firClass?.classId?.isLocal != true) {
return this
}
if (firClass.superTypeRefs.size > 1) {
return buildErrorTypeRef {
diagnostic = ConeSimpleDiagnostic("Cannot hide local type ${firClass.render()}")
}
}
val superType = firClass.superTypeRefs.single()
if (superType is FirResolvedTypeRef && !superType.isAny) {
return superType
}
}
return this
}