diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmTypeSpecificityComparator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmTypeSpecificityComparator.kt new file mode 100644 index 00000000000..ea684e6f7c3 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmTypeSpecificityComparator.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.resolve.jvm + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.flexibility +import org.jetbrains.kotlin.types.isFlexible + +object JvmTypeSpecificityComparator : TypeSpecificityComparator { + + override fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType): Boolean { + if (!specific.isFlexible() || general.isFlexible()) return false + + // general is inflexible + val flexibility = specific.flexibility() + + // 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.isPrimitiveType(general) || !KotlinBuiltIns.isPrimitiveType(flexibility.lowerBound)) { + return false + } + + // Int? >< Int! + if (general.isMarkedNullable) return false + // Int! lessSpecific Int + return true + } +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index 0f8f8cf9cad..3b7454dbe4e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -18,11 +18,13 @@ package org.jetbrains.kotlin.resolve.jvm.platform import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.useImpl +import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.jvm.RuntimeAssertionsTypeChecker import org.jetbrains.kotlin.load.kotlin.JavaAnnotationCallChecker import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeFunChecker import org.jetbrains.kotlin.resolve.PlatformConfigurator import org.jetbrains.kotlin.resolve.jvm.JvmOverloadFilter +import org.jetbrains.kotlin.resolve.jvm.JvmTypeSpecificityComparator import org.jetbrains.kotlin.resolve.jvm.checkers.* import org.jetbrains.kotlin.synthetic.JavaSyntheticScopes import org.jetbrains.kotlin.types.DynamicTypesSettings @@ -79,5 +81,6 @@ object JvmPlatformConfigurator : PlatformConfigurator( container.useImpl() container.useImpl() + container.useInstance(JvmTypeSpecificityComparator) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadChecker.kt index 8656d331661..c3b26bdd288 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadChecker.kt @@ -21,17 +21,14 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.calls.results.FlatSignature -import org.jetbrains.kotlin.resolve.calls.results.SpecificityComparisonCallbacks -import org.jetbrains.kotlin.resolve.calls.results.isSignatureNotLessSpecific -import org.jetbrains.kotlin.resolve.calls.results.varargParameterPosition +import org.jetbrains.kotlin.resolve.calls.results.* import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.singletonOrEmptyList -class OverloadChecker { +class OverloadChecker(val specificityComparator: TypeSpecificityComparator) { /** * Does not check names. */ @@ -64,8 +61,8 @@ class OverloadChecker { val aSignature = FlatSignature.createFromCallableDescriptor(a) val bSignature = FlatSignature.createFromCallableDescriptor(b) - val aIsNotLessSpecificThanB = isSignatureNotLessSpecific(aSignature, bSignature, OverloadabilitySpecificityCallbacks) - val bIsNotLessSpecificThanA = isSignatureNotLessSpecific(bSignature, aSignature, OverloadabilitySpecificityCallbacks) + val aIsNotLessSpecificThanB = isSignatureNotLessSpecific(aSignature, bSignature, OverloadabilitySpecificityCallbacks, specificityComparator) + val bIsNotLessSpecificThanA = isSignatureNotLessSpecific(bSignature, aSignature, OverloadabilitySpecificityCallbacks, specificityComparator) return !(aIsNotLessSpecificThanB && bIsNotLessSpecificThanA) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt index 20b31c95e99..aee0714ae10 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.ModuleParameters import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.checkers.* +import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes import org.jetbrains.kotlin.resolve.validation.DeprecatedSymbolValidator import org.jetbrains.kotlin.resolve.validation.InfixValidator @@ -50,6 +51,7 @@ abstract class TargetPlatform( override fun configure(container: StorageComponentContainer) { super.configure(container) container.useInstance(SyntheticScopes.Empty) + container.useInstance(TypeSpecificityComparator.NONE) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignatureSpecificity.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignatureSpecificity.kt index 0ebd9b90c55..d4a92ec3a21 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignatureSpecificity.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignatureSpecificity.kt @@ -20,8 +20,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.CallHandle import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.valueParameterPosition -import org.jetbrains.kotlin.types.Flexibility -import org.jetbrains.kotlin.types.Flexibility.SpecificityRelation import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance @@ -31,10 +29,19 @@ interface SpecificityComparisonCallbacks { fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean } +interface TypeSpecificityComparator { + fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType): Boolean + + object NONE: TypeSpecificityComparator { + override fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType) = false + } +} + fun isSignatureNotLessSpecific( specific: FlatSignature, general: FlatSignature, callbacks: SpecificityComparisonCallbacks, + specificityComparator: TypeSpecificityComparator, callHandle: CallHandle = CallHandle.NONE ): Boolean { if (specific.hasExtensionReceiver != general.hasExtensionReceiver) return false @@ -48,7 +55,7 @@ fun isSignatureNotLessSpecific( for ((specificType, generalType) in specific.valueParameterTypes.zip(general.valueParameterTypes)) { if (specificType == null || generalType == null) continue - if (isDefinitelyLessSpecificByTypeSpecificity(specificType, generalType)) { + if (specificityComparator.isDefinitelyLessSpecific(specificType, generalType)) { return false } @@ -69,13 +76,3 @@ fun isSignatureNotLessSpecific( val constraintSystem = constraintSystemBuilder.build() return !constraintSystem.status.hasContradiction() } - -private fun KotlinType.getSpecificityRelationTo(otherType: KotlinType) = - this.getCapability(Flexibility::class.java)?.getSpecificityRelationTo(otherType) ?: Flexibility.SpecificityRelation.DONT_KNOW - -private fun isDefinitelyLessSpecificByTypeSpecificity(specific: KotlinType, general: KotlinType): Boolean { - val sThanG = specific.getSpecificityRelationTo(general) - val gThanS = general.getSpecificityRelationTo(specific) - return sThanG == SpecificityRelation.LESS_SPECIFIC && - gThanS != SpecificityRelation.LESS_SPECIFIC -} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt index aacf49a2a85..92712cd45b3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,10 @@ import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils -class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) { +class OverloadingConflictResolver( + private val builtIns: KotlinBuiltIns, + private val specificityComparator: TypeSpecificityComparator +) { fun findMaximallySpecific( candidates: Set>, @@ -157,7 +160,7 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) { if (isGeneric1 && isGeneric2) return false } - return isSignatureNotLessSpecific(call1, call2, SpecificityComparisonWithNumerics, call1.callHandle()) + return isSignatureNotLessSpecific(call1, call2, SpecificityComparisonWithNumerics, specificityComparator, call1.callHandle()) } private val SpecificityComparisonWithNumerics = object : SpecificityComparisonCallbacks { @@ -243,7 +246,7 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) { val fSignature = FlatSignature.createFromCallableDescriptor(f) val gSignature = FlatSignature.createFromCallableDescriptor(g) - return isSignatureNotLessSpecific(fSignature, gSignature, SpecificityComparisonWithNumerics) + return isSignatureNotLessSpecific(fSignature, gSignature, SpecificityComparisonWithNumerics, specificityComparator) } private fun isNotLessSpecificCallableReference(f: CallableDescriptor, g: CallableDescriptor): Boolean = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingUtils.java index a4d3b446a34..18a60e57545 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingUtils.java @@ -82,7 +82,10 @@ public class ExpressionTypingUtils { @NotNull public static LexicalWritableScope newWritableScopeImpl( - @NotNull ExpressionTypingContext context, @NotNull LexicalScopeKind scopeKind, @NotNull OverloadChecker overloadChecker) { + @NotNull ExpressionTypingContext context, + @NotNull LexicalScopeKind scopeKind, + @NotNull OverloadChecker overloadChecker + ) { return new LexicalWritableScope(context.scope, context.scope.getOwnerDescriptor(), false, null, new TraceBasedLocalRedeclarationChecker(context.trace, overloadChecker), scopeKind); } diff --git a/compiler/tests/org/jetbrains/kotlin/types/KotlinOverloadTest.java b/compiler/tests/org/jetbrains/kotlin/types/KotlinOverloadTest.java index 7ab61f1aa7b..b30cd1d6f5e 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/KotlinOverloadTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/KotlinOverloadTest.java @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.psi.KtNamedFunction; import org.jetbrains.kotlin.psi.KtPsiFactoryKt; import org.jetbrains.kotlin.resolve.FunctionDescriptorResolver; import org.jetbrains.kotlin.resolve.OverloadChecker; +import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory; import org.jetbrains.kotlin.resolve.scopes.LexicalScope; import org.jetbrains.kotlin.test.ConfigurationKind; @@ -34,7 +35,7 @@ import org.jetbrains.kotlin.tests.di.InjectionKt; public class KotlinOverloadTest extends KotlinTestWithEnvironment { private final ModuleDescriptor root = KotlinTestUtils.createEmptyModule(""); private FunctionDescriptorResolver functionDescriptorResolver; - private final OverloadChecker overloadChecker = new OverloadChecker(); + private final OverloadChecker overloadChecker = new OverloadChecker(TypeSpecificityComparator.NONE.INSTANCE); @Override protected KotlinCoreEnvironment createEnvironment() { @@ -155,8 +156,6 @@ public class KotlinOverloadTest extends KotlinTestWithEnvironment { FunctionDescriptor a = makeFunction(funA); FunctionDescriptor b = makeFunction(funB); - - boolean aOverloadableWithB = overloadChecker.isOverloadable(a, b); assertEquals(expectedIsError, !aOverloadableWithB); diff --git a/compiler/tests/org/jetbrains/kotlin/types/TypeSubstitutorTest.java b/compiler/tests/org/jetbrains/kotlin/types/TypeSubstitutorTest.java index a8f41293cbc..35b52f7c249 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/TypeSubstitutorTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/TypeSubstitutorTest.java @@ -40,6 +40,7 @@ import org.jetbrains.kotlin.psi.KtPsiFactoryKt; import org.jetbrains.kotlin.psi.KtTypeReference; import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.resolve.*; +import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator; import org.jetbrains.kotlin.resolve.lazy.LazyResolveTestUtil; import org.jetbrains.kotlin.resolve.scopes.*; import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt; @@ -90,7 +91,8 @@ public class TypeSubstitutorTest extends KotlinTestWithEnvironment { LexicalScope topLevelScope = trace.get(BindingContext.LEXICAL_SCOPE, jetFile); final ClassifierDescriptor contextClass = ScopeUtilsKt.findClassifier(topLevelScope, Name.identifier("___Context"), NoLookupLocation.FROM_TEST); assert contextClass instanceof ClassDescriptor; - LocalRedeclarationChecker redeclarationChecker = new ThrowingLocalRedeclarationChecker(new OverloadChecker()); + LocalRedeclarationChecker redeclarationChecker = new ThrowingLocalRedeclarationChecker(new OverloadChecker( + TypeSpecificityComparator.NONE.INSTANCE)); LexicalScope typeParameters = new LexicalScopeImpl(topLevelScope, module, false, null, LexicalScopeKind.SYNTHETIC, redeclarationChecker, new Function1() { diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt index 98fd5370ab2..08b8623d942 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.load.java.lazy.types -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -34,9 +33,7 @@ import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.Flexibility.SpecificityRelation import org.jetbrains.kotlin.types.Variance.* -import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.createProjection import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections @@ -315,21 +312,6 @@ class LazyJavaTypeResolver( else create(replacement, TypeUtils.makeNullable(replacement)) } - override fun getSpecificityRelationTo(otherType: KotlinType): SpecificityRelation { - // 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.isPrimitiveType(otherType) || !KotlinBuiltIns.isPrimitiveType(lowerBound)) { - return SpecificityRelation.DONT_KNOW - } - // Int! >< Int? - if (otherType.isFlexible()) return SpecificityRelation.DONT_KNOW - // Int? >< Int! - if (otherType.isMarkedNullable) return SpecificityRelation.DONT_KNOW - // Int! lessSpecific Int - return SpecificityRelation.LESS_SPECIFIC - } } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt index ebdb48bf256..3471af803be 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.types.Flexibility.SpecificityRelation import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.typeUtil.builtIns @@ -53,10 +52,6 @@ object DynamicTypeFactory : FlexibleTypeFactory { override val delegateType: KotlinType get() = upperBound - override fun getSpecificityRelationTo(otherType: KotlinType): SpecificityRelation { - return if (!otherType.isDynamic()) SpecificityRelation.LESS_SPECIFIC else SpecificityRelation.DONT_KNOW - } - override fun makeNullableAsSpecified(nullable: Boolean): KotlinType { // Nullability has no effect on dynamics return createDynamicType(delegateType.builtIns) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt index 4b6e630df32..e3930e7b341 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt @@ -49,13 +49,6 @@ interface Flexibility : TypeCapability, SubtypingRepresentatives { fun makeNullableAsSpecified(nullable: Boolean): KotlinType - enum class SpecificityRelation { - LESS_SPECIFIC, - MORE_SPECIFIC, - DONT_KNOW - } - - fun getSpecificityRelationTo(otherType: KotlinType): SpecificityRelation } fun KotlinType.isFlexible(): Boolean = this.getCapability(Flexibility::class.java) != null diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt index 1ccae7d13c4..ed95a4ee6f1 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,5 +43,6 @@ object JsPlatformConfigurator : PlatformConfigurator( container.useImpl() container.useInstance(SyntheticScopes.Empty) + container.useInstance(JsTypeSpecificityComparator) } } diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsTypeSpecificityComparator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsTypeSpecificityComparator.kt new file mode 100644 index 00000000000..e70c3663237 --- /dev/null +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsTypeSpecificityComparator.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.resolve + +import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.isDynamic +import org.jetbrains.kotlin.types.isFlexible + +object JsTypeSpecificityComparator: TypeSpecificityComparator { + + private fun checkOnlyDynamicFlexibleType(type: KotlinType) { + if (type.isFlexible()) { + assert(type.isDynamic()) { + "Unexpected flexible type in Js: $type" + } + } + } + + override fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType): Boolean { + checkOnlyDynamicFlexibleType(specific) + checkOnlyDynamicFlexibleType(general) + + return specific.isDynamic() && !general.isDynamic() + } +} \ No newline at end of file