Skip to content

Commit b7849da

Browse files
committed
[NI] Introduce flag to change constraint system for overload resolution
This commit doesn't change behaviour of any inference algorithm, it introduces opportunity to switch constraint system that is used for overload resolution and fix problematic cases by changing one enum entry. Due to fundamental changes, there are cases where a new inference algorithm reports overload resolution ambiguity errors (#KT-31670, #KT-31758), which is correct from its point of view. However, this is a breaking change and to really make it, we should be very confident and have enough motivation for it, therefore, we don't change behavior now in order to collect more examples (if there are any). And if we find a lot of erroneous examples, we'll be able to change the behavior quite simply
1 parent e7064f5 commit b7849da

20 files changed

+377
-2
lines changed

compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/frontend/src/org/jetbrains/kotlin/config/AnalysisFlags.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,7 @@ object AnalysisFlags {
2929

3030
@JvmStatic
3131
val allowResultReturnType by AnalysisFlag.Delegates.Boolean
32+
33+
@JvmStatic
34+
val constraintSystemForOverloadResolution by AnalysisFlag.Delegates.ConstraintSystemForOverloadResolution
3235
}

compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.jetbrains.kotlin.resolve.calls.tower
1818

1919
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
20+
import org.jetbrains.kotlin.config.AnalysisFlags
2021
import org.jetbrains.kotlin.config.LanguageVersionSettings
2122
import org.jetbrains.kotlin.descriptors.CallableDescriptor
2223
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall
2829
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isSuperOrDelegatingConstructorCall
2930
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
3031
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionStatelessCallbacks
32+
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
3133
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
3234
import org.jetbrains.kotlin.resolve.calls.inference.components.SimpleConstraintSystemImpl
3335
import org.jetbrains.kotlin.resolve.calls.inference.isCoroutineCallWithAdditionalInference
@@ -88,6 +90,9 @@ class KotlinResolutionStatelessCallbacksImpl(
8890
override fun createConstraintSystemForOverloadResolution(
8991
constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns
9092
): SimpleConstraintSystem {
91-
return SimpleConstraintSystemImpl(constraintInjector, builtIns)
93+
return if (languageVersionSettings.getFlag(AnalysisFlags.constraintSystemForOverloadResolution).forNewInference())
94+
SimpleConstraintSystemImpl(constraintInjector, builtIns)
95+
else
96+
ConstraintSystemBuilderImpl.forSpecificity()
9297
}
9398
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// !WITH_NEW_INFERENCE
2+
// !CONSTRAINT_SYSTEM_FOR_OVERLOAD_RESOLUTION: CONSTRAINT_SYSTEM_FOR_NEW_INFERENCE
3+
4+
open class A<T>(val value: T)
5+
class B<T>(value: T) : A<T>(value)
6+
7+
fun <T> A<T>.foo(block: (T?) -> Unit) {
8+
block(value)
9+
}
10+
fun <T> B<T>.foo(block: (T) -> Unit) {
11+
block(value)
12+
}
13+
14+
fun main() {
15+
B("string").<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!> { }
16+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package
2+
3+
public fun main(): kotlin.Unit
4+
public fun </*0*/ T> A<T>.foo(/*0*/ block: (T?) -> kotlin.Unit): kotlin.Unit
5+
public fun </*0*/ T> B<T>.foo(/*0*/ block: (T) -> kotlin.Unit): kotlin.Unit
6+
7+
public open class A</*0*/ T> {
8+
public constructor A</*0*/ T>(/*0*/ value: T)
9+
public final val value: T
10+
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
11+
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
12+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
13+
}
14+
15+
public final class B</*0*/ T> : A<T> {
16+
public constructor B</*0*/ T>(/*0*/ value: T)
17+
public final override /*1*/ /*fake_override*/ val value: T
18+
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
19+
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
20+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
21+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// !WITH_NEW_INFERENCE
2+
// !CONSTRAINT_SYSTEM_FOR_OVERLOAD_RESOLUTION: CONSTRAINT_SYSTEM_FOR_OLD_INFERENCE
3+
4+
open class A<T>(val value: T)
5+
class B<T>(value: T) : A<T>(value)
6+
7+
fun <T> A<T>.foo(block: (T?) -> Unit) {
8+
block(value)
9+
}
10+
fun <T> B<T>.foo(block: (T) -> Unit) {
11+
block(value)
12+
}
13+
14+
fun main() {
15+
B("string").foo { }
16+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package
2+
3+
public fun main(): kotlin.Unit
4+
public fun </*0*/ T> A<T>.foo(/*0*/ block: (T?) -> kotlin.Unit): kotlin.Unit
5+
public fun </*0*/ T> B<T>.foo(/*0*/ block: (T) -> kotlin.Unit): kotlin.Unit
6+
7+
public open class A</*0*/ T> {
8+
public constructor A</*0*/ T>(/*0*/ value: T)
9+
public final val value: T
10+
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
11+
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
12+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
13+
}
14+
15+
public final class B</*0*/ T> : A<T> {
16+
public constructor B</*0*/ T>(/*0*/ value: T)
17+
public final override /*1*/ /*fake_override*/ val value: T
18+
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
19+
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
20+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
21+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// !WITH_NEW_INFERENCE
2+
// !CONSTRAINT_SYSTEM_FOR_OVERLOAD_RESOLUTION: CONSTRAINT_SYSTEM_FOR_NEW_INFERENCE
3+
// !DIAGNOSTICS: -UNUSED_PARAMETER
4+
5+
// FILE: a.kt
6+
7+
package a
8+
9+
enum class A { A1 }
10+
11+
fun <T : Enum<T>> foo(arg: T.() -> Unit) = 1
12+
13+
// FILE: b.kt
14+
15+
package b
16+
17+
fun <T : Any> foo(arg: T.() -> Unit) = 2
18+
19+
// FILE: test.kt
20+
21+
import a.*
22+
import b.*
23+
24+
fun test() {
25+
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!><A> { }
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package
2+
3+
public fun test(): kotlin.Unit
4+
5+
package a {
6+
public fun </*0*/ T : kotlin.Enum<T>> foo(/*0*/ arg: T.() -> kotlin.Unit): kotlin.Int
7+
8+
public final enum class A : kotlin.Enum<a.A> {
9+
enum entry A1
10+
11+
private constructor A()
12+
public final override /*1*/ /*fake_override*/ val name: kotlin.String
13+
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
14+
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
15+
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: a.A): kotlin.Int
16+
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
17+
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
18+
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<a.A!>!
19+
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
20+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
21+
22+
// Static members
23+
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): a.A
24+
public final /*synthesized*/ fun values(): kotlin.Array<a.A>
25+
}
26+
}
27+
28+
package b {
29+
public fun </*0*/ T : kotlin.Any> foo(/*0*/ arg: T.() -> kotlin.Unit): kotlin.Int
30+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// !WITH_NEW_INFERENCE
2+
// !CONSTRAINT_SYSTEM_FOR_OVERLOAD_RESOLUTION: CONSTRAINT_SYSTEM_FOR_OLD_INFERENCE
3+
// !DIAGNOSTICS: -UNUSED_PARAMETER
4+
5+
// FILE: a.kt
6+
7+
package a
8+
9+
enum class A { A1 }
10+
11+
fun <T : Enum<T>> foo(arg: T.() -> Unit) = 1
12+
13+
// FILE: b.kt
14+
15+
package b
16+
17+
fun <T : Any> foo(arg: T.() -> Unit) = 2
18+
19+
// FILE: test.kt
20+
21+
import a.*
22+
import b.*
23+
24+
fun test() {
25+
foo<A> { }
26+
}

0 commit comments

Comments
 (0)