FIR: Add preliminary support for context receivers in resolution
This commit is contained in:
+2
-2
@@ -335,14 +335,14 @@ internal class KtFirCallResolver(
|
|||||||
// Implicit invoke (e.g., `x()`) will have a different callee symbol (e.g., `x`) than the candidate (e.g., `invoke`).
|
// Implicit invoke (e.g., `x()`) will have a different callee symbol (e.g., `x`) than the candidate (e.g., `invoke`).
|
||||||
createKtPartiallyAppliedSymbolForImplicitInvoke(
|
createKtPartiallyAppliedSymbolForImplicitInvoke(
|
||||||
candidate.dispatchReceiverValue?.receiverExpression ?: FirNoReceiverExpression,
|
candidate.dispatchReceiverValue?.receiverExpression ?: FirNoReceiverExpression,
|
||||||
candidate.extensionReceiverValue?.receiverExpression ?: FirNoReceiverExpression,
|
candidate.chosenExtensionReceiverValue?.receiverExpression ?: FirNoReceiverExpression,
|
||||||
candidate.explicitReceiverKind
|
candidate.explicitReceiverKind
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
KtPartiallyAppliedSymbol(
|
KtPartiallyAppliedSymbol(
|
||||||
unsubstitutedKtSignature.substitute(substitutor),
|
unsubstitutedKtSignature.substitute(substitutor),
|
||||||
candidate.dispatchReceiverValue?.receiverExpression?.toKtReceiverValue(),
|
candidate.dispatchReceiverValue?.receiverExpression?.toKtReceiverValue(),
|
||||||
candidate.extensionReceiverValue?.receiverExpression?.toKtReceiverValue(),
|
candidate.chosenExtensionReceiverValue?.receiverExpression?.toKtReceiverValue(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (fir is FirQualifiedAccess) {
|
} else if (fir is FirQualifiedAccess) {
|
||||||
|
|||||||
+26
@@ -1608,6 +1608,32 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.NO_CONTEXT_RECEIVER) { firDiagnostic ->
|
||||||
|
NoContextReceiverImpl(
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER) { firDiagnostic ->
|
||||||
|
MultipleArgumentsApplicableForContextReceiverImpl(
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER) { firDiagnostic ->
|
||||||
|
AmbiguousCallWithImplicitContextReceiverImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL) { firDiagnostic ->
|
||||||
|
UnsupportedContextualDeclarationCallImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.RECURSION_IN_IMPLICIT_TYPES) { firDiagnostic ->
|
add(FirErrors.RECURSION_IN_IMPLICIT_TYPES) { firDiagnostic ->
|
||||||
RecursionInImplicitTypesImpl(
|
RecursionInImplicitTypesImpl(
|
||||||
firDiagnostic as KtPsiDiagnostic,
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
|||||||
+18
@@ -1145,6 +1145,24 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val candidates: List<KtSymbol>
|
abstract val candidates: List<KtSymbol>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NoContextReceiver : KtFirDiagnostic<KtElement>() {
|
||||||
|
override val diagnosticClass get() = NoContextReceiver::class
|
||||||
|
abstract val contextReceiverRepresentation: KtType
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class MultipleArgumentsApplicableForContextReceiver : KtFirDiagnostic<KtElement>() {
|
||||||
|
override val diagnosticClass get() = MultipleArgumentsApplicableForContextReceiver::class
|
||||||
|
abstract val contextReceiverRepresentation: KtType
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AmbiguousCallWithImplicitContextReceiver : KtFirDiagnostic<KtElement>() {
|
||||||
|
override val diagnosticClass get() = AmbiguousCallWithImplicitContextReceiver::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class UnsupportedContextualDeclarationCall : KtFirDiagnostic<KtElement>() {
|
||||||
|
override val diagnosticClass get() = UnsupportedContextualDeclarationCall::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class RecursionInImplicitTypes : KtFirDiagnostic<PsiElement>() {
|
abstract class RecursionInImplicitTypes : KtFirDiagnostic<PsiElement>() {
|
||||||
override val diagnosticClass get() = RecursionInImplicitTypes::class
|
override val diagnosticClass get() = RecursionInImplicitTypes::class
|
||||||
}
|
}
|
||||||
|
|||||||
+22
@@ -1373,6 +1373,28 @@ internal class NextAmbiguityImpl(
|
|||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtFirDiagnostic.NextAmbiguity(), KtAbstractFirDiagnostic<PsiElement>
|
) : KtFirDiagnostic.NextAmbiguity(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
|
internal class NoContextReceiverImpl(
|
||||||
|
override val contextReceiverRepresentation: KtType,
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NoContextReceiver(), KtAbstractFirDiagnostic<KtElement>
|
||||||
|
|
||||||
|
internal class MultipleArgumentsApplicableForContextReceiverImpl(
|
||||||
|
override val contextReceiverRepresentation: KtType,
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.MultipleArgumentsApplicableForContextReceiver(), KtAbstractFirDiagnostic<KtElement>
|
||||||
|
|
||||||
|
internal class AmbiguousCallWithImplicitContextReceiverImpl(
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.AmbiguousCallWithImplicitContextReceiver(), KtAbstractFirDiagnostic<KtElement>
|
||||||
|
|
||||||
|
internal class UnsupportedContextualDeclarationCallImpl(
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.UnsupportedContextualDeclarationCall(), KtAbstractFirDiagnostic<KtElement>
|
||||||
|
|
||||||
internal class RecursionInImplicitTypesImpl(
|
internal class RecursionInImplicitTypesImpl(
|
||||||
override val firDiagnostic: KtPsiDiagnostic,
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
+6
-5
@@ -53,11 +53,12 @@ class SingleCandidateResolver(
|
|||||||
resolutionParameters.callableSymbol,
|
resolutionParameters.callableSymbol,
|
||||||
explicitReceiverKind = explicitReceiverKind,
|
explicitReceiverKind = explicitReceiverKind,
|
||||||
dispatchReceiverValue = dispatchReceiverValue,
|
dispatchReceiverValue = dispatchReceiverValue,
|
||||||
extensionReceiverValue =
|
givenExtensionReceiverOptions = listOfNotNull(
|
||||||
if (explicitReceiverKind.isExtensionReceiver)
|
if (explicitReceiverKind.isExtensionReceiver)
|
||||||
callInfo.explicitReceiver?.let { ExpressionReceiverValue(it) }
|
callInfo.explicitReceiver?.let { ExpressionReceiverValue(it) }
|
||||||
else
|
else
|
||||||
implicitExtensionReceiverValue,
|
implicitExtensionReceiverValue
|
||||||
|
),
|
||||||
scope = null,
|
scope = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+11
@@ -531,6 +531,17 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val CONTEXT_RECEIVERS_RESOLUTION by object : DiagnosticGroup("Context receivers resolution") {
|
||||||
|
val NO_CONTEXT_RECEIVER by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||||
|
parameter<ConeKotlinType>("contextReceiverRepresentation")
|
||||||
|
}
|
||||||
|
val MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||||
|
parameter<ConeKotlinType>("contextReceiverRepresentation")
|
||||||
|
}
|
||||||
|
val AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED)
|
||||||
|
val UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL by error<KtElement>()
|
||||||
|
}
|
||||||
|
|
||||||
val TYPES_AND_TYPE_PARAMETERS by object : DiagnosticGroup("Types & type parameters") {
|
val TYPES_AND_TYPE_PARAMETERS by object : DiagnosticGroup("Types & type parameters") {
|
||||||
val RECURSION_IN_IMPLICIT_TYPES by error<PsiElement>()
|
val RECURSION_IN_IMPLICIT_TYPES by error<PsiElement>()
|
||||||
val INFERENCE_ERROR by error<PsiElement>()
|
val INFERENCE_ERROR by error<PsiElement>()
|
||||||
|
|||||||
@@ -355,6 +355,12 @@ object FirErrors {
|
|||||||
val HAS_NEXT_FUNCTION_AMBIGUITY by error1<PsiElement, Collection<FirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val HAS_NEXT_FUNCTION_AMBIGUITY by error1<PsiElement, Collection<FirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
val NEXT_AMBIGUITY by error1<PsiElement, Collection<FirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val NEXT_AMBIGUITY by error1<PsiElement, Collection<FirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
|
||||||
|
// Context receivers resolution
|
||||||
|
val NO_CONTEXT_RECEIVER by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
val MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
val AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER by error0<KtElement>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
val UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL by error0<KtElement>()
|
||||||
|
|
||||||
// Types & type parameters
|
// Types & type parameters
|
||||||
val RECURSION_IN_IMPLICIT_TYPES by error0<PsiElement>()
|
val RECURSION_IN_IMPLICIT_TYPES by error0<PsiElement>()
|
||||||
val INFERENCE_ERROR by error0<PsiElement>()
|
val INFERENCE_ERROR by error0<PsiElement>()
|
||||||
|
|||||||
+19
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_WITHOUT_EXPECT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_WITHOUT_EXPECT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ACTUALS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ACTUALS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ANONYMOUS_TYPE_INFERRED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ANONYMOUS_TYPE_INFERRED
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_EXPECTS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_EXPECTS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_SUPER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_SUPER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR
|
||||||
@@ -294,6 +295,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISPLACED_TYPE_PA
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_STDLIB_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_STDLIB_CLASS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||||
@@ -336,6 +338,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_YET_SUPPORTED
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_FOR_EXPECT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_FOR_EXPECT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_COMPANION_OBJECT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_COMPANION_OBJECT
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_CONTEXT_RECEIVER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING
|
||||||
@@ -517,6 +520,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_IMPLICIT_I
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_INFIX_CALL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_INFIX_CALL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_OPERATOR_CALL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_OPERATOR_CALL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATURE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATURE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
|
||||||
@@ -974,6 +978,21 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
map.put(NEXT_AMBIGUITY, "Method ''next()'' is ambiguous for this expression: {0}", SYMBOLS)
|
map.put(NEXT_AMBIGUITY, "Method ''next()'' is ambiguous for this expression: {0}", SYMBOLS)
|
||||||
map.put(NEXT_NONE_APPLICABLE, "None of the ''next()'' functions is applicable for ''iterator()'' of type ''{0}''", SYMBOLS)
|
map.put(NEXT_NONE_APPLICABLE, "None of the ''next()'' functions is applicable for ''iterator()'' of type ''{0}''", SYMBOLS)
|
||||||
|
|
||||||
|
map.put(NO_CONTEXT_RECEIVER, "No required context receiver found: {0}", RENDER_TYPE)
|
||||||
|
map.put(
|
||||||
|
MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER,
|
||||||
|
"Multiple arguments applicable for context receiver: {0}",
|
||||||
|
RENDER_TYPE
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER,
|
||||||
|
"With implicit context receiver, call is ambiguous. Specify the receiver explicitly"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL,
|
||||||
|
"To use contextual declarations, specify the `-Xcontext-receivers` compiler option"
|
||||||
|
)
|
||||||
|
|
||||||
// Ambiguity
|
// Ambiguity
|
||||||
map.put(OVERLOAD_RESOLUTION_AMBIGUITY, "Overload resolution ambiguity between candidates: {0}", SYMBOLS)
|
map.put(OVERLOAD_RESOLUTION_AMBIGUITY, "Overload resolution ambiguity between candidates: {0}", SYMBOLS)
|
||||||
map.put(ASSIGN_OPERATOR_AMBIGUITY, "Ambiguity between assign operator candidates: {0}", SYMBOLS)
|
map.put(ASSIGN_OPERATOR_AMBIGUITY, "Ambiguity between assign operator candidates: {0}", SYMBOLS)
|
||||||
|
|||||||
+13
-1
@@ -186,6 +186,7 @@ private fun mapInapplicableCandidateError(
|
|||||||
source: KtSourceElement,
|
source: KtSourceElement,
|
||||||
qualifiedAccessSource: KtSourceElement?,
|
qualifiedAccessSource: KtSourceElement?,
|
||||||
): List<KtDiagnostic> {
|
): List<KtDiagnostic> {
|
||||||
|
val typeContext = session.typeContext
|
||||||
val genericDiagnostic = FirErrors.INAPPLICABLE_CANDIDATE.createOn(source, diagnostic.candidate.symbol)
|
val genericDiagnostic = FirErrors.INAPPLICABLE_CANDIDATE.createOn(source, diagnostic.candidate.symbol)
|
||||||
val diagnostics = diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause ->
|
val diagnostics = diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause ->
|
||||||
when (rootCause) {
|
when (rootCause) {
|
||||||
@@ -197,7 +198,6 @@ private fun mapInapplicableCandidateError(
|
|||||||
rootCause.forbiddenNamedArgumentsTarget
|
rootCause.forbiddenNamedArgumentsTarget
|
||||||
)
|
)
|
||||||
is ArgumentTypeMismatch -> {
|
is ArgumentTypeMismatch -> {
|
||||||
val typeContext = session.typeContext
|
|
||||||
FirErrors.ARGUMENT_TYPE_MISMATCH.createOn(
|
FirErrors.ARGUMENT_TYPE_MISMATCH.createOn(
|
||||||
rootCause.argument.source ?: source,
|
rootCause.argument.source ?: source,
|
||||||
rootCause.expectedType.removeTypeVariableTypes(typeContext),
|
rootCause.expectedType.removeTypeVariableTypes(typeContext),
|
||||||
@@ -205,6 +205,18 @@ private fun mapInapplicableCandidateError(
|
|||||||
rootCause.isMismatchDueToNullability
|
rootCause.isMismatchDueToNullability
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is MultipleContextReceiversApplicableForExtensionReceivers ->
|
||||||
|
FirErrors.AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER.createOn(qualifiedAccessSource ?: source)
|
||||||
|
is NoApplicableValueForContextReceiver ->
|
||||||
|
FirErrors.NO_CONTEXT_RECEIVER.createOn(
|
||||||
|
qualifiedAccessSource ?: source,
|
||||||
|
rootCause.expectedContextReceiverType.removeTypeVariableTypes(typeContext)
|
||||||
|
)
|
||||||
|
is AmbiguousValuesForContextReceiverParameter ->
|
||||||
|
FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER.createOn(
|
||||||
|
qualifiedAccessSource ?: source,
|
||||||
|
rootCause.expectedContextReceiverType.removeTypeVariableTypes(typeContext)
|
||||||
|
)
|
||||||
is NullForNotNullType -> FirErrors.NULL_FOR_NONNULL_TYPE.createOn(
|
is NullForNotNullType -> FirErrors.NULL_FOR_NONNULL_TYPE.createOn(
|
||||||
rootCause.argument.source ?: source
|
rootCause.argument.source ?: source
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,8 +22,12 @@ import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
|||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.SmartcastStability
|
import org.jetbrains.kotlin.types.SmartcastStability
|
||||||
|
|
||||||
interface Receiver
|
interface Receiver
|
||||||
@@ -79,6 +83,8 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
|
|||||||
final override var type: ConeKotlinType = type
|
final override var type: ConeKotlinType = type
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
abstract val isContextReceiver: Boolean
|
||||||
|
|
||||||
val originalType: ConeKotlinType = type
|
val originalType: ConeKotlinType = type
|
||||||
|
|
||||||
var implicitScope: FirTypeScope? = type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
var implicitScope: FirTypeScope? = type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||||
@@ -144,6 +150,9 @@ class ImplicitDispatchReceiverValue(
|
|||||||
override fun createSnapshot(): ImplicitReceiverValue<FirClassSymbol<*>> {
|
override fun createSnapshot(): ImplicitReceiverValue<FirClassSymbol<*>> {
|
||||||
return ImplicitDispatchReceiverValue(boundSymbol, type, useSiteSession, scopeSession, false)
|
return ImplicitDispatchReceiverValue(boundSymbol, type, useSiteSession, scopeSession, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val isContextReceiver: Boolean
|
||||||
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImplicitExtensionReceiverValue(
|
class ImplicitExtensionReceiverValue(
|
||||||
@@ -156,6 +165,9 @@ class ImplicitExtensionReceiverValue(
|
|||||||
override fun createSnapshot(): ImplicitReceiverValue<FirCallableSymbol<*>> {
|
override fun createSnapshot(): ImplicitReceiverValue<FirCallableSymbol<*>> {
|
||||||
return ImplicitExtensionReceiverValue(boundSymbol, type, useSiteSession, scopeSession, false)
|
return ImplicitExtensionReceiverValue(boundSymbol, type, useSiteSession, scopeSession, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val isContextReceiver: Boolean
|
||||||
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -169,4 +181,54 @@ class InaccessibleImplicitReceiverValue(
|
|||||||
override fun createSnapshot(): ImplicitReceiverValue<FirClassSymbol<*>> {
|
override fun createSnapshot(): ImplicitReceiverValue<FirClassSymbol<*>> {
|
||||||
return InaccessibleImplicitReceiverValue(boundSymbol, type, useSiteSession, scopeSession, false)
|
return InaccessibleImplicitReceiverValue(boundSymbol, type, useSiteSession, scopeSession, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val isContextReceiver: Boolean
|
||||||
|
get() = false
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class ContextReceiverValue<S : FirBasedSymbol<*>>(
|
||||||
|
boundSymbol: S,
|
||||||
|
type: ConeKotlinType,
|
||||||
|
val labelName: Name?,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
scopeSession: ScopeSession,
|
||||||
|
mutable: Boolean = true,
|
||||||
|
) : ImplicitReceiverValue<S>(
|
||||||
|
boundSymbol, type, useSiteSession, scopeSession, mutable
|
||||||
|
) {
|
||||||
|
abstract override fun createSnapshot(): ContextReceiverValue<S>
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContextReceiverValueForCallable(
|
||||||
|
boundSymbol: FirCallableSymbol<*>,
|
||||||
|
type: ConeKotlinType,
|
||||||
|
labelName: Name?,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
scopeSession: ScopeSession,
|
||||||
|
mutable: Boolean = true,
|
||||||
|
) : ContextReceiverValue<FirCallableSymbol<*>>(
|
||||||
|
boundSymbol, type, labelName, useSiteSession, scopeSession, mutable
|
||||||
|
) {
|
||||||
|
override fun createSnapshot(): ContextReceiverValue<FirCallableSymbol<*>> =
|
||||||
|
ContextReceiverValueForCallable(boundSymbol, type, labelName, useSiteSession, scopeSession, mutable = false)
|
||||||
|
|
||||||
|
override val isContextReceiver: Boolean
|
||||||
|
get() = true
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContextReceiverValueForClass(
|
||||||
|
boundSymbol: FirClassSymbol<*>,
|
||||||
|
type: ConeKotlinType,
|
||||||
|
labelName: Name?,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
scopeSession: ScopeSession,
|
||||||
|
mutable: Boolean = true,
|
||||||
|
) : ContextReceiverValue<FirClassSymbol<*>>(
|
||||||
|
boundSymbol, type, labelName, useSiteSession, scopeSession, mutable
|
||||||
|
) {
|
||||||
|
override fun createSnapshot(): ContextReceiverValue<FirClassSymbol<*>> =
|
||||||
|
ContextReceiverValueForClass(boundSymbol, type, labelName, useSiteSession, scopeSession, mutable = false)
|
||||||
|
|
||||||
|
override val isContextReceiver: Boolean
|
||||||
|
get() = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,9 @@ private fun ConeTypeProjection.typeOrDefault(default: ConeKotlinType): ConeKotli
|
|||||||
|
|
||||||
fun ConeKotlinType.receiverType(session: FirSession): ConeKotlinType? {
|
fun ConeKotlinType.receiverType(session: FirSession): ConeKotlinType? {
|
||||||
if (!isBuiltinFunctionalType(session) || !isExtensionFunctionType(session)) return null
|
if (!isBuiltinFunctionalType(session) || !isExtensionFunctionType(session)) return null
|
||||||
return fullyExpandedType(session).typeArguments.first().typeOrDefault(session.builtinTypes.nothingType.type)
|
return fullyExpandedType(session).let { expanded ->
|
||||||
|
expanded.typeArguments[expanded.contextReceiversNumberForFunctionType].typeOrDefault(session.builtinTypes.nothingType.type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ConeKotlinType.returnType(session: FirSession): ConeKotlinType {
|
fun ConeKotlinType.returnType(session: FirSession): ConeKotlinType {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class FirCallResolver(
|
|||||||
functionCall.copyAsImplicitInvokeCall {
|
functionCall.copyAsImplicitInvokeCall {
|
||||||
explicitReceiver = candidate.callInfo.explicitReceiver
|
explicitReceiver = candidate.callInfo.explicitReceiver
|
||||||
dispatchReceiver = candidate.dispatchReceiverExpression()
|
dispatchReceiver = candidate.dispatchReceiverExpression()
|
||||||
extensionReceiver = candidate.extensionReceiverExpression()
|
extensionReceiver = candidate.chosenExtensionReceiverExpression()
|
||||||
argumentList = candidate.callInfo.argumentList
|
argumentList = candidate.callInfo.argumentList
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -381,7 +381,7 @@ class FirCallResolver(
|
|||||||
if (reducedCandidates.size == 1) {
|
if (reducedCandidates.size == 1) {
|
||||||
val candidate = reducedCandidates.single()
|
val candidate = reducedCandidates.single()
|
||||||
resultExpression = resultExpression.transformDispatchReceiver(StoreReceiver, candidate.dispatchReceiverExpression())
|
resultExpression = resultExpression.transformDispatchReceiver(StoreReceiver, candidate.dispatchReceiverExpression())
|
||||||
resultExpression = resultExpression.transformExtensionReceiver(StoreReceiver, candidate.extensionReceiverExpression())
|
resultExpression = resultExpression.transformExtensionReceiver(StoreReceiver, candidate.chosenExtensionReceiverExpression())
|
||||||
}
|
}
|
||||||
if (resultExpression is FirExpression) transformer.storeTypeFromCallee(resultExpression)
|
if (resultExpression is FirExpression) transformer.storeTypeFromCallee(resultExpression)
|
||||||
return resultExpression
|
return resultExpression
|
||||||
|
|||||||
@@ -47,9 +47,10 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||||
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
import org.jetbrains.kotlin.types.SmartcastStability
|
import org.jetbrains.kotlin.types.SmartcastStability
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
@@ -73,7 +74,10 @@ fun FirFunction.constructFunctionalType(isSuspend: Boolean = false): ConeLookupT
|
|||||||
}
|
}
|
||||||
val rawReturnType = (this as FirCallableDeclaration).returnTypeRef.coneType
|
val rawReturnType = (this as FirCallableDeclaration).returnTypeRef.coneType
|
||||||
|
|
||||||
return createFunctionalType(parameters, receiverTypeRef?.coneType, rawReturnType, isSuspend = isSuspend)
|
return createFunctionalType(
|
||||||
|
parameters, receiverTypeRef?.coneType, rawReturnType, isSuspend = isSuspend,
|
||||||
|
contextReceivers = contextReceivers.map { it.typeRef.coneType }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirFunction.constructFunctionalTypeRef(isSuspend: Boolean = false): FirResolvedTypeRef {
|
fun FirFunction.constructFunctionalTypeRef(isSuspend: Boolean = false): FirResolvedTypeRef {
|
||||||
@@ -88,9 +92,16 @@ fun createFunctionalType(
|
|||||||
receiverType: ConeKotlinType?,
|
receiverType: ConeKotlinType?,
|
||||||
rawReturnType: ConeKotlinType,
|
rawReturnType: ConeKotlinType,
|
||||||
isSuspend: Boolean,
|
isSuspend: Boolean,
|
||||||
|
contextReceivers: List<ConeKotlinType> = emptyList(),
|
||||||
isKFunctionType: Boolean = false
|
isKFunctionType: Boolean = false
|
||||||
): ConeLookupTagBasedType {
|
): ConeLookupTagBasedType {
|
||||||
val receiverAndParameterTypes = listOfNotNull(receiverType) + parameters + listOf(rawReturnType)
|
val receiverAndParameterTypes =
|
||||||
|
buildList {
|
||||||
|
addAll(contextReceivers)
|
||||||
|
addIfNotNull(receiverType)
|
||||||
|
addAll(parameters)
|
||||||
|
add(rawReturnType)
|
||||||
|
}
|
||||||
|
|
||||||
val kind = if (isSuspend) {
|
val kind = if (isSuspend) {
|
||||||
if (isKFunctionType) FunctionClassKind.KSuspendFunction else FunctionClassKind.SuspendFunction
|
if (isKFunctionType) FunctionClassKind.KSuspendFunction else FunctionClassKind.SuspendFunction
|
||||||
@@ -99,7 +110,18 @@ fun createFunctionalType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(receiverAndParameterTypes.size - 1))
|
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(receiverAndParameterTypes.size - 1))
|
||||||
val attributes = if (receiverType != null) ConeAttributes.WithExtensionFunctionType else ConeAttributes.Empty
|
val attributes = when {
|
||||||
|
contextReceivers.isNotEmpty() -> ConeAttributes.create(
|
||||||
|
buildList {
|
||||||
|
add(CompilerConeAttributes.ContextFunctionTypeParams(contextReceivers.size))
|
||||||
|
if (receiverType != null) {
|
||||||
|
add(CompilerConeAttributes.ExtensionFunctionType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
receiverType != null -> ConeAttributes.WithExtensionFunctionType
|
||||||
|
else -> ConeAttributes.Empty
|
||||||
|
}
|
||||||
return ConeClassLikeTypeImpl(
|
return ConeClassLikeTypeImpl(
|
||||||
ConeClassLikeLookupTagImpl(functionalTypeId),
|
ConeClassLikeLookupTagImpl(functionalTypeId),
|
||||||
receiverAndParameterTypes.toTypedArray(),
|
receiverAndParameterTypes.toTypedArray(),
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
|||||||
CollectTypeVariableUsagesInfo,
|
CollectTypeVariableUsagesInfo,
|
||||||
CheckDispatchReceiver,
|
CheckDispatchReceiver,
|
||||||
CheckExtensionReceiver,
|
CheckExtensionReceiver,
|
||||||
|
CheckContextReceivers,
|
||||||
CheckDslScopeViolation,
|
CheckDslScopeViolation,
|
||||||
CheckLowPriorityInOverloadResolution,
|
CheckLowPriorityInOverloadResolution,
|
||||||
PostponedVariablesInitializerResolutionStage,
|
PostponedVariablesInitializerResolutionStage,
|
||||||
@@ -43,6 +44,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
|||||||
CollectTypeVariableUsagesInfo,
|
CollectTypeVariableUsagesInfo,
|
||||||
CheckDispatchReceiver,
|
CheckDispatchReceiver,
|
||||||
CheckExtensionReceiver,
|
CheckExtensionReceiver,
|
||||||
|
CheckContextReceivers,
|
||||||
CheckDslScopeViolation,
|
CheckDslScopeViolation,
|
||||||
CheckArguments,
|
CheckArguments,
|
||||||
CheckCallModifiers,
|
CheckCallModifiers,
|
||||||
@@ -113,6 +115,7 @@ class ResolutionSequenceBuilder(
|
|||||||
var mapTypeArguments: Boolean = false,
|
var mapTypeArguments: Boolean = false,
|
||||||
var resolveCallableReferenceArguments: Boolean = false,
|
var resolveCallableReferenceArguments: Boolean = false,
|
||||||
var checkCallableReferenceExpectedType: Boolean = false,
|
var checkCallableReferenceExpectedType: Boolean = false,
|
||||||
|
val checkContextReceivers: Boolean = false,
|
||||||
) {
|
) {
|
||||||
fun build(): CallKind {
|
fun build(): CallKind {
|
||||||
val stages = mutableListOf<ResolutionStage>().apply {
|
val stages = mutableListOf<ResolutionStage>().apply {
|
||||||
@@ -125,6 +128,7 @@ class ResolutionSequenceBuilder(
|
|||||||
if (checkDispatchReceiver) add(CheckDispatchReceiver)
|
if (checkDispatchReceiver) add(CheckDispatchReceiver)
|
||||||
if (checkExtensionReceiver) add(CheckExtensionReceiver)
|
if (checkExtensionReceiver) add(CheckExtensionReceiver)
|
||||||
if (checkArguments) add(CheckArguments)
|
if (checkArguments) add(CheckArguments)
|
||||||
|
if (checkContextReceivers) add(CheckContextReceivers)
|
||||||
if (resolveCallableReferenceArguments) add(EagerResolveOfCallableReferences)
|
if (resolveCallableReferenceArguments) add(EagerResolveOfCallableReferences)
|
||||||
if (checkLowPriorityInOverloadResolution) add(CheckLowPriorityInOverloadResolution)
|
if (checkLowPriorityInOverloadResolution) add(CheckLowPriorityInOverloadResolution)
|
||||||
if (initializePostponedVariables) add(PostponedVariablesInitializerResolutionStage)
|
if (initializePostponedVariables) add(PostponedVariablesInitializerResolutionStage)
|
||||||
|
|||||||
@@ -28,9 +28,11 @@ import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
|||||||
class Candidate(
|
class Candidate(
|
||||||
override val symbol: FirBasedSymbol<*>,
|
override val symbol: FirBasedSymbol<*>,
|
||||||
override val dispatchReceiverValue: ReceiverValue?,
|
override val dispatchReceiverValue: ReceiverValue?,
|
||||||
override val extensionReceiverValue: ReceiverValue?,
|
// In most cases, it contains zero or single element
|
||||||
|
// More than one, only in case of context receiver group
|
||||||
|
val givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||||
override val explicitReceiverKind: ExplicitReceiverKind,
|
override val explicitReceiverKind: ExplicitReceiverKind,
|
||||||
val constraintSystemFactory: InferenceComponents.ConstraintSystemFactory,
|
private val constraintSystemFactory: InferenceComponents.ConstraintSystemFactory,
|
||||||
private val baseSystem: ConstraintStorage,
|
private val baseSystem: ConstraintStorage,
|
||||||
override val callInfo: CallInfo,
|
override val callInfo: CallInfo,
|
||||||
val originScope: FirScope?,
|
val originScope: FirScope?,
|
||||||
@@ -73,6 +75,10 @@ class Candidate(
|
|||||||
var currentApplicability = CandidateApplicability.RESOLVED
|
var currentApplicability = CandidateApplicability.RESOLVED
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
override var chosenExtensionReceiverValue: ReceiverValue? = givenExtensionReceiverOptions.singleOrNull()
|
||||||
|
|
||||||
|
var contextReceiverArguments: List<FirExpression>? = null
|
||||||
|
|
||||||
override val applicability: CandidateApplicability
|
override val applicability: CandidateApplicability
|
||||||
get() = currentApplicability
|
get() = currentApplicability
|
||||||
|
|
||||||
@@ -95,8 +101,8 @@ class Candidate(
|
|||||||
fun dispatchReceiverExpression(): FirExpression =
|
fun dispatchReceiverExpression(): FirExpression =
|
||||||
dispatchReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
dispatchReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
||||||
|
|
||||||
fun extensionReceiverExpression(): FirExpression =
|
fun chosenExtensionReceiverExpression(): FirExpression =
|
||||||
extensionReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
chosenExtensionReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
||||||
|
|
||||||
var hasVisibleBackingField = false
|
var hasVisibleBackingField = false
|
||||||
|
|
||||||
|
|||||||
@@ -49,19 +49,20 @@ class CandidateFactory private constructor(
|
|||||||
explicitReceiverKind: ExplicitReceiverKind,
|
explicitReceiverKind: ExplicitReceiverKind,
|
||||||
scope: FirScope?,
|
scope: FirScope?,
|
||||||
dispatchReceiverValue: ReceiverValue? = null,
|
dispatchReceiverValue: ReceiverValue? = null,
|
||||||
extensionReceiverValue: ReceiverValue? = null,
|
givenExtensionReceiverOptions: List<ReceiverValue> = emptyList(),
|
||||||
objectsByName: Boolean = false
|
objectsByName: Boolean = false
|
||||||
): Candidate {
|
): Candidate {
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val symbol = symbol.unwrapIntegerOperatorSymbolIfNeeded(callInfo)
|
val symbol = symbol.unwrapIntegerOperatorSymbolIfNeeded(callInfo)
|
||||||
|
|
||||||
val result = Candidate(
|
val result = Candidate(
|
||||||
symbol, dispatchReceiverValue, extensionReceiverValue,
|
symbol, dispatchReceiverValue, givenExtensionReceiverOptions,
|
||||||
explicitReceiverKind, context.inferenceComponents.constraintSystemFactory, baseSystem,
|
explicitReceiverKind, context.inferenceComponents.constraintSystemFactory, baseSystem,
|
||||||
callInfo,
|
callInfo,
|
||||||
scope,
|
scope,
|
||||||
isFromCompanionObjectTypeScope = when (explicitReceiverKind) {
|
isFromCompanionObjectTypeScope = when (explicitReceiverKind) {
|
||||||
ExplicitReceiverKind.EXTENSION_RECEIVER -> extensionReceiverValue.isCandidateFromCompanionObjectTypeScope()
|
ExplicitReceiverKind.EXTENSION_RECEIVER ->
|
||||||
|
givenExtensionReceiverOptions.singleOrNull().isCandidateFromCompanionObjectTypeScope()
|
||||||
ExplicitReceiverKind.DISPATCH_RECEIVER -> dispatchReceiverValue.isCandidateFromCompanionObjectTypeScope()
|
ExplicitReceiverKind.DISPATCH_RECEIVER -> dispatchReceiverValue.isCandidateFromCompanionObjectTypeScope()
|
||||||
// The following cases are not applicable for companion objects.
|
// The following cases are not applicable for companion objects.
|
||||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> false
|
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> false
|
||||||
@@ -121,7 +122,7 @@ class CandidateFactory private constructor(
|
|||||||
return Candidate(
|
return Candidate(
|
||||||
symbol,
|
symbol,
|
||||||
dispatchReceiverValue = null,
|
dispatchReceiverValue = null,
|
||||||
extensionReceiverValue = null,
|
givenExtensionReceiverOptions = emptyList(),
|
||||||
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||||
context.inferenceComponents.constraintSystemFactory,
|
context.inferenceComponents.constraintSystemFactory,
|
||||||
baseSystem,
|
baseSystem,
|
||||||
|
|||||||
+108
-10
@@ -34,6 +34,8 @@ import org.jetbrains.kotlin.fir.visibilityChecker
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.isSubtypeConstraintCompatible
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
|
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
|
||||||
@@ -76,18 +78,43 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
|
|||||||
object CheckExtensionReceiver : ResolutionStage() {
|
object CheckExtensionReceiver : ResolutionStage() {
|
||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
val expectedReceiverType = candidate.getReceiverType(context) ?: return
|
val expectedReceiverType = candidate.getReceiverType(context) ?: return
|
||||||
|
|
||||||
val argumentExtensionReceiverValue = candidate.extensionReceiverValue ?: return
|
|
||||||
val expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverType.type)
|
val expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverType.type)
|
||||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(
|
|
||||||
argumentType = argumentExtensionReceiverValue.type,
|
// Probably, we should add an assertion here since we check consistency on the level of scope tower levels
|
||||||
expectedType = expectedType,
|
if (candidate.givenExtensionReceiverOptions.isEmpty()) return
|
||||||
session = context.session
|
|
||||||
)
|
val preparedReceivers = candidate.givenExtensionReceiverOptions.map {
|
||||||
|
candidate.prepareReceivers(it, expectedType, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preparedReceivers.size == 1) {
|
||||||
|
resolveExtensionReceiver(preparedReceivers, candidate, expectedType, sink, context)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val successfulReceivers = preparedReceivers.filter {
|
||||||
|
candidate.system.isSubtypeConstraintCompatible(it.type, expectedType, SimpleConstraintSystemConstraintPosition)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (successfulReceivers.size) {
|
||||||
|
0 -> sink.yieldDiagnostic(InapplicableWrongReceiver())
|
||||||
|
1 -> resolveExtensionReceiver(successfulReceivers, candidate, expectedType, sink, context)
|
||||||
|
else -> sink.yieldDiagnostic(MultipleContextReceiversApplicableForExtensionReceivers())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun resolveExtensionReceiver(
|
||||||
|
receivers: List<ReceiverDescription>,
|
||||||
|
candidate: Candidate,
|
||||||
|
expectedType: ConeKotlinType,
|
||||||
|
sink: CheckerSink,
|
||||||
|
context: ResolutionContext
|
||||||
|
) {
|
||||||
|
val receiver = receivers.single()
|
||||||
candidate.resolvePlainArgumentType(
|
candidate.resolvePlainArgumentType(
|
||||||
candidate.csBuilder,
|
candidate.csBuilder,
|
||||||
argumentExtensionReceiverValue.receiverExpression,
|
receiver.expression,
|
||||||
argumentType = argumentType,
|
argumentType = receiver.type,
|
||||||
expectedType = expectedType,
|
expectedType = expectedType,
|
||||||
sink = sink,
|
sink = sink,
|
||||||
context = context,
|
context = context,
|
||||||
@@ -109,6 +136,25 @@ object CheckExtensionReceiver : ResolutionStage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Candidate.prepareReceivers(
|
||||||
|
argumentExtensionReceiverValue: ReceiverValue,
|
||||||
|
expectedType: ConeKotlinType,
|
||||||
|
context: ResolutionContext,
|
||||||
|
): ReceiverDescription {
|
||||||
|
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(
|
||||||
|
argumentType = argumentExtensionReceiverValue.type,
|
||||||
|
expectedType = expectedType,
|
||||||
|
session = context.session
|
||||||
|
).let { prepareCapturedType(it, context) }
|
||||||
|
|
||||||
|
return ReceiverDescription(argumentExtensionReceiverValue.receiverExpression, argumentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ReceiverDescription(
|
||||||
|
val expression: FirExpression,
|
||||||
|
val type: ConeKotlinType,
|
||||||
|
)
|
||||||
|
|
||||||
object CheckDispatchReceiver : ResolutionStage() {
|
object CheckDispatchReceiver : ResolutionStage() {
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class)
|
||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
@@ -156,6 +202,58 @@ object CheckDispatchReceiver : ResolutionStage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object CheckContextReceivers : ResolutionStage() {
|
||||||
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
|
val contextReceiverExpectedTypes = (candidate.symbol as? FirCallableSymbol<*>)?.fir?.contextReceivers?.map {
|
||||||
|
candidate.substitutor.substituteOrSelf(it.typeRef.coneType)
|
||||||
|
}?.takeUnless { it.isEmpty() } ?: return
|
||||||
|
|
||||||
|
val receiverGroups: List<List<ImplicitReceiverValue<*>>> =
|
||||||
|
context.bodyResolveContext.towerDataContext.towerDataElements.mapNotNull { towerDataElement ->
|
||||||
|
towerDataElement.implicitReceiver?.let(::listOf) ?: towerDataElement.contextReceiverGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
val resultingContextReceiverArguments = mutableListOf<FirExpression>()
|
||||||
|
for (expectedType in contextReceiverExpectedTypes) {
|
||||||
|
val matchingReceivers = candidate.findClosestMatchingReceivers(expectedType, receiverGroups, context)
|
||||||
|
when (matchingReceivers.size) {
|
||||||
|
0 -> {
|
||||||
|
sink.reportDiagnostic(NoApplicableValueForContextReceiver(expectedType))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
val matchingReceiver = matchingReceivers.single()
|
||||||
|
resultingContextReceiverArguments.add(matchingReceiver.expression)
|
||||||
|
candidate.system.addSubtypeConstraint(matchingReceiver.type, expectedType, SimpleConstraintSystemConstraintPosition)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
sink.reportDiagnostic(AmbiguousValuesForContextReceiverParameter(expectedType))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
candidate.contextReceiverArguments = resultingContextReceiverArguments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Candidate.findClosestMatchingReceivers(
|
||||||
|
expectedType: ConeKotlinType,
|
||||||
|
receiverGroups: List<List<ImplicitReceiverValue<*>>>,
|
||||||
|
context: ResolutionContext,
|
||||||
|
): List<ReceiverDescription> {
|
||||||
|
for (receiverGroup in receiverGroups) {
|
||||||
|
val currentResult =
|
||||||
|
receiverGroup
|
||||||
|
.map { prepareReceivers(it, expectedType, context) }
|
||||||
|
.filter { system.isSubtypeConstraintCompatible(it.type, expectedType, SimpleConstraintSystemConstraintPosition) }
|
||||||
|
|
||||||
|
if (currentResult.isNotEmpty()) return currentResult
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-dsl-marker/ for more details and
|
* See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-dsl-marker/ for more details and
|
||||||
* /compiler/testData/diagnostics/tests/resolve/dslMarker for the test files.
|
* /compiler/testData/diagnostics/tests/resolve/dslMarker for the test files.
|
||||||
@@ -176,7 +274,7 @@ object CheckDslScopeViolation : ResolutionStage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkReceiverValue(candidate.dispatchReceiverValue)
|
checkReceiverValue(candidate.dispatchReceiverValue)
|
||||||
checkReceiverValue(candidate.extensionReceiverValue)
|
checkReceiverValue(candidate.chosenExtensionReceiverValue)
|
||||||
|
|
||||||
// For value of builtin functional type with implicit extension receiver, the receiver is passed as the first argument rather than
|
// For value of builtin functional type with implicit extension receiver, the receiver is passed as the first argument rather than
|
||||||
// an extension receiver of the `invoke` call. Hence, we need to specially handle this case.
|
// an extension receiver of the `invoke` call. Hence, we need to specially handle this case.
|
||||||
|
|||||||
+8
-1
@@ -162,7 +162,7 @@ internal class FirInvokeResolveTowerExtension(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression()
|
val extensionReceiverExpression = invokeReceiverCandidate.chosenExtensionReceiverExpression()
|
||||||
val useImplicitReceiverAsBuiltinInvokeArgument =
|
val useImplicitReceiverAsBuiltinInvokeArgument =
|
||||||
!invokeBuiltinExtensionMode && isExtensionFunctionType &&
|
!invokeBuiltinExtensionMode && isExtensionFunctionType &&
|
||||||
invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||||
@@ -391,6 +391,13 @@ private class InvokeFunctionResolveTask(
|
|||||||
info, group.Member,
|
info, group.Member,
|
||||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
onContextReceiverGroup = { contextReceiverGroup, towerGroup ->
|
||||||
|
processLevelForRegularInvoke(
|
||||||
|
contextReceiverGroup.toMemberScopeTowerLevel(extensionReceiver = invokeReceiverValue),
|
||||||
|
info, towerGroup.Member,
|
||||||
|
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+84
-19
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.calls.tower
|
package org.jetbrains.kotlin.fir.resolve.calls.tower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirTowerDataContext
|
import org.jetbrains.kotlin.fir.declarations.FirTowerDataContext
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
@@ -47,6 +48,12 @@ internal class TowerDataElementsForName(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val contextReceiverGroups by lazy(LazyThreadSafetyMode.NONE) {
|
||||||
|
nonLocalTowerDataElements.mapIndexedNotNull { index, towerDataElement ->
|
||||||
|
towerDataElement.contextReceiverGroup?.let { receiver -> IndexedValue(index, receiver) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val emptyScopes = mutableSetOf<FirScope>()
|
val emptyScopes = mutableSetOf<FirScope>()
|
||||||
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
|
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
|
||||||
}
|
}
|
||||||
@@ -81,22 +88,34 @@ internal abstract class FirBaseTowerResolveTask(
|
|||||||
extensionReceiver: ReceiverValue? = null,
|
extensionReceiver: ReceiverValue? = null,
|
||||||
withHideMembersOnly: Boolean = false,
|
withHideMembersOnly: Boolean = false,
|
||||||
includeInnerConstructors: Boolean = extensionReceiver != null,
|
includeInnerConstructors: Boolean = extensionReceiver != null,
|
||||||
|
contextReceiverGroup: ContextReceiverGroup? = null,
|
||||||
): ScopeTowerLevel = ScopeTowerLevel(
|
): ScopeTowerLevel = ScopeTowerLevel(
|
||||||
components, this,
|
components, this,
|
||||||
extensionReceiver, withHideMembersOnly, includeInnerConstructors
|
givenExtensionReceiverOptions = contextReceiverGroup ?: listOfNotNull(extensionReceiver),
|
||||||
|
withHideMembersOnly, includeInnerConstructors
|
||||||
)
|
)
|
||||||
|
|
||||||
protected fun ReceiverValue.toMemberScopeTowerLevel(
|
protected fun ReceiverValue.toMemberScopeTowerLevel(
|
||||||
extensionReceiver: ReceiverValue? = null
|
extensionReceiver: ReceiverValue? = null,
|
||||||
|
contextReceiverGroup: ContextReceiverGroup? = null,
|
||||||
) = MemberScopeTowerLevel(
|
) = MemberScopeTowerLevel(
|
||||||
components, this,
|
components, this,
|
||||||
extensionReceiver,
|
givenExtensionReceiverOptions = contextReceiverGroup ?: listOfNotNull(extensionReceiver),
|
||||||
|
)
|
||||||
|
|
||||||
|
protected fun ContextReceiverGroup.toMemberScopeTowerLevel(
|
||||||
|
extensionReceiver: ReceiverValue? = null,
|
||||||
|
otherContextReceiverGroup: ContextReceiverGroup? = null,
|
||||||
|
) = ContextReceiverGroupMemberScopeTowerLevel(
|
||||||
|
components, this,
|
||||||
|
givenExtensionReceiverOptions = otherContextReceiverGroup ?: listOfNotNull(extensionReceiver),
|
||||||
)
|
)
|
||||||
|
|
||||||
protected inline fun enumerateTowerLevels(
|
protected inline fun enumerateTowerLevels(
|
||||||
parentGroup: TowerGroup = TowerGroup.EmptyRoot,
|
parentGroup: TowerGroup = TowerGroup.EmptyRoot,
|
||||||
onScope: (FirScope, TowerGroup) -> Unit,
|
onScope: (FirScope, TowerGroup) -> Unit,
|
||||||
onImplicitReceiver: (ImplicitReceiverValue<*>, TowerGroup) -> Unit,
|
onImplicitReceiver: (ImplicitReceiverValue<*>, TowerGroup) -> Unit,
|
||||||
|
onContextReceiverGroup: (ContextReceiverGroup, TowerGroup) -> Unit,
|
||||||
) {
|
) {
|
||||||
for ((index, localScope) in towerDataElementsForName.reversedFilteredLocalScopes) {
|
for ((index, localScope) in towerDataElementsForName.reversedFilteredLocalScopes) {
|
||||||
onScope(localScope, parentGroup.Local(index))
|
onScope(localScope, parentGroup.Local(index))
|
||||||
@@ -118,6 +137,10 @@ internal abstract class FirBaseTowerResolveTask(
|
|||||||
onImplicitReceiver(receiver, parentGroup.Implicit(depth))
|
onImplicitReceiver(receiver, parentGroup.Implicit(depth))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ((depth, contextReceiverGroup) in towerDataElementsForName.contextReceiverGroups) {
|
||||||
|
onContextReceiverGroup(contextReceiverGroup, parentGroup.ContextReceiverGroup(depth))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,7 +266,17 @@ internal open class FirTowerResolveTask(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onImplicitReceiver = { implicitReceiverValue, group ->
|
onImplicitReceiver = { implicitReceiverValue, group ->
|
||||||
processCombinationOfReceivers(implicitReceiverValue, explicitReceiverValue, info, group)
|
// Member extensions
|
||||||
|
processLevel(
|
||||||
|
implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = explicitReceiverValue),
|
||||||
|
info, group.Member, ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onContextReceiverGroup = { contextReceiverGroup, towerGroup ->
|
||||||
|
processLevel(
|
||||||
|
contextReceiverGroup.toMemberScopeTowerLevel(extensionReceiver = explicitReceiverValue),
|
||||||
|
info, towerGroup, ExplicitReceiverKind.EXTENSION_RECEIVER,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -277,7 +310,13 @@ internal open class FirTowerResolveTask(
|
|||||||
implicitReceiverValuesWithEmptyScopes,
|
implicitReceiverValuesWithEmptyScopes,
|
||||||
emptyScopes
|
emptyScopes
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
onContextReceiverGroup = { contextReceiverGroup, towerGroup ->
|
||||||
|
processCandidatesWithGivenContextReceiverGroup(
|
||||||
|
contextReceiverGroup,
|
||||||
|
info, towerGroup,
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,6 +347,7 @@ internal open class FirTowerResolveTask(
|
|||||||
ExplicitReceiverKind.EXTENSION_RECEIVER, parentGroup
|
ExplicitReceiverKind.EXTENSION_RECEIVER, parentGroup
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
// context?
|
||||||
for ((depth, implicitReceiverValue) in towerDataElementsForName.implicitReceivers) {
|
for ((depth, implicitReceiverValue) in towerDataElementsForName.implicitReceivers) {
|
||||||
processHideMembersLevel(
|
processHideMembersLevel(
|
||||||
implicitReceiverValue, topLevelScope, info, index, depth,
|
implicitReceiverValue, topLevelScope, info, index, depth,
|
||||||
@@ -331,19 +371,6 @@ internal open class FirTowerResolveTask(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun processCombinationOfReceivers(
|
|
||||||
implicitReceiverValue: ImplicitReceiverValue<*>,
|
|
||||||
explicitReceiverValue: ExpressionReceiverValue,
|
|
||||||
info: CallInfo,
|
|
||||||
parentGroup: TowerGroup
|
|
||||||
) {
|
|
||||||
// Member extensions
|
|
||||||
processLevel(
|
|
||||||
implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = explicitReceiverValue),
|
|
||||||
info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun processCandidatesWithGivenImplicitReceiverAsValue(
|
private suspend fun processCandidatesWithGivenImplicitReceiverAsValue(
|
||||||
receiver: ImplicitReceiverValue<*>,
|
receiver: ImplicitReceiverValue<*>,
|
||||||
info: CallInfo,
|
info: CallInfo,
|
||||||
@@ -377,11 +404,49 @@ internal open class FirTowerResolveTask(
|
|||||||
implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = receiver),
|
implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = receiver),
|
||||||
info, group
|
info, group
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
onContextReceiverGroup = { contextReceiverGroup, towerGroup ->
|
||||||
|
processLevel(
|
||||||
|
contextReceiverGroup.toMemberScopeTowerLevel(extensionReceiver = receiver),
|
||||||
|
info, towerGroup
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun processCandidatesWithGivenContextReceiverGroup(
|
||||||
|
contextReceiverGroup: ContextReceiverGroup,
|
||||||
|
info: CallInfo,
|
||||||
|
parentGroup: TowerGroup,
|
||||||
|
) {
|
||||||
|
processLevel(
|
||||||
|
contextReceiverGroup.toMemberScopeTowerLevel(), info, parentGroup.Member,
|
||||||
|
)
|
||||||
|
|
||||||
|
enumerateTowerLevels(
|
||||||
|
parentGroup,
|
||||||
|
onScope = { scope, towerGroup ->
|
||||||
|
processLevel(
|
||||||
|
scope.toScopeTowerLevel(contextReceiverGroup = contextReceiverGroup),
|
||||||
|
info, towerGroup,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onImplicitReceiver = { implicitReceiverValue, towerGroup ->
|
||||||
|
processLevel(
|
||||||
|
implicitReceiverValue.toMemberScopeTowerLevel(contextReceiverGroup = contextReceiverGroup),
|
||||||
|
info, towerGroup
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onContextReceiverGroup = { otherContextReceiverGroup, towerGroup ->
|
||||||
|
processLevel(
|
||||||
|
contextReceiverGroup.toMemberScopeTowerLevel(otherContextReceiverGroup = otherContextReceiverGroup),
|
||||||
|
info, towerGroup,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun processHideMembersLevel(
|
private suspend fun processHideMembersLevel(
|
||||||
receiverValue: ReceiverValue,
|
receiverValue: ReceiverValue,
|
||||||
topLevelScope: FirScope,
|
topLevelScope: FirScope,
|
||||||
|
|||||||
+1
-1
@@ -116,7 +116,7 @@ class FirTowerResolver(
|
|||||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||||
scope,
|
scope,
|
||||||
dispatchReceiver,
|
dispatchReceiver,
|
||||||
extensionReceiverValue = null
|
givenExtensionReceiverOptions = emptyList()
|
||||||
),
|
),
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -40,9 +40,11 @@ sealed class TowerGroupKind(val index: Byte) : Comparable<TowerGroupKind> {
|
|||||||
|
|
||||||
class ImplicitOrNonLocal(depth: Int, val kindForDebugSake: String) : WithDepth(6, depth)
|
class ImplicitOrNonLocal(depth: Int, val kindForDebugSake: String) : WithDepth(6, depth)
|
||||||
|
|
||||||
object InvokeExtension : TowerGroupKind(7)
|
class ContextReceiverGroup(depth: Int) : WithDepth(7, depth)
|
||||||
|
|
||||||
object QualifierValue : TowerGroupKind(8)
|
object InvokeExtension : TowerGroupKind(8)
|
||||||
|
|
||||||
|
object QualifierValue : TowerGroupKind(9)
|
||||||
|
|
||||||
class UnqualifiedEnum(depth: Int) : WithDepth(9, depth)
|
class UnqualifiedEnum(depth: Int) : WithDepth(9, depth)
|
||||||
|
|
||||||
@@ -166,6 +168,8 @@ private constructor(
|
|||||||
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
|
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
|
||||||
fun NonLocal(depth: Int) = kindOf(TowerGroupKind.NonLocal(depth))
|
fun NonLocal(depth: Int) = kindOf(TowerGroupKind.NonLocal(depth))
|
||||||
|
|
||||||
|
fun ContextReceiverGroup(depth: Int) = kindOf(TowerGroupKind.ContextReceiverGroup(depth))
|
||||||
|
|
||||||
fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth))
|
fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth))
|
||||||
|
|
||||||
val Last = kindOf(TowerGroupKind.Last)
|
val Last = kindOf(TowerGroupKind.Last)
|
||||||
@@ -180,6 +184,8 @@ private constructor(
|
|||||||
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
|
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
|
||||||
fun NonLocal(depth: Int) = kindOf(TowerGroupKind.NonLocal(depth))
|
fun NonLocal(depth: Int) = kindOf(TowerGroupKind.NonLocal(depth))
|
||||||
|
|
||||||
|
fun ContextReceiverGroup(depth: Int) = kindOf(TowerGroupKind.ContextReceiverGroup(depth))
|
||||||
|
|
||||||
val InvokeExtension get() = kindOf(TowerGroupKind.InvokeExtension)
|
val InvokeExtension get() = kindOf(TowerGroupKind.InvokeExtension)
|
||||||
|
|
||||||
fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth))
|
fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth))
|
||||||
|
|||||||
+3
-3
@@ -45,7 +45,7 @@ internal class TowerLevelHandler {
|
|||||||
CallKind.VariableAccess -> {
|
CallKind.VariableAccess -> {
|
||||||
processResult += towerLevel.processPropertiesByName(info, processor)
|
processResult += towerLevel.processPropertiesByName(info, processor)
|
||||||
|
|
||||||
if (!collector.isSuccess() && towerLevel is ScopeTowerLevel && towerLevel.extensionReceiver == null) {
|
if (!collector.isSuccess() && towerLevel is ScopeTowerLevel && !towerLevel.areThereExtensionReceiverOptions()) {
|
||||||
processResult += towerLevel.processObjectsByName(info, processor)
|
processResult += towerLevel.processObjectsByName(info, processor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ private class TowerScopeLevelProcessor(
|
|||||||
override fun consumeCandidate(
|
override fun consumeCandidate(
|
||||||
symbol: FirBasedSymbol<*>,
|
symbol: FirBasedSymbol<*>,
|
||||||
dispatchReceiverValue: ReceiverValue?,
|
dispatchReceiverValue: ReceiverValue?,
|
||||||
extensionReceiverValue: ReceiverValue?,
|
givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||||
scope: FirScope,
|
scope: FirScope,
|
||||||
objectsByName: Boolean
|
objectsByName: Boolean
|
||||||
) {
|
) {
|
||||||
@@ -85,7 +85,7 @@ private class TowerScopeLevelProcessor(
|
|||||||
explicitReceiverKind,
|
explicitReceiverKind,
|
||||||
scope,
|
scope,
|
||||||
dispatchReceiverValue,
|
dispatchReceiverValue,
|
||||||
extensionReceiverValue,
|
givenExtensionReceiverOptions,
|
||||||
objectsByName
|
objectsByName
|
||||||
), candidateFactory.context
|
), candidateFactory.context
|
||||||
)
|
)
|
||||||
|
|||||||
+56
-32
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.resolve.calls.tower
|
package org.jetbrains.kotlin.fir.resolve.calls.tower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
|
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||||
@@ -56,7 +57,7 @@ abstract class TowerScopeLevel {
|
|||||||
fun consumeCandidate(
|
fun consumeCandidate(
|
||||||
symbol: T,
|
symbol: T,
|
||||||
dispatchReceiverValue: ReceiverValue?,
|
dispatchReceiverValue: ReceiverValue?,
|
||||||
extensionReceiverValue: ReceiverValue?,
|
givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||||
scope: FirScope,
|
scope: FirScope,
|
||||||
objectsByName: Boolean = false
|
objectsByName: Boolean = false
|
||||||
)
|
)
|
||||||
@@ -73,7 +74,7 @@ abstract class TowerScopeLevel {
|
|||||||
class MemberScopeTowerLevel(
|
class MemberScopeTowerLevel(
|
||||||
private val bodyResolveComponents: BodyResolveComponents,
|
private val bodyResolveComponents: BodyResolveComponents,
|
||||||
val dispatchReceiverValue: ReceiverValue,
|
val dispatchReceiverValue: ReceiverValue,
|
||||||
private val extensionReceiver: ReceiverValue? = null,
|
private val givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||||
) : TowerScopeLevel() {
|
) : TowerScopeLevel() {
|
||||||
private val scopeSession: ScopeSession get() = bodyResolveComponents.scopeSession
|
private val scopeSession: ScopeSession get() = bodyResolveComponents.scopeSession
|
||||||
private val session: FirSession get() = bodyResolveComponents.session
|
private val session: FirSession get() = bodyResolveComponents.session
|
||||||
@@ -86,11 +87,11 @@ class MemberScopeTowerLevel(
|
|||||||
var (empty, candidates) = scope.collectCandidates(processScopeMembers)
|
var (empty, candidates) = scope.collectCandidates(processScopeMembers)
|
||||||
consumeCandidates(output, candidates.map { scope to it })
|
consumeCandidates(output, candidates.map { scope to it })
|
||||||
|
|
||||||
if (extensionReceiver == null) {
|
if (givenExtensionReceiverOptions.isEmpty()) {
|
||||||
val withSynthetic = FirSyntheticPropertiesScope(session, scope)
|
val withSynthetic = FirSyntheticPropertiesScope(session, scope)
|
||||||
withSynthetic.processScopeMembers { symbol ->
|
withSynthetic.processScopeMembers { symbol ->
|
||||||
empty = false
|
empty = false
|
||||||
output.consumeCandidate(symbol, dispatchReceiverValue, null, scope)
|
output.consumeCandidate(symbol, dispatchReceiverValue, givenExtensionReceiverOptions = emptyList(), scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return if (empty) ProcessResult.SCOPE_EMPTY else ProcessResult.FOUND
|
return if (empty) ProcessResult.SCOPE_EMPTY else ProcessResult.FOUND
|
||||||
@@ -103,7 +104,7 @@ class MemberScopeTowerLevel(
|
|||||||
val result = mutableListOf<T>()
|
val result = mutableListOf<T>()
|
||||||
processScopeMembers { candidate ->
|
processScopeMembers { candidate ->
|
||||||
empty = false
|
empty = false
|
||||||
if (candidate is FirCallableSymbol<*> && candidate.hasConsistentExtensionReceiver(extensionReceiver)) {
|
if (candidate is FirCallableSymbol<*> && candidate.hasConsistentExtensionReceiver(givenExtensionReceiverOptions)) {
|
||||||
val fir = candidate.fir
|
val fir = candidate.fir
|
||||||
if ((fir as? FirConstructor)?.isInner == false) {
|
if ((fir as? FirConstructor)?.isInner == false) {
|
||||||
return@processScopeMembers
|
return@processScopeMembers
|
||||||
@@ -121,14 +122,14 @@ class MemberScopeTowerLevel(
|
|||||||
candidatesWithScope: List<Pair<FirScope, T>>
|
candidatesWithScope: List<Pair<FirScope, T>>
|
||||||
) {
|
) {
|
||||||
for ((scope, candidate) in candidatesWithScope) {
|
for ((scope, candidate) in candidatesWithScope) {
|
||||||
if (candidate is FirCallableSymbol<*> && candidate.hasConsistentExtensionReceiver(extensionReceiver)) {
|
if (candidate is FirCallableSymbol<*> && candidate.hasConsistentExtensionReceiver(givenExtensionReceiverOptions)) {
|
||||||
output.consumeCandidate(
|
output.consumeCandidate(
|
||||||
candidate, dispatchReceiverValue,
|
candidate, dispatchReceiverValue,
|
||||||
extensionReceiverValue = extensionReceiver,
|
givenExtensionReceiverOptions,
|
||||||
scope
|
scope
|
||||||
)
|
)
|
||||||
} else if (candidate is FirClassLikeSymbol<*>) {
|
} else if (candidate is FirClassLikeSymbol<*>) {
|
||||||
output.consumeCandidate(candidate, null, extensionReceiver, scope)
|
output.consumeCandidate(candidate, null, givenExtensionReceiverOptions, scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,8 +202,30 @@ class MemberScopeTowerLevel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(extensionReceiver: Receiver?): Boolean {
|
private fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(givenExtensionReceivers: List<ReceiverValue>): Boolean {
|
||||||
return (extensionReceiver != null) == hasExtensionReceiver()
|
return givenExtensionReceivers.isNotEmpty() == hasExtensionReceiver()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContextReceiverGroupMemberScopeTowerLevel(
|
||||||
|
bodyResolveComponents: BodyResolveComponents,
|
||||||
|
contextReceiverGroup: ContextReceiverGroup,
|
||||||
|
givenExtensionReceiverOptions: List<ReceiverValue> = emptyList(),
|
||||||
|
) : TowerScopeLevel() {
|
||||||
|
private val memberScopeLevels = contextReceiverGroup.map {
|
||||||
|
MemberScopeTowerLevel(bodyResolveComponents, it, givenExtensionReceiverOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processFunctionsByName(info: CallInfo, processor: TowerScopeLevelProcessor<FirFunctionSymbol<*>>): ProcessResult {
|
||||||
|
return memberScopeLevels.minOf { it.processFunctionsByName(info, processor) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processPropertiesByName(info: CallInfo, processor: TowerScopeLevelProcessor<FirVariableSymbol<*>>): ProcessResult {
|
||||||
|
return memberScopeLevels.minOf { it.processPropertiesByName(info, processor) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processObjectsByName(info: CallInfo, processor: TowerScopeLevelProcessor<FirBasedSymbol<*>>): ProcessResult {
|
||||||
|
return memberScopeLevels.minOf { it.processObjectsByName(info, processor) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,12 +239,14 @@ class MemberScopeTowerLevel(
|
|||||||
class ScopeTowerLevel(
|
class ScopeTowerLevel(
|
||||||
private val bodyResolveComponents: BodyResolveComponents,
|
private val bodyResolveComponents: BodyResolveComponents,
|
||||||
val scope: FirScope,
|
val scope: FirScope,
|
||||||
val extensionReceiver: ReceiverValue?,
|
private val givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||||
private val withHideMembersOnly: Boolean,
|
private val withHideMembersOnly: Boolean,
|
||||||
private val includeInnerConstructors: Boolean
|
private val includeInnerConstructors: Boolean
|
||||||
) : TowerScopeLevel() {
|
) : TowerScopeLevel() {
|
||||||
private val session: FirSession get() = bodyResolveComponents.session
|
private val session: FirSession get() = bodyResolveComponents.session
|
||||||
|
|
||||||
|
fun areThereExtensionReceiverOptions(): Boolean = givenExtensionReceiverOptions.isNotEmpty()
|
||||||
|
|
||||||
private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>): ReceiverValue? {
|
private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>): ReceiverValue? {
|
||||||
candidate.fir.importedFromObjectData?.let { data ->
|
candidate.fir.importedFromObjectData?.let { data ->
|
||||||
val objectClassId = data.objectClassId
|
val objectClassId = data.objectClassId
|
||||||
@@ -257,26 +282,25 @@ class ScopeTowerLevel(
|
|||||||
|
|
||||||
private fun shouldSkipCandidateWithInconsistentExtensionReceiver(candidate: FirCallableSymbol<*>): Boolean {
|
private fun shouldSkipCandidateWithInconsistentExtensionReceiver(candidate: FirCallableSymbol<*>): Boolean {
|
||||||
// Pre-check explicit extension receiver for default package top-level members
|
// Pre-check explicit extension receiver for default package top-level members
|
||||||
if (scope is FirDefaultStarImportingScope && extensionReceiver != null) {
|
if (scope !is FirDefaultStarImportingScope || !areThereExtensionReceiverOptions()) return false
|
||||||
|
|
||||||
|
val declarationReceiverType = candidate.resolvedReceiverTypeRef?.coneType as? ConeClassLikeType ?: return false
|
||||||
|
val startProjectedDeclarationReceiverType = declarationReceiverType.lookupTag.constructClassType(
|
||||||
|
declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
|
||||||
|
isNullable = true
|
||||||
|
)
|
||||||
|
|
||||||
|
return givenExtensionReceiverOptions.none { extensionReceiver ->
|
||||||
val extensionReceiverType = extensionReceiver.type
|
val extensionReceiverType = extensionReceiver.type
|
||||||
if (extensionReceiverType is ConeClassLikeType) {
|
// If some receiver is non class like, we should not skip it
|
||||||
val declarationReceiverType = candidate.resolvedReceiverTypeRef?.coneType
|
if (extensionReceiverType !is ConeClassLikeType) return@none true
|
||||||
if (declarationReceiverType is ConeClassLikeType) {
|
|
||||||
if (!AbstractTypeChecker.isSubtypeOf(
|
AbstractTypeChecker.isSubtypeOf(
|
||||||
session.typeContext,
|
session.typeContext,
|
||||||
extensionReceiverType,
|
extensionReceiverType,
|
||||||
declarationReceiverType.lookupTag.constructClassType(
|
startProjectedDeclarationReceiverType
|
||||||
declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
|
)
|
||||||
isNullable = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : FirBasedSymbol<*>> consumeCallableCandidate(
|
private fun <T : FirBasedSymbol<*>> consumeCallableCandidate(
|
||||||
@@ -287,7 +311,7 @@ class ScopeTowerLevel(
|
|||||||
if (withHideMembersOnly && candidate.getAnnotationByClassId(HidesMembers) == null) {
|
if (withHideMembersOnly && candidate.getAnnotationByClassId(HidesMembers) == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val receiverExpected = withHideMembersOnly || extensionReceiver != null
|
val receiverExpected = withHideMembersOnly || areThereExtensionReceiverOptions()
|
||||||
if (candidateReceiverTypeRef == null == receiverExpected) return
|
if (candidateReceiverTypeRef == null == receiverExpected) return
|
||||||
val dispatchReceiverValue = dispatchReceiverValue(candidate)
|
val dispatchReceiverValue = dispatchReceiverValue(candidate)
|
||||||
if (dispatchReceiverValue == null && shouldSkipCandidateWithInconsistentExtensionReceiver(candidate)) {
|
if (dispatchReceiverValue == null && shouldSkipCandidateWithInconsistentExtensionReceiver(candidate)) {
|
||||||
@@ -297,7 +321,7 @@ class ScopeTowerLevel(
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
processor.consumeCandidate(
|
processor.consumeCandidate(
|
||||||
unwrappedCandidate as T, dispatchReceiverValue,
|
unwrappedCandidate as T, dispatchReceiverValue,
|
||||||
extensionReceiverValue = extensionReceiver,
|
givenExtensionReceiverOptions,
|
||||||
scope
|
scope
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -343,7 +367,7 @@ class ScopeTowerLevel(
|
|||||||
empty = false
|
empty = false
|
||||||
processor.consumeCandidate(
|
processor.consumeCandidate(
|
||||||
it, dispatchReceiverValue = null,
|
it, dispatchReceiverValue = null,
|
||||||
extensionReceiverValue = null,
|
givenExtensionReceiverOptions = emptyList(),
|
||||||
scope = scope,
|
scope = scope,
|
||||||
objectsByName = true
|
objectsByName = true
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ class FirBuilderInferenceSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Candidate.isSuitableForBuilderInference(): Boolean {
|
private fun Candidate.isSuitableForBuilderInference(): Boolean {
|
||||||
val extensionReceiver = extensionReceiverValue
|
val extensionReceiver = chosenExtensionReceiverValue
|
||||||
val dispatchReceiver = dispatchReceiverValue
|
val dispatchReceiver = dispatchReceiverValue
|
||||||
return when {
|
return when {
|
||||||
extensionReceiver == null && dispatchReceiver == null -> false
|
extensionReceiver == null && dispatchReceiver == null -> false
|
||||||
|
|||||||
+15
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.*
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildContextReceiver
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||||
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
|||||||
import org.jetbrains.kotlin.fir.resolve.typeFromCallee
|
import org.jetbrains.kotlin.fir.resolve.typeFromCallee
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -259,6 +261,7 @@ class FirCallCompleter(
|
|||||||
override fun analyzeAndGetLambdaReturnArguments(
|
override fun analyzeAndGetLambdaReturnArguments(
|
||||||
lambdaAtom: ResolvedLambdaAtom,
|
lambdaAtom: ResolvedLambdaAtom,
|
||||||
receiverType: ConeKotlinType?,
|
receiverType: ConeKotlinType?,
|
||||||
|
contextReceivers: List<ConeKotlinType>,
|
||||||
parameters: List<ConeKotlinType>,
|
parameters: List<ConeKotlinType>,
|
||||||
expectedReturnType: ConeKotlinType?,
|
expectedReturnType: ConeKotlinType?,
|
||||||
stubsForPostponedVariables: Map<TypeVariableMarker, StubTypeMarker>,
|
stubsForPostponedVariables: Map<TypeVariableMarker, StubTypeMarker>,
|
||||||
@@ -307,6 +310,18 @@ class FirCallCompleter(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (contextReceivers.isNotEmpty()) {
|
||||||
|
lambdaArgument.replaceContextReceivers(
|
||||||
|
contextReceivers.map { contextReceiverType ->
|
||||||
|
buildContextReceiver {
|
||||||
|
typeRef = buildResolvedTypeRef {
|
||||||
|
type = contextReceiverType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val lookupTracker = session.lookupTracker
|
val lookupTracker = session.lookupTracker
|
||||||
val fileSource = components.file.source
|
val fileSource = components.file.source
|
||||||
lambdaArgument.valueParameters.forEachIndexed { index, parameter ->
|
lambdaArgument.valueParameters.forEachIndexed { index, parameter ->
|
||||||
|
|||||||
+1
-2
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubsti
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionContext
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.BuilderInferencePosition
|
import org.jetbrains.kotlin.resolve.calls.inference.model.BuilderInferencePosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.registerTypeVariableIfNotPresent
|
import org.jetbrains.kotlin.resolve.calls.inference.registerTypeVariableIfNotPresent
|
||||||
@@ -74,7 +73,7 @@ class FirDelegatedPropertyInferenceSession(
|
|||||||
if (callee.candidate.system.hasContradiction) return true
|
if (callee.candidate.system.hasContradiction) return true
|
||||||
|
|
||||||
val hasStubType =
|
val hasStubType =
|
||||||
callee.candidate.extensionReceiverValue?.type?.containsStubType() ?: false
|
callee.candidate.chosenExtensionReceiverValue?.type?.containsStubType() ?: false
|
||||||
|| callee.candidate.dispatchReceiverValue?.type?.containsStubType() ?: false
|
|| callee.candidate.dispatchReceiverValue?.type?.containsStubType() ?: false
|
||||||
|
|
||||||
if (!hasStubType) {
|
if (!hasStubType) {
|
||||||
|
|||||||
+15
-1
@@ -51,10 +51,16 @@ fun extractLambdaInfoFromFunctionalType(
|
|||||||
// For lambdas, the existence of the receiver is always implied by the expected type, and a value parameter
|
// For lambdas, the existence of the receiver is always implied by the expected type, and a value parameter
|
||||||
// can never fill its role.
|
// can never fill its role.
|
||||||
val receiverType = if (argument.isLambda) expectedType.receiverType(session) else argument.receiverType
|
val receiverType = if (argument.isLambda) expectedType.receiverType(session) else argument.receiverType
|
||||||
|
val contextReceiversNumber =
|
||||||
|
if (argument.isLambda) expectedType.contextReceiversNumberForFunctionType else argument.contextReceivers.size
|
||||||
|
|
||||||
val valueParametersTypesIncludingReceiver = expectedType.valueParameterTypesIncludingReceiver(session)
|
val valueParametersTypesIncludingReceiver = expectedType.valueParameterTypesIncludingReceiver(session)
|
||||||
val isExtensionFunctionType = expectedType.isExtensionFunctionType(session)
|
val isExtensionFunctionType = expectedType.isExtensionFunctionType(session)
|
||||||
val expectedParameters = valueParametersTypesIncludingReceiver.let {
|
val expectedParameters = valueParametersTypesIncludingReceiver.let {
|
||||||
if (receiverType != null && isExtensionFunctionType) it.drop(1) else it
|
val forExtension = if (receiverType != null && isExtensionFunctionType) 1 else 0
|
||||||
|
val toDrop = forExtension + contextReceiversNumber
|
||||||
|
|
||||||
|
if (toDrop > 0) it.drop(toDrop) else it
|
||||||
}
|
}
|
||||||
|
|
||||||
var coerceFirstParameterToExtensionReceiver = false
|
var coerceFirstParameterToExtensionReceiver = false
|
||||||
@@ -84,11 +90,19 @@ fun extractLambdaInfoFromFunctionalType(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val contextReceivers =
|
||||||
|
when {
|
||||||
|
contextReceiversNumber == 0 -> emptyList()
|
||||||
|
argument.isLambda -> valueParametersTypesIncludingReceiver.subList(0, contextReceiversNumber)
|
||||||
|
else -> argument.contextReceivers.map { it.typeRef.coneType }
|
||||||
|
}
|
||||||
|
|
||||||
return ResolvedLambdaAtom(
|
return ResolvedLambdaAtom(
|
||||||
argument,
|
argument,
|
||||||
expectedType,
|
expectedType,
|
||||||
expectedType.isSuspendFunctionType(session),
|
expectedType.isSuspendFunctionType(session),
|
||||||
receiverType,
|
receiverType,
|
||||||
|
contextReceivers,
|
||||||
parameters,
|
parameters,
|
||||||
returnType,
|
returnType,
|
||||||
typeVariableForLambdaReturnType = returnTypeVariable,
|
typeVariableForLambdaReturnType = returnTypeVariable,
|
||||||
|
|||||||
+7
-1
@@ -66,7 +66,8 @@ fun Candidate.preprocessLambdaArgument(
|
|||||||
if (resolvedArgument.coerceFirstParameterToExtensionReceiver) parameters.drop(1) else parameters,
|
if (resolvedArgument.coerceFirstParameterToExtensionReceiver) parameters.drop(1) else parameters,
|
||||||
resolvedArgument.receiver,
|
resolvedArgument.receiver,
|
||||||
resolvedArgument.returnType,
|
resolvedArgument.returnType,
|
||||||
isSuspend = resolvedArgument.isSuspend
|
isSuspend = resolvedArgument.isSuspend,
|
||||||
|
contextReceivers = resolvedArgument.contextReceivers,
|
||||||
)
|
)
|
||||||
|
|
||||||
val position = ConeArgumentConstraintPosition(resolvedArgument.atom)
|
val position = ConeArgumentConstraintPosition(resolvedArgument.atom)
|
||||||
@@ -124,6 +125,10 @@ private fun extractLambdaInfo(
|
|||||||
it.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: nothingType
|
it.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: nothingType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val contextReceivers = argument.contextReceivers.map {
|
||||||
|
it.typeRef.coneTypeSafe<ConeKotlinType>() ?: nothingType
|
||||||
|
}
|
||||||
|
|
||||||
val newTypeVariableUsed = returnType == typeVariable.defaultType
|
val newTypeVariableUsed = returnType == typeVariable.defaultType
|
||||||
if (newTypeVariableUsed) csBuilder.registerVariable(typeVariable)
|
if (newTypeVariableUsed) csBuilder.registerVariable(typeVariable)
|
||||||
|
|
||||||
@@ -132,6 +137,7 @@ private fun extractLambdaInfo(
|
|||||||
expectedType,
|
expectedType,
|
||||||
isSuspend,
|
isSuspend,
|
||||||
receiverType,
|
receiverType,
|
||||||
|
contextReceivers,
|
||||||
parameters,
|
parameters,
|
||||||
returnType,
|
returnType,
|
||||||
typeVariable.takeIf { newTypeVariableUsed },
|
typeVariable.takeIf { newTypeVariableUsed },
|
||||||
|
|||||||
+3
@@ -37,6 +37,7 @@ interface LambdaAnalyzer {
|
|||||||
fun analyzeAndGetLambdaReturnArguments(
|
fun analyzeAndGetLambdaReturnArguments(
|
||||||
lambdaAtom: ResolvedLambdaAtom,
|
lambdaAtom: ResolvedLambdaAtom,
|
||||||
receiverType: ConeKotlinType?,
|
receiverType: ConeKotlinType?,
|
||||||
|
contextReceivers: List<ConeKotlinType>,
|
||||||
parameters: List<ConeKotlinType>,
|
parameters: List<ConeKotlinType>,
|
||||||
expectedReturnType: ConeKotlinType?, // null means, that return type is not proper i.e. it depends on some type variables
|
expectedReturnType: ConeKotlinType?, // null means, that return type is not proper i.e. it depends on some type variables
|
||||||
stubsForPostponedVariables: Map<TypeVariableMarker, StubTypeMarker>,
|
stubsForPostponedVariables: Map<TypeVariableMarker, StubTypeMarker>,
|
||||||
@@ -122,6 +123,7 @@ class PostponedArgumentsAnalyzer(
|
|||||||
fun substitute(type: ConeKotlinType) = currentSubstitutor.safeSubstitute(c, type) as ConeKotlinType
|
fun substitute(type: ConeKotlinType) = currentSubstitutor.safeSubstitute(c, type) as ConeKotlinType
|
||||||
|
|
||||||
val receiver = lambda.receiver?.let(::substitute)
|
val receiver = lambda.receiver?.let(::substitute)
|
||||||
|
val contextReceivers = lambda.contextReceivers.map(::substitute)
|
||||||
val parameters = lambda.parameters.map(::substitute)
|
val parameters = lambda.parameters.map(::substitute)
|
||||||
val rawReturnType = lambda.returnType
|
val rawReturnType = lambda.returnType
|
||||||
|
|
||||||
@@ -137,6 +139,7 @@ class PostponedArgumentsAnalyzer(
|
|||||||
val results = lambdaAnalyzer.analyzeAndGetLambdaReturnArguments(
|
val results = lambdaAnalyzer.analyzeAndGetLambdaReturnArguments(
|
||||||
lambda,
|
lambda,
|
||||||
receiver,
|
receiver,
|
||||||
|
contextReceivers,
|
||||||
parameters,
|
parameters,
|
||||||
expectedTypeForReturnArguments,
|
expectedTypeForReturnArguments,
|
||||||
stubsForPostponedVariables,
|
stubsForPostponedVariables,
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class ResolvedLambdaAtom(
|
|||||||
expectedType: ConeKotlinType?,
|
expectedType: ConeKotlinType?,
|
||||||
val isSuspend: Boolean,
|
val isSuspend: Boolean,
|
||||||
val receiver: ConeKotlinType?,
|
val receiver: ConeKotlinType?,
|
||||||
|
val contextReceivers: List<ConeKotlinType>,
|
||||||
val parameters: List<ConeKotlinType>,
|
val parameters: List<ConeKotlinType>,
|
||||||
var returnType: ConeKotlinType,
|
var returnType: ConeKotlinType,
|
||||||
typeVariableForLambdaReturnType: ConeTypeVariableForLambdaReturnType?,
|
typeVariableForLambdaReturnType: ConeTypeVariableForLambdaReturnType?,
|
||||||
|
|||||||
+3
-3
@@ -467,8 +467,8 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
|||||||
|
|
||||||
private fun createFunctionalType(typeRef: FirFunctionTypeRef): ConeClassLikeType {
|
private fun createFunctionalType(typeRef: FirFunctionTypeRef): ConeClassLikeType {
|
||||||
val parameters =
|
val parameters =
|
||||||
listOfNotNull(typeRef.receiverTypeRef?.coneType) +
|
typeRef.contextReceiverTypeRefs.map { it.coneType } +
|
||||||
typeRef.contextReceiverTypeRefs.map { it.coneType } +
|
listOfNotNull(typeRef.receiverTypeRef?.coneType) +
|
||||||
typeRef.valueParameters.map { it.returnTypeRef.coneType.withParameterNameAnnotation(it) } +
|
typeRef.valueParameters.map { it.returnTypeRef.coneType.withParameterNameAnnotation(it) } +
|
||||||
listOf(typeRef.returnTypeRef.coneType)
|
listOf(typeRef.returnTypeRef.coneType)
|
||||||
val classId = if (typeRef.isSuspend) {
|
val classId = if (typeRef.isSuspend) {
|
||||||
@@ -550,7 +550,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
|||||||
override val dispatchReceiverValue: ReceiverValue?
|
override val dispatchReceiverValue: ReceiverValue?
|
||||||
get() = null
|
get() = null
|
||||||
|
|
||||||
override val extensionReceiverValue: ReceiverValue?
|
override val chosenExtensionReceiverValue: ReceiverValue?
|
||||||
get() = null
|
get() = null
|
||||||
|
|
||||||
override val explicitReceiverKind: ExplicitReceiverKind
|
override val explicitReceiverKind: ExplicitReceiverKind
|
||||||
|
|||||||
+2
-2
@@ -131,7 +131,7 @@ class FirCallCompletionResultsWriterTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dispatchReceiver = subCandidate.dispatchReceiverExpression()
|
var dispatchReceiver = subCandidate.dispatchReceiverExpression()
|
||||||
var extensionReceiver = subCandidate.extensionReceiverExpression()
|
var extensionReceiver = subCandidate.chosenExtensionReceiverExpression()
|
||||||
if (!declaration.isWrappedIntegerOperator()) {
|
if (!declaration.isWrappedIntegerOperator()) {
|
||||||
val expectedDispatchReceiverType = (declaration as? FirCallableDeclaration)?.dispatchReceiverType
|
val expectedDispatchReceiverType = (declaration as? FirCallableDeclaration)?.dispatchReceiverType
|
||||||
val expectedExtensionReceiverType = (declaration as? FirCallableDeclaration)?.receiverTypeRef?.coneType
|
val expectedExtensionReceiverType = (declaration as? FirCallableDeclaration)?.receiverTypeRef?.coneType
|
||||||
@@ -403,7 +403,7 @@ class FirCallCompletionResultsWriterTransformer(
|
|||||||
StoreCalleeReference,
|
StoreCalleeReference,
|
||||||
resolvedReference,
|
resolvedReference,
|
||||||
).transformDispatchReceiver(StoreReceiver, subCandidate.dispatchReceiverExpression())
|
).transformDispatchReceiver(StoreReceiver, subCandidate.dispatchReceiverExpression())
|
||||||
.transformExtensionReceiver(StoreReceiver, subCandidate.extensionReceiverExpression())
|
.transformExtensionReceiver(StoreReceiver, subCandidate.chosenExtensionReceiverExpression())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transformVariableAssignment(
|
override fun transformVariableAssignment(
|
||||||
|
|||||||
+3
-1
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.*
|
|||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||||
import org.jetbrains.kotlin.fir.declarations.primaryConstructorIfAny
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
@@ -228,6 +227,8 @@ class BodyResolveContext(
|
|||||||
holder: SessionHolder,
|
holder: SessionHolder,
|
||||||
f: () -> T
|
f: () -> T
|
||||||
): T = withTowerDataCleanup {
|
): T = withTowerDataCleanup {
|
||||||
|
replaceTowerDataContext(towerDataContext.addContextReceiverGroup(owner.createContextReceiverValues(holder)))
|
||||||
|
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
val receiver = ImplicitExtensionReceiverValue(
|
val receiver = ImplicitExtensionReceiverValue(
|
||||||
owner.symbol,
|
owner.symbol,
|
||||||
@@ -450,6 +451,7 @@ class BodyResolveContext(
|
|||||||
val forMembersResolution =
|
val forMembersResolution =
|
||||||
staticsAndCompanion
|
staticsAndCompanion
|
||||||
.addReceiver(labelName, towerElementsForClass.thisReceiver)
|
.addReceiver(labelName, towerElementsForClass.thisReceiver)
|
||||||
|
.addContextReceiverGroup(towerElementsForClass.contextReceivers)
|
||||||
.addNonLocalScopeIfNotNull(typeParameterScope)
|
.addNonLocalScopeIfNotNull(typeParameterScope)
|
||||||
|
|
||||||
val scopeForConstructorHeader =
|
val scopeForConstructorHeader =
|
||||||
|
|||||||
+14
-1
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fakeElement
|
|||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunctionCopy
|
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunctionCopy
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildContextReceiver
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
@@ -34,7 +35,6 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeLocalVariableNoTypeOrIni
|
|||||||
import org.jetbrains.kotlin.fir.resolve.inference.FirStubTypeTransformer
|
import org.jetbrains.kotlin.fir.resolve.inference.FirStubTypeTransformer
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.ResolvedLambdaAtom
|
import org.jetbrains.kotlin.fir.resolve.inference.ResolvedLambdaAtom
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType
|
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType
|
||||||
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
|
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||||
@@ -809,6 +809,19 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
lambda = buildAnonymousFunctionCopy(lambda) {
|
lambda = buildAnonymousFunctionCopy(lambda) {
|
||||||
receiverTypeRef = lambda.receiverTypeRef?.takeIf { it !is FirImplicitTypeRef }
|
receiverTypeRef = lambda.receiverTypeRef?.takeIf { it !is FirImplicitTypeRef }
|
||||||
?: resolvedLambdaAtom?.receiver?.let { lambda.receiverTypeRef?.resolvedTypeFromPrototype(it) }
|
?: resolvedLambdaAtom?.receiver?.let { lambda.receiverTypeRef?.resolvedTypeFromPrototype(it) }
|
||||||
|
|
||||||
|
contextReceivers.clear()
|
||||||
|
contextReceivers.addAll(
|
||||||
|
lambda.contextReceivers.takeIf { it.isNotEmpty() }
|
||||||
|
?: resolvedLambdaAtom?.contextReceivers?.map { receiverType ->
|
||||||
|
buildContextReceiver {
|
||||||
|
this.typeRef = buildResolvedTypeRef {
|
||||||
|
type = receiverType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.orEmpty()
|
||||||
|
)
|
||||||
|
|
||||||
this.valueParameters.clear()
|
this.valueParameters.clear()
|
||||||
this.valueParameters.addAll(valueParameters)
|
this.valueParameters.addAll(valueParameters)
|
||||||
returnTypeRef = (lambda.returnTypeRef as? FirResolvedTypeRef)
|
returnTypeRef = (lambda.returnTypeRef as? FirResolvedTypeRef)
|
||||||
|
|||||||
+70
-18
@@ -8,14 +8,14 @@ package org.jetbrains.kotlin.fir.declarations
|
|||||||
import kotlinx.collections.immutable.PersistentList
|
import kotlinx.collections.immutable.PersistentList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toPersistentList
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
|
import org.jetbrains.kotlin.fir.labelName
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType
|
import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
@@ -23,32 +23,39 @@ fun SessionHolder.collectImplicitReceivers(
|
|||||||
type: ConeKotlinType?,
|
type: ConeKotlinType?,
|
||||||
owner: FirDeclaration
|
owner: FirDeclaration
|
||||||
): ImplicitReceivers {
|
): ImplicitReceivers {
|
||||||
if (type == null) return ImplicitReceivers(null, emptyList())
|
|
||||||
|
|
||||||
val implicitCompanionValues = mutableListOf<ImplicitReceiverValue<*>>()
|
val implicitCompanionValues = mutableListOf<ImplicitReceiverValue<*>>()
|
||||||
|
val contextReceiverValues = mutableListOf<ContextReceiverValue<*>>()
|
||||||
val implicitReceiverValue = when (owner) {
|
val implicitReceiverValue = when (owner) {
|
||||||
is FirClass -> {
|
is FirClass -> {
|
||||||
val towerElementsForClass = collectTowerDataElementsForClass(owner, type)
|
val towerElementsForClass = collectTowerDataElementsForClass(owner, type!!)
|
||||||
implicitCompanionValues.addAll(towerElementsForClass.implicitCompanionValues)
|
implicitCompanionValues.addAll(towerElementsForClass.implicitCompanionValues)
|
||||||
|
contextReceiverValues.addAll(towerElementsForClass.contextReceivers)
|
||||||
|
|
||||||
towerElementsForClass.thisReceiver
|
towerElementsForClass.thisReceiver
|
||||||
}
|
}
|
||||||
is FirFunction -> {
|
is FirFunction -> {
|
||||||
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession)
|
contextReceiverValues.addAll(owner.createContextReceiverValues(this))
|
||||||
|
type?.let { ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) }
|
||||||
}
|
}
|
||||||
is FirVariable -> {
|
is FirVariable -> {
|
||||||
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession)
|
contextReceiverValues.addAll(owner.createContextReceiverValues(this))
|
||||||
|
type?.let { ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) }
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
|
if (type != null) {
|
||||||
|
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
|
||||||
|
}
|
||||||
|
|
||||||
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ImplicitReceivers(implicitReceiverValue, implicitCompanionValues)
|
return ImplicitReceivers(implicitReceiverValue, implicitCompanionValues, contextReceiverValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ImplicitReceivers(
|
data class ImplicitReceivers(
|
||||||
val implicitReceiverValue: ImplicitReceiverValue<*>?,
|
val implicitReceiverValue: ImplicitReceiverValue<*>?,
|
||||||
val implicitCompanionValues: List<ImplicitReceiverValue<*>>
|
val implicitCompanionValues: List<ImplicitReceiverValue<*>>,
|
||||||
|
val contextReceivers: List<ContextReceiverValue<*>>,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun SessionHolder.collectTowerDataElementsForClass(owner: FirClass, defaultType: ConeKotlinType): TowerElementsForClass {
|
fun SessionHolder.collectTowerDataElementsForClass(owner: FirClass, defaultType: ConeKotlinType): TowerElementsForClass {
|
||||||
@@ -83,9 +90,15 @@ fun SessionHolder.collectTowerDataElementsForClass(owner: FirClass, defaultType:
|
|||||||
}
|
}
|
||||||
|
|
||||||
val thisReceiver = ImplicitDispatchReceiverValue(owner.symbol, defaultType, session, scopeSession)
|
val thisReceiver = ImplicitDispatchReceiverValue(owner.symbol, defaultType, session, scopeSession)
|
||||||
|
val contextReceivers = (owner as? FirRegularClass)?.contextReceivers?.map {
|
||||||
|
ContextReceiverValueForClass(
|
||||||
|
owner.symbol, it.typeRef.coneType, it.labelName, session, scopeSession,
|
||||||
|
)
|
||||||
|
}.orEmpty()
|
||||||
|
|
||||||
return TowerElementsForClass(
|
return TowerElementsForClass(
|
||||||
thisReceiver,
|
thisReceiver,
|
||||||
|
contextReceivers,
|
||||||
owner.staticScope(this),
|
owner.staticScope(this),
|
||||||
companionReceiver,
|
companionReceiver,
|
||||||
companionObject?.staticScope(this),
|
companionObject?.staticScope(this),
|
||||||
@@ -96,6 +109,7 @@ fun SessionHolder.collectTowerDataElementsForClass(owner: FirClass, defaultType:
|
|||||||
|
|
||||||
class TowerElementsForClass(
|
class TowerElementsForClass(
|
||||||
val thisReceiver: ImplicitReceiverValue<*>,
|
val thisReceiver: ImplicitReceiverValue<*>,
|
||||||
|
val contextReceivers: List<ContextReceiverValueForClass>,
|
||||||
val staticScope: FirScope?,
|
val staticScope: FirScope?,
|
||||||
val companionReceiver: ImplicitReceiverValue<*>?,
|
val companionReceiver: ImplicitReceiverValue<*>?,
|
||||||
val companionStaticScope: FirScope?,
|
val companionStaticScope: FirScope?,
|
||||||
@@ -137,7 +151,9 @@ class FirTowerDataContext private constructor(
|
|||||||
fun addNonLocalTowerDataElements(newElements: List<FirTowerDataElement>): FirTowerDataContext {
|
fun addNonLocalTowerDataElements(newElements: List<FirTowerDataElement>): FirTowerDataContext {
|
||||||
return FirTowerDataContext(
|
return FirTowerDataContext(
|
||||||
towerDataElements.addAll(newElements),
|
towerDataElements.addAll(newElements),
|
||||||
implicitReceiverStack.addAll(newElements.mapNotNull { it.implicitReceiver }),
|
implicitReceiverStack
|
||||||
|
.addAll(newElements.mapNotNull { it.implicitReceiver })
|
||||||
|
.addAllContextReceivers(newElements.flatMap { it.contextReceiverGroup.orEmpty() }),
|
||||||
localScopes,
|
localScopes,
|
||||||
nonLocalTowerDataElements.addAll(newElements)
|
nonLocalTowerDataElements.addAll(newElements)
|
||||||
)
|
)
|
||||||
@@ -162,6 +178,18 @@ class FirTowerDataContext private constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addContextReceiverGroup(contextReceiverGroup: ContextReceiverGroup): FirTowerDataContext {
|
||||||
|
if (contextReceiverGroup.isEmpty()) return this
|
||||||
|
val element = contextReceiverGroup.asTowerDataElement()
|
||||||
|
|
||||||
|
return FirTowerDataContext(
|
||||||
|
towerDataElements.add(element),
|
||||||
|
contextReceiverGroup.fold(implicitReceiverStack, PersistentImplicitReceiverStack::addContextReceiver),
|
||||||
|
localScopes,
|
||||||
|
nonLocalTowerDataElements.add(element)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun addNonLocalScopeIfNotNull(scope: FirScope?): FirTowerDataContext {
|
fun addNonLocalScopeIfNotNull(scope: FirScope?): FirTowerDataContext {
|
||||||
if (scope == null) return this
|
if (scope == null) return this
|
||||||
return addNonLocalScope(scope)
|
return addNonLocalScope(scope)
|
||||||
@@ -179,23 +207,47 @@ class FirTowerDataContext private constructor(
|
|||||||
|
|
||||||
fun createSnapshot(): FirTowerDataContext {
|
fun createSnapshot(): FirTowerDataContext {
|
||||||
return FirTowerDataContext(
|
return FirTowerDataContext(
|
||||||
towerDataElements.map { FirTowerDataElement(it.scope, it.implicitReceiver?.createSnapshot(), it.isLocal) }.toPersistentList(),
|
towerDataElements.map(FirTowerDataElement::createSnapshot).toPersistentList(),
|
||||||
implicitReceiverStack.createSnapshot(),
|
implicitReceiverStack.createSnapshot(),
|
||||||
localScopes.toPersistentList(),
|
localScopes.toPersistentList(),
|
||||||
nonLocalTowerDataElements.map { FirTowerDataElement(it.scope, it.implicitReceiver?.createSnapshot(), it.isLocal) }
|
nonLocalTowerDataElements.map(FirTowerDataElement::createSnapshot).toPersistentList()
|
||||||
.toPersistentList()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FirTowerDataElement(val scope: FirScope?, val implicitReceiver: ImplicitReceiverValue<*>?, val isLocal: Boolean)
|
class FirTowerDataElement(
|
||||||
|
val scope: FirScope?,
|
||||||
|
val implicitReceiver: ImplicitReceiverValue<*>?,
|
||||||
|
val contextReceiverGroup: ContextReceiverGroup? = null,
|
||||||
|
val isLocal: Boolean,
|
||||||
|
) {
|
||||||
|
fun createSnapshot(): FirTowerDataElement =
|
||||||
|
FirTowerDataElement(
|
||||||
|
scope,
|
||||||
|
implicitReceiver?.createSnapshot(),
|
||||||
|
contextReceiverGroup?.map { it.createSnapshot() },
|
||||||
|
isLocal,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun ImplicitReceiverValue<*>.asTowerDataElement(): FirTowerDataElement =
|
fun ImplicitReceiverValue<*>.asTowerDataElement(): FirTowerDataElement =
|
||||||
FirTowerDataElement(scope = null, this, isLocal = false)
|
FirTowerDataElement(scope = null, implicitReceiver = this, isLocal = false)
|
||||||
|
|
||||||
|
fun ContextReceiverGroup.asTowerDataElement(): FirTowerDataElement =
|
||||||
|
FirTowerDataElement(scope = null, implicitReceiver = null, contextReceiverGroup = this, isLocal = false)
|
||||||
|
|
||||||
fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement =
|
fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement =
|
||||||
FirTowerDataElement(this, implicitReceiver = null, isLocal)
|
FirTowerDataElement(scope = this, implicitReceiver = null, isLocal = isLocal)
|
||||||
|
|
||||||
fun FirClass.staticScope(sessionHolder: SessionHolder) =
|
fun FirClass.staticScope(sessionHolder: SessionHolder) =
|
||||||
scopeProvider.getStaticScope(this, sessionHolder.session, sessionHolder.scopeSession)
|
scopeProvider.getStaticScope(this, sessionHolder.session, sessionHolder.scopeSession)
|
||||||
|
|
||||||
|
typealias ContextReceiverGroup = List<ContextReceiverValue<*>>
|
||||||
typealias FirLocalScopes = PersistentList<FirLocalScope>
|
typealias FirLocalScopes = PersistentList<FirLocalScope>
|
||||||
|
|
||||||
|
fun FirCallableDeclaration.createContextReceiverValues(
|
||||||
|
sessionHolder: SessionHolder,
|
||||||
|
): List<ContextReceiverValueForCallable> =
|
||||||
|
contextReceivers.map {
|
||||||
|
ContextReceiverValueForCallable(symbol, it.typeRef.coneType, it.labelName, sessionHolder.session, sessionHolder.scopeSession)
|
||||||
|
}
|
||||||
|
|||||||
+33
-6
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.resolve
|
package org.jetbrains.kotlin.fir.resolve
|
||||||
|
|
||||||
import kotlinx.collections.immutable.*
|
import kotlinx.collections.immutable.*
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.calls.ContextReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
@@ -16,7 +17,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
class PersistentImplicitReceiverStack private constructor(
|
class PersistentImplicitReceiverStack private constructor(
|
||||||
private val stack: PersistentList<ImplicitReceiverValue<*>>,
|
private val stack: PersistentList<ImplicitReceiverValue<*>>,
|
||||||
// This multi-map holds indexes of the stack ^
|
// This multi-map holds indexes of the stack ^
|
||||||
private val indexesPerLabel: PersistentSetMultimap<Name, Int>,
|
private val receiversPerLabel: PersistentSetMultimap<Name, ImplicitReceiverValue<*>>,
|
||||||
private val indexesPerSymbol: PersistentMap<FirBasedSymbol<*>, Int>,
|
private val indexesPerSymbol: PersistentMap<FirBasedSymbol<*>, Int>,
|
||||||
private val originalTypes: PersistentList<ConeKotlinType>,
|
private val originalTypes: PersistentList<ConeKotlinType>,
|
||||||
) : ImplicitReceiverStack(), Iterable<ImplicitReceiverValue<*>> {
|
) : ImplicitReceiverStack(), Iterable<ImplicitReceiverValue<*>> {
|
||||||
@@ -33,16 +34,42 @@ class PersistentImplicitReceiverStack private constructor(
|
|||||||
return receivers.fold(this) { acc, value -> acc.add(name = null, value) }
|
return receivers.fold(this) { acc, value -> acc.add(name = null, value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(name: Name?, value: ImplicitReceiverValue<*>): PersistentImplicitReceiverStack {
|
fun addAllContextReceivers(receivers: List<ContextReceiverValue<*>>): PersistentImplicitReceiverStack {
|
||||||
|
return receivers.fold(this) { acc, value -> acc.addContextReceiver(value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(name: Name?, value: ImplicitReceiverValue<*>, aliasLabel: Name? = null): PersistentImplicitReceiverStack {
|
||||||
val stack = stack.add(value)
|
val stack = stack.add(value)
|
||||||
val originalTypes = originalTypes.add(value.originalType)
|
val originalTypes = originalTypes.add(value.originalType)
|
||||||
val index = stack.size - 1
|
val index = stack.size - 1
|
||||||
val indexesPerLabel = name?.let { indexesPerLabel.put(it, index) } ?: indexesPerLabel
|
val receiversPerLabel = name?.let { receiversPerLabel.put(it, value) } ?: receiversPerLabel
|
||||||
val indexesPerSymbol = indexesPerSymbol.put(value.boundSymbol, index)
|
val indexesPerSymbol = indexesPerSymbol.put(value.boundSymbol, index)
|
||||||
|
|
||||||
return PersistentImplicitReceiverStack(
|
return PersistentImplicitReceiverStack(
|
||||||
stack,
|
stack,
|
||||||
indexesPerLabel,
|
receiversPerLabel,
|
||||||
|
indexesPerSymbol,
|
||||||
|
originalTypes
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addContextReceiver(value: ContextReceiverValue<*>): PersistentImplicitReceiverStack {
|
||||||
|
val labelName = value.labelName ?: return this
|
||||||
|
|
||||||
|
val receiversPerLabel = receiversPerLabel.put(labelName, value)
|
||||||
|
return PersistentImplicitReceiverStack(
|
||||||
|
stack,
|
||||||
|
receiversPerLabel,
|
||||||
|
indexesPerSymbol,
|
||||||
|
originalTypes
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addReceiverLabelAlias(aliasLabel: Name, value: ImplicitReceiverValue<*>): PersistentImplicitReceiverStack {
|
||||||
|
val receiversPerLabel = receiversPerLabel.put(aliasLabel, value)
|
||||||
|
return PersistentImplicitReceiverStack(
|
||||||
|
stack,
|
||||||
|
receiversPerLabel,
|
||||||
indexesPerSymbol,
|
indexesPerSymbol,
|
||||||
originalTypes
|
originalTypes
|
||||||
)
|
)
|
||||||
@@ -50,7 +77,7 @@ class PersistentImplicitReceiverStack private constructor(
|
|||||||
|
|
||||||
override operator fun get(name: String?): ImplicitReceiverValue<*>? {
|
override operator fun get(name: String?): ImplicitReceiverValue<*>? {
|
||||||
if (name == null) return stack.lastOrNull()
|
if (name == null) return stack.lastOrNull()
|
||||||
return indexesPerLabel[Name.identifier(name)].lastOrNull()?.let { stack[it] }
|
return receiversPerLabel[Name.identifier(name)].lastOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun lastDispatchReceiver(): ImplicitDispatchReceiverValue? {
|
override fun lastDispatchReceiver(): ImplicitDispatchReceiverValue? {
|
||||||
@@ -85,7 +112,7 @@ class PersistentImplicitReceiverStack private constructor(
|
|||||||
fun createSnapshot(): PersistentImplicitReceiverStack {
|
fun createSnapshot(): PersistentImplicitReceiverStack {
|
||||||
return PersistentImplicitReceiverStack(
|
return PersistentImplicitReceiverStack(
|
||||||
stack.map { it.createSnapshot() }.toPersistentList(),
|
stack.map { it.createSnapshot() }.toPersistentList(),
|
||||||
indexesPerLabel,
|
receiversPerLabel,
|
||||||
indexesPerSymbol,
|
indexesPerSymbol,
|
||||||
originalTypes
|
originalTypes
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
|||||||
abstract class AbstractCandidate {
|
abstract class AbstractCandidate {
|
||||||
abstract val symbol: FirBasedSymbol<*>
|
abstract val symbol: FirBasedSymbol<*>
|
||||||
abstract val dispatchReceiverValue: ReceiverValue?
|
abstract val dispatchReceiverValue: ReceiverValue?
|
||||||
abstract val extensionReceiverValue: ReceiverValue?
|
abstract val chosenExtensionReceiverValue: ReceiverValue?
|
||||||
abstract val explicitReceiverKind: ExplicitReceiverKind
|
abstract val explicitReceiverKind: ExplicitReceiverKind
|
||||||
abstract val callInfo: AbstractCallInfo
|
abstract val callInfo: AbstractCallInfo
|
||||||
abstract val diagnostics: List<ResolutionDiagnostic>
|
abstract val diagnostics: List<ResolutionDiagnostic>
|
||||||
|
|||||||
+12
-1
@@ -82,7 +82,8 @@ object LowerPriorityToPreserveCompatibilityDiagnostic : ResolutionDiagnostic(RES
|
|||||||
|
|
||||||
object CandidateChosenUsingOverloadResolutionByLambdaAnnotation : ResolutionDiagnostic(RESOLVED)
|
object CandidateChosenUsingOverloadResolutionByLambdaAnnotation : ResolutionDiagnostic(RESOLVED)
|
||||||
|
|
||||||
class UnstableSmartCast(val argument: FirExpressionWithSmartcast, val targetType: ConeKotlinType, val isCastToNotNull: Boolean) : ResolutionDiagnostic(UNSTABLE_SMARTCAST)
|
class UnstableSmartCast(val argument: FirExpressionWithSmartcast, val targetType: ConeKotlinType, val isCastToNotNull: Boolean) :
|
||||||
|
ResolutionDiagnostic(UNSTABLE_SMARTCAST)
|
||||||
|
|
||||||
class ArgumentTypeMismatch(
|
class ArgumentTypeMismatch(
|
||||||
val expectedType: ConeKotlinType,
|
val expectedType: ConeKotlinType,
|
||||||
@@ -108,3 +109,13 @@ class Unsupported(val message: String, val source: KtSourceElement? = null) : Re
|
|||||||
object PropertyAsOperator : ResolutionDiagnostic(PROPERTY_AS_OPERATOR)
|
object PropertyAsOperator : ResolutionDiagnostic(PROPERTY_AS_OPERATOR)
|
||||||
|
|
||||||
class DslScopeViolation(val calleeSymbol: FirBasedSymbol<*>) : ResolutionDiagnostic(DSL_SCOPE_VIOLATION)
|
class DslScopeViolation(val calleeSymbol: FirBasedSymbol<*>) : ResolutionDiagnostic(DSL_SCOPE_VIOLATION)
|
||||||
|
|
||||||
|
class MultipleContextReceiversApplicableForExtensionReceivers : ResolutionDiagnostic(INAPPLICABLE)
|
||||||
|
|
||||||
|
class NoApplicableValueForContextReceiver(
|
||||||
|
val expectedContextReceiverType: ConeKotlinType
|
||||||
|
) : ResolutionDiagnostic(INAPPLICABLE)
|
||||||
|
|
||||||
|
class AmbiguousValuesForContextReceiverParameter(
|
||||||
|
val expectedContextReceiverType: ConeKotlinType,
|
||||||
|
) : ResolutionDiagnostic(INAPPLICABLE)
|
||||||
|
|||||||
@@ -81,9 +81,9 @@ val FirTypeRef.isMarkedNullable: Boolean?
|
|||||||
|
|
||||||
val FirFunctionTypeRef.parametersCount: Int
|
val FirFunctionTypeRef.parametersCount: Int
|
||||||
get() = if (receiverTypeRef != null)
|
get() = if (receiverTypeRef != null)
|
||||||
valueParameters.size + 1
|
valueParameters.size + contextReceiverTypeRefs.size + 1
|
||||||
else
|
else
|
||||||
valueParameters.size
|
valueParameters.size + contextReceiverTypeRefs.size
|
||||||
|
|
||||||
val EXTENSION_FUNCTION_ANNOTATION = ClassId.fromString("kotlin/ExtensionFunctionType")
|
val EXTENSION_FUNCTION_ANNOTATION = ClassId.fromString("kotlin/ExtensionFunctionType")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user