Added missing specificity comparator to FIR
This is required to correctly resolve overloading in cases when we need to find most specific alternative in Java between int and Integer.
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
// FULL_JDK
|
||||
import java.lang.Integer.getInteger
|
||||
|
||||
fun foo() {
|
||||
getInteger("text", 239)
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
FILE: FlexiblePrimitiveOverloading.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
R|java/lang/Integer.getInteger|(String(text), Int(239))
|
||||
}
|
||||
+5
@@ -725,6 +725,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/FieldSubstitution.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("FlexiblePrimitiveOverloading.kt")
|
||||
public void testFlexiblePrimitiveOverloading() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/FlexiblePrimitiveOverloading.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("flexibleTypeAliases.kt")
|
||||
public void testFlexibleTypeAliases() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/flexibleTypeAliases.kt");
|
||||
|
||||
@@ -8,6 +8,7 @@ dependencies {
|
||||
implementation(project(":compiler:fir:cones"))
|
||||
implementation(project(":compiler:fir:tree"))
|
||||
implementation(project(":compiler:fir:resolve"))
|
||||
implementation(project(":compiler:frontend.java"))
|
||||
}
|
||||
|
||||
|
||||
|
||||
+8
-4
@@ -10,14 +10,18 @@ import org.jetbrains.kotlin.fir.resolve.calls.ConeCompositeConflictResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ConeOverloadConflictResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmTypeSpecificityComparator
|
||||
|
||||
object JvmCallConflictResolverFactory : ConeCallConflictResolverFactory() {
|
||||
override fun create(
|
||||
typeSpecificityComparator: TypeSpecificityComparator,
|
||||
components: InferenceComponents
|
||||
) = ConeCompositeConflictResolver(
|
||||
ConeOverloadConflictResolver(TypeSpecificityComparator.NONE, components),
|
||||
ConeEquivalentCallConflictResolver(TypeSpecificityComparator.NONE, components)
|
||||
)
|
||||
): ConeCompositeConflictResolver {
|
||||
val specificityComparator = JvmTypeSpecificityComparator(components.ctx)
|
||||
return ConeCompositeConflictResolver(
|
||||
ConeOverloadConflictResolver(specificityComparator, components),
|
||||
ConeEquivalentCallConflictResolver(specificityComparator, components)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -379,7 +379,10 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.isPrimitiveType(): Boolean {
|
||||
return false //TODO
|
||||
if (this is ConeClassLikeType) {
|
||||
return StandardClassIds.primitiveTypes.contains(this.lookupTag.classId)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.isStubType(): Boolean {
|
||||
|
||||
+7
-1
@@ -18,9 +18,15 @@ package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate
|
||||
|
||||
class JvmTypeSpecificityComparator(val context: TypeSystemInferenceExtensionContextDelegate) : TypeSpecificityComparator {
|
||||
/**
|
||||
* We should use delegate context for DI in old frontend. For the FIR we don't have context delegate, so we should use parent class.
|
||||
*/
|
||||
class JvmTypeSpecificityComparatorDelegate(override val context: TypeSystemInferenceExtensionContextDelegate) : JvmTypeSpecificityComparator(context)
|
||||
|
||||
open class JvmTypeSpecificityComparator(open val context: TypeSystemInferenceExtensionContext) : TypeSpecificityComparator {
|
||||
|
||||
override fun isDefinitelyLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean = with(context) {
|
||||
val simpleGeneral = general.asSimpleType()
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
container.useImpl<InlinePlatformCompatibilityChecker>()
|
||||
container.useImpl<JvmModuleAccessibilityChecker>()
|
||||
container.useImpl<JvmModuleAccessibilityChecker.ClassifierUsage>()
|
||||
container.useImpl<JvmTypeSpecificityComparator>()
|
||||
container.useImpl<JvmTypeSpecificityComparatorDelegate>()
|
||||
container.useImpl<JvmPlatformOverloadsSpecificityComparator>()
|
||||
container.useImpl<JvmDefaultSuperCallChecker>()
|
||||
container.useImpl<JvmSamConversionOracle>()
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
// JAVAC_EXPECTED_FILE
|
||||
// FILE: B.java
|
||||
public interface B<T1, T2> {
|
||||
double put(int x, double y);
|
||||
T2 put(T1 x, T2 y);
|
||||
}
|
||||
// FILE: A.java
|
||||
import java.util.HashMap;
|
||||
|
||||
public class A extends HashMap<Integer, Double> implements B<Integer, Double> {
|
||||
public double put(int x, double y) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double put(Integer key, Double value) {
|
||||
return super.put(key, value);
|
||||
}
|
||||
}
|
||||
// FILE: main.kt
|
||||
fun test(){
|
||||
val o = A()
|
||||
o.<!AMBIGUITY!>put<!>(1, 2.0)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JAVAC_EXPECTED_FILE
|
||||
// FILE: B.java
|
||||
public interface B<T1, T2> {
|
||||
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
// FILE: AbstractSpecializedMap.java
|
||||
public abstract class AbstractSpecializedMap implements java.util.Map<Integer, Double> {
|
||||
public abstract double put(int x, double y);
|
||||
public abstract double remove(int k);
|
||||
public abstract double get(int k);
|
||||
|
||||
public abstract boolean containsKey(int k);
|
||||
public boolean containsKey(Object x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract boolean containsValue(double v);
|
||||
public boolean containsValue(Object x) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: SpecializedMap.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class SpecializedMap extends AbstractSpecializedMap {
|
||||
public double put(int x, double y) {
|
||||
return 123.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double get(Object key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double put(Integer key, Double value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public double remove(int k) {
|
||||
return 456.0;
|
||||
}
|
||||
|
||||
|
||||
public Double remove(Object ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public double get(int k) {
|
||||
return 789.0;
|
||||
}
|
||||
|
||||
public boolean containsKey(int k) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean containsValue(double v) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends Integer, ? extends Double> m) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Integer> keySet() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Double> values() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<Integer, Double>> entrySet() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun foo(x: SpecializedMap) {
|
||||
x.containsKey(1)
|
||||
x.containsKey(null)
|
||||
|
||||
x.get(2)
|
||||
x.get(null)
|
||||
|
||||
x.remove(3)
|
||||
x.remove(null)
|
||||
|
||||
x.<!AMBIGUITY!>put<!>(4, 5.0)
|
||||
x.put(4, null)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: AbstractSpecializedMap.java
|
||||
public abstract class AbstractSpecializedMap implements java.util.Map<Integer, Double> {
|
||||
public abstract double put(int x, double y);
|
||||
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
// !CHECK_TYPE
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// FILE: p/J.java
|
||||
|
||||
package p;
|
||||
|
||||
public class J {
|
||||
public interface A {}
|
||||
public static A foo(int s);
|
||||
|
||||
public interface B {}
|
||||
public static B foo(Integer s);
|
||||
|
||||
public static Integer getInteger();
|
||||
}
|
||||
|
||||
// FILE: k.kt
|
||||
|
||||
import p.*
|
||||
import p.J.*
|
||||
|
||||
class C
|
||||
|
||||
fun foo(i: Int?) : C = null!!
|
||||
|
||||
fun test(i: Int, ni: Int?) {
|
||||
checkSubtype<C>(foo(2))
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><J.A>(J.<!AMBIGUITY!>foo<!>(2))
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><J.A>(J.<!AMBIGUITY!>foo<!>(i))
|
||||
checkSubtype<J.B>(J.foo(ni))
|
||||
checkSubtype<C>(foo(ni))
|
||||
checkSubtype<J.B>(J.foo(ni))
|
||||
|
||||
foo(J.getInteger())
|
||||
J.<!AMBIGUITY!>foo<!>(J.getInteger())
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !CHECK_TYPE
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// FILE: p/J.java
|
||||
|
||||
Reference in New Issue
Block a user