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:
Alexander Podkhalyuzin
2020-04-28 17:17:31 +03:00
parent b6b8dd1eab
commit 6372c01e49
14 changed files with 39 additions and 181 deletions
@@ -0,0 +1,6 @@
// FULL_JDK
import java.lang.Integer.getInteger
fun foo() {
getInteger("text", 239)
}
@@ -0,0 +1,4 @@
FILE: FlexiblePrimitiveOverloading.kt
public final fun foo(): R|kotlin/Unit| {
R|java/lang/Integer.getInteger|(String(text), Int(239))
}
@@ -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");
+1
View File
@@ -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"))
}
@@ -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 {
@@ -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()
@@ -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> {
@@ -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);
@@ -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