diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt new file mode 100644 index 00000000000..edcec819b5d --- /dev/null +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt @@ -0,0 +1,326 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.multiplatform + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.mpp.* +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS +import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.getKotlinTypeRefiner +import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.* +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.TypeConstructorMarker +import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker +import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext +import org.jetbrains.kotlin.types.typeUtil.asTypeProjection +import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction +import org.jetbrains.kotlin.utils.addToStdlib.castAll +import org.jetbrains.kotlin.utils.keysToMap + +class ClassicExpectActualMatchingContext(val platformModule: ModuleDescriptor) : ExpectActualMatchingContext, + TypeSystemInferenceExtensionContext by ClassicTypeSystemContextForCS(platformModule.builtIns, KotlinTypeRefiner.Default) +{ + override val shouldCheckReturnTypesOfCallables: Boolean + get() = true + + private fun CallableSymbolMarker.asDescriptor(): CallableDescriptor = this as CallableDescriptor + private fun FunctionSymbolMarker.asDescriptor(): FunctionDescriptor = this as FunctionDescriptor + private fun PropertySymbolMarker.asDescriptor(): PropertyDescriptor = this as PropertyDescriptor + private fun ValueParameterSymbolMarker.asDescriptor(): ValueParameterDescriptor = this as ValueParameterDescriptor + private fun TypeParameterSymbolMarker.asDescriptor(): TypeParameterDescriptor = this as TypeParameterDescriptor + private fun ClassLikeSymbolMarker.asDescriptor(): ClassifierDescriptorWithTypeParameters = this as ClassifierDescriptorWithTypeParameters + private fun RegularClassSymbolMarker.asDescriptor(): ClassDescriptor = this as ClassDescriptor + private fun TypeAliasSymbolMarker.asDescriptor(): TypeAliasDescriptor = this as TypeAliasDescriptor + private inline fun DeclarationSymbolMarker.safeAsDescriptor(): T? = this as? T + + override val RegularClassSymbolMarker.classId: ClassId + get() = (this as ClassifierDescriptor).classId!! + override val TypeAliasSymbolMarker.classId: ClassId + get() = (this as ClassifierDescriptor).classId!! + override val CallableSymbolMarker.callableId: CallableId + get() { + val descriptor = asDescriptor() + return when (val parent = descriptor.containingDeclaration) { + is PackageFragmentDescriptor -> CallableId(parent.fqName, descriptor.name) + is ClassifierDescriptor -> CallableId(parent.classId!!, descriptor.name) + else -> error("Callable descriptor without callableId: $descriptor") + } + } + override val TypeParameterSymbolMarker.parameterName: Name + get() = asDescriptor().name + override val ValueParameterSymbolMarker.parameterName: Name + get() = asDescriptor().name + + override fun TypeAliasSymbolMarker.expandToRegularClass(): RegularClassSymbolMarker? { + return asDescriptor().classDescriptor + } + + override val RegularClassSymbolMarker.classKind: ClassKind + get() = asDescriptor().kind + override val RegularClassSymbolMarker.isCompanion: Boolean + get() = safeAsDescriptor()?.isCompanionObject == true + override val RegularClassSymbolMarker.isInner: Boolean + get() = asDescriptor().isInner + override val RegularClassSymbolMarker.isInline: Boolean + get() = safeAsDescriptor()?.isInline == true + override val RegularClassSymbolMarker.isValue: Boolean + get() = safeAsDescriptor()?.isValue == true + override val RegularClassSymbolMarker.isFun: Boolean + get() = safeAsDescriptor()?.isFun == true + override val ClassLikeSymbolMarker.typeParameters: List + get() = asDescriptor().declaredTypeParameters + override val ClassLikeSymbolMarker.modality: Modality + get() = asDescriptor().modality + override val ClassLikeSymbolMarker.visibility: Visibility + get() = asDescriptor().visibility.delegate + override val CallableSymbolMarker.modality: Modality? + get() = safeAsDescriptor()?.modality + override val CallableSymbolMarker.visibility: Visibility + get() = asDescriptor().visibility.delegate + override val RegularClassSymbolMarker.superTypes: List + get() = asDescriptor().typeConstructor.supertypes.toList() + override val CallableSymbolMarker.isExpect: Boolean + get() = safeAsDescriptor()?.isExpect == true + + override val CallableSymbolMarker.isInline: Boolean + get() = when (this) { + is FunctionDescriptor -> isInline + is PropertyDescriptor -> getter?.isInline == true + else -> false + } + + override val CallableSymbolMarker.isSuspend: Boolean + get() = when (this) { + is FunctionDescriptor -> isSuspend + is PropertyDescriptor -> getter?.isSuspend == true + else -> false + } + + override val CallableSymbolMarker.isExternal: Boolean + get() = safeAsDescriptor()?.isExternal == true + override val CallableSymbolMarker.isInfix: Boolean + get() = safeAsDescriptor()?.isInfix == true + override val CallableSymbolMarker.isOperator: Boolean + get() = safeAsDescriptor()?.isOperator == true + override val CallableSymbolMarker.isTailrec: Boolean + get() = safeAsDescriptor()?.isTailrec == true + override val PropertySymbolMarker.isVar: Boolean + get() = asDescriptor().isVar + override val PropertySymbolMarker.isLateinit: Boolean + get() = asDescriptor().isLateInit + override val PropertySymbolMarker.isConst: Boolean + get() = asDescriptor().isConst + override val PropertySymbolMarker.setter: FunctionSymbolMarker? + get() = asDescriptor().setter + + @OptIn(UnsafeCastFunction::class) + override fun createExpectActualTypeParameterSubstitutor( + expectTypeParameters: List, + actualTypeParameters: List, + parentSubstitutor: TypeSubstitutorMarker?, + ): TypeSubstitutorMarker { + val expectParameters = expectTypeParameters.castAll() + val actualParameters = actualTypeParameters.castAll() + val substitutor = TypeSubstitutor.create( + TypeConstructorSubstitution.createByParametersMap(expectParameters.keysToMap { + actualParameters[it.index].defaultType.asTypeProjection() + }) + ) + return when (parentSubstitutor) { + null -> substitutor + is TypeSubstitutor -> TypeSubstitutor.createChainedSubstitutor(parentSubstitutor.substitution, substitutor.substitution) + else -> error("Unsupported substitutor type: $parentSubstitutor") + } + } + + override fun RegularClassSymbolMarker.collectAllMembers(isActualDeclaration: Boolean): List { + return asDescriptor().getMembers(name = null) + } + + override fun RegularClassSymbolMarker.getMembersForExpectClass(name: Name): List { + return asDescriptor().getMembers(name) + } + + private fun ClassDescriptor.getMembers(name: Name? = null): List { + val nameFilter = if (name != null) { it -> it == name } else MemberScope.ALL_NAME_FILTER + return defaultType.memberScope + .getDescriptorsFiltered(nameFilter = nameFilter) + .filterIsInstance() + .filterNot(DescriptorUtils::isEnumEntry) + .plus(constructors.filter { nameFilter(it.name) }) + } + + override fun RegularClassSymbolMarker.collectEnumEntryNames(): List { + return asDescriptor() + .unsubstitutedMemberScope + .getDescriptorsFiltered() + .filter(DescriptorUtils::isEnumEntry) + .map { it.name } + } + + override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker? + get() = asDescriptor().dispatchReceiverParameter?.type + override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker? + get() = asDescriptor().extensionReceiverParameter?.type + override val CallableSymbolMarker.returnType: KotlinTypeMarker + get() = asDescriptor().returnType!! + override val CallableSymbolMarker.typeParameters: List + get() = asDescriptor().typeParameters + override val FunctionSymbolMarker.valueParameters: List + get() = asDescriptor().valueParameters + override val ValueParameterSymbolMarker.isVararg: Boolean + get() = asDescriptor().varargElementType != null + override val ValueParameterSymbolMarker.isNoinline: Boolean + get() = asDescriptor().isNoinline + override val ValueParameterSymbolMarker.isCrossinline: Boolean + get() = asDescriptor().isCrossinline + override val ValueParameterSymbolMarker.hasDefaultValue: Boolean + get() = asDescriptor().declaresDefaultValue() + + override fun CallableSymbolMarker.isAnnotationConstructor(): Boolean { + val descriptor = safeAsDescriptor() ?: return false + return DescriptorUtils.isAnnotationClass(descriptor.constructedClass) + } + + override val TypeParameterSymbolMarker.bounds: List + get() = asDescriptor().upperBounds + override val TypeParameterSymbolMarker.variance: Variance + get() = asDescriptor().variance + override val TypeParameterSymbolMarker.isReified: Boolean + get() = asDescriptor().isReified + + override fun areCompatibleExpectActualTypes(expectType: KotlinTypeMarker?, actualType: KotlinTypeMarker?): Boolean { + if (expectType == null) return actualType == null + if (actualType == null) return false + + require(expectType is KotlinType && actualType is KotlinType) + return if (platformModule.isTypeRefinementEnabled()) { + areCompatibleTypesViaTypeRefinement(expectType, actualType) + } else { + areCompatibleTypesViaTypeContext(expectType, actualType) + } + } + + @OptIn(TypeRefinement::class) + private fun areCompatibleTypesViaTypeRefinement(a: KotlinType, b: KotlinType): Boolean { + val typeRefinerForPlatformModule = platformModule.getKotlinTypeRefiner().let { moduleRefiner -> + if (moduleRefiner is KotlinTypeRefiner.Default) + KotlinTypeRefinerImpl.createStandaloneInstanceFor(platformModule) + else + moduleRefiner + } + + return areCompatibleTypes( + a, b, + typeSystemContext = SimpleClassicTypeSystemContext, + kotlinTypeRefiner = typeRefinerForPlatformModule, + ) + } + + private fun areCompatibleTypesViaTypeContext(a: KotlinType, b: KotlinType): Boolean { + val typeSystemContext = object : ClassicTypeSystemContext { + override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean { + require(c1 is TypeConstructor) + require(c2 is TypeConstructor) + return isExpectedClassAndActualTypeAlias(c1, c2, platformModule) || + isExpectedClassAndActualTypeAlias(c2, c1, platformModule) || + super.areEqualTypeConstructors(c1, c2) + } + } + + return areCompatibleTypes( + a, b, + typeSystemContext = typeSystemContext, + kotlinTypeRefiner = KotlinTypeRefiner.Default, + ) + } + + private fun areCompatibleTypes( + a: KotlinType, + b: KotlinType, + typeSystemContext: ClassicTypeSystemContext, + kotlinTypeRefiner: KotlinTypeRefiner, + ): Boolean { + with(NewKotlinTypeCheckerImpl(kotlinTypeRefiner)) { + return createClassicTypeCheckerState( + isErrorTypeEqualsToAnything = false, + typeSystemContext = typeSystemContext, + kotlinTypeRefiner = kotlinTypeRefiner, + ).equalTypes(a.unwrap(), b.unwrap()) + } + } + + // For example, expectedTypeConstructor may be the expected class kotlin.text.StringBuilder, while actualTypeConstructor + // is java.lang.StringBuilder. For the purposes of type compatibility checking, we must consider these types equal here. + // Note that the case of an "actual class" works as expected though, because the actual class by definition has the same FQ name + // as the corresponding expected class, so their type constructors are equal as per AbstractClassTypeConstructor#equals + private fun isExpectedClassAndActualTypeAlias( + expectedTypeConstructor: TypeConstructor, + actualTypeConstructor: TypeConstructor, + platformModule: ModuleDescriptor + ): Boolean { + val expected = expectedTypeConstructor.declarationDescriptor + val actual = actualTypeConstructor.declarationDescriptor + return expected is ClassifierDescriptorWithTypeParameters && + expected.isExpect && + actual is ClassifierDescriptorWithTypeParameters && + findClassifiersFromModule(expected.classId, platformModule, moduleFilter = ALL_MODULES).any { classifier -> + // Note that it's fine to only check that this "actual 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 + // allow simple cases like "actual typealias Foo = FooImpl", see DeclarationsChecker#checkActualTypeAlias + (classifier as? TypeAliasDescriptor)?.classDescriptor == actual + } + } + + fun findClassifiersFromModule( + classId: ClassId?, + module: ModuleDescriptor, + moduleFilter: (ModuleDescriptor) -> Boolean + ): Collection { + if (classId == null) return emptyList() + + fun MemberScope.getAllClassifiers(name: Name): Collection = + getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name } + .filterIsInstance() + + val segments = classId.relativeClassName.pathSegments() + var classifiers = module.getPackage(classId.packageFqName).memberScope.getAllClassifiers(segments.first()) + classifiers = classifiers.applyFilter(moduleFilter) + + for (name in segments.subList(1, segments.size)) { + classifiers = classifiers.mapNotNull { classifier -> + (classifier as? ClassDescriptor)?.unsubstitutedInnerClassesScope?.getContributedClassifier( + name, NoLookupLocation.FOR_ALREADY_TRACKED + ) as? ClassifierDescriptorWithTypeParameters + } + } + + return classifiers + } + + override fun RegularClassSymbolMarker.isNotSamInterface(): Boolean { + val descriptor = asDescriptor() + return descriptor.isDefinitelyNotSamInterface || descriptor.defaultFunctionTypeForSamInterface == null + } + + override fun CallableSymbolMarker.shouldSkipMatching(containingExpectClass: RegularClassSymbolMarker): Boolean { + return safeAsDescriptor()?.kind?.isReal == false + } + + override val CallableSymbolMarker.hasStableParameterNames: Boolean + get() = asDescriptor().hasStableParameterNames() +} diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt index 1bfa9cbc0f8..6a6712f01ea 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt @@ -5,48 +5,49 @@ package org.jetbrains.kotlin.resolve.multiplatform -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.descriptorUtil.* +import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualCompatibilityChecker +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Compatible -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered -import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.checker.* -import org.jetbrains.kotlin.types.model.TypeConstructorMarker -import org.jetbrains.kotlin.types.typeUtil.asTypeProjection -import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.kotlin.utils.keysToMap +import org.jetbrains.kotlin.utils.addToStdlib.runIf object ExpectedActualResolver { - fun findActualForExpected( expected: MemberDescriptor, platformModule: ModuleDescriptor, moduleVisibilityFilter: ModuleFilter = allModulesProvidingActualsFor(expected.module, platformModule), ): Map, List>? { + val context = ClassicExpectActualMatchingContext(platformModule) return when (expected) { is CallableMemberDescriptor -> { - expected.findNamesakesFromModule(platformModule, moduleVisibilityFilter).filter { actual -> + expected.findNamesakesFromModule(context, platformModule, moduleVisibilityFilter).filter { actual -> expected != actual && !actual.isExpect && // TODO: use some other way to determine that the declaration is from Kotlin. // This way behavior differs between fast and PSI-based Java class reading mode // TODO: support non-source definitions (e.g. from Java) actual.couldHaveASource }.groupBy { actual -> - areCompatibleCallables(expected, actual, platformModule) + AbstractExpectActualCompatibilityChecker.areCompatibleCallables( + expected, + actual, + parentSubstitutor = null, + expectContainingClass = null, + actualContainingClass = null, + context + ) } } is ClassDescriptor -> { - expected.findClassifiersFromModule(platformModule, moduleVisibilityFilter).filter { actual -> + context.findClassifiersFromModule(expected.classId, platformModule, moduleVisibilityFilter).filter { actual -> expected != actual && !actual.isExpect && actual.couldHaveASource }.groupBy { actual -> - areCompatibleClassifiers(expected, actual) + AbstractExpectActualCompatibilityChecker.areCompatibleClassifiers( + expected, + actual, + context + ) } } else -> null @@ -57,6 +58,7 @@ object ExpectedActualResolver { actual: MemberDescriptor, moduleFilter: (ModuleDescriptor) -> Boolean = allModulesProvidingExpectsFor(actual.module) ): Map, List>? { + val context = ClassicExpectActualMatchingContext(actual.module) return when (actual) { is CallableMemberDescriptor -> { val container = actual.containingDeclaration @@ -65,9 +67,11 @@ object ExpectedActualResolver { // TODO: replace with 'singleOrNull' as soon as multi-module diagnostic tests are refactored val expectedClass = findExpectedForActual(container, moduleFilter)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor - expectedClass?.getMembers(actual.name)?.filterIsInstance().orEmpty() + with(context) { + expectedClass?.getMembersForExpectClass(actual.name)?.filterIsInstance().orEmpty() + } } - is PackageFragmentDescriptor -> actual.findNamesakesFromModule(actual.module, moduleFilter) + is PackageFragmentDescriptor -> actual.findNamesakesFromModule(context, actual.module, moduleFilter) else -> return null // do not report anything for incorrect code, e.g. 'actual' local function } @@ -75,22 +79,43 @@ object ExpectedActualResolver { actual != declaration && declaration.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && declaration.isExpect }.groupBy { declaration -> // TODO: optimize by caching this per actual-expected class pair, do not create a new substitutor for each actual member + var expectedClass: ClassDescriptor? = null + var actualClass: ClassDescriptor? = null val substitutor = - if (container is ClassDescriptor) { - val expectedClass = declaration.containingDeclaration as ClassDescriptor - // TODO: this might not work for members of inner generic classes - if (expectedClass.declaredTypeParameters.size == container.declaredTypeParameters.size) { - Substitutor(expectedClass.declaredTypeParameters, container.declaredTypeParameters) - } else null - } else null - areCompatibleCallables(declaration, actual, parentSubstitutor = substitutor) + when (container) { + is ClassDescriptor -> { + actualClass = container + expectedClass = declaration.containingDeclaration as ClassDescriptor + // TODO: this might not work for members of inner generic classes + runIf(expectedClass.declaredTypeParameters.size == container.declaredTypeParameters.size) { + context.createExpectActualTypeParameterSubstitutor( + expectedClass.declaredTypeParameters, + container.declaredTypeParameters, + parentSubstitutor = null + ) + } + } + else -> null + } + AbstractExpectActualCompatibilityChecker.areCompatibleCallables( + expectDeclaration = declaration, + actualDeclaration = actual, + parentSubstitutor = substitutor, + expectContainingClass = expectedClass, + actualContainingClass = actualClass, + context + ) } } is ClassifierDescriptorWithTypeParameters -> { - actual.findClassifiersFromModule(actual.module, moduleFilter).filter { declaration -> + context.findClassifiersFromModule(actual.classId, actual.module, moduleFilter).filter { declaration -> actual != declaration && declaration is ClassDescriptor && declaration.isExpect }.groupBy { expected -> - areCompatibleClassifiers(expected as ClassDescriptor, actual) + AbstractExpectActualCompatibilityChecker.areCompatibleClassifiers( + expected as ClassDescriptor, + actual, + context + ) } } else -> null @@ -98,6 +123,7 @@ object ExpectedActualResolver { } private fun CallableMemberDescriptor.findNamesakesFromModule( + context: ClassicExpectActualMatchingContext, module: ModuleDescriptor, moduleFilter: (ModuleDescriptor) -> Boolean ): Collection { @@ -106,7 +132,7 @@ object ExpectedActualResolver { listOf(module.getPackage(containingDeclaration.fqName).memberScope) } is ClassDescriptor -> { - val classes = containingDeclaration.findClassifiersFromModule(module, moduleFilter) + val classes = context.findClassifiersFromModule(containingDeclaration.classId, module, moduleFilter) .mapNotNull { if (it is TypeAliasDescriptor) it.classDescriptor else it } .filterIsInstance() if (this is ConstructorDescriptor) return classes.flatMap { it.constructors } @@ -132,412 +158,6 @@ object ExpectedActualResolver { else -> throw AssertionError("Unsupported declaration: $this") }.applyFilter(moduleFilter) } - - private fun ClassifierDescriptorWithTypeParameters.findClassifiersFromModule( - module: ModuleDescriptor, - moduleFilter: (ModuleDescriptor) -> Boolean - ): Collection { - val classId = classId ?: return emptyList() - - fun MemberScope.getAllClassifiers(name: Name): Collection = - getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name } - .filterIsInstance() - - val segments = classId.relativeClassName.pathSegments() - var classifiers = module.getPackage(classId.packageFqName).memberScope.getAllClassifiers(segments.first()) - classifiers = classifiers.applyFilter(moduleFilter) - - for (name in segments.subList(1, segments.size)) { - classifiers = classifiers.mapNotNull { classifier -> - (classifier as? ClassDescriptor)?.unsubstitutedInnerClassesScope?.getContributedClassifier( - name, NoLookupLocation.FOR_ALREADY_TRACKED - ) as? ClassifierDescriptorWithTypeParameters - } - } - - return classifiers - } - - // a is the declaration in common code, b is the definition in the platform-specific code - private fun areCompatibleCallables( - a: CallableMemberDescriptor, - b: CallableMemberDescriptor, - platformModule: ModuleDescriptor = b.module, - parentSubstitutor: Substitutor? = null - ): ExpectActualCompatibility { - assert(a.name == b.name) { - "This function should be invoked only for declarations with the same name: $a, $b" - } - assert(a.containingDeclaration is ClassifierDescriptorWithTypeParameters == b.containingDeclaration is ClassifierDescriptorWithTypeParameters) { - "This function should be invoked only for declarations in the same kind of container (both members or both top level): $a, $b" - } - - if (a is FunctionDescriptor && b !is FunctionDescriptor || - a !is FunctionDescriptor && b is FunctionDescriptor - ) return Incompatible.CallableKind - - val aExtensionReceiver = a.extensionReceiverParameter - val bExtensionReceiver = b.extensionReceiverParameter - if ((aExtensionReceiver != null) != (bExtensionReceiver != null)) return Incompatible.ParameterShape - - val aParams = a.valueParameters - val bParams = b.valueParameters - if (!valueParametersCountCompatible(a, b, aParams, bParams)) { - return Incompatible.ParameterCount - } - - val aTypeParams = a.typeParameters - val bTypeParams = b.typeParameters - if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount - - val substitutor = Substitutor(aTypeParams, bTypeParams, parentSubstitutor) - - if (!areCompatibleTypeLists(aParams.map { substitutor(it.type) }, bParams.map { it.type }, platformModule) || - !areCompatibleTypes(aExtensionReceiver?.type?.let(substitutor), bExtensionReceiver?.type, platformModule) - ) return Incompatible.ParameterTypes - if (!areCompatibleTypes(substitutor(a.returnType), b.returnType, platformModule)) return Incompatible.ReturnType - - if (b.hasStableParameterNames() && - !equalsBy(aParams, bParams, ValueParameterDescriptor::getName) - ) return Incompatible.ParameterNames - if (!equalsBy(aTypeParams, bTypeParams, TypeParameterDescriptor::getName)) return Incompatible.TypeParameterNames - - if (!areCompatibleModalities(a.modality, b.modality)) return Incompatible.Modality - if (!areDeclarationsWithCompatibleVisibilities(a, b)) return Incompatible.Visibility - - areCompatibleTypeParameters(aTypeParams, bTypeParams, platformModule, substitutor).let { if (it != Compatible) return it } - - if (!equalsBy(aParams, bParams) { p -> listOf(p.varargElementType != null) }) return Incompatible.ValueParameterVararg - - // Adding noinline/crossinline to parameters is disallowed, except if the expected declaration was not inline at all - if (a is FunctionDescriptor && a.isInline) { - if (aParams.indices.any { i -> !aParams[i].isNoinline && bParams[i].isNoinline }) return Incompatible.ValueParameterNoinline - if (aParams.indices.any { i -> !aParams[i].isCrossinline && bParams[i].isCrossinline }) return Incompatible.ValueParameterCrossinline - } - - when { - a is FunctionDescriptor && b is FunctionDescriptor -> areCompatibleFunctions(a, b).let { if (it != Compatible) return it } - a is PropertyDescriptor && b is PropertyDescriptor -> areCompatibleProperties(a, b).let { if (it != Compatible) return it } - else -> throw AssertionError("Unsupported declarations: $a, $b") - } - - return Compatible - } - - private fun valueParametersCountCompatible( - a: CallableMemberDescriptor, - b: CallableMemberDescriptor, - aParams: List, - bParams: List - ): Boolean { - if (aParams.size == bParams.size) return true - - return if (a.isAnnotationConstructor() && b.isAnnotationConstructor()) - aParams.isEmpty() && bParams.all { it.declaresDefaultValue() } - else - false - } - - private fun areCompatibleTypes(a: KotlinType?, b: KotlinType?, platformModule: ModuleDescriptor): Boolean { - if (a == null) return b == null - if (b == null) return false - - return if (platformModule.isTypeRefinementEnabled()) { - areCompatibleTypesViaTypeRefinement(a, b, platformModule) - } else { - areCompatibleTypesViaTypeContext(a, b, platformModule) - } - } - - @OptIn(TypeRefinement::class) - private fun areCompatibleTypesViaTypeRefinement(a: KotlinType, b: KotlinType, platformModule: ModuleDescriptor): Boolean { - val typeRefinerForPlatformModule = platformModule.getKotlinTypeRefiner().let { moduleRefiner -> - if (moduleRefiner is KotlinTypeRefiner.Default) - KotlinTypeRefinerImpl.createStandaloneInstanceFor(platformModule) - else - moduleRefiner - } - - return areCompatibleTypes( - a, b, - typeSystemContext = SimpleClassicTypeSystemContext, - kotlinTypeRefiner = typeRefinerForPlatformModule, - ) - } - - private fun areCompatibleTypesViaTypeContext(a: KotlinType, b: KotlinType, platformModule: ModuleDescriptor): Boolean { - val typeSystemContext = object : ClassicTypeSystemContext { - override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean { - require(c1 is TypeConstructor) - require(c2 is TypeConstructor) - return isExpectedClassAndActualTypeAlias(c1, c2, platformModule) || - isExpectedClassAndActualTypeAlias(c2, c1, platformModule) || - super.areEqualTypeConstructors(c1, c2) - } - } - - return areCompatibleTypes( - a, b, - typeSystemContext = typeSystemContext, - kotlinTypeRefiner = KotlinTypeRefiner.Default, - ) - } - - private fun areCompatibleTypes( - a: KotlinType, - b: KotlinType, - typeSystemContext: ClassicTypeSystemContext, - kotlinTypeRefiner: KotlinTypeRefiner, - ): Boolean { - with(NewKotlinTypeCheckerImpl(kotlinTypeRefiner)) { - return createClassicTypeCheckerState( - isErrorTypeEqualsToAnything = false, - typeSystemContext = typeSystemContext, - kotlinTypeRefiner = kotlinTypeRefiner, - ).equalTypes(a.unwrap(), b.unwrap()) - } - } - - // For example, expectedTypeConstructor may be the expected class kotlin.text.StringBuilder, while actualTypeConstructor - // is java.lang.StringBuilder. For the purposes of type compatibility checking, we must consider these types equal here. - // Note that the case of an "actual class" works as expected though, because the actual class by definition has the same FQ name - // as the corresponding expected class, so their type constructors are equal as per AbstractClassTypeConstructor#equals - private fun isExpectedClassAndActualTypeAlias( - expectedTypeConstructor: TypeConstructor, - actualTypeConstructor: TypeConstructor, - platformModule: ModuleDescriptor - ): Boolean { - val expected = expectedTypeConstructor.declarationDescriptor - val actual = actualTypeConstructor.declarationDescriptor - return expected is ClassifierDescriptorWithTypeParameters && - expected.isExpect && - actual is ClassifierDescriptorWithTypeParameters && - expected.findClassifiersFromModule(platformModule, moduleFilter = ALL_MODULES).any { classifier -> - // Note that it's fine to only check that this "actual 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 - // allow simple cases like "actual typealias Foo = FooImpl", see DeclarationsChecker#checkActualTypeAlias - (classifier as? TypeAliasDescriptor)?.classDescriptor == actual - } - } - - private fun areCompatibleTypeLists(a: List, b: List, platformModule: ModuleDescriptor): Boolean { - for (i in a.indices) { - if (!areCompatibleTypes(a[i], b[i], platformModule)) return false - } - return true - } - - private fun areCompatibleTypeParameters( - a: List, - b: List, - platformModule: ModuleDescriptor, - substitutor: Substitutor - ): ExpectActualCompatibility { - for (i in a.indices) { - val aBounds = a[i].upperBounds - val bBounds = b[i].upperBounds - if (aBounds.size != bBounds.size || !areCompatibleTypeLists(aBounds.map(substitutor), bBounds, platformModule)) { - return Incompatible.TypeParameterUpperBounds - } - } - - if (!equalsBy(a, b, TypeParameterDescriptor::getVariance)) return Incompatible.TypeParameterVariance - - // Removing "reified" from an expected function's type parameter is fine - if (a.indices.any { i -> !a[i].isReified && b[i].isReified }) return Incompatible.TypeParameterReified - - return Compatible - } - - private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): ExpectActualCompatibility { - if (!equalBy(a, b) { f -> f.isSuspend }) return Incompatible.FunctionModifiersDifferent - - if (a.isExternal && !b.isExternal || - a.isInfix && !b.isInfix || - a.isInline && !b.isInline || - a.isOperator && !b.isOperator || - a.isTailrec && !b.isTailrec - ) return Incompatible.FunctionModifiersNotSubset - - return Compatible - } - - private fun areCompatibleProperties( - expected: PropertyDescriptor, - actual: PropertyDescriptor, - ): ExpectActualCompatibility { - return when { - !equalBy(expected, actual) { p -> p.isVar } -> Incompatible.PropertyKind - !equalBy(expected, actual) { p -> p.isLateInit } -> Incompatible.PropertyLateinitModifier - expected.isConst && !actual.isConst -> Incompatible.PropertyConstModifier - !arePropertySettersWithCompatibleVisibilities(expected, actual) -> Incompatible.PropertySetterVisibility - else -> Compatible - } - } - - private fun arePropertySettersWithCompatibleVisibilities(expected: PropertyDescriptor, actual: PropertyDescriptor): Boolean { - val expectedSetter = expected.setter - val actualSetter = actual.setter - if (expectedSetter == null || actualSetter == null) { - return true - } - return areDeclarationsWithCompatibleVisibilities(expectedSetter, actualSetter) - } - - private fun areCompatibleClassifiers(a: ClassDescriptor, other: ClassifierDescriptor): ExpectActualCompatibility { - // Can't check FQ names here because nested expected class may be implemented via actual typealias's expansion with the other FQ name - assert(a.name == other.name) { "This function should be invoked only for declarations with the same name: $a, $other" } - - val b = when (other) { - is ClassDescriptor -> other - is TypeAliasDescriptor -> other.classDescriptor ?: return Compatible // do not report extra error on erroneous typealias - else -> throw AssertionError("Incorrect actual classifier for $a: $other") - } - - if (a.kind != b.kind) return Incompatible.ClassKind - - if (!equalBy(a, b) { listOf(it.isCompanionObject, it.isInner, it.isInline || it.isValue) }) return Incompatible.ClassModifiers - if (a.isFun && !b.isFun && b.isNotJavaSamInterface()) { - return Incompatible.FunInterfaceModifier - } - - val aTypeParams = a.declaredTypeParameters - val bTypeParams = b.declaredTypeParameters - if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount - - if (!areCompatibleModalities(a.modality, b.modality)) return Incompatible.Modality - - if (a.visibility != b.visibility) return Incompatible.Visibility - - val platformModule = other.module - val substitutor = Substitutor(aTypeParams, bTypeParams) - areCompatibleTypeParameters(aTypeParams, bTypeParams, platformModule, substitutor).let { if (it != Compatible) return it } - - // Subtract kotlin.Any from supertypes because it's implicitly added if no explicit supertype is specified, - // and not added if an explicit supertype _is_ specified - val aSupertypes = a.typeConstructor.supertypes.filterNot(KotlinBuiltIns::isAny) - val bSupertypes = b.typeConstructor.supertypes.filterNot(KotlinBuiltIns::isAny) - if (aSupertypes.map(substitutor).any { aSupertype -> - bSupertypes.none { bSupertype -> areCompatibleTypes(aSupertype, bSupertype, platformModule) } - } - ) return Incompatible.Supertypes - - areCompatibleClassScopes(a, b, platformModule, substitutor).let { if (it != Compatible) return it } - - return Compatible - } - - private fun areCompatibleModalities(a: Modality, b: Modality): Boolean { - return a == Modality.FINAL && b == Modality.OPEN || - a == b - } - - private fun areDeclarationsWithCompatibleVisibilities( - a: CallableMemberDescriptor, - b: CallableMemberDescriptor - ): Boolean { - val compare = DescriptorVisibilities.compare(a.visibility, b.visibility) - return if (a.isOverridable) { - // For overridable declarations visibility should match precisely, see KT-19664 - compare == 0 - } else { - // For non-overridable declarations actuals are allowed to have more permissive visibility - compare != null && compare <= 0 - } - } - - private fun areCompatibleClassScopes( - a: ClassDescriptor, - b: ClassDescriptor, - platformModule: ModuleDescriptor, - substitutor: Substitutor - ): ExpectActualCompatibility { - val unfulfilled = arrayListOf, MutableCollection>>>() - - val bMembersByName = b.getMembers().groupBy { it.name } - - outer@ for (aMember in a.getMembers()) { - if (aMember is CallableMemberDescriptor && !aMember.kind.isReal) continue - - val bMembers = bMembersByName[aMember.name]?.filter { bMember -> - aMember is CallableMemberDescriptor && bMember is CallableMemberDescriptor || - aMember is ClassDescriptor && bMember is ClassDescriptor - }.orEmpty() - - val mapping = bMembers.keysToMap { bMember -> - when (aMember) { - is CallableMemberDescriptor -> - areCompatibleCallables(aMember, bMember as CallableMemberDescriptor, platformModule, substitutor) - is ClassDescriptor -> - areCompatibleClassifiers(aMember, bMember as ClassDescriptor) - else -> throw UnsupportedOperationException("Unsupported declaration: $aMember ($bMembers)") - } - } - if (mapping.values.any { it == Compatible }) continue - - val incompatibilityMap = mutableMapOf, MutableCollection>() - for ((descriptor, compatibility) in mapping) { - when (compatibility) { - Compatible -> continue@outer - is Incompatible -> incompatibilityMap.getOrPut(compatibility) { SmartList() }.add(descriptor) - } - } - - unfulfilled.add(aMember to incompatibilityMap) - } - - if (a.kind == ClassKind.ENUM_CLASS) { - fun ClassDescriptor.enumEntries() = - unsubstitutedMemberScope.getDescriptorsFiltered().filter(DescriptorUtils::isEnumEntry).map { it.name } - - val aEntries = a.enumEntries() - val bEntries = b.enumEntries() - - if (!bEntries.containsAll(aEntries)) return Incompatible.EnumEntries - } - - // TODO: check static scope? - - if (unfulfilled.isEmpty()) return Compatible - - return Incompatible.ClassScopes(unfulfilled) - } - - private fun ClassDescriptor.getMembers(name: Name? = null): Collection { - val nameFilter = if (name != null) { it -> it == name } else MemberScope.ALL_NAME_FILTER - return defaultType.memberScope - .getDescriptorsFiltered(nameFilter = nameFilter) - .filterIsInstance() - .filterNot(DescriptorUtils::isEnumEntry) - .plus(constructors.filter { nameFilter(it.name) }) - } - - private inline fun equalBy(first: T, second: T, selector: (T) -> K): Boolean = - selector(first) == selector(second) - - private inline fun equalsBy(first: List, second: List, selector: (T) -> K): Boolean { - for (i in first.indices) { - if (selector(first[i]) != selector(second[i])) return false - } - - return true - } - - // This substitutor takes the type from A's signature and returns the type that should be in that place in B's signature - private class Substitutor( - aTypeParams: List, - bTypeParams: List, - private val parent: Substitutor? = null - ) : (KotlinType?) -> KotlinType? { - private val typeSubstitutor = TypeSubstitutor.create( - TypeConstructorSubstitution.createByParametersMap(aTypeParams.keysToMap { - bTypeParams[it.index].defaultType.asTypeProjection() - }) - ) - - override fun invoke(type: KotlinType?): KotlinType? = - (parent?.invoke(type) ?: type)?.asTypeProjection()?.let(typeSubstitutor::substitute)?.type - } } // FIXME(dsavvinov): review clients, as they won't work properly in HMPP projects @@ -576,7 +196,3 @@ fun DeclarationDescriptor.findActuals(inModule: ModuleDescriptor): List { + Substitutable, CallableSymbolMarker { @NotNull @ReadOnly List getContextReceiverParameters(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassConstructorDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassConstructorDescriptor.kt index 7ce3505e99a..35b18fdfa67 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassConstructorDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassConstructorDescriptor.kt @@ -16,10 +16,11 @@ package org.jetbrains.kotlin.descriptors +import org.jetbrains.kotlin.mpp.ConstructorSymbolMarker import org.jetbrains.kotlin.types.TypeSubstitutor -interface ClassConstructorDescriptor : ConstructorDescriptor { +interface ClassConstructorDescriptor : ConstructorDescriptor, ConstructorSymbolMarker { override fun getContainingDeclaration(): ClassDescriptor override fun getOriginal(): ClassConstructorDescriptor diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassDescriptor.java index 7e5619d3530..47e906d9e5e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassDescriptor.java @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors; import kotlin.annotations.jvm.ReadOnly; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker; import org.jetbrains.kotlin.resolve.scopes.MemberScope; import org.jetbrains.kotlin.types.SimpleType; import org.jetbrains.kotlin.types.TypeProjection; @@ -16,7 +17,8 @@ import org.jetbrains.kotlin.types.TypeSubstitution; import java.util.Collection; import java.util.List; -public interface ClassDescriptor extends ClassifierDescriptorWithTypeParameters, ClassOrPackageFragmentDescriptor { +public interface ClassDescriptor extends ClassifierDescriptorWithTypeParameters, ClassOrPackageFragmentDescriptor, + RegularClassSymbolMarker { @NotNull MemberScope getMemberScope(@NotNull List typeArguments); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassifierDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassifierDescriptor.java index ca95ce4247b..9f3f61ed479 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassifierDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassifierDescriptor.java @@ -17,10 +17,11 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.mpp.ClassifierSymbolMarker; import org.jetbrains.kotlin.types.SimpleType; import org.jetbrains.kotlin.types.TypeConstructor; -public interface ClassifierDescriptor extends DeclarationDescriptorNonRoot { +public interface ClassifierDescriptor extends DeclarationDescriptorNonRoot, ClassifierSymbolMarker { @NotNull TypeConstructor getTypeConstructor(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassifierDescriptorWithTypeParameters.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassifierDescriptorWithTypeParameters.java index 59d130ca5f7..8eb28377c1e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassifierDescriptorWithTypeParameters.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassifierDescriptorWithTypeParameters.java @@ -18,12 +18,14 @@ package org.jetbrains.kotlin.descriptors; import kotlin.annotations.jvm.ReadOnly; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.mpp.ClassLikeSymbolMarker; +import org.jetbrains.kotlin.mpp.ClassifierSymbolMarker; import java.util.List; public interface ClassifierDescriptorWithTypeParameters extends ClassifierDescriptor, DeclarationDescriptorWithVisibility, MemberDescriptor, - Substitutable { + Substitutable, ClassLikeSymbolMarker, ClassifierSymbolMarker { /** * @return true if this class contains a reference to its outer class (as opposed to static nested class) */ diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/DeclarationDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/DeclarationDescriptor.java index 254f6690826..f48dee7b19d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/DeclarationDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/DeclarationDescriptor.java @@ -19,8 +19,9 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.annotations.Annotated; +import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker; -public interface DeclarationDescriptor extends Annotated, Named, ValidateableDescriptor { +public interface DeclarationDescriptor extends Annotated, Named, ValidateableDescriptor, DeclarationSymbolMarker { /** * @return The descriptor that corresponds to the original declaration of this element. * A descriptor can be obtained from its original by substituting type arguments (of the declaring class diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java index fac13c824f0..4809109af43 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.annotations.Annotations; +import org.jetbrains.kotlin.mpp.FunctionSymbolMarker; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.TypeSubstitution; @@ -16,7 +17,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor; import java.util.Collection; import java.util.List; -public interface FunctionDescriptor extends CallableMemberDescriptor { +public interface FunctionDescriptor extends CallableMemberDescriptor, FunctionSymbolMarker { @Override @NotNull DeclarationDescriptor getContainingDeclaration(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyDescriptor.java index cb5ca7ccae4..35a04207f56 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyDescriptor.java @@ -18,13 +18,14 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.mpp.PropertySymbolMarker; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.TypeSubstitutor; import java.util.Collection; import java.util.List; -public interface PropertyDescriptor extends VariableDescriptorWithAccessors, CallableMemberDescriptor { +public interface PropertyDescriptor extends VariableDescriptorWithAccessors, CallableMemberDescriptor, PropertySymbolMarker { @Override @Nullable PropertyGetterDescriptor getGetter(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/SimpleFunctionDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/SimpleFunctionDescriptor.java index 520ce27d4c7..2029b8fa876 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/SimpleFunctionDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/SimpleFunctionDescriptor.java @@ -17,11 +17,12 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.mpp.SimpleFunctionSymbolMarker; /** * Simple functions are the ones with 'fun' keyword and function literals */ -public interface SimpleFunctionDescriptor extends FunctionDescriptor { +public interface SimpleFunctionDescriptor extends FunctionDescriptor, SimpleFunctionSymbolMarker { @NotNull @Override SimpleFunctionDescriptor copy(DeclarationDescriptor newOwner, Modality modality, DescriptorVisibility visibility, Kind kind, boolean copyOverrides); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeAliasDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeAliasDescriptor.kt index a8a4f4649e8..441fea2339a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeAliasDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeAliasDescriptor.kt @@ -17,9 +17,10 @@ package org.jetbrains.kotlin.descriptors import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor +import org.jetbrains.kotlin.mpp.TypeAliasSymbolMarker import org.jetbrains.kotlin.types.SimpleType -interface TypeAliasDescriptor : ClassifierDescriptorWithTypeParameters { +interface TypeAliasDescriptor : ClassifierDescriptorWithTypeParameters, TypeAliasSymbolMarker { /// Right-hand side of the type alias definition. /// May contain type aliases. val underlyingType: SimpleType diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java index e322d676da9..b5f1755db39 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.mpp.TypeParameterSymbolMarker; import org.jetbrains.kotlin.storage.StorageManager; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.TypeConstructor; @@ -25,7 +26,7 @@ import org.jetbrains.kotlin.types.model.TypeParameterMarker; import java.util.List; -public interface TypeParameterDescriptor extends ClassifierDescriptor, TypeParameterMarker { +public interface TypeParameterDescriptor extends ClassifierDescriptor, TypeParameterMarker, TypeParameterSymbolMarker { boolean isReified(); @NotNull diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ValueParameterDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ValueParameterDescriptor.kt index 8d02d6b865a..67ec107c424 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ValueParameterDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ValueParameterDescriptor.kt @@ -16,11 +16,12 @@ package org.jetbrains.kotlin.descriptors +import org.jetbrains.kotlin.mpp.ValueParameterSymbolMarker import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeSubstitutor -interface ValueParameterDescriptor : VariableDescriptor, ParameterDescriptor { +interface ValueParameterDescriptor : VariableDescriptor, ParameterDescriptor, ValueParameterSymbolMarker { override fun getContainingDeclaration(): CallableDescriptor /**