Skip to content

Commit 55ac0b4

Browse files
dzharkovSpace Team
authored andcommitted
FE: Revert incorrect SAM conversion enhancements brought to K2
NB: It also makes the test for KT-76453 (hugeMixedCapturedTypes.kt) pass the BACKEND phase, which was previously impossible due to the previous seemingly exponential algorithm ^KT-79535 Fixed
1 parent 9bf34e1 commit 55ac0b4

File tree

8 files changed

+46
-91
lines changed

8 files changed

+46
-91
lines changed

compiler/fir/analysis-tests/testData/resolve/inference/capturedTypes/hugeMixedCapturedType.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN_PIPELINE_TILL: FRONTEND
1+
// RUN_PIPELINE_TILL: BACKEND
22
// ISSUE: KT-76453
33

44
// FILE: JavaClass.java
@@ -150,8 +150,6 @@ fun bar(a: JavaClass.A<*, *, *, *, *, *, *, *, *, *>) {
150150
.foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo()
151151
.foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo()
152152
.foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo().foo()
153-
154-
"".<!UNRESOLVED_REFERENCE!>qwer<!>
155153
}
156154

157155
/* GENERATED_FIR_TAGS: classDeclaration, functionDeclaration, inProjection, lambdaLiteral, localProperty, nullableType,

compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSamResolver.kt

Lines changed: 19 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,11 @@ import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
1010
import org.jetbrains.kotlin.descriptors.ClassKind
1111
import org.jetbrains.kotlin.descriptors.Modality
1212
import org.jetbrains.kotlin.fakeElement
13-
import org.jetbrains.kotlin.fir.FirSession
14-
import org.jetbrains.kotlin.fir.FirSessionComponent
15-
import org.jetbrains.kotlin.fir.SessionAndScopeSessionHolder
13+
import org.jetbrains.kotlin.fir.*
1614
import org.jetbrains.kotlin.fir.caches.FirCache
1715
import org.jetbrains.kotlin.fir.caches.NullableMap
1816
import org.jetbrains.kotlin.fir.caches.firCachesFactory
1917
import org.jetbrains.kotlin.fir.caches.getOrPut
20-
import org.jetbrains.kotlin.fir.containingClassForStaticMemberAttr
21-
import org.jetbrains.kotlin.fir.copy
2218
import org.jetbrains.kotlin.fir.declarations.*
2319
import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder
2420
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
@@ -27,7 +23,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
2723
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferTypeParameterType
2824
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
2925
import org.jetbrains.kotlin.fir.extensions.extensionService
30-
import org.jetbrains.kotlin.fir.moduleData
3126
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
3227
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
3328
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
@@ -310,80 +305,27 @@ class FirSamResolver(
310305
private fun FirTypeParameterRefsOwner.buildSubstitutorWithUpperBounds(session: FirSession, type: ConeClassLikeType): ConeSubstitutor {
311306
if (typeParameters.isEmpty()) return ConeSubstitutor.Empty
312307

313-
var containsNonSubstitutedArguments = false
314-
315-
fun createMapping(substitutor: ConeSubstitutor): Map<FirTypeParameterSymbol, ConeKotlinType> {
316-
return typeParameters.zip(type.typeArguments).associate { (parameter, projection) ->
317-
val typeArgument =
318-
projection.type?.let(substitutor::substituteOrSelf)
319-
// TODO: Consider using `parameterSymbol.fir.bounds.first().coneType` once sure that it won't fail with exception
320-
?: parameter.symbol.fir.bounds.firstOrNull()?.coneTypeOrNull
321-
?.let(substitutor::substituteOrSelf)
322-
?.also { bound ->
323-
// We only check for type parameters in upper bounds
324-
// because `projection` can contain a type parameter type as well in a situation like
325-
// fun interface Sam<T> {
326-
// fun invoke()
327-
// fun foo(s: Sam<T>) {} <--- here T is substituted with T but it's not a recursion
328-
// }
329-
if (bound.containsReferenceToOtherTypeParameter(this)) {
330-
containsNonSubstitutedArguments = true
331-
}
308+
val substitutionMap = typeParameters.zip(type.typeArguments).associate { (parameter, projection) ->
309+
val typeArgument =
310+
projection.type
311+
// TODO: Consider using `parameterSymbol.fir.bounds.first().coneType` once sure that it won't fail with exception
312+
?: parameter.symbol.fir.bounds.firstOrNull()?.coneTypeOrNull
313+
?.let { bound ->
314+
if (!bound.containsReferenceToOtherTypeParameter(this)) {
315+
bound
316+
} else {
317+
val diagnostic = ConeCannotInferTypeParameterType(
318+
parameter.symbol,
319+
reason = "Parameter ${parameter.symbol.name} has a cycle in its upper bounds",
320+
)
321+
ConeErrorType(diagnostic)
332322
}
333-
?: session.builtinTypes.nullableAnyType.coneType
334-
Pair(parameter.symbol, typeArgument)
335-
}
336-
}
337-
338-
/*
339-
*
340-
* There might be a case when there is a recursion in upper bounds of SAM type parameters:
341-
*
342-
* ```
343-
* public interface Function<E extends CharSequence, F extends Map<String, E>> {
344-
* E handle(F f);
345-
* }
346-
* ```
347-
*
348-
* In this case, it's not enough to just take the upper bound of the parameter, as it may contain the reference to another parameter.
349-
* To handle it correctly, we need to substitute upper bounds with existing substitutor too.
350-
* This recursive substitution process may last at most as the number of presented type parameters
351-
*/
352-
var substitutor: ConeSubstitutor = ConeSubstitutor.Empty
353-
354-
for (i in typeParameters.indices) {
355-
containsNonSubstitutedArguments = false
356-
val mapping = createMapping(substitutor)
357-
substitutor = substitutorByMap(mapping, session)
358-
if (!containsNonSubstitutedArguments) {
359-
break
360-
}
361-
}
362-
363-
/*
364-
* If there are still unsubstituted
365-
* parameters, then it means that there is a cycle in parameters themselves and it's impossible to infer proper substitution. For that
366-
* case we just create error types for such parameters
367-
*
368-
* ```
369-
* public interface Function1<A extends B, B extends A> {
370-
* B handle(A a);
371-
* }
372-
* ```
373-
*/
374-
if (containsNonSubstitutedArguments) {
375-
val errorSubstitution = typeParameters.associate {
376-
val diagnostic = ConeCannotInferTypeParameterType(
377-
it.symbol,
378-
reason = "Parameter ${it.symbol.name} has a cycle in its upper bounds",
379-
)
380-
it.symbol to ConeErrorType(diagnostic)
381-
}
382-
val errorSubstitutor = substitutorByMap(errorSubstitution, session)
383-
substitutor = substitutorByMap(createMapping(errorSubstitutor), session)
323+
}
324+
?: session.builtinTypes.nullableAnyType.coneType
325+
Pair(parameter.symbol, typeArgument)
384326
}
385327

386-
return substitutor
328+
return substitutorByMap(substitutionMap, session)
387329
}
388330

389331
private fun ConeKotlinType.containsReferenceToOtherTypeParameter(owner: FirTypeParameterRefsOwner): Boolean {

compiler/testData/codegen/box/sam/samWithInferenceToDefaultBounds.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// TARGET_BACKEND: JVM_IR
22
// IGNORE_BACKEND_K1: ANY
3+
// IGNORE_BACKEND_K2: ANY
34
// ISSUE: KT-67021
45

56
// FILE: Function.java
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
/main.kt:(63,64): error: Cannot infer type for type parameter 'B'. Specify it explicitly.
1+
/main.kt:(63,64): error: Cannot infer type for type parameter 'A'. Specify it explicitly.
22

3-
/main.kt:(117,139): error: Cannot infer type for type parameter 'B'. Specify it explicitly.
3+
/main.kt:(117,139): error: Cannot infer type for type parameter 'A'. Specify it explicitly.
44

5-
/main.kt:(170,171): error: Cannot infer type for type parameter 'B'. Specify it explicitly.
5+
/main.kt:(170,171): error: Cannot infer type for type parameter 'A'. Specify it explicitly.
66

7-
/main.kt:(173,174): error: Cannot infer type for type parameter 'C'. Specify it explicitly.
7+
/main.kt:(173,174): error: Cannot infer type for type parameter 'B'. Specify it explicitly.

compiler/testData/diagnostics/tests/j+k/samByProjectedType/javaSamTypeWithRecursionInBounds.fir.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
FILE: main.kt
22
public final fun test_1(): R|kotlin/Unit| {
3-
Q|A|.R|/A.foo*s|(<L> = SAM(foo@fun <anonymous>(a: <ERROR TYPE REF: Parameter B has a cycle in its upper bounds>): <ERROR TYPE REF: Parameter A has a cycle in its upper bounds> <inline=NoInline> {
3+
Q|A|.R|/A.foo*s|(<L> = SAM(foo@fun <anonymous>(a: <ERROR TYPE REF: Parameter A has a cycle in its upper bounds>): <ERROR TYPE REF: Parameter B has a cycle in its upper bounds> <inline=NoInline> {
44
Null(null)!!
55
}
66
))
77
}
88
public final fun test_2(): R|kotlin/Unit| {
9-
Q|A|.R|/A.foo*s|(<L> = SAM(foo@fun <anonymous>(it: <ERROR TYPE REF: Parameter B has a cycle in its upper bounds>): <ERROR TYPE REF: Parameter A has a cycle in its upper bounds> <inline=NoInline> {
9+
Q|A|.R|/A.foo*s|(<L> = SAM(foo@fun <anonymous>(it: <ERROR TYPE REF: Parameter A has a cycle in its upper bounds>): <ERROR TYPE REF: Parameter B has a cycle in its upper bounds> <inline=NoInline> {
1010
Null(null)!!
1111
}
1212
))
1313
}
1414
public final fun test_3(): R|kotlin/Unit| {
15-
Q|A|.R|/A.bar*s|(<L> = SAM(bar@fun <anonymous>(a: <ERROR TYPE REF: Parameter B has a cycle in its upper bounds>, b: <ERROR TYPE REF: Parameter C has a cycle in its upper bounds>): <ERROR TYPE REF: Parameter A has a cycle in its upper bounds> <inline=NoInline> {
15+
Q|A|.R|/A.bar*s|(<L> = SAM(bar@fun <anonymous>(a: <ERROR TYPE REF: Parameter A has a cycle in its upper bounds>, b: <ERROR TYPE REF: Parameter B has a cycle in its upper bounds>): <ERROR TYPE REF: Parameter C has a cycle in its upper bounds> <inline=NoInline> {
1616
Null(null)!!
1717
}
1818
))

compiler/testData/diagnostics/tests/j+k/samByProjectedType/noAdapterBecuaseOfRecursiveUpperBound.fir.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ public class A {
1818
// FILE: main.kt
1919
fun main() {
2020
A().foo {
21-
x ->
21+
<!CANNOT_INFER_PARAMETER_TYPE!>x<!> ->
2222
""
2323
}
2424

2525
A.bar {
26-
x ->
26+
<!CANNOT_INFER_PARAMETER_TYPE!>x<!> ->
2727
""
2828
}
29+
30+
A.bar(<!CANNOT_INFER_PARAMETER_TYPE, CANNOT_INFER_PARAMETER_TYPE!>Function<!> { <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> "" })
31+
A.bar(Function<CharSequence, Map<String, CharSequence>>{ x -> x[""] })
2932
}
3033

3134
/* GENERATED_FIR_TAGS: classDeclaration, flexibleType, funWithExtensionReceiver, functionDeclaration, functionalType,
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
FILE: main.kt
22
public final fun main(): R|kotlin/Unit| {
3-
R|/A.A|().R|/A.foo|(<L> = SAM(foo@fun <anonymous>(x: R|ft<kotlin/collections/MutableMap<kotlin/String!, kotlin/CharSequence!>, kotlin/collections/Map<kotlin/String!, kotlin/CharSequence!>?>|): R|kotlin/CharSequence!| <inline=NoInline> {
3+
R|/A.A|().R|/A.foo|(<L> = SAM(foo@fun <anonymous>(x: <ERROR TYPE REF: Parameter F has a cycle in its upper bounds>): R|kotlin/CharSequence!| <inline=NoInline> {
44
^ String()
55
}
66
))
7-
Q|A|.R|/A.bar*s|(<L> = SAM(bar@fun <anonymous>(x: R|ft<kotlin/collections/MutableMap<kotlin/String!, kotlin/CharSequence!>, kotlin/collections/Map<kotlin/String!, kotlin/CharSequence!>?>|): R|kotlin/CharSequence!| <inline=NoInline> {
7+
Q|A|.R|/A.bar*s|(<L> = SAM(bar@fun <anonymous>(x: <ERROR TYPE REF: Parameter F has a cycle in its upper bounds>): R|kotlin/CharSequence!| <inline=NoInline> {
88
^ String()
99
}
1010
))
11+
Q|A|.R|/A.bar*s<CS errors: /A.bar>#|(R|/Function|<<ERROR TYPE REF: Cannot infer argument for type parameter E>, <ERROR TYPE REF: Cannot infer argument for type parameter F>>(<L> = Function@fun <anonymous>(x: <ERROR TYPE REF: Cannot infer argument for type parameter F>): <ERROR TYPE REF: Cannot infer argument for type parameter E> <inline=NoInline> {
12+
^ String()
13+
}
14+
))
15+
Q|A|.R|/A.bar*s|(R|/Function|<R|kotlin/CharSequence|, R|kotlin/collections/Map<kotlin/String, kotlin/CharSequence>|>(<L> = Function@fun <anonymous>(x: R|ft<kotlin/collections/Map<kotlin/String, kotlin/CharSequence>, kotlin/collections/Map<kotlin/String, kotlin/CharSequence>?>|): R|kotlin/CharSequence!| <inline=NoInline> {
16+
^ R|<local>/x|.R|SubstitutionOverride<kotlin/collections/Map.get: R|kotlin/CharSequence?|>|(String())
17+
}
18+
))
1119
}

compiler/testData/diagnostics/tests/j+k/samByProjectedType/noAdapterBecuaseOfRecursiveUpperBound.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ fun main() {
2626
<!CANNOT_INFER_PARAMETER_TYPE!>x<!> ->
2727
""
2828
}<!>
29+
30+
A.bar(<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Function<!> { <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> "" })
31+
A.bar(Function<CharSequence, Map<String, CharSequence>>{ x -> x[""] })
2932
}
3033

3134
/* GENERATED_FIR_TAGS: classDeclaration, flexibleType, funWithExtensionReceiver, functionDeclaration, functionalType,

0 commit comments

Comments
 (0)