[FE 1.0] Provide implementation of ExpectActualMatchingContext for FE 1.0

^KT-58578
This commit is contained in:
Dmitriy Novozhilov
2023-05-11 13:24:59 +03:00
committed by Space Team
parent b26b649d4e
commit 8338370fbd
14 changed files with 410 additions and 454 deletions
@@ -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<MemberDescriptor>,
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 <reified T : DeclarationDescriptor> 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<ClassDescriptor>()?.isCompanionObject == true
override val RegularClassSymbolMarker.isInner: Boolean
get() = asDescriptor().isInner
override val RegularClassSymbolMarker.isInline: Boolean
get() = safeAsDescriptor<ClassDescriptor>()?.isInline == true
override val RegularClassSymbolMarker.isValue: Boolean
get() = safeAsDescriptor<ClassDescriptor>()?.isValue == true
override val RegularClassSymbolMarker.isFun: Boolean
get() = safeAsDescriptor<ClassDescriptor>()?.isFun == true
override val ClassLikeSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
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<CallableMemberDescriptor>()?.modality
override val CallableSymbolMarker.visibility: Visibility
get() = asDescriptor().visibility.delegate
override val RegularClassSymbolMarker.superTypes: List<KotlinTypeMarker>
get() = asDescriptor().typeConstructor.supertypes.toList()
override val CallableSymbolMarker.isExpect: Boolean
get() = safeAsDescriptor<MemberDescriptor>()?.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<MemberDescriptor>()?.isExternal == true
override val CallableSymbolMarker.isInfix: Boolean
get() = safeAsDescriptor<FunctionDescriptor>()?.isInfix == true
override val CallableSymbolMarker.isOperator: Boolean
get() = safeAsDescriptor<FunctionDescriptor>()?.isOperator == true
override val CallableSymbolMarker.isTailrec: Boolean
get() = safeAsDescriptor<FunctionDescriptor>()?.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<TypeParameterSymbolMarker>,
actualTypeParameters: List<TypeParameterSymbolMarker>,
parentSubstitutor: TypeSubstitutorMarker?,
): TypeSubstitutorMarker {
val expectParameters = expectTypeParameters.castAll<TypeParameterDescriptor>()
val actualParameters = actualTypeParameters.castAll<TypeParameterDescriptor>()
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<DeclarationSymbolMarker> {
return asDescriptor().getMembers(name = null)
}
override fun RegularClassSymbolMarker.getMembersForExpectClass(name: Name): List<DeclarationSymbolMarker> {
return asDescriptor().getMembers(name)
}
private fun ClassDescriptor.getMembers(name: Name? = null): List<MemberDescriptor> {
val nameFilter = if (name != null) { it -> it == name } else MemberScope.ALL_NAME_FILTER
return defaultType.memberScope
.getDescriptorsFiltered(nameFilter = nameFilter)
.filterIsInstance<MemberDescriptor>()
.filterNot(DescriptorUtils::isEnumEntry)
.plus(constructors.filter { nameFilter(it.name) })
}
override fun RegularClassSymbolMarker.collectEnumEntryNames(): List<Name> {
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<TypeParameterSymbolMarker>
get() = asDescriptor().typeParameters
override val FunctionSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
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<ConstructorDescriptor>() ?: return false
return DescriptorUtils.isAnnotationClass(descriptor.constructedClass)
}
override val TypeParameterSymbolMarker.bounds: List<KotlinTypeMarker>
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<A, B> = FooImpl<A, B>", see DeclarationsChecker#checkActualTypeAlias
(classifier as? TypeAliasDescriptor)?.classDescriptor == actual
}
}
fun findClassifiersFromModule(
classId: ClassId?,
module: ModuleDescriptor,
moduleFilter: (ModuleDescriptor) -> Boolean
): Collection<ClassifierDescriptorWithTypeParameters> {
if (classId == null) return emptyList()
fun MemberScope.getAllClassifiers(name: Name): Collection<ClassifierDescriptorWithTypeParameters> =
getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name }
.filterIsInstance<ClassifierDescriptorWithTypeParameters>()
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<CallableMemberDescriptor>()?.kind?.isReal == false
}
override val CallableSymbolMarker.hasStableParameterNames: Boolean
get() = asDescriptor().hasStableParameterNames()
}
@@ -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<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
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<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
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<CallableMemberDescriptor>().orEmpty()
with(context) {
expectedClass?.getMembersForExpectClass(actual.name)?.filterIsInstance<CallableMemberDescriptor>().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<CallableMemberDescriptor> {
@@ -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<ClassDescriptor>()
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<ClassifierDescriptorWithTypeParameters> {
val classId = classId ?: return emptyList()
fun MemberScope.getAllClassifiers(name: Name): Collection<ClassifierDescriptorWithTypeParameters> =
getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name }
.filterIsInstance<ClassifierDescriptorWithTypeParameters>()
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<MemberDescriptor> {
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<ValueParameterDescriptor>,
bParams: List<ValueParameterDescriptor>
): 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<A, B> = FooImpl<A, B>", see DeclarationsChecker#checkActualTypeAlias
(classifier as? TypeAliasDescriptor)?.classDescriptor == actual
}
}
private fun areCompatibleTypeLists(a: List<KotlinType?>, b: List<KotlinType?>, platformModule: ModuleDescriptor): Boolean {
for (i in a.indices) {
if (!areCompatibleTypes(a[i], b[i], platformModule)) return false
}
return true
}
private fun areCompatibleTypeParameters(
a: List<TypeParameterDescriptor>,
b: List<TypeParameterDescriptor>,
platformModule: ModuleDescriptor,
substitutor: Substitutor
): ExpectActualCompatibility<MemberDescriptor> {
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<MemberDescriptor> {
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<MemberDescriptor> {
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<MemberDescriptor> {
// 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<MemberDescriptor> {
val unfulfilled = arrayListOf<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, MutableCollection<MemberDescriptor>>>>()
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<Incompatible<MemberDescriptor>, MutableCollection<MemberDescriptor>>()
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<MemberDescriptor> {
val nameFilter = if (name != null) { it -> it == name } else MemberScope.ALL_NAME_FILTER
return defaultType.memberScope
.getDescriptorsFiltered(nameFilter = nameFilter)
.filterIsInstance<MemberDescriptor>()
.filterNot(DescriptorUtils::isEnumEntry)
.plus(constructors.filter { nameFilter(it.name) })
}
private inline fun <T, K> equalBy(first: T, second: T, selector: (T) -> K): Boolean =
selector(first) == selector(second)
private inline fun <T, K> equalsBy(first: List<T>, second: List<T>, 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<TypeParameterDescriptor>,
bTypeParams: List<TypeParameterDescriptor>,
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<MemberDe
val DeclarationDescriptorWithSource.couldHaveASource: Boolean
get() = this.source.containingFile != SourceFile.NO_SOURCE_FILE ||
this is DeserializedDescriptor
private fun ClassDescriptor.isNotJavaSamInterface(): Boolean {
return isDefinitelyNotSamInterface || defaultFunctionTypeForSamInterface == null
}
@@ -19,13 +19,14 @@ 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.CallableSymbolMarker;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.Collection;
import java.util.List;
public interface CallableDescriptor extends DeclarationDescriptorWithVisibility, DeclarationDescriptorNonRoot,
Substitutable<CallableDescriptor> {
Substitutable<CallableDescriptor>, CallableSymbolMarker {
@NotNull
@ReadOnly
List<ReceiverParameterDescriptor> getContextReceiverParameters();
@@ -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
@@ -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<? extends TypeProjection> typeArguments);
@@ -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();
@@ -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<ClassifierDescriptorWithTypeParameters> {
Substitutable<ClassifierDescriptorWithTypeParameters>, ClassLikeSymbolMarker, ClassifierSymbolMarker {
/**
* @return <code>true</code> if this class contains a reference to its outer class (as opposed to static nested class)
*/
@@ -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
@@ -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();
@@ -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();
@@ -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);
@@ -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
@@ -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
@@ -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
/**