[FE] Move context receivers checks to the separate resolution part
This commit is contained in:
committed by
TeamCityServer
parent
37a981cc29
commit
bfd20e1890
+54
-38
@@ -697,47 +697,10 @@ internal object CheckReceivers : ResolutionPart() {
|
||||
shouldCheckImplicitInvoke = false, // reproduce old inference behaviour
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
resolvedCall.contextReceiversArguments = searchForAdditionalReceivers() ?: return
|
||||
for (i in resolvedCall.contextReceiversArguments.indices) {
|
||||
checkReceiver(
|
||||
resolvedCall.contextReceiversArguments[i],
|
||||
candidateDescriptor.contextReceiverParameters[i],
|
||||
shouldCheckImplicitInvoke = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun ResolutionCandidate.workCount() = 3
|
||||
|
||||
private fun ResolutionCandidate.searchForAdditionalReceivers(): List<SimpleKotlinCallArgument>? {
|
||||
val result = mutableListOf<ReceiverValueWithSmartCastInfo>()
|
||||
val candidateReceivers = scopeTower.lexicalScope.parentsWithSelf
|
||||
.flatMap { if (it is LexicalScope) scopeTower.getImplicitReceivers(it) else emptyList() }
|
||||
|
||||
fun KotlinType.prepared(): KotlinType = if (containsTypeParameter()) replaceArgumentsWithStarProjections() else this
|
||||
|
||||
for (receiver in candidateDescriptor.contextReceiverParameters) {
|
||||
val expectedReceiverType = receiver.type
|
||||
val expectedReceiverTypeClosestBound =
|
||||
if (expectedReceiverType.isTypeParameter()) expectedReceiverType.supertypes().first()
|
||||
else expectedReceiverType
|
||||
val selectedCandidate = candidateReceivers.firstOrNull { candidateReceiver ->
|
||||
val candidateReceiverType = candidateReceiver.receiverValue.type
|
||||
org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker.Default.isSubtypeOf(
|
||||
candidateReceiverType.prepared(),
|
||||
expectedReceiverTypeClosestBound.prepared()
|
||||
)
|
||||
} ?: run {
|
||||
this.diagnosticsFromResolutionParts.add(NoContextReceiver(receiver))
|
||||
return null
|
||||
}
|
||||
result.add(selectedCandidate)
|
||||
}
|
||||
return result.map { ReceiverExpressionKotlinCallArgument(it) }
|
||||
}
|
||||
override fun ResolutionCandidate.workCount() = 2
|
||||
}
|
||||
|
||||
internal object CheckArgumentsInParenthesis : ResolutionPart() {
|
||||
@@ -841,3 +804,56 @@ internal object ErrorDescriptorResolutionPart : ResolutionPart() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal object CheckContextReceiversResolutionPart : ResolutionPart() {
|
||||
private fun ResolutionCandidate.checkReceiver(
|
||||
receiverArgument: SimpleKotlinCallArgument?,
|
||||
receiverParameter: ReceiverParameterDescriptor?
|
||||
) {
|
||||
if ((receiverArgument == null) != (receiverParameter == null)) {
|
||||
error("Inconsistency receiver state for call $kotlinCall and candidate descriptor: $candidateDescriptor")
|
||||
}
|
||||
if (receiverArgument == null || receiverParameter == null) return
|
||||
val receiverInfo = ReceiverInfo(
|
||||
isReceiver = true,
|
||||
shouldReportUnsafeCall = true,
|
||||
reportUnsafeCallAsUnsafeImplicitInvoke = false
|
||||
)
|
||||
|
||||
resolveKotlinArgument(receiverArgument, receiverParameter, receiverInfo)
|
||||
}
|
||||
|
||||
private fun ResolutionCandidate.searchForAdditionalReceivers(): List<SimpleKotlinCallArgument>? {
|
||||
val result = mutableListOf<ReceiverValueWithSmartCastInfo>()
|
||||
val candidateReceivers = scopeTower.lexicalScope.parentsWithSelf
|
||||
.flatMap { if (it is LexicalScope) scopeTower.getImplicitReceivers(it) else emptyList() }
|
||||
|
||||
fun KotlinType.prepared(): KotlinType = if (containsTypeParameter()) replaceArgumentsWithStarProjections() else this
|
||||
|
||||
for (receiver in candidateDescriptor.contextReceiverParameters) {
|
||||
val expectedReceiverType = receiver.type
|
||||
val expectedReceiverTypeClosestBound =
|
||||
if (expectedReceiverType.isTypeParameter()) expectedReceiverType.supertypes().first()
|
||||
else expectedReceiverType
|
||||
val selectedCandidate = candidateReceivers.firstOrNull { candidateReceiver ->
|
||||
val candidateReceiverType = candidateReceiver.receiverValue.type
|
||||
NewKotlinTypeChecker.Default.isSubtypeOf(candidateReceiverType.prepared(), expectedReceiverTypeClosestBound.prepared())
|
||||
} ?: run {
|
||||
this.diagnosticsFromResolutionParts.add(NoContextReceiver(receiver))
|
||||
return null
|
||||
}
|
||||
result.add(selectedCandidate)
|
||||
}
|
||||
return result.map { ReceiverExpressionKotlinCallArgument(it) }
|
||||
}
|
||||
|
||||
override fun ResolutionCandidate.process(workIndex: Int) {
|
||||
resolvedCall.contextReceiversArguments = searchForAdditionalReceivers() ?: return
|
||||
for (i in resolvedCall.contextReceiversArguments.indices) {
|
||||
checkReceiver(
|
||||
resolvedCall.contextReceiversArguments[i],
|
||||
candidateDescriptor.contextReceiverParameters[i]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -7,5 +7,5 @@ context(T)
|
||||
fun <T> T.f(t: B<T>) {}
|
||||
|
||||
fun Int.main(a: A, b: B<String>) {
|
||||
a.f(<!TYPE_MISMATCH, TYPE_MISMATCH!>b<!>)
|
||||
a.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>f<!>(b)
|
||||
}
|
||||
Reference in New Issue
Block a user