Migration to expect/actual: ExpectedActualDeclarationChecker

This commit is contained in:
Mikhail Glukhikh
2017-09-14 19:10:11 +03:00
parent c4fd1a8e5c
commit 2d0ac0011a
5 changed files with 82 additions and 82 deletions
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.load.java.sam.SamConversionResolverImpl
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.resolve.PlatformConfigurator import org.jetbrains.kotlin.resolve.PlatformConfigurator
import org.jetbrains.kotlin.resolve.calls.checkers.ReifiedTypeParameterSubstitutionChecker import org.jetbrains.kotlin.resolve.calls.checkers.ReifiedTypeParameterSubstitutionChecker
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.jvm.* import org.jetbrains.kotlin.resolve.jvm.*
import org.jetbrains.kotlin.resolve.jvm.checkers.* import org.jetbrains.kotlin.resolve.jvm.checkers.*
import org.jetbrains.kotlin.synthetic.JavaSyntheticScopes import org.jetbrains.kotlin.synthetic.JavaSyntheticScopes
@@ -43,7 +43,7 @@ object JvmPlatformConfigurator : PlatformConfigurator(
TypeParameterBoundIsNotArrayChecker(), TypeParameterBoundIsNotArrayChecker(),
JvmSyntheticApplicabilityChecker(), JvmSyntheticApplicabilityChecker(),
StrictfpApplicabilityChecker(), StrictfpApplicabilityChecker(),
HeaderImplDeclarationChecker ExpectedActualDeclarationChecker
), ),
additionalCallCheckers = listOf( additionalCallCheckers = listOf(
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData; import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.tower.WrongResolutionToClassifier; import org.jetbrains.kotlin.resolve.calls.tower.WrongResolutionToClassifier;
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Incompatible; import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Compatibility.Incompatible;
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData; import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.SinceKotlinInfo; import org.jetbrains.kotlin.serialization.deserialization.descriptors.SinceKotlinInfo;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.diagnostics.rendering
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Incompatible import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Compatibility.Incompatible
class PlatformIncompatibilityDiagnosticRenderer( class PlatformIncompatibilityDiagnosticRenderer(
private val mode: MultiplatformDiagnosticRenderingMode private val mode: MultiplatformDiagnosticRenderingMode
@@ -32,8 +32,8 @@ import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Compatible import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Compatibility.Compatible
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Incompatible import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Compatibility.Incompatible
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -49,7 +49,7 @@ import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.keysToMap import org.jetbrains.kotlin.utils.keysToMap
object HeaderImplDeclarationChecker : DeclarationChecker { object ExpectedActualDeclarationChecker : DeclarationChecker {
override fun check( override fun check(
declaration: KtDeclaration, declaration: KtDeclaration,
descriptor: DeclarationDescriptor, descriptor: DeclarationDescriptor,
@@ -62,15 +62,15 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
if (descriptor !is MemberDescriptor || DescriptorUtils.isEnumEntry(descriptor)) return if (descriptor !is MemberDescriptor || DescriptorUtils.isEnumEntry(descriptor)) return
if (descriptor.isExpect) { if (descriptor.isExpect) {
checkHeaderDeclarationHasImplementation(declaration, descriptor, diagnosticHolder, descriptor.module) checkExpectedDeclarationHasActual(declaration, descriptor, diagnosticHolder, descriptor.module)
} }
else { else {
val checkImpl = !languageVersionSettings.getFlag(AnalysisFlag.multiPlatformDoNotCheckImpl) val checkExpected = !languageVersionSettings.getFlag(AnalysisFlag.multiPlatformDoNotCheckImpl)
checkImplementationHasHeaderDeclaration(declaration, descriptor, diagnosticHolder, checkImpl) checkActualDeclarationHasExpected(declaration, descriptor, diagnosticHolder, checkExpected)
} }
} }
fun checkHeaderDeclarationHasImplementation( fun checkExpectedDeclarationHasActual(
reportOn: KtDeclaration, reportOn: KtDeclaration,
descriptor: MemberDescriptor, descriptor: MemberDescriptor,
diagnosticHolder: DiagnosticSink, diagnosticHolder: DiagnosticSink,
@@ -79,13 +79,13 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
// Only look for implementations of top level members; class members will be handled as a part of that header class // Only look for implementations of top level members; class members will be handled as a part of that header class
if (descriptor.containingDeclaration !is PackageFragmentDescriptor) return if (descriptor.containingDeclaration !is PackageFragmentDescriptor) return
val compatibility = findImplForHeader(descriptor, platformModule) ?: return val compatibility = findActualForExpected(descriptor, platformModule) ?: return
val shouldReportError = val shouldReportError =
compatibility.isEmpty() || compatibility.isEmpty() ||
Compatible !in compatibility && compatibility.values.flatMapTo(hashSetOf()) { it }.all { impl -> Compatible !in compatibility && compatibility.values.flatMapTo(hashSetOf()) { it }.all { actual ->
val headers = findHeaderForImpl(impl, descriptor.module) val expectedOnes = findExpectedForActual(actual, descriptor.module)
headers != null && Compatible in headers.keys expectedOnes != null && Compatible in expectedOnes.keys
} }
if (shouldReportError) { if (shouldReportError) {
@@ -96,42 +96,42 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
} }
} }
private fun findImplForHeader(header: MemberDescriptor, platformModule: ModuleDescriptor): Map<Compatibility, List<MemberDescriptor>>? { private fun findActualForExpected(expected: MemberDescriptor, platformModule: ModuleDescriptor): Map<Compatibility, List<MemberDescriptor>>? {
return when (header) { return when (expected) {
is CallableMemberDescriptor -> { is CallableMemberDescriptor -> {
header.findNamesakesFromModule(platformModule).filter { impl -> expected.findNamesakesFromModule(platformModule).filter { actual ->
header != impl && !impl.isExpect && expected != actual && !actual.isExpect &&
// TODO: support non-source definitions (e.g. from Java) // TODO: support non-source definitions (e.g. from Java)
DescriptorToSourceUtils.getSourceFromDescriptor(impl) is KtElement DescriptorToSourceUtils.getSourceFromDescriptor(actual) is KtElement
}.groupBy { impl -> }.groupBy { actual ->
areCompatibleCallables(header, impl) areCompatibleCallables(expected, actual)
} }
} }
is ClassDescriptor -> { is ClassDescriptor -> {
header.findClassifiersFromModule(platformModule).filter { impl -> expected.findClassifiersFromModule(platformModule).filter { actual ->
header != impl && !impl.isExpect && expected != actual && !actual.isExpect &&
DescriptorToSourceUtils.getSourceFromDescriptor(impl) is KtElement DescriptorToSourceUtils.getSourceFromDescriptor(actual) is KtElement
}.groupBy { impl -> }.groupBy { actual ->
areCompatibleClassifiers(header, impl) areCompatibleClassifiers(expected, actual)
} }
} }
else -> null else -> null
} }
} }
private fun checkImplementationHasHeaderDeclaration( private fun checkActualDeclarationHasExpected(
reportOn: KtDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink, checkImpl: Boolean reportOn: KtDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink, checkExpected: Boolean
) { ) {
// Using the platform module instead of the common module is sort of fine here because the former always depends on the latter. // Using the platform module instead of the common module is sort of fine here because the former always depends on the latter.
// However, it would be clearer to find the common module this platform module implements and look for headers there instead. // However, it would be clearer to find the common module this platform module implements and look for headers there instead.
// TODO: use common module here // TODO: use common module here
val compatibility = findHeaderForImpl(descriptor, descriptor.module) ?: return val compatibility = findExpectedForActual(descriptor, descriptor.module) ?: return
val hasImplModifier = descriptor.isActual && reportOn.hasActualModifier() val hasExpectedModifier = descriptor.isActual && reportOn.hasActualModifier()
if (!hasImplModifier) { if (!hasExpectedModifier) {
if (Compatible !in compatibility) return if (Compatible !in compatibility) return
if (checkImpl) { if (checkExpected) {
diagnosticHolder.report(Errors.IMPL_MISSING.on(reportOn)) diagnosticHolder.report(Errors.IMPL_MISSING.on(reportOn))
} }
} }
@@ -148,17 +148,17 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
// (albeit maybe incompatible) single implementation suspect, declared in the impl class. // (albeit maybe incompatible) single implementation suspect, declared in the impl class.
// This is needed only to reduce the number of errors. Incompatibility errors for those members will be reported // This is needed only to reduce the number of errors. Incompatibility errors for those members will be reported
// later when this checker is called for them // later when this checker is called for them
fun hasSingleImplSuspect( fun hasSingleActualSuspect(
headerWithIncompatibility: Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>> expectedWithIncompatibility: Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>
): Boolean { ): Boolean {
val (headerMember, incompatibility) = headerWithIncompatibility val (expectedMember, incompatibility) = expectedWithIncompatibility
val implMember = incompatibility.values.singleOrNull()?.singleOrNull() val actualMember = incompatibility.values.singleOrNull()?.singleOrNull()
return implMember != null && return actualMember != null &&
implMember.isExplicitImplDeclaration() && actualMember.isExplicitActualDeclaration() &&
findHeaderForImpl(implMember, headerMember.module)?.values?.singleOrNull()?.singleOrNull() == headerMember findExpectedForActual(actualMember, expectedMember.module)?.values?.singleOrNull()?.singleOrNull() == expectedMember
} }
val nonTrivialUnimplemented = singleIncompatibility.unimplemented.filterNot(::hasSingleImplSuspect) val nonTrivialUnimplemented = singleIncompatibility.unimplemented.filterNot(::hasSingleActualSuspect)
if (nonTrivialUnimplemented.isNotEmpty()) { if (nonTrivialUnimplemented.isNotEmpty()) {
val classDescriptor = val classDescriptor =
@@ -179,65 +179,65 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
// This should ideally be handled by CallableMemberDescriptor.Kind, but default constructors have kind DECLARATION and non-empty source. // This should ideally be handled by CallableMemberDescriptor.Kind, but default constructors have kind DECLARATION and non-empty source.
// Their source is the containing KtClass instance though, as opposed to explicit constructors, whose source is KtConstructor // Their source is the containing KtClass instance though, as opposed to explicit constructors, whose source is KtConstructor
private fun MemberDescriptor.isExplicitImplDeclaration(): Boolean = private fun MemberDescriptor.isExplicitActualDeclaration(): Boolean =
when (this) { when (this) {
is ConstructorDescriptor -> DescriptorToSourceUtils.getSourceFromDescriptor(this) is KtConstructor<*> is ConstructorDescriptor -> DescriptorToSourceUtils.getSourceFromDescriptor(this) is KtConstructor<*>
is CallableMemberDescriptor -> kind == CallableMemberDescriptor.Kind.DECLARATION is CallableMemberDescriptor -> kind == CallableMemberDescriptor.Kind.DECLARATION
else -> true else -> true
} }
private fun findHeaderForImpl(impl: MemberDescriptor, commonModule: ModuleDescriptor): Map<Compatibility, List<MemberDescriptor>>? { private fun findExpectedForActual(actual: MemberDescriptor, commonModule: ModuleDescriptor): Map<Compatibility, List<MemberDescriptor>>? {
return when (impl) { return when (actual) {
is CallableMemberDescriptor -> { is CallableMemberDescriptor -> {
val container = impl.containingDeclaration val container = actual.containingDeclaration
val candidates = when (container) { val candidates = when (container) {
is ClassDescriptor -> { is ClassDescriptor -> {
// TODO: replace with 'singleOrNull' as soon as multi-module diagnostic tests are refactored // TODO: replace with 'singleOrNull' as soon as multi-module diagnostic tests are refactored
val headerClass = findHeaderForImpl(container, commonModule)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor val expectedClass = findExpectedForActual(container, commonModule)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor
headerClass?.getMembers(impl.name)?.filterIsInstance<CallableMemberDescriptor>().orEmpty() expectedClass?.getMembers(actual.name)?.filterIsInstance<CallableMemberDescriptor>().orEmpty()
} }
is PackageFragmentDescriptor -> impl.findNamesakesFromModule(commonModule) is PackageFragmentDescriptor -> actual.findNamesakesFromModule(commonModule)
else -> return null // do not report anything for incorrect code, e.g. 'impl' local function else -> return null // do not report anything for incorrect code, e.g. 'impl' local function
} }
candidates.filter { declaration -> candidates.filter { declaration ->
impl != declaration && declaration.isExpect actual != declaration && declaration.isExpect
}.groupBy { declaration -> }.groupBy { declaration ->
// TODO: optimize by caching this per impl-header class pair, do not create a new substitutor for each impl member // TODO: optimize by caching this per impl-header class pair, do not create a new substitutor for each impl member
val substitutor = val substitutor =
if (container is ClassDescriptor) { if (container is ClassDescriptor) {
val headerClass = declaration.containingDeclaration as ClassDescriptor val expectedClass = declaration.containingDeclaration as ClassDescriptor
// TODO: this might not work for members of inner generic classes // TODO: this might not work for members of inner generic classes
Substitutor(headerClass.declaredTypeParameters, container.declaredTypeParameters) Substitutor(expectedClass.declaredTypeParameters, container.declaredTypeParameters)
} }
else null else null
areCompatibleCallables(declaration, impl, parentSubstitutor = substitutor) areCompatibleCallables(declaration, actual, parentSubstitutor = substitutor)
} }
} }
is ClassifierDescriptorWithTypeParameters -> { is ClassifierDescriptorWithTypeParameters -> {
impl.findClassifiersFromModule(commonModule).filter { declaration -> actual.findClassifiersFromModule(commonModule).filter { declaration ->
impl != declaration && actual != declaration &&
declaration is ClassDescriptor && declaration.isExpect declaration is ClassDescriptor && declaration.isExpect
}.groupBy { header -> }.groupBy { expected ->
areCompatibleClassifiers(header as ClassDescriptor, impl) areCompatibleClassifiers(expected as ClassDescriptor, actual)
} }
} }
else -> null else -> null
} }
} }
fun MemberDescriptor.findCompatibleImplForHeader(platformModule: ModuleDescriptor): List<MemberDescriptor> = fun MemberDescriptor.findCompatibleActualForExpected(platformModule: ModuleDescriptor): List<MemberDescriptor> =
findImplForHeader(this, platformModule)?.get(Compatible).orEmpty() findActualForExpected(this, platformModule)?.get(Compatible).orEmpty()
fun MemberDescriptor.findAnyImplForHeader(platformModule: ModuleDescriptor): List<MemberDescriptor> { fun MemberDescriptor.findAnyActualForExpected(platformModule: ModuleDescriptor): List<MemberDescriptor> {
val implsGroupedByCompatibility = findImplForHeader(this, platformModule) val actualsGroupedByCompatibility = findActualForExpected(this, platformModule)
return implsGroupedByCompatibility?.get(Compatible) return actualsGroupedByCompatibility?.get(Compatible)
?: implsGroupedByCompatibility?.values?.flatten() ?: actualsGroupedByCompatibility?.values?.flatten()
?: emptyList() ?: emptyList()
} }
fun MemberDescriptor.findCompatibleHeaderForImpl(commonModule: ModuleDescriptor): List<MemberDescriptor> = fun MemberDescriptor.findCompatibleExpectedForActual(commonModule: ModuleDescriptor): List<MemberDescriptor> =
findHeaderForImpl(this, commonModule)?.get(Compatible).orEmpty() findExpectedForActual(this, commonModule)?.get(Compatible).orEmpty()
private fun CallableMemberDescriptor.findNamesakesFromModule(module: ModuleDescriptor): Collection<CallableMemberDescriptor> { private fun CallableMemberDescriptor.findNamesakesFromModule(module: ModuleDescriptor): Collection<CallableMemberDescriptor> {
val containingDeclaration = containingDeclaration val containingDeclaration = containingDeclaration
@@ -308,7 +308,7 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
// Functions // Functions
object FunctionModifiersDifferent : Incompatible("modifiers are different (suspend)") object FunctionModifiersDifferent : Incompatible("modifiers are different (suspend)")
object FunctionModifiersNotSubset : Incompatible("some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec)") object FunctionModifiersNotSubset : Incompatible("some modifiers on expected declaration are missing on the actual one (external, infix, inline, operator, tailrec)")
// Properties // Properties
@@ -321,13 +321,13 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
object ClassModifiers : Incompatible("modifiers are different (companion, inner)") object ClassModifiers : Incompatible("modifiers are different (companion, inner)")
object Supertypes : Incompatible("some supertypes are missing in the implementation") object Supertypes : Incompatible("some supertypes are missing in the actual declaration")
class ClassScopes( class ClassScopes(
val unimplemented: List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>> val unimplemented: List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>
) : Incompatible("some members are not implemented") ) : Incompatible("some members are not implemented")
object EnumEntries : Incompatible("some entries from header enum are missing in the impl enum") object EnumEntries : Incompatible("some entries from expected enum are missing in the actual enum")
// Common // Common
@@ -408,8 +408,8 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
with(NewKotlinTypeChecker) { with(NewKotlinTypeChecker) {
val context = object : TypeCheckerContext(false) { val context = object : TypeCheckerContext(false) {
override fun areEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean { override fun areEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean {
return isExpectClassAndImplTypeAlias(a, b, platformModule) || return isExpectedClassAndActualTypeAlias(a, b, platformModule) ||
isExpectClassAndImplTypeAlias(b, a, platformModule) || isExpectedClassAndActualTypeAlias(b, a, platformModule) ||
super.areEqualTypeConstructors(a, b) super.areEqualTypeConstructors(a, b)
} }
} }
@@ -421,21 +421,21 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
// is java.lang.StringBuilder. For the purposes of type compatibility checking, we must consider these types equal here. // is java.lang.StringBuilder. For the purposes of type compatibility checking, we must consider these types equal here.
// Note that the case of an "impl class" works as expected though, because the impl class by definition has the same FQ name // Note that the case of an "impl class" works as expected though, because the impl class by definition has the same FQ name
// as the corresponding header class, so their type constructors are equal as per AbstractClassTypeConstructor#equals // as the corresponding header class, so their type constructors are equal as per AbstractClassTypeConstructor#equals
private fun isExpectClassAndImplTypeAlias( private fun isExpectedClassAndActualTypeAlias(
headerTypeConstructor: TypeConstructor, expectedTypeConstructor: TypeConstructor,
implTypeConstructor: TypeConstructor, actualTypeConstructor: TypeConstructor,
platformModule: ModuleDescriptor platformModule: ModuleDescriptor
): Boolean { ): Boolean {
val header = headerTypeConstructor.declarationDescriptor val expected = expectedTypeConstructor.declarationDescriptor
val impl = implTypeConstructor.declarationDescriptor val actual = actualTypeConstructor.declarationDescriptor
return header is ClassifierDescriptorWithTypeParameters && return expected is ClassifierDescriptorWithTypeParameters &&
header.isExpect && expected.isExpect &&
impl is ClassifierDescriptorWithTypeParameters && actual is ClassifierDescriptorWithTypeParameters &&
header.findClassifiersFromModule(platformModule).any { classifier -> expected.findClassifiersFromModule(platformModule).any { classifier ->
// Note that it's fine to only check that this "impl typealias" expands to the expected class, without checking // Note that it's fine to only check that this "impl typealias" expands to the expected class, without checking
// whether the type arguments in the expansion are in the correct order or have the correct variance, because we only // whether the type arguments in the expansion are in the correct order or have the correct variance, because we only
// allow simple cases like "impl typealias Foo<A, B> = FooImpl<A, B>", see DeclarationsChecker#checkImplTypeAlias // allow simple cases like "impl typealias Foo<A, B> = FooImpl<A, B>", see DeclarationsChecker#checkImplTypeAlias
(classifier as? TypeAliasDescriptor)?.classDescriptor == impl (classifier as? TypeAliasDescriptor)?.classDescriptor == actual
} }
} }
@@ -488,7 +488,7 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
val b = when (other) { val b = when (other) {
is ClassDescriptor -> other is ClassDescriptor -> other
is TypeAliasDescriptor -> other.classDescriptor ?: return Compatible // do not report extra error on erroneous typealias is TypeAliasDescriptor -> other.classDescriptor ?: return Compatible // do not report extra error on erroneous typealias
else -> throw AssertionError("Incorrect impl classifier for $a: $other") else -> throw AssertionError("Incorrect actual classifier for $a: $other")
} }
if (a.kind != b.kind) return Incompatible.ClassKind if (a.kind != b.kind) return Incompatible.ClassKind
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.resolve.OverloadFilter
import org.jetbrains.kotlin.resolve.OverridesBackwardCompatibilityHelper import org.jetbrains.kotlin.resolve.OverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.resolve.PlatformConfigurator import org.jetbrains.kotlin.resolve.PlatformConfigurator
import org.jetbrains.kotlin.resolve.calls.checkers.ReifiedTypeParameterSubstitutionChecker import org.jetbrains.kotlin.resolve.calls.checkers.ReifiedTypeParameterSubstitutionChecker
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.types.DynamicTypesAllowed import org.jetbrains.kotlin.types.DynamicTypesAllowed
@@ -38,7 +38,7 @@ object JsPlatformConfigurator : PlatformConfigurator(
JsExternalChecker, JsInheritanceChecker, JsExternalChecker, JsInheritanceChecker,
JsRuntimeAnnotationChecker, JsRuntimeAnnotationChecker,
JsDynamicDeclarationChecker, JsDynamicDeclarationChecker,
HeaderImplDeclarationChecker ExpectedActualDeclarationChecker
), ),
additionalCallCheckers = listOf( additionalCallCheckers = listOf(
ReifiedTypeParameterSubstitutionChecker(), ReifiedTypeParameterSubstitutionChecker(),