[FIR] Migrate compiler.fir to use resolvedType where applicable

#KT-61367
This commit is contained in:
Kirill Rakhman
2023-09-11 15:33:26 +02:00
committed by Space Team
parent 1c6776b2b4
commit 66b911c923
22 changed files with 119 additions and 110 deletions
@@ -28,11 +28,8 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol
import org.jetbrains.kotlin.fir.types.ConeErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.constructType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.SmartcastStability
@@ -51,9 +48,7 @@ abstract class ReceiverValue {
class ExpressionReceiverValue(override val receiverExpression: FirExpression) : ReceiverValue() {
override val type: ConeKotlinType
// NB: safe cast is necessary here
get() = receiverExpression.coneTypeSafe()
?: ConeErrorType(ConeIntermediateDiagnostic("No type calculated for: ${receiverExpression.renderWithType()}")) // TODO: assert here
get() = receiverExpression.resolvedType
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? {
var receiverExpr: FirExpression? = receiverExpression
@@ -549,7 +549,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
val customAnnotations = attributes.customAnnotations
return customAnnotations.any {
it.coneTypeSafe<ConeKotlinType>()?.fullyExpandedType(session)?.classId?.asSingleFqName() == fqName
it.resolvedType.fullyExpandedType(session).classId?.asSingleFqName() == fqName
}
}
@@ -558,7 +558,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
// We don't check for compiler attributes because all of them doesn't have parameters
val customAnnotations = attributes.customAnnotations
val annotationCall = customAnnotations.firstOrNull {
it.coneTypeSafe<ConeKotlinType>()?.fullyExpandedType(session)?.classId?.asSingleFqName() == fqName
it.resolvedType.fullyExpandedType(session).classId?.asSingleFqName() == fqName
} ?: return null
val argument = when (val argument = annotationCall.argumentMapping.mapping.values.firstOrNull() ?: return null) {
is FirVarargArgumentsExpression -> argument.arguments.firstOrNull()
@@ -826,7 +826,7 @@ class FirCallResolver(
*/
if (components.context.inferenceSession !is FirBuilderInferenceSession &&
createResolvedReferenceWithoutCandidateForLocalVariables &&
explicitReceiver?.coneTypeSafe<ConeIntegerLiteralType>() == null &&
explicitReceiver?.resolvedType !is ConeIntegerLiteralType &&
coneSymbol is FirVariableSymbol &&
(coneSymbol !is FirPropertySymbol || (coneSymbol.fir as FirMemberDeclaration).typeParameters.isEmpty()) &&
!candidate.doesResolutionResultOverrideOtherToPreserveCompatibility()
@@ -64,7 +64,7 @@ fun FirAnonymousFunction.addReturnToLastStatementIfNeeded(session: FirSession) {
val lastStatement = body.statements.lastOrNull() as? FirExpression ?: return
if (lastStatement is FirReturnExpression) return
val returnType = body.coneTypeOrNull ?: return
val returnType = body.resolvedType
if (returnType.isNothing) return
val returnTarget = FirFunctionTarget(null, isLambda = isLambda).also { it.bind(this) }
@@ -211,7 +211,7 @@ fun BodyResolveComponents.buildResolvedQualifierForClass(
this.annotations.addAll(annotations)
}.build().apply {
if (classId.isLocal) {
resultType = typeForQualifierByDeclaration(regularClass.fir, resultType, session)
resultType = typeForQualifierByDeclaration(regularClass.fir, session)
?.also { replaceCanBeValue(true) }
?: session.builtinTypes.unitType.type
} else {
@@ -222,12 +222,11 @@ fun BodyResolveComponents.buildResolvedQualifierForClass(
fun FirResolvedQualifier.setTypeOfQualifier(session: FirSession) {
val classSymbol = symbol
val resultType = resultType
if (classSymbol != null) {
classSymbol.lazyResolveToPhase(FirResolvePhase.TYPES)
val declaration = classSymbol.fir
if (declaration !is FirTypeAlias || typeArguments.isEmpty()) {
val typeByDeclaration = typeForQualifierByDeclaration(declaration, resultType, session)
val typeByDeclaration = typeForQualifierByDeclaration(declaration, session)
if (typeByDeclaration != null) {
this.resultType = typeByDeclaration
replaceCanBeValue(true)
@@ -243,10 +242,10 @@ internal fun typeForReifiedParameterReference(parameterReferenceBuilder: FirReso
return typeParameterSymbol.constructType(emptyArray(), false)
}
internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultType: ConeKotlinType?, session: FirSession): ConeKotlinType? {
internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, session: FirSession): ConeKotlinType? {
if (declaration is FirTypeAlias) {
val expandedDeclaration = declaration.expandedConeType?.lookupTag?.toSymbol(session)?.fir ?: return null
return typeForQualifierByDeclaration(expandedDeclaration, resultType, session)
return typeForQualifierByDeclaration(expandedDeclaration, session)
}
if (declaration is FirRegularClass) {
if (declaration.classKind == ClassKind.OBJECT) {
@@ -398,7 +397,7 @@ private fun FirSmartCastExpressionBuilder.applyResultTypeRef() {
if (smartcastStability == SmartcastStability.STABLE_VALUE)
smartcastType.coneTypeOrNull
else
originalExpression.coneTypeOrNull
originalExpression.resolvedType
}
private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSmartcastInfo(
@@ -473,8 +472,7 @@ fun FirCheckedSafeCallSubject.propagateTypeFromOriginalReceiver(
?.takeIf { it.isStable }
?.smartcastTypeWithoutNullableNothing
?.coneTypeSafe<ConeKotlinType>()
?: nullableReceiverExpression.coneTypeOrNull
?: return
?: nullableReceiverExpression.resolvedType
val expandedReceiverType = receiverType.fullyExpandedType(session)
val updatedReceiverType = expandedReceiverType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext).independentInstance()
@@ -490,7 +488,7 @@ fun FirSafeCallExpression.propagateTypeFromQualifiedAccessAfterNullCheck(
val resultingType = when {
selector is FirExpression && !selector.isStatementLikeExpression -> {
val type = selector.coneTypeSafe<ConeKotlinType>() ?: return
val type = selector.resolvedType
type.withNullability(ConeNullability.NULLABLE, session.typeContext)
}
// Branch for things that shouldn't be used as expressions.
@@ -222,7 +222,7 @@ fun Candidate.resolvePlainExpressionArgument(
) {
if (expectedType == null) return
val argumentType = argument.coneTypeSafe<ConeKotlinType>() ?: return
val argumentType = argument.resolvedType
resolvePlainArgumentType(
csBuilder,
argument,
@@ -434,7 +434,9 @@ internal fun Candidate.resolveArgument(
sink: CheckerSink,
context: ResolutionContext
) {
argument.resultType.ensureResolvedTypeDeclaration(context.session)
// Lambdas and callable references can be unresolved at this point
@OptIn(UnresolvedExpressionTypeAccess::class)
argument.coneTypeOrNull.ensureResolvedTypeDeclaration(context.session)
val expectedType =
prepareExpectedType(context.session, context.bodyResolveComponents.scopeSession, callInfo, argument, parameter, context)
resolveArgumentExpression(
@@ -533,7 +535,7 @@ fun FirExpression.isFunctional(
is FirAnonymousFunctionExpression, is FirCallableReferenceAccess -> return true
else -> {
// Either a functional type or a subtype of a class that has a contributed `invoke`.
val coneType = coneTypeSafe<ConeKotlinType>() ?: return false
val coneType = resolvedType
if (coneType.isSomeFunctionType(session)) {
return true
}
@@ -12,10 +12,7 @@ import org.jetbrains.kotlin.builtins.functions.isBasicFunctionOrKFunction
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildNamedArgumentExpression
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedCallableReferenceTarget
@@ -409,6 +406,7 @@ class FirFakeArgumentForCallableReference(
override val source: KtSourceElement?
get() = null
@UnresolvedExpressionTypeAccess
override val coneTypeOrNull: ConeKotlinType
get() = shouldNotBeCalled()
@@ -62,7 +62,7 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
when (receiverKind) {
NO_EXPLICIT_RECEIVER -> {
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier && !explicitReceiver.isSuperReferenceExpression()) {
return sink.yieldDiagnostic(InapplicableWrongReceiver(actualType = explicitReceiver.coneTypeSafe()))
return sink.yieldDiagnostic(InapplicableWrongReceiver(actualType = explicitReceiver.resolvedType))
}
}
EXTENSION_RECEIVER, DISPATCH_RECEIVER -> {
@@ -742,7 +742,7 @@ internal object LowerPriorityIfDynamic : ResolutionStage() {
when {
candidate.symbol.origin is FirDeclarationOrigin.DynamicScope ->
candidate.addDiagnostic(LowerPriorityForDynamic)
candidate.callInfo.isImplicitInvoke && candidate.callInfo.explicitReceiver?.coneTypeSafe<ConeDynamicType>() != null ->
candidate.callInfo.isImplicitInvoke && candidate.callInfo.explicitReceiver?.resolvedType is ConeDynamicType ->
candidate.addDiagnostic(LowerPriorityForDynamic)
}
}
@@ -923,7 +923,7 @@ abstract class FirDataFlowAnalyzer(
}
fun exitConstExpression(constExpression: FirConstExpression<*>) {
if (constExpression.coneTypeOrNull != null) return
if (constExpression.isResolved) return
graphBuilder.exitConstExpression(constExpression).mergeIncomingFlow()
}
@@ -1135,7 +1135,6 @@ abstract class FirDataFlowAnalyzer(
}
}
@OptIn(UnexpandedTypeCheck::class)
fun exitElvis(elvisExpression: FirElvisExpression, isLhsNotNull: Boolean, callCompleted: Boolean) {
val node = graphBuilder.exitElvis(isLhsNotNull, callCompleted)
node.mergeIncomingFlow { path, flow ->
@@ -1146,7 +1145,8 @@ abstract class FirDataFlowAnalyzer(
val elvisVariable by lazy { variableStorage.createSynthetic(elvisExpression) }
// If (x ?: null) != null then x != null
if (elvisExpression.rhs.resultType?.isNullableNothing == true) {
@OptIn(UnresolvedExpressionTypeAccess::class) // Lambdas can have unresolved type here, see KT-61837
if (elvisExpression.rhs.coneTypeOrNull?.isNullableNothing == true) {
val lhsVariable = variableStorage.getOrCreateIfReal(flow, elvisExpression.lhs)
if (lhsVariable != null) {
flow.addImplication((elvisVariable notEq null) implies (lhsVariable notEq null))
@@ -1154,7 +1154,8 @@ abstract class FirDataFlowAnalyzer(
}
// If (null ?: x) != null then x != null
if (elvisExpression.lhs.resultType?.isNullableNothing == true) {
@OptIn(UnresolvedExpressionTypeAccess::class) // Lambdas can have unresolved type here, see KT-61837
if (elvisExpression.lhs.coneTypeOrNull?.isNullableNothing == true) {
val rhsVariable = variableStorage.getOrCreateIfReal(flow, elvisExpression.rhs)
if (rhsVariable != null) {
flow.addImplication((elvisVariable notEq null) implies (rhsVariable notEq null))
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression
import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.dfa.*
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.*
@@ -1115,7 +1114,7 @@ class ControlFlowGraphBuilder {
// KT-59726
// @returns `true` if node actually returned Nothing
private fun completeFunctionCall(node: FunctionCallNode): Boolean {
if (node.fir.resultType?.isNothing != true) return false
if (!node.fir.hasNothingType) return false
val stub = StubNode(node.owner, node.level)
val edges = node.followingNodes.map { it to node.edgeTo(it) }
CFGNode.removeAllOutgoingEdges(node)
@@ -1132,7 +1131,7 @@ class ControlFlowGraphBuilder {
// ----------------------------------- Resolvable call -----------------------------------
fun exitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression): QualifiedAccessNode {
val returnsNothing = qualifiedAccessExpression.resultType?.isNothing == true
val returnsNothing = qualifiedAccessExpression.hasNothingType
val node = createQualifiedAccessNode(qualifiedAccessExpression)
if (returnsNothing) {
addNonSuccessfullyTerminatingNode(node)
@@ -1143,7 +1142,7 @@ class ControlFlowGraphBuilder {
}
fun exitSmartCastExpression(smartCastExpression: FirSmartCastExpression): SmartCastExpressionExitNode {
val returnsNothing = smartCastExpression.resultType?.isNothing == true
val returnsNothing = smartCastExpression.hasNothingType
val node = createSmartCastExitNode(smartCastExpression)
if (returnsNothing) {
addNonSuccessfullyTerminatingNode(node)
@@ -1176,7 +1175,7 @@ class ControlFlowGraphBuilder {
}
fun exitFunctionCall(functionCall: FirFunctionCall, callCompleted: Boolean): FunctionCallNode {
val returnsNothing = functionCall.resultType?.isNothing == true
val returnsNothing = functionCall.hasNothingType
val node = createFunctionCallNode(functionCall)
unifyDataFlowFromPostponedLambdas(node, callCompleted)
if (returnsNothing) {
@@ -1241,7 +1240,7 @@ class ControlFlowGraphBuilder {
fun exitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, callCompleted: Boolean): CheckNotNullCallNode {
val node = createCheckNotNullCallNode(checkNotNullCall)
unifyDataFlowFromPostponedLambdas(node, callCompleted)
if (checkNotNullCall.resultType?.isNothing == true) {
if (checkNotNullCall.hasNothingType) {
addNonSuccessfullyTerminatingNode(node)
} else {
addNewSimpleNode(node)
@@ -1348,7 +1347,9 @@ class ControlFlowGraphBuilder {
}
val lhsIsNotNullNode = createElvisLhsIsNotNullNode(elvisExpression).also {
val lhsIsNull = elvisExpression.lhs.coneTypeSafe<ConeKotlinType>()?.isNullableNothing == true
// TODO Refactor annotation arguments phase to not build CFG so that we can use resolvedType instead, see KT-61834
@OptIn(UnresolvedExpressionTypeAccess::class)
val lhsIsNull = elvisExpression.lhs.coneTypeOrNull?.isNullableNothing == true
addEdge(lhsExitNode, it, isDead = lhsIsNull)
addEdge(it, exitNode, propagateDeadness = false)
}
@@ -1465,3 +1466,8 @@ val FirControlFlowGraphOwner.isUsedInControlFlowGraphBuilderForFile: Boolean
is FirProperty -> memberShouldHaveGraph
else -> false
}
// TODO Refactor annotation arguments phase to not build CFG so that we can use resolvedType instead, see KT-61834
@OptIn(UnresolvedExpressionTypeAccess::class)
private val FirExpression.hasNothingType: Boolean
get() = coneTypeOrNull?.isNothing == true
@@ -263,6 +263,8 @@ class FirStubTypeTransformer(private val substitutor: ConeSubstitutor) : FirDefa
// FirAnonymousFunctionExpression doesn't support replacing the type
// since it delegates the getter to the underlying FirAnonymousFunction.
if (element is FirExpression && element !is FirAnonymousFunctionExpression) {
// TODO Check why some expressions have unresolved type in builder inference session KT-61835
@OptIn(UnresolvedExpressionTypeAccess::class)
element.coneTypeOrNull
?.let(substitutor::substituteOrNull)
?.let { element.replaceConeTypeOrNull(it) }
@@ -273,7 +275,7 @@ class FirStubTypeTransformer(private val substitutor: ConeSubstitutor) : FirDefa
}
override fun transformTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Nothing?): FirStatement {
if (typeOperatorCall.argument.coneTypeOrNull is ConeStubType) {
if (typeOperatorCall.argument.resolvedType is ConeStubType) {
typeOperatorCall.replaceArgFromStubType(true)
}
return super.transformTypeOperatorCall(typeOperatorCall, data)
@@ -265,7 +265,7 @@ class FirCallCompletionResultsWriterTransformer(
val result = prepareQualifiedTransform(qualifiedAccessExpression, calleeReference)
val subCandidate = calleeReference.candidate
val resultType = result.coneTypeOrNull?.substituteType(subCandidate)
val resultType = result.resolvedType.substituteType(subCandidate)
resultType.ensureResolvedTypeDeclaration(session)
result.replaceConeTypeOrNull(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, qualifiedAccessExpression.source, context.file.source)
@@ -726,18 +726,16 @@ class FirCallCompletionResultsWriterTransformer(
}
override fun transformBlock(block: FirBlock, data: ExpectedArgumentType?): FirStatement {
val initialType = block.coneTypeSafe<ConeKotlinType>()
if (initialType != null) {
var resultType = finallySubstituteOrNull(initialType) ?: block.resultType
(resultType as? ConeIntegerLiteralType)?.let {
resultType =
it.getApproximatedType(data?.getExpectedType(block)?.fullyExpandedType(session))
}
block.replaceConeTypeOrNull(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, block.source, context.file.source)
val initialType = block.resolvedType
var resultType = finallySubstituteOrNull(initialType) ?: block.resolvedType
(resultType as? ConeIntegerLiteralType)?.let {
resultType =
it.getApproximatedType(data?.getExpectedType(block)?.fullyExpandedType(session))
}
block.replaceConeTypeOrNull(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, block.source, context.file.source)
transformElement(block, data)
if (block.resultType is ConeErrorType) {
if (block.resolvedType is ConeErrorType) {
block.writeResultType(session)
}
return block
@@ -838,7 +836,7 @@ class FirCallCompletionResultsWriterTransformer(
}
override fun transformArrayLiteral(arrayLiteral: FirArrayLiteral, data: ExpectedArgumentType?): FirStatement {
if (arrayLiteral.coneTypeOrNull != null) return arrayLiteral
if (arrayLiteral.isResolved) return arrayLiteral
val expectedArrayType = data?.getExpectedType(arrayLiteral)
val expectedArrayElementType = expectedArrayType?.arrayElementType()
arrayLiteral.transformChildren(this, expectedArrayElementType?.toExpectedType())
@@ -242,7 +242,7 @@ class FirSyntheticCallGenerator(
// If the callable reference cannot be resolved with the expected type, let's try to resolve it with any type and report
// something like INITIALIZER_TYPE_MISMATCH or NONE_APPLICABLE instead of UNRESOLVED_REFERENCE.
check(callableReferenceAccess.calleeReference is FirSimpleNamedReference && callableReferenceAccess.coneTypeOrNull == null) {
check(callableReferenceAccess.calleeReference is FirSimpleNamedReference && !callableReferenceAccess.isResolved) {
"Expected FirCallableReferenceAccess to be unresolved."
}
@@ -223,7 +223,7 @@ private object WhenOnNullableExhaustivenessChecker : WhenExhaustivenessChecker()
private object ConditionChecker : AbstractConditionChecker<Flags>() {
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Flags) {
val argument = equalityOperatorCall.arguments[1]
if (argument.coneTypeOrNull?.isNullableNothing == true) {
if (argument.resolvedType.isNullableNothing) {
data.containsNull = true
}
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.UnresolvedExpressionTypeAccess
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
@@ -59,8 +60,9 @@ class IntegerLiteralAndOperatorApproximationTransformer(
override fun <T> transformConstExpression(
constExpression: FirConstExpression<T>,
data: ConeKotlinType?
data: ConeKotlinType?,
): FirStatement {
@OptIn(UnresolvedExpressionTypeAccess::class)
val type = constExpression.coneTypeSafe<ConeIntegerLiteralType>() ?: return constExpression
val approximatedType = type.getApproximatedType(data?.fullyExpandedType(session))
constExpression.resultType = approximatedType
@@ -72,10 +74,12 @@ class IntegerLiteralAndOperatorApproximationTransformer(
override fun transformIntegerLiteralOperatorCall(
integerLiteralOperatorCall: FirIntegerLiteralOperatorCall,
data: ConeKotlinType?
data: ConeKotlinType?,
): FirStatement {
@Suppress("UnnecessaryVariable")
val call = integerLiteralOperatorCall
@OptIn(UnresolvedExpressionTypeAccess::class)
val operatorType = call.coneTypeSafe<ConeIntegerLiteralType>() ?: return call
val approximatedType = operatorType.getApproximatedType(data?.fullyExpandedType(session))
call.transformDispatchReceiver(this, null)
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.UnresolvedExpressionTypeAccess
import org.jetbrains.kotlin.fir.expressions.builder.buildVarargArgumentsExpression
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.types.*
@@ -22,8 +23,9 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.ConstantValueKind
internal inline var FirExpression.resultType: ConeKotlinType?
get() = coneTypeOrNull
internal inline var FirExpression.resultType: ConeKotlinType
get() = resolvedType
set(type) {
replaceConeTypeOrNull(type)
}
@@ -87,11 +89,10 @@ fun FirBlock.writeResultType(session: FirSession) {
is FirExpression -> statement
else -> null
}
resultType = if (resultExpression == null) {
session.builtinTypes.unitType.type
} else {
resultExpression.resultType ?: ConeErrorType(ConeSimpleDiagnostic("No type for block", DiagnosticKind.InferenceError))
}
// If a lambda contains another lambda as result expression, it won't be resolved at this point
@OptIn(UnresolvedExpressionTypeAccess::class)
resultType = resultExpression?.coneTypeOrNull ?: session.builtinTypes.unitType.type
}
fun ConstantValueKind<*>.expectedConeType(session: FirSession): ConeKotlinType {
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.isArrayType
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
/**
@@ -45,7 +46,7 @@ class FirArrayOfCallTransformer : FirDefaultTransformer<FirSession>() {
}
}
}
coneTypeOrNull = functionCall.coneTypeOrNull
coneTypeOrNull = functionCall.resolvedType
}
val calleeReference = functionCall.calleeReference
@@ -56,7 +56,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
// ------------------------------- When expressions -------------------------------
override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ResolutionMode): FirStatement {
if (whenExpression.calleeReference is FirResolvedNamedReference && whenExpression.resultType != null) {
if (whenExpression.calleeReference is FirResolvedNamedReference && whenExpression.isResolved) {
return whenExpression
}
whenExpression.annotations.forEach { it.accept(this, data) }
@@ -71,7 +71,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
whenExpression.branches.isEmpty() -> {}
whenExpression.isOneBranch() && data.forceFullCompletion && data !is ResolutionMode.WithExpectedType -> {
whenExpression = whenExpression.transformBranches(transformer, ResolutionMode.ContextIndependent)
whenExpression.resultType = whenExpression.branches.first().result.resultType
whenExpression.resultType = whenExpression.branches.first().result.resolvedType
// when with one branch cannot be completed if it's not already complete in the first place
}
else -> {
@@ -143,7 +143,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
data: ResolutionMode
): FirStatement {
val parentWhen = whenSubjectExpression.whenRef.value
val subjectType = parentWhen.subject?.resultType ?: parentWhen.subjectVariable?.returnTypeRef?.coneTypeOrNull
val subjectType = parentWhen.subject?.resolvedType ?: parentWhen.subjectVariable?.returnTypeRef?.coneTypeOrNull
if (subjectType != null) {
whenSubjectExpression.resultType = subjectType
}
@@ -154,7 +154,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
// ------------------------------- Try/catch expressions -------------------------------
override fun transformTryExpression(tryExpression: FirTryExpression, data: ResolutionMode): FirStatement {
if (tryExpression.calleeReference is FirResolvedNamedReference && tryExpression.resultType != null) {
if (tryExpression.calleeReference is FirResolvedNamedReference && tryExpression.isResolved) {
return tryExpression
}
@@ -262,22 +262,21 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
)
var isLhsNotNull = false
if (result.rhs.coneTypeSafe<ConeKotlinType>()?.isNothing == true) {
val lhsType = result.lhs.coneTypeSafe<ConeKotlinType>()
if (lhsType != null) {
// Converting to non-raw type is necessary to preserver the K1 semantics (see KT-54526)
val newReturnType =
lhsType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
.convertToNonRawVersion()
result.replaceConeTypeOrNull(newReturnType)
isLhsNotNull = true
}
// TODO Check if the type of the RHS being null can lead to a bug, see KT-61837
@OptIn(UnresolvedExpressionTypeAccess::class)
if (result.rhs.coneTypeOrNull?.isNothing == true) {
val lhsType = result.lhs.resolvedType
// Converting to non-raw type is necessary to preserver the K1 semantics (see KT-54526)
val newReturnType =
lhsType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
.convertToNonRawVersion()
result.replaceConeTypeOrNull(newReturnType)
isLhsNotNull = true
}
session.typeContext.run {
if (result.coneTypeSafe<ConeKotlinType>()?.isNullableType() == true
&& result.rhs.coneTypeSafe<ConeKotlinType>()?.isNullableType() == false
) {
if (result.resolvedType.isNullableType() && !result.rhs.resolvedType.isNullableType()) {
// Sometimes return type for special call for elvis operator might be nullable,
// but result is not nullable if the right type is not nullable
result.replaceConeTypeOrNull(
@@ -233,8 +233,8 @@ open class FirDeclarationsResolveTransformer(
// get() = delegate.getValue(thisRef, kProperty: KProperty0/1/2<..., SomeType>)
// set() = delegate.getValue(thisRef, kProperty: KProperty0/1/2<..., SomeType>, value)
val propertyReferenceAccess = resolvedArgumentMapping?.keys?.toList()?.getOrNull(1) as? FirCallableReferenceAccess ?: return
val type = propertyReferenceAccess.coneTypeOrNull
if (type != null && property.returnTypeRef is FirResolvedTypeRef) {
val type = propertyReferenceAccess.resolvedType
if (property.returnTypeRef is FirResolvedTypeRef) {
val typeArguments = (type.type as ConeClassLikeType).typeArguments
val extensionType = property.receiverParameter?.typeRef?.coneType
val dispatchType = context.containingClass?.let { containingClass ->
@@ -763,7 +763,7 @@ open class FirDeclarationsResolveTransformer(
if (result.returnTypeRef is FirImplicitTypeRef) {
val simpleFunction = function as? FirSimpleFunction
val returnExpression = (body?.statements?.singleOrNull() as? FirReturnExpression)?.result
val expressionType = returnExpression?.coneTypeOrNull
val expressionType = returnExpression?.resolvedType
val returnTypeRef = expressionType
?.toFirResolvedTypeRef(result.returnTypeRef.source)
?.approximateDeclarationType(
@@ -1104,7 +1104,7 @@ open class FirDeclarationsResolveTransformer(
val inferredType = if (backingField is FirDefaultPropertyBackingField) {
propertyType
} else {
backingField.initializer?.unwrapSmartcastExpression()?.coneTypeOrNull?.toFirResolvedTypeRef()
backingField.initializer?.unwrapSmartcastExpression()?.resolvedType?.toFirResolvedTypeRef()
}
val resultType = inferredType
?: return backingField.transformReturnTypeRef(
@@ -1133,7 +1133,7 @@ open class FirDeclarationsResolveTransformer(
val resultType = when {
initializer != null -> {
val unwrappedInitializer = initializer.unwrapSmartcastExpression()
unwrappedInitializer.resultType?.toFirResolvedTypeRef()
unwrappedInitializer.resolvedType.toFirResolvedTypeRef()
}
variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> variable.getter?.returnTypeRef
else -> null
@@ -1216,10 +1216,10 @@ open class FirDeclarationsResolveTransformer(
private val FirVariable.initializerResolved: Boolean
get() {
val initializer = initializer ?: return false
return initializer.coneTypeOrNull != null && initializer !is FirErrorExpression
return initializer.isResolved && initializer !is FirErrorExpression
}
protected val FirFunction.bodyResolved: Boolean
get() = body !is FirLazyBlock && body?.coneTypeOrNull != null
get() = body !is FirLazyBlock && body?.isResolved == true
}
@@ -68,7 +68,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
override fun transformExpression(expression: FirExpression, data: ResolutionMode): FirStatement {
if (expression.resultType == null && expression !is FirWrappedExpression) {
if (!expression.isResolved && expression !is FirWrappedExpression) {
expression.resultType = ConeErrorType(
ConeSimpleDiagnostic(
"Type calculating for ${expression::class} is not supported",
@@ -95,7 +95,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
data: ResolutionMode,
isUsedAsReceiver: Boolean,
): FirStatement {
if (qualifiedAccessExpression.coneTypeOrNull != null && qualifiedAccessExpression.calleeReference !is FirSimpleNamedReference) {
if (qualifiedAccessExpression.isResolved && qualifiedAccessExpression.calleeReference !is FirSimpleNamedReference) {
return qualifiedAccessExpression
}
@@ -134,12 +134,12 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
is FirDelegateFieldReference -> {
val delegateFieldSymbol = callee.resolvedSymbol
qualifiedAccessExpression.resultType = delegateFieldSymbol.fir.delegate!!.coneTypeOrNull
qualifiedAccessExpression.resultType = delegateFieldSymbol.fir.delegate!!.resolvedType
qualifiedAccessExpression
}
is FirResolvedNamedReference,
is FirErrorNamedReference -> {
if (qualifiedAccessExpression.coneTypeOrNull == null) {
if (!qualifiedAccessExpression.isResolved) {
storeTypeFromCallee(qualifiedAccessExpression, isLhsOfAssignment = false)
}
qualifiedAccessExpression
@@ -395,7 +395,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val calleeReference = functionCall.calleeReference
if (
(calleeReference is FirResolvedNamedReference || calleeReference is FirErrorNamedReference) &&
functionCall.resultType == null
!functionCall.isResolved
) {
storeTypeFromCallee(functionCall, isLhsOfAssignment = false)
}
@@ -724,7 +724,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
source = desugaredSource,
name = name,
initializer = initializer,
typeRef = initializer.coneTypeOrNull?.toFirResolvedTypeRef(desugaredSource),
typeRef = initializer.resolvedType.toFirResolvedTypeRef(desugaredSource),
)
fun buildAndResolveOperatorCall(receiver: FirExpression): FirFunctionCall = buildFunctionCall {
@@ -781,7 +781,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
statements += unaryVariable.toQualifiedAccess()
}
}.apply {
replaceConeTypeOrNull((statements.last() as FirExpression).coneTypeOrNull)
replaceConeTypeOrNull((statements.last() as FirExpression).resolvedType)
}
return if (originalExpression is FirSafeCallExpression) {
@@ -840,7 +840,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val firClass = type.lookupTag.toSymbol(session)?.fir ?: return this
if (firClass.typeParameters.isEmpty()) return this
val originalType = argument.unwrapSmartcastExpression().coneTypeSafe<ConeKotlinType>() ?: return this
val originalType = argument.unwrapSmartcastExpression().resolvedType
val newType = components.computeRepresentativeTypeForBareType(type, originalType)
?: if (firClass.isLocal && (operation == FirOperation.AS || operation == FirOperation.SAFE_AS)) {
(firClass as FirClass).defaultType()
@@ -937,7 +937,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
// fun <K> checkNotNull(arg: K?): K
// ...in order to get the not-nullable type of the argument.
if (checkNotNullCall.calleeReference is FirResolvedNamedReference && checkNotNullCall.resultType != null) {
if (checkNotNullCall.calleeReference is FirResolvedNamedReference && checkNotNullCall.isResolved) {
return checkNotNullCall
}
@@ -981,7 +981,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
) ?: typeFromCallee.type
} else {
desugaredAssignmentValueReferenceExpression.resultType = referencedExpression.resultType
desugaredAssignmentValueReferenceExpression.resultType = referencedExpression.resolvedType
}
return desugaredAssignmentValueReferenceExpression
}
@@ -1022,7 +1022,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val result = variableAssignment.transformRValue(
transformer,
withExpectedType(
variableAssignment.lValue.coneTypeOrNull?.toFirResolvedTypeRef() ?: FirImplicitTypeRefImplWithoutSource,
variableAssignment.lValue.resolvedType.toFirResolvedTypeRef(),
expectedTypeMismatchIsReportedInChecker = true
),
)
@@ -1130,11 +1130,11 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
else -> {
if (!shouldComputeTypeOfGetClassCallWithNotQualifierInLhs(getClassCall)) return transformedGetClassCall
val resultType = lhs.resultType
val resultType = lhs.resolvedType
if (resultType is ConeErrorType) {
resultType
} else {
ConeKotlinTypeProjectionOut(resultType!!)
ConeKotlinTypeProjectionOut(resultType)
}
}
}
@@ -1291,6 +1291,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
.resolveDelegatingConstructorCall(delegatedConstructorCall, constructorType, containingClass.symbol.toLookupTag())
if (reference is FirThisReference && reference.boundSymbol == null) {
@OptIn(UnresolvedExpressionTypeAccess::class)
resolvedCall.dispatchReceiver?.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.toSymbol(session)?.let {
reference.replaceBoundSymbol(it)
}
@@ -1518,7 +1519,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
source = lhsGetCall.explicitReceiver?.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment),
name = SpecialNames.ARRAY,
initializer = initializer,
typeRef = initializer.coneTypeOrNull?.toFirResolvedTypeRef(initializer.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)),
typeRef = initializer.resolvedType.toFirResolvedTypeRef(initializer.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)),
)
val indexVariables = lhsGetCall.arguments.flatMap {
@@ -1532,7 +1533,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
source = index.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment),
name = SpecialNames.subscribeOperatorIndex(i),
initializer = index,
typeRef = index.coneTypeOrNull?.toFirResolvedTypeRef(),
typeRef = index.resolvedType.toFirResolvedTypeRef(),
)
}
@@ -1562,7 +1563,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
arguments += indicesQualifiedAccess.subList(i, i + varargSize)
i += varargSize
source = argument.source
coneTypeOrNull = argument.coneTypeOrNull
coneTypeOrNull = argument.resolvedType
varargElementType = argument.varargElementType
}
} else {
@@ -1571,7 +1572,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
}
origin = FirFunctionCallOrigin.Operator
coneTypeOrNull = lhsGetCall.coneTypeOrNull
coneTypeOrNull = lhsGetCall.resolvedType
}
val generator = GeneratorOfPlusAssignCalls(
@@ -1649,7 +1650,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
data: ResolutionMode,
): FirStatement {
anonymousObjectExpression.transformAnonymousObject(transformer, data)
if (anonymousObjectExpression.coneTypeOrNull == null) {
if (!anonymousObjectExpression.isResolved) {
anonymousObjectExpression.resultType = anonymousObjectExpression.anonymousObject.defaultType()
}
dataFlowAnalyzer.exitAnonymousObjectExpression(anonymousObjectExpression)
@@ -179,6 +179,8 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
property.visibility == Visibilities.Private -> PropertyStability.STABLE_VALUE
property.modality != Modality.FINAL -> {
val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccessExpression)?.dispatchReceiver ?: return null
@OptIn(UnresolvedExpressionTypeAccess::class)
val receiverType = dispatchReceiver.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return null
val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return null
when (val receiverFir = receiverSymbol.fir) {
@@ -860,6 +860,7 @@ class WhenSubjectExpressionExitNode(owner: ControlFlowGraph, override val fir: F
object FirStub : FirExpression() {
override val source: KtSourceElement? get() = null
@UnresolvedExpressionTypeAccess
override val coneTypeOrNull: ConeKotlinType = StandardClassIds.Nothing.constructClassLikeType()
override val annotations: List<FirAnnotation> get() = listOf()
@@ -12,16 +12,16 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.UnresolvedExpressionTypeAccess
import org.jetbrains.kotlin.fir.expressions.unexpandedClassId
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.toEffectiveVisibility
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.types.toLookupTag
import org.jetbrains.kotlin.fir.types.typeContext
import org.jetbrains.kotlin.name.StandardClassIds
@@ -57,7 +57,7 @@ fun computePublishedApiEffectiveVisibility(
session: FirSession,
): EffectiveVisibility? {
val hasPublishedApiAnnotation = annotations.any {
it.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId == StandardClassIds.Annotations.PublishedApi
(it.resolvedType as? ConeClassLikeType)?.lookupTag?.classId == StandardClassIds.Annotations.PublishedApi
}
return computePublishedApiEffectiveVisibility(