[FE 1.0] Provide implementation of ExpectActualMatchingContext for FE 1.0
^KT-58578
This commit is contained in:
committed by
Space Team
parent
b26b649d4e
commit
8338370fbd
+326
@@ -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()
|
||||||
|
}
|
||||||
+58
-442
@@ -5,48 +5,49 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.multiplatform
|
package org.jetbrains.kotlin.resolve.multiplatform
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualCompatibilityChecker
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Compatible
|
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.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
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
|
|
||||||
|
|
||||||
object ExpectedActualResolver {
|
object ExpectedActualResolver {
|
||||||
|
|
||||||
fun findActualForExpected(
|
fun findActualForExpected(
|
||||||
expected: MemberDescriptor,
|
expected: MemberDescriptor,
|
||||||
platformModule: ModuleDescriptor,
|
platformModule: ModuleDescriptor,
|
||||||
moduleVisibilityFilter: ModuleFilter = allModulesProvidingActualsFor(expected.module, platformModule),
|
moduleVisibilityFilter: ModuleFilter = allModulesProvidingActualsFor(expected.module, platformModule),
|
||||||
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
|
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
|
||||||
|
val context = ClassicExpectActualMatchingContext(platformModule)
|
||||||
return when (expected) {
|
return when (expected) {
|
||||||
is CallableMemberDescriptor -> {
|
is CallableMemberDescriptor -> {
|
||||||
expected.findNamesakesFromModule(platformModule, moduleVisibilityFilter).filter { actual ->
|
expected.findNamesakesFromModule(context, platformModule, moduleVisibilityFilter).filter { actual ->
|
||||||
expected != actual && !actual.isExpect &&
|
expected != actual && !actual.isExpect &&
|
||||||
// TODO: use some other way to determine that the declaration is from Kotlin.
|
// 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
|
// This way behavior differs between fast and PSI-based Java class reading mode
|
||||||
// TODO: support non-source definitions (e.g. from Java)
|
// TODO: support non-source definitions (e.g. from Java)
|
||||||
actual.couldHaveASource
|
actual.couldHaveASource
|
||||||
}.groupBy { actual ->
|
}.groupBy { actual ->
|
||||||
areCompatibleCallables(expected, actual, platformModule)
|
AbstractExpectActualCompatibilityChecker.areCompatibleCallables(
|
||||||
|
expected,
|
||||||
|
actual,
|
||||||
|
parentSubstitutor = null,
|
||||||
|
expectContainingClass = null,
|
||||||
|
actualContainingClass = null,
|
||||||
|
context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is ClassDescriptor -> {
|
is ClassDescriptor -> {
|
||||||
expected.findClassifiersFromModule(platformModule, moduleVisibilityFilter).filter { actual ->
|
context.findClassifiersFromModule(expected.classId, platformModule, moduleVisibilityFilter).filter { actual ->
|
||||||
expected != actual && !actual.isExpect && actual.couldHaveASource
|
expected != actual && !actual.isExpect && actual.couldHaveASource
|
||||||
}.groupBy { actual ->
|
}.groupBy { actual ->
|
||||||
areCompatibleClassifiers(expected, actual)
|
AbstractExpectActualCompatibilityChecker.areCompatibleClassifiers(
|
||||||
|
expected,
|
||||||
|
actual,
|
||||||
|
context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
@@ -57,6 +58,7 @@ object ExpectedActualResolver {
|
|||||||
actual: MemberDescriptor,
|
actual: MemberDescriptor,
|
||||||
moduleFilter: (ModuleDescriptor) -> Boolean = allModulesProvidingExpectsFor(actual.module)
|
moduleFilter: (ModuleDescriptor) -> Boolean = allModulesProvidingExpectsFor(actual.module)
|
||||||
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
|
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
|
||||||
|
val context = ClassicExpectActualMatchingContext(actual.module)
|
||||||
return when (actual) {
|
return when (actual) {
|
||||||
is CallableMemberDescriptor -> {
|
is CallableMemberDescriptor -> {
|
||||||
val container = actual.containingDeclaration
|
val container = actual.containingDeclaration
|
||||||
@@ -65,9 +67,11 @@ object ExpectedActualResolver {
|
|||||||
// TODO: replace with 'singleOrNull' as soon as multi-module diagnostic tests are refactored
|
// TODO: replace with 'singleOrNull' as soon as multi-module diagnostic tests are refactored
|
||||||
val expectedClass =
|
val expectedClass =
|
||||||
findExpectedForActual(container, moduleFilter)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor
|
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
|
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
|
actual != declaration && declaration.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && declaration.isExpect
|
||||||
}.groupBy { declaration ->
|
}.groupBy { declaration ->
|
||||||
// TODO: optimize by caching this per actual-expected class pair, do not create a new substitutor for each actual member
|
// 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 =
|
val substitutor =
|
||||||
if (container is ClassDescriptor) {
|
when (container) {
|
||||||
val expectedClass = declaration.containingDeclaration as ClassDescriptor
|
is ClassDescriptor -> {
|
||||||
// TODO: this might not work for members of inner generic classes
|
actualClass = container
|
||||||
if (expectedClass.declaredTypeParameters.size == container.declaredTypeParameters.size) {
|
expectedClass = declaration.containingDeclaration as ClassDescriptor
|
||||||
Substitutor(expectedClass.declaredTypeParameters, container.declaredTypeParameters)
|
// TODO: this might not work for members of inner generic classes
|
||||||
} else null
|
runIf(expectedClass.declaredTypeParameters.size == container.declaredTypeParameters.size) {
|
||||||
} else null
|
context.createExpectActualTypeParameterSubstitutor(
|
||||||
areCompatibleCallables(declaration, actual, parentSubstitutor = substitutor)
|
expectedClass.declaredTypeParameters,
|
||||||
|
container.declaredTypeParameters,
|
||||||
|
parentSubstitutor = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
AbstractExpectActualCompatibilityChecker.areCompatibleCallables(
|
||||||
|
expectDeclaration = declaration,
|
||||||
|
actualDeclaration = actual,
|
||||||
|
parentSubstitutor = substitutor,
|
||||||
|
expectContainingClass = expectedClass,
|
||||||
|
actualContainingClass = actualClass,
|
||||||
|
context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is ClassifierDescriptorWithTypeParameters -> {
|
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
|
actual != declaration && declaration is ClassDescriptor && declaration.isExpect
|
||||||
}.groupBy { expected ->
|
}.groupBy { expected ->
|
||||||
areCompatibleClassifiers(expected as ClassDescriptor, actual)
|
AbstractExpectActualCompatibilityChecker.areCompatibleClassifiers(
|
||||||
|
expected as ClassDescriptor,
|
||||||
|
actual,
|
||||||
|
context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
@@ -98,6 +123,7 @@ object ExpectedActualResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun CallableMemberDescriptor.findNamesakesFromModule(
|
private fun CallableMemberDescriptor.findNamesakesFromModule(
|
||||||
|
context: ClassicExpectActualMatchingContext,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
moduleFilter: (ModuleDescriptor) -> Boolean
|
moduleFilter: (ModuleDescriptor) -> Boolean
|
||||||
): Collection<CallableMemberDescriptor> {
|
): Collection<CallableMemberDescriptor> {
|
||||||
@@ -106,7 +132,7 @@ object ExpectedActualResolver {
|
|||||||
listOf(module.getPackage(containingDeclaration.fqName).memberScope)
|
listOf(module.getPackage(containingDeclaration.fqName).memberScope)
|
||||||
}
|
}
|
||||||
is ClassDescriptor -> {
|
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 }
|
.mapNotNull { if (it is TypeAliasDescriptor) it.classDescriptor else it }
|
||||||
.filterIsInstance<ClassDescriptor>()
|
.filterIsInstance<ClassDescriptor>()
|
||||||
if (this is ConstructorDescriptor) return classes.flatMap { it.constructors }
|
if (this is ConstructorDescriptor) return classes.flatMap { it.constructors }
|
||||||
@@ -132,412 +158,6 @@ object ExpectedActualResolver {
|
|||||||
else -> throw AssertionError("Unsupported declaration: $this")
|
else -> throw AssertionError("Unsupported declaration: $this")
|
||||||
}.applyFilter(moduleFilter)
|
}.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
|
// 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
|
val DeclarationDescriptorWithSource.couldHaveASource: Boolean
|
||||||
get() = this.source.containingFile != SourceFile.NO_SOURCE_FILE ||
|
get() = this.source.containingFile != SourceFile.NO_SOURCE_FILE ||
|
||||||
this is DeserializedDescriptor
|
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 kotlin.annotations.jvm.ReadOnly;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.mpp.CallableSymbolMarker;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface CallableDescriptor extends DeclarationDescriptorWithVisibility, DeclarationDescriptorNonRoot,
|
public interface CallableDescriptor extends DeclarationDescriptorWithVisibility, DeclarationDescriptorNonRoot,
|
||||||
Substitutable<CallableDescriptor> {
|
Substitutable<CallableDescriptor>, CallableSymbolMarker {
|
||||||
@NotNull
|
@NotNull
|
||||||
@ReadOnly
|
@ReadOnly
|
||||||
List<ReceiverParameterDescriptor> getContextReceiverParameters();
|
List<ReceiverParameterDescriptor> getContextReceiverParameters();
|
||||||
|
|||||||
@@ -16,10 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.descriptors
|
package org.jetbrains.kotlin.descriptors
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.mpp.ConstructorSymbolMarker
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
|
|
||||||
interface ClassConstructorDescriptor : ConstructorDescriptor {
|
interface ClassConstructorDescriptor : ConstructorDescriptor, ConstructorSymbolMarker {
|
||||||
override fun getContainingDeclaration(): ClassDescriptor
|
override fun getContainingDeclaration(): ClassDescriptor
|
||||||
|
|
||||||
override fun getOriginal(): ClassConstructorDescriptor
|
override fun getOriginal(): ClassConstructorDescriptor
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors;
|
|||||||
import kotlin.annotations.jvm.ReadOnly;
|
import kotlin.annotations.jvm.ReadOnly;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||||
import org.jetbrains.kotlin.types.SimpleType;
|
import org.jetbrains.kotlin.types.SimpleType;
|
||||||
import org.jetbrains.kotlin.types.TypeProjection;
|
import org.jetbrains.kotlin.types.TypeProjection;
|
||||||
@@ -16,7 +17,8 @@ import org.jetbrains.kotlin.types.TypeSubstitution;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ClassDescriptor extends ClassifierDescriptorWithTypeParameters, ClassOrPackageFragmentDescriptor {
|
public interface ClassDescriptor extends ClassifierDescriptorWithTypeParameters, ClassOrPackageFragmentDescriptor,
|
||||||
|
RegularClassSymbolMarker {
|
||||||
@NotNull
|
@NotNull
|
||||||
MemberScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments);
|
MemberScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments);
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,11 @@
|
|||||||
package org.jetbrains.kotlin.descriptors;
|
package org.jetbrains.kotlin.descriptors;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.mpp.ClassifierSymbolMarker;
|
||||||
import org.jetbrains.kotlin.types.SimpleType;
|
import org.jetbrains.kotlin.types.SimpleType;
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor;
|
import org.jetbrains.kotlin.types.TypeConstructor;
|
||||||
|
|
||||||
public interface ClassifierDescriptor extends DeclarationDescriptorNonRoot {
|
public interface ClassifierDescriptor extends DeclarationDescriptorNonRoot, ClassifierSymbolMarker {
|
||||||
@NotNull
|
@NotNull
|
||||||
TypeConstructor getTypeConstructor();
|
TypeConstructor getTypeConstructor();
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -18,12 +18,14 @@ package org.jetbrains.kotlin.descriptors;
|
|||||||
|
|
||||||
import kotlin.annotations.jvm.ReadOnly;
|
import kotlin.annotations.jvm.ReadOnly;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.mpp.ClassLikeSymbolMarker;
|
||||||
|
import org.jetbrains.kotlin.mpp.ClassifierSymbolMarker;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ClassifierDescriptorWithTypeParameters
|
public interface ClassifierDescriptorWithTypeParameters
|
||||||
extends ClassifierDescriptor, DeclarationDescriptorWithVisibility, MemberDescriptor,
|
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)
|
* @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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
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.
|
* @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
|
* 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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
|
import org.jetbrains.kotlin.mpp.FunctionSymbolMarker;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitution;
|
import org.jetbrains.kotlin.types.TypeSubstitution;
|
||||||
@@ -16,7 +17,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface FunctionDescriptor extends CallableMemberDescriptor {
|
public interface FunctionDescriptor extends CallableMemberDescriptor, FunctionSymbolMarker {
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
DeclarationDescriptor getContainingDeclaration();
|
DeclarationDescriptor getContainingDeclaration();
|
||||||
|
|||||||
@@ -18,13 +18,14 @@ package org.jetbrains.kotlin.descriptors;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.mpp.PropertySymbolMarker;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface PropertyDescriptor extends VariableDescriptorWithAccessors, CallableMemberDescriptor {
|
public interface PropertyDescriptor extends VariableDescriptorWithAccessors, CallableMemberDescriptor, PropertySymbolMarker {
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
PropertyGetterDescriptor getGetter();
|
PropertyGetterDescriptor getGetter();
|
||||||
|
|||||||
@@ -17,11 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.descriptors;
|
package org.jetbrains.kotlin.descriptors;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.mpp.SimpleFunctionSymbolMarker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple functions are the ones with 'fun' keyword and function literals
|
* Simple functions are the ones with 'fun' keyword and function literals
|
||||||
*/
|
*/
|
||||||
public interface SimpleFunctionDescriptor extends FunctionDescriptor {
|
public interface SimpleFunctionDescriptor extends FunctionDescriptor, SimpleFunctionSymbolMarker {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
SimpleFunctionDescriptor copy(DeclarationDescriptor newOwner, Modality modality, DescriptorVisibility visibility, Kind kind, boolean copyOverrides);
|
SimpleFunctionDescriptor copy(DeclarationDescriptor newOwner, Modality modality, DescriptorVisibility visibility, Kind kind, boolean copyOverrides);
|
||||||
|
|||||||
@@ -17,9 +17,10 @@
|
|||||||
package org.jetbrains.kotlin.descriptors
|
package org.jetbrains.kotlin.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.mpp.TypeAliasSymbolMarker
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
|
|
||||||
interface TypeAliasDescriptor : ClassifierDescriptorWithTypeParameters {
|
interface TypeAliasDescriptor : ClassifierDescriptorWithTypeParameters, TypeAliasSymbolMarker {
|
||||||
/// Right-hand side of the type alias definition.
|
/// Right-hand side of the type alias definition.
|
||||||
/// May contain type aliases.
|
/// May contain type aliases.
|
||||||
val underlyingType: SimpleType
|
val underlyingType: SimpleType
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.descriptors;
|
package org.jetbrains.kotlin.descriptors;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.mpp.TypeParameterSymbolMarker;
|
||||||
import org.jetbrains.kotlin.storage.StorageManager;
|
import org.jetbrains.kotlin.storage.StorageManager;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor;
|
import org.jetbrains.kotlin.types.TypeConstructor;
|
||||||
@@ -25,7 +26,7 @@ import org.jetbrains.kotlin.types.model.TypeParameterMarker;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface TypeParameterDescriptor extends ClassifierDescriptor, TypeParameterMarker {
|
public interface TypeParameterDescriptor extends ClassifierDescriptor, TypeParameterMarker, TypeParameterSymbolMarker {
|
||||||
boolean isReified();
|
boolean isReified();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -16,11 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.descriptors
|
package org.jetbrains.kotlin.descriptors
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.mpp.ValueParameterSymbolMarker
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
interface ValueParameterDescriptor : VariableDescriptor, ParameterDescriptor {
|
interface ValueParameterDescriptor : VariableDescriptor, ParameterDescriptor, ValueParameterSymbolMarker {
|
||||||
override fun getContainingDeclaration(): CallableDescriptor
|
override fun getContainingDeclaration(): CallableDescriptor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user