FIR: Allow selector of safe calls to be a FirStatement
It's necessary to allow a?.b += v be interpreted as a?.(b += v) But currently FirAssignmentOperatorStatement is not FirQualifiedAccess ^KT-41034 In Progress
This commit is contained in:
@@ -30,11 +30,9 @@ import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirPropertyWithExplicitBackingFieldResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.PropertyStability
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectData
|
||||
@@ -50,7 +48,6 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
|
||||
@@ -395,7 +392,7 @@ fun FirSafeCallExpression.propagateTypeFromQualifiedAccessAfterNullCheck(
|
||||
session: FirSession,
|
||||
) {
|
||||
val receiverType = nullableReceiverExpression.typeRef.coneTypeSafe<ConeKotlinType>()
|
||||
val typeAfterNullCheck = regularQualifiedAccess.expressionTypeOrUnitForAssignment() ?: return
|
||||
val typeAfterNullCheck = (selector as? FirQualifiedAccess)?.expressionTypeOrUnitForAssignment() ?: return
|
||||
val isReceiverActuallyNullable = if (session.languageVersionSettings.supportsFeature(LanguageFeature.SafeCallsAreAlwaysNullable)) {
|
||||
true
|
||||
} else {
|
||||
|
||||
@@ -15,7 +15,8 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.*
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.preprocessCallableReference
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.preprocessLambdaArgument
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclaration
|
||||
import org.jetbrains.kotlin.fir.returnExpressions
|
||||
@@ -63,8 +64,8 @@ fun Candidate.resolveArgumentExpression(
|
||||
// and then add constraint: typeOf(`$not-null-receiver$.bar()`).makeNullable() <: EXPECTED_TYPE
|
||||
// NB: argument.regularQualifiedAccess is either a call or a qualified access
|
||||
is FirSafeCallExpression -> {
|
||||
val nestedQualifier = argument.regularQualifiedAccess
|
||||
if (nestedQualifier is FirExpression) {
|
||||
val nestedQualifier = argument.selector
|
||||
if (nestedQualifier is FirQualifiedAccessExpression) {
|
||||
resolveSubCallArgument(
|
||||
csBuilder,
|
||||
nestedQualifier,
|
||||
|
||||
@@ -151,7 +151,7 @@ fun PostponedArgumentsAnalyzerContext.addSubsystemFromExpression(statement: FirS
|
||||
is FirElvisExpression
|
||||
-> (statement as FirResolvable).candidate()?.let { addOtherSystem(it.system.asReadOnlyStorage()) }
|
||||
|
||||
is FirSafeCallExpression -> addSubsystemFromExpression(statement.regularQualifiedAccess)
|
||||
is FirSafeCallExpression -> addSubsystemFromExpression(statement.selector)
|
||||
is FirWrappedArgumentExpression -> addSubsystemFromExpression(statement.expression)
|
||||
is FirBlock -> statement.returnExpressions().forEach { addSubsystemFromExpression(it) }
|
||||
}
|
||||
|
||||
+1
-1
@@ -464,7 +464,7 @@ fun FirStatement.processAllContainingCallCandidates(processBlocks: Boolean, proc
|
||||
}
|
||||
|
||||
is FirSafeCallExpression -> {
|
||||
this.regularQualifiedAccess.processAllContainingCallCandidates(processBlocks, processor)
|
||||
this.selector.processAllContainingCallCandidates(processBlocks, processor)
|
||||
}
|
||||
|
||||
is FirWhenExpression -> {
|
||||
|
||||
+1
-1
@@ -354,7 +354,7 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
safeCallExpression: FirSafeCallExpression,
|
||||
data: ExpectedArgumentType?
|
||||
): FirStatement {
|
||||
safeCallExpression.transformRegularQualifiedAccess(
|
||||
safeCallExpression.transformSelector(
|
||||
this,
|
||||
data?.getExpectedType(
|
||||
safeCallExpression
|
||||
|
||||
+3
-3
@@ -119,7 +119,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
transformSuperReceiver(
|
||||
callee,
|
||||
qualifiedAccessExpression,
|
||||
containingSafeCallExpression?.takeIf { qualifiedAccessExpression == it.receiver }?.regularQualifiedAccess
|
||||
containingSafeCallExpression?.takeIf { qualifiedAccessExpression == it.receiver }?.selector as? FirQualifiedAccess
|
||||
)
|
||||
}
|
||||
is FirDelegateFieldReference -> {
|
||||
@@ -312,7 +312,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
|
||||
safeCallExpression.apply {
|
||||
checkedSubjectRef.value.propagateTypeFromOriginalReceiver(receiver, components.session)
|
||||
transformRegularQualifiedAccess(this@FirExpressionsResolveTransformer, data)
|
||||
transformSelector(this@FirExpressionsResolveTransformer, data)
|
||||
propagateTypeFromQualifiedAccessAfterNullCheck(receiver, session)
|
||||
}
|
||||
|
||||
@@ -685,7 +685,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
// AS operator doesn't add expected type to any other expressions
|
||||
// See https://kotlinlang.org/docs/whatsnew12.html#support-for-foo-as-a-shorthand-for-this-foo
|
||||
// And limitations at org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleterKt.isFunctionForExpectTypeFromCastFeature(org.jetbrains.kotlin.fir.declarations.FirFunction<?>)
|
||||
if (argument is FirFunctionCall || (argument is FirSafeCallExpression && argument.regularQualifiedAccess is FirFunctionCall)) {
|
||||
if (argument is FirFunctionCall || (argument is FirSafeCallExpression && argument.selector is FirFunctionCall)) {
|
||||
val expectedType = conversionTypeRef.coneTypeSafe<ConeKotlinType>()?.takeIf {
|
||||
// is not bare type
|
||||
it !is ConeClassLikeType ||
|
||||
|
||||
Reference in New Issue
Block a user