Extensible specificity expressed as a type capability
This commit is contained in:
+6
-14
@@ -25,9 +25,7 @@ import org.jetbrains.jet.lang.resolve.OverrideResolver;
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||||
import org.jetbrains.jet.lang.types.BoundsSubstitutor;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
|
|
||||||
@@ -240,21 +238,15 @@ public class OverloadingConflictResolver {
|
|||||||
|
|
||||||
private boolean typeMoreSpecific(@NotNull JetType specific, @NotNull JetType general) {
|
private boolean typeMoreSpecific(@NotNull JetType specific, @NotNull JetType general) {
|
||||||
boolean isSubtype = JetTypeChecker.DEFAULT.isSubtypeOf(specific, general) ||
|
boolean isSubtype = JetTypeChecker.DEFAULT.isSubtypeOf(specific, general) ||
|
||||||
numericTypeMoreSpecific(specific, general);
|
numericTypeMoreSpecific(specific, general);
|
||||||
|
|
||||||
if (!isSubtype) return false;
|
if (!isSubtype) return false;
|
||||||
|
|
||||||
boolean specificIsFlexible = specific.isFlexible();
|
Specificity.Relation sThanG = TypesPackage.getSpecificityRelationTo(specific, general);
|
||||||
boolean generalIsFlexible = general.isFlexible();
|
Specificity.Relation gThanS = TypesPackage.getSpecificityRelationTo(general, specific);
|
||||||
|
if (sThanG == Specificity.Relation.LESS_SPECIFIC && gThanS != Specificity.Relation.LESS_SPECIFIC) {
|
||||||
if (specificIsFlexible && !generalIsFlexible) {
|
|
||||||
// Int! lessSpecific Int
|
|
||||||
// Int! >< Int?
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!specificIsFlexible && generalIsFlexible) {
|
|
||||||
// Int? >< Int!
|
|
||||||
if (specific.isNullable()) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ public class J {
|
|||||||
|
|
||||||
public interface B {}
|
public interface B {}
|
||||||
public static B foo(Integer s);
|
public static B foo(Integer s);
|
||||||
|
|
||||||
|
public static Integer getInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: k.kt
|
// FILE: k.kt
|
||||||
@@ -25,5 +27,8 @@ fun test(i: Int, ni: Int?) {
|
|||||||
foo(i) : J.A
|
foo(i) : J.A
|
||||||
J.foo(ni) : J.B
|
J.foo(ni) : J.B
|
||||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(ni)
|
<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(ni)
|
||||||
|
|
||||||
|
foo(J.getInteger())
|
||||||
|
J.foo(J.getInteger())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// FILE: p/Super.java
|
||||||
|
package p;
|
||||||
|
|
||||||
|
public interface Super {}
|
||||||
|
|
||||||
|
// FILE: p/Sub.java
|
||||||
|
package p;
|
||||||
|
|
||||||
|
public interface Sub extends Super {}
|
||||||
|
|
||||||
|
// FILE: p/Util.java
|
||||||
|
|
||||||
|
package p;
|
||||||
|
|
||||||
|
public abstract class Util {
|
||||||
|
public abstract void foo(String s, Super sup)
|
||||||
|
public void foo(String s, Sub sub) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: k.kt
|
||||||
|
|
||||||
|
import p.*
|
||||||
|
|
||||||
|
class C: Util() {
|
||||||
|
override fun foo(s: String, sub: Super) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(sub: Sub) {
|
||||||
|
C().foo("", sub)
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun foo(/*0*/ sub: p.Sub): kotlin.Unit
|
||||||
|
|
||||||
|
internal final class C : p.Util {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun foo(/*0*/ s: kotlin.String, /*1*/ sub: p.Super): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun foo(/*0*/ s: kotlin.String!, /*1*/ sub: p.Sub!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -7863,6 +7863,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overloadingForSubclass.kt")
|
||||||
|
public void testOverloadingForSubclass() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/methodCall/overloadingForSubclass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("sam.kt")
|
@TestMetadata("sam.kt")
|
||||||
public void testSam() throws Exception {
|
public void testSam() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/methodCall/sam.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/methodCall/sam.kt");
|
||||||
|
|||||||
+17
-3
@@ -34,8 +34,6 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker
|
|||||||
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
|
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
|
||||||
import org.jetbrains.jet.lang.resolve.java.lazy.types.Flexibility.*
|
import org.jetbrains.jet.lang.resolve.java.lazy.types.Flexibility.*
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
|
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName
|
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
|
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames
|
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames
|
||||||
|
|
||||||
class LazyJavaTypeResolver(
|
class LazyJavaTypeResolver(
|
||||||
@@ -273,7 +271,7 @@ class LazyJavaTypeResolver(
|
|||||||
public open class FlexibleJavaClassifierType protected (
|
public open class FlexibleJavaClassifierType protected (
|
||||||
lowerBound: JetType,
|
lowerBound: JetType,
|
||||||
upperBound: JetType
|
upperBound: JetType
|
||||||
) : DelegatingFlexibleType(lowerBound, upperBound), CustomTypeVariable {
|
) : DelegatingFlexibleType(lowerBound, upperBound), CustomTypeVariable, Specificity {
|
||||||
public class object {
|
public class object {
|
||||||
public fun create(lowerBound: JetType, upperBound: JetType): JetType {
|
public fun create(lowerBound: JetType, upperBound: JetType): JetType {
|
||||||
if (lowerBound == upperBound) return lowerBound
|
if (lowerBound == upperBound) return lowerBound
|
||||||
@@ -294,6 +292,22 @@ class LazyJavaTypeResolver(
|
|||||||
return if (replacement.isFlexible()) replacement
|
return if (replacement.isFlexible()) replacement
|
||||||
else FlexibleJavaClassifierType(TypeUtils.makeNotNullable(replacement), TypeUtils.makeNullable(replacement))
|
else FlexibleJavaClassifierType(TypeUtils.makeNotNullable(replacement), TypeUtils.makeNullable(replacement))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSpecificityRelationTo(otherType: JetType): Specificity.Relation {
|
||||||
|
// For primitive types we have to take care of the case when there are two overloaded methods like
|
||||||
|
// foo(int) and foo(Integer)
|
||||||
|
// if we do not discriminate one of them, any call to foo(kotlin.Int) will result in overload resolution ambiguity
|
||||||
|
// so, for such cases, we discriminate Integer in favour of int
|
||||||
|
if (!KotlinBuiltIns.getInstance().isPrimitiveType(otherType) || !KotlinBuiltIns.getInstance().isPrimitiveType(getLowerBound())) {
|
||||||
|
return Specificity.Relation.DONT_KNOW
|
||||||
|
}
|
||||||
|
// Int! >< Int?
|
||||||
|
if (otherType.isFlexible()) return Specificity.Relation.DONT_KNOW
|
||||||
|
// Int? >< Int!
|
||||||
|
if (otherType.isNullable()) return Specificity.Relation.DONT_KNOW
|
||||||
|
// Int! lessSpecific Int
|
||||||
|
return Specificity.Relation.LESS_SPECIFIC
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -16,6 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.types
|
package org.jetbrains.jet.lang.types
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
|
||||||
|
|
||||||
public trait TypeCapability
|
public trait TypeCapability
|
||||||
|
|
||||||
|
public trait Specificity : TypeCapability {
|
||||||
|
|
||||||
|
public enum class Relation {
|
||||||
|
LESS_SPECIFIC
|
||||||
|
MORE_SPECIFIC
|
||||||
|
DONT_KNOW
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun getSpecificityRelationTo(otherType: JetType): Relation
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JetType.getSpecificityRelationTo(otherType: JetType) = this.getCapability(javaClass<Specificity>())?.getSpecificityRelationTo(otherType) ?: Specificity.Relation.DONT_KNOW
|
||||||
Reference in New Issue
Block a user