@@ -8,96 +8,91 @@ package org.jetbrains.kotlin.fir.resolve.calls.overloads
8
8
import org.jetbrains.kotlin.fir.FirSession
9
9
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
10
10
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOverloadabilityHelper
11
+ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOverloadabilityHelper.ContextParameterShadowing
11
12
import org.jetbrains.kotlin.fir.declarations.typeSpecificityComparatorProvider
12
13
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
13
14
import org.jetbrains.kotlin.fir.resolve.inference.inferenceLogger
14
15
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
15
16
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
16
17
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
17
- import org.jetbrains.kotlin.fir.types.ConeKotlinType
18
+ import org.jetbrains.kotlin.resolve.calls.inference.runTransaction
18
19
import org.jetbrains.kotlin.resolve.calls.results.*
19
20
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
20
21
21
22
// 16 is enough to compare two CP lists with 4 types each.
22
23
private const val MAX_COMPLEXITY_FOR_CONTEXT_PARAMETERS = 16
23
24
24
25
class FirDeclarationOverloadabilityHelperImpl (val session : FirSession ) : FirDeclarationOverloadabilityHelper {
25
- override fun isConflicting (a : FirCallableSymbol <* >, b : FirCallableSymbol <* >, ignoreContextParameters : Boolean ): Boolean {
26
- val sigA = createSignature(a, ignoreContextParameters)
27
- val sigB = createSignature(b, ignoreContextParameters)
26
+ override fun isConflicting (a : FirCallableSymbol <* >, b : FirCallableSymbol <* >): Boolean {
27
+ val sigA = createSignature(a, ignoreContextParameters = false )
28
+ val sigB = createSignature(b, ignoreContextParameters = false )
28
29
29
30
return isEquallyOrMoreSpecific(sigA, sigB) && isEquallyOrMoreSpecific(sigB, sigA)
30
31
}
31
32
32
33
override fun getContextParameterShadowing (
33
34
a : FirCallableSymbol <* >,
34
35
b : FirCallableSymbol <* >,
35
- ): FirDeclarationOverloadabilityHelper .ContextParameterShadowing {
36
+ ): ContextParameterShadowing {
37
+ // Fast-path when either symbol has no context parameters.
38
+ if (a.contextParameterSymbols.none() || b.contextParameterSymbols.none()) {
39
+ return if (isConflicting(a, b)) ContextParameterShadowing .BothWays else ContextParameterShadowing .None
40
+ }
41
+
42
+ val sigA = createSignature(a, ignoreContextParameters = true )
43
+ val sigB = createSignature(b, ignoreContextParameters = true )
44
+
45
+ val csB = createEmptyConstraintSystem()
46
+ val stateB = csB.signatureComparisonStateIfEquallyOrMoreSpecific(sigA, sigB) ? : return ContextParameterShadowing .None
47
+
48
+ val csA = createEmptyConstraintSystem()
49
+ val stateA = csA.signatureComparisonStateIfEquallyOrMoreSpecific(sigB, sigA) ? : return ContextParameterShadowing .None
50
+
51
+ // The complexity of this check is O(a.contextParameterSymbols.size * b.contextParameterSymbols.size),
52
+ // to limit quadratic explosion, we only check below a certain threshold.
53
+ if (a.contextParameterSymbols.size * b.contextParameterSymbols.size > MAX_COMPLEXITY_FOR_CONTEXT_PARAMETERS ) {
54
+ return ContextParameterShadowing .None
55
+ }
56
+
36
57
// bShadowsA && aShadowsB => BothWays
37
58
// bShadowsA && !aShadowsB => Shadowing
38
59
// else => None
39
60
40
- val bShadowsA = isShadowingContextParameters(b, a)
61
+ val bShadowsA = isShadowingContextParameters(b, a, csB, stateB )
41
62
// Early return to skip needless computation of aShadowsB
42
- if (! bShadowsA) return FirDeclarationOverloadabilityHelper . ContextParameterShadowing .None
63
+ if (! bShadowsA) return ContextParameterShadowing .None
43
64
44
- val aShadowsB = isShadowingContextParameters(a, b)
65
+ val aShadowsB = isShadowingContextParameters(a, b, csA, stateA )
45
66
46
67
return if (aShadowsB) {
47
- FirDeclarationOverloadabilityHelper . ContextParameterShadowing .BothWays
68
+ ContextParameterShadowing .BothWays
48
69
} else {
49
- FirDeclarationOverloadabilityHelper . ContextParameterShadowing .Shadowing
70
+ ContextParameterShadowing .Shadowing
50
71
}
51
72
}
52
73
53
74
private fun isShadowingContextParameters (
54
75
a : FirCallableSymbol <* >,
55
76
b : FirCallableSymbol <* >,
77
+ cs : ConeSimpleConstraintSystemImpl ,
78
+ state : FlatSignatureComparisonState ,
56
79
): Boolean {
57
- // The complexity of this check is O(a.contextParameterSymbols.size * b.contextParameterSymbols.size),
58
- // to limit quadratic explosion, we only check below a certain threshold.
59
- if (a.contextParameterSymbols.size * b.contextParameterSymbols.size > MAX_COMPLEXITY_FOR_CONTEXT_PARAMETERS ) {
60
- return false
61
- }
62
-
63
80
// A is shadowing B if for every type in A's context parameter list, there is a type in B's context parameter list
64
81
// that is equally or more specific.
65
82
66
- fun singleTypeSignature (type : ConeKotlinType , symbol : FirCallableSymbol <* >): FlatSignature <FirCallableSymbol <* >> {
67
- return FlatSignature (
68
- origin = symbol,
69
- typeParameters = symbol.typeParameterSymbols.map { it.toLookupTag() },
70
- valueParameterTypes = listOf (type),
71
- hasExtensionReceiver = false ,
72
- contextReceiverCount = 0 ,
73
- hasVarargs = false ,
74
- numDefaults = 0 ,
75
- isExpect = false ,
76
- isSyntheticMember = false
77
- )
78
- }
79
-
80
- val bSingleTypeSignatures = b.contextParameterSymbols.map { singleTypeSignature(it.resolvedReturnType, b) }
81
-
82
- return a.contextParameterSymbols.all {
83
- val aType = singleTypeSignature(it.resolvedReturnType, a)
84
- bSingleTypeSignatures.any { bType ->
85
- isEquallyOrMoreSpecific(bType, aType)
83
+ return a.contextParameterSymbols.all { cpA ->
84
+ b.contextParameterSymbols.any { cpB ->
85
+ cs.system.runTransaction {
86
+ ! state.isLessSpecific(cpB.resolvedReturnType, cpA.resolvedReturnType)
87
+ }
86
88
}
87
89
}
88
90
}
89
91
90
92
override fun isEquallyOrMoreSpecific (
91
93
sigA : FlatSignature <FirCallableSymbol <* >>,
92
94
sigB : FlatSignature <FirCallableSymbol <* >>,
93
- ): Boolean = createEmptyConstraintSystem().also {
94
- session.inferenceLogger?.logStage(" Some isEquallyOrMoreSpecific() call" , it.constraintSystemMarker)
95
- }.isSignatureEquallyOrMoreSpecific(
96
- sigA,
97
- sigB,
98
- OverloadabilitySpecificityCallbacks ,
99
- session.typeSpecificityComparatorProvider?.typeSpecificityComparator ? : TypeSpecificityComparator .NONE ,
100
- )
95
+ ): Boolean = createEmptyConstraintSystem().signatureComparisonStateIfEquallyOrMoreSpecific(sigA, sigB) != null
101
96
102
97
override fun createSignature (declaration : FirCallableSymbol <* >, ignoreContextParameters : Boolean ): FlatSignature <FirCallableSymbol <* >> {
103
98
val valueParameters = (declaration as ? FirFunctionSymbol <* >)?.valueParameterSymbols.orEmpty()
@@ -143,7 +138,21 @@ class FirDeclarationOverloadabilityHelperImpl(val session: FirSession) : FirDecl
143
138
)
144
139
}
145
140
146
- private fun createEmptyConstraintSystem (): SimpleConstraintSystem {
147
- return ConeSimpleConstraintSystemImpl (session.inferenceComponents.createConstraintSystem(), session)
141
+ private fun createEmptyConstraintSystem (): ConeSimpleConstraintSystemImpl {
142
+ return ConeSimpleConstraintSystemImpl (session.inferenceComponents.createConstraintSystem(), session).also {
143
+ session.inferenceLogger?.logStage(" Some isEquallyOrMoreSpecific() call" , it.constraintSystemMarker)
144
+ }
145
+ }
146
+
147
+ private fun ConeSimpleConstraintSystemImpl.signatureComparisonStateIfEquallyOrMoreSpecific (
148
+ sigA : FlatSignature <FirCallableSymbol <* >>,
149
+ sigB : FlatSignature <FirCallableSymbol <* >>,
150
+ ): FlatSignatureComparisonState ? {
151
+ return signatureComparisonStateIfEquallyOrMoreSpecific(
152
+ sigA,
153
+ sigB,
154
+ OverloadabilitySpecificityCallbacks ,
155
+ session.typeSpecificityComparatorProvider?.typeSpecificityComparator ? : TypeSpecificityComparator .NONE
156
+ )
148
157
}
149
158
}
0 commit comments