FIR Java: implement correct type matching in SuperTypeScope
This commit is contained in:
@@ -19,9 +19,9 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
|
||||
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
|
||||
import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteMemberScope
|
||||
import org.jetbrains.kotlin.fir.java.scopes.JavaSuperTypeScope
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
@@ -109,7 +109,7 @@ class JavaSymbolProvider(
|
||||
}
|
||||
JavaClassUseSiteMemberScope(
|
||||
regularClass, useSiteSession,
|
||||
FirSuperTypeScope(useSiteSession, superTypeEnhancementScopes), declaredScope
|
||||
JavaSuperTypeScope(regularClass, useSiteSession, superTypeEnhancementScopes), declaredScope
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-85
@@ -5,24 +5,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.java.scopes
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
||||
import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable
|
||||
import org.jetbrains.kotlin.fir.java.toNotNullConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.*
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.STOP
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class JavaClassUseSiteMemberScope(
|
||||
@@ -30,84 +24,14 @@ class JavaClassUseSiteMemberScope(
|
||||
session: FirSession,
|
||||
superTypesScope: FirSuperTypeScope,
|
||||
declaredMemberScope: FirScope
|
||||
) : AbstractFirUseSiteMemberScope(session, superTypesScope, declaredMemberScope) {
|
||||
) : AbstractFirUseSiteMemberScope(
|
||||
session,
|
||||
JavaOverrideChecker(session, if (klass is FirJavaClass) klass.javaTypeParameterStack else JavaTypeParameterStack.EMPTY),
|
||||
superTypesScope,
|
||||
declaredMemberScope
|
||||
) {
|
||||
internal val symbol = klass.symbol
|
||||
|
||||
private val javaTypeParameterStack: JavaTypeParameterStack =
|
||||
if (klass is FirJavaClass) klass.javaTypeParameterStack else JavaTypeParameterStack.EMPTY
|
||||
|
||||
private fun isEqualTypes(a: ConeKotlinType, b: ConeKotlinType, substitutor: ConeSubstitutor): Boolean {
|
||||
if (a is ConeFlexibleType) return isEqualTypes(a.lowerBound, b, substitutor)
|
||||
if (b is ConeFlexibleType) return isEqualTypes(a, b.lowerBound, substitutor)
|
||||
return if (a is ConeClassType && b is ConeClassType) {
|
||||
a.lookupTag.classId.let { it.readOnlyToMutable() ?: it } == b.lookupTag.classId.let { it.readOnlyToMutable() ?: it }
|
||||
} else {
|
||||
with(context) {
|
||||
isEqualTypeConstructors(
|
||||
substitutor.substituteOrSelf(a).typeConstructor(),
|
||||
substitutor.substituteOrSelf(b).typeConstructor()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isEqualTypes(a: FirTypeRef, b: FirTypeRef, substitutor: ConeSubstitutor) =
|
||||
isEqualTypes(
|
||||
a.toNotNullConeKotlinType(session, javaTypeParameterStack),
|
||||
b.toNotNullConeKotlinType(session, javaTypeParameterStack),
|
||||
substitutor
|
||||
)
|
||||
|
||||
override fun isOverriddenFunCheck(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
||||
// NB: overrideCandidate is from Java and has no receiver
|
||||
val receiverTypeRef = baseDeclaration.receiverTypeRef
|
||||
val baseParameterTypes = listOfNotNull(receiverTypeRef) + baseDeclaration.valueParameters.map { it.returnTypeRef }
|
||||
|
||||
if (overrideCandidate.valueParameters.size != baseParameterTypes.size) return false
|
||||
if (overrideCandidate.typeParameters.size != baseDeclaration.typeParameters.size) return false
|
||||
|
||||
val types = baseDeclaration.typeParameters.map {
|
||||
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
|
||||
}
|
||||
val substitution = substitutorByMap(overrideCandidate.typeParameters.map { it.symbol }.zip(types).toMap())
|
||||
if (!overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).all { (a, b) ->
|
||||
a.bounds.size == b.bounds.size && a.bounds.zip(b.bounds).all { (aBound, bBound) ->
|
||||
isEqualTypes(aBound, bBound, substitution)
|
||||
}
|
||||
}
|
||||
) return false
|
||||
|
||||
|
||||
return overrideCandidate.valueParameters.zip(baseParameterTypes).all { (paramFromJava, baseType) ->
|
||||
isEqualTypes(paramFromJava.returnTypeRef, baseType, substitution)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isOverriddenPropertyCheck(overrideCandidate: FirCallableMemberDeclaration<*>, baseDeclaration: FirProperty): Boolean {
|
||||
if (baseDeclaration.modality == Modality.FINAL) return false
|
||||
val receiverTypeRef = baseDeclaration.receiverTypeRef
|
||||
return when (overrideCandidate) {
|
||||
is FirSimpleFunction -> {
|
||||
if (receiverTypeRef == null) {
|
||||
// TODO: setters
|
||||
return overrideCandidate.valueParameters.isEmpty()
|
||||
} else {
|
||||
if (overrideCandidate.valueParameters.size != 1) return false
|
||||
return isEqualTypes(receiverTypeRef, overrideCandidate.valueParameters.single().returnTypeRef, ConeSubstitutor.Empty)
|
||||
}
|
||||
}
|
||||
is FirProperty -> {
|
||||
val overrideReceiverTypeRef = overrideCandidate.receiverTypeRef
|
||||
return when {
|
||||
receiverTypeRef == null -> overrideReceiverTypeRef == null
|
||||
overrideReceiverTypeRef == null -> false
|
||||
else -> isEqualTypes(receiverTypeRef, overrideReceiverTypeRef, ConeSubstitutor.Empty)
|
||||
}
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
internal fun bindOverrides(name: Name) {
|
||||
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
||||
declaredMemberScope.processFunctionsByName(name) {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir.java.scopes
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.modality
|
||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||
import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable
|
||||
import org.jetbrains.kotlin.fir.java.toNotNullConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
|
||||
class JavaOverrideChecker internal constructor(
|
||||
private val session: FirSession,
|
||||
private val javaTypeParameterStack: JavaTypeParameterStack
|
||||
) : FirAbstractOverrideChecker() {
|
||||
private val context: ConeTypeContext = session.typeContext
|
||||
|
||||
private fun isEqualTypes(candidateType: ConeKotlinType, baseType: ConeKotlinType, substitutor: ConeSubstitutor): Boolean {
|
||||
if (candidateType is ConeFlexibleType) return isEqualTypes(candidateType.lowerBound, baseType, substitutor)
|
||||
if (baseType is ConeFlexibleType) return isEqualTypes(candidateType, baseType.lowerBound, substitutor)
|
||||
return if (candidateType is ConeClassType && baseType is ConeClassType) {
|
||||
candidateType.lookupTag.classId.let { it.readOnlyToMutable() ?: it } == baseType.lookupTag.classId.let { it.readOnlyToMutable() ?: it }
|
||||
} else {
|
||||
with(context) {
|
||||
isEqualTypeConstructors(
|
||||
substitutor.substituteOrSelf(candidateType).typeConstructor(),
|
||||
substitutor.substituteOrSelf(baseType).typeConstructor()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isEqualTypes(candidateTypeRef: FirTypeRef, baseTypeRef: FirTypeRef, substitutor: ConeSubstitutor) =
|
||||
isEqualTypes(
|
||||
candidateTypeRef.toNotNullConeKotlinType(session, javaTypeParameterStack),
|
||||
baseTypeRef.toNotNullConeKotlinType(session, javaTypeParameterStack),
|
||||
substitutor
|
||||
)
|
||||
|
||||
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
||||
// NB: overrideCandidate is from Java and has no receiver
|
||||
val receiverTypeRef = baseDeclaration.receiverTypeRef
|
||||
val baseParameterTypes = listOfNotNull(receiverTypeRef) + baseDeclaration.valueParameters.map { it.returnTypeRef }
|
||||
|
||||
if (overrideCandidate.valueParameters.size != baseParameterTypes.size) return false
|
||||
val substitutor = getSubstitutorIfTypeParametersAreCompatible(overrideCandidate, baseDeclaration) ?: return false
|
||||
|
||||
return overrideCandidate.valueParameters.zip(baseParameterTypes).all { (paramFromJava, baseType) ->
|
||||
isEqualTypes(paramFromJava.returnTypeRef, baseType, substitutor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isOverriddenProperty(overrideCandidate: FirCallableMemberDeclaration<*>, baseDeclaration: FirProperty): Boolean {
|
||||
if (baseDeclaration.modality == Modality.FINAL) return false
|
||||
val receiverTypeRef = baseDeclaration.receiverTypeRef
|
||||
return when (overrideCandidate) {
|
||||
is FirSimpleFunction -> {
|
||||
if (receiverTypeRef == null) {
|
||||
// TODO: setters
|
||||
return overrideCandidate.valueParameters.isEmpty()
|
||||
} else {
|
||||
if (overrideCandidate.valueParameters.size != 1) return false
|
||||
return isEqualTypes(receiverTypeRef, overrideCandidate.valueParameters.single().returnTypeRef, ConeSubstitutor.Empty)
|
||||
}
|
||||
}
|
||||
is FirProperty -> {
|
||||
val overrideReceiverTypeRef = overrideCandidate.receiverTypeRef
|
||||
return when {
|
||||
receiverTypeRef == null -> overrideReceiverTypeRef == null
|
||||
overrideReceiverTypeRef == null -> false
|
||||
else -> isEqualTypes(receiverTypeRef, overrideReceiverTypeRef, ConeSubstitutor.Empty)
|
||||
}
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir.java.scopes
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope
|
||||
|
||||
class JavaSuperTypeScope(
|
||||
klass: FirRegularClass,
|
||||
session: FirSession,
|
||||
scopes: List<FirScope>
|
||||
) : FirSuperTypeScope(
|
||||
session,
|
||||
JavaOverrideChecker(session, if (klass is FirJavaClass) klass.javaTypeParameterStack else JavaTypeParameterStack.EMPTY),
|
||||
scopes
|
||||
)
|
||||
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirClassUseSiteMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
|
||||
@@ -86,7 +83,11 @@ fun FirClass<*>.buildDefaultUseSiteMemberScope(useSiteSession: FirSession, build
|
||||
null
|
||||
}
|
||||
}
|
||||
FirClassUseSiteMemberScope(useSiteSession, FirSuperTypeScope(useSiteSession, scopes), declaredScope)
|
||||
FirClassUseSiteMemberScope(
|
||||
useSiteSession,
|
||||
FirSuperTypeScope(useSiteSession, FirStandardOverrideChecker(useSiteSession), scopes),
|
||||
declaredScope
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
|
||||
interface FirOverrideChecker {
|
||||
fun isOverriddenFunction(
|
||||
overrideCandidate: FirSimpleFunction,
|
||||
baseDeclaration: FirSimpleFunction
|
||||
): Boolean
|
||||
|
||||
fun isOverriddenProperty(
|
||||
overrideCandidate: FirCallableMemberDeclaration<*>, // NB: in Java it can be a function which overrides accessor
|
||||
baseDeclaration: FirProperty
|
||||
): Boolean
|
||||
}
|
||||
+9
-51
@@ -8,63 +8,21 @@ package org.jetbrains.kotlin.fir.scopes.impl
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
abstract class AbstractFirOverrideScope(val session: FirSession) : FirScope() {
|
||||
abstract class AbstractFirOverrideScope(val session: FirSession, private val overrideChecker: FirOverrideChecker) : FirScope() {
|
||||
//base symbol as key, overridden as value
|
||||
val overrideByBase = mutableMapOf<FirCallableSymbol<*>, FirCallableSymbol<*>?>()
|
||||
|
||||
protected val context: ConeTypeContext = session.typeContext
|
||||
|
||||
private fun isEqualTypes(a: ConeKotlinType, b: ConeKotlinType, substitution: ConeSubstitutor) =
|
||||
AbstractStrictEqualityTypeChecker.strictEqualTypes(context, substitution.substituteOrSelf(a), substitution.substituteOrSelf(b))
|
||||
|
||||
private fun isEqualTypes(a: FirTypeRef, b: FirTypeRef, substitution: ConeSubstitutor) =
|
||||
isEqualTypes(a.cast<FirResolvedTypeRef>().type, b.cast<FirResolvedTypeRef>().type, substitution)
|
||||
|
||||
protected open fun isOverriddenFunCheck(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
||||
if (overrideCandidate.valueParameters.size != baseDeclaration.valueParameters.size) return false
|
||||
if (overrideCandidate.typeParameters.size != baseDeclaration.typeParameters.size) return false
|
||||
|
||||
val types = baseDeclaration.typeParameters.map {
|
||||
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
|
||||
}
|
||||
val substitution = substitutorByMap(overrideCandidate.typeParameters.map { it.symbol }.zip(types).toMap())
|
||||
if (!overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).all { (a, b) ->
|
||||
a.bounds.size == b.bounds.size &&
|
||||
a.bounds.zip(b.bounds).all { (aBound, bBound) -> isEqualTypes(aBound, bBound, substitution) }
|
||||
}
|
||||
) return false
|
||||
if (!sameReceivers(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, substitution)) return false
|
||||
|
||||
return overrideCandidate.valueParameters.zip(baseDeclaration.valueParameters).all { (memberParam, selfParam) ->
|
||||
isEqualTypes(memberParam.returnTypeRef, selfParam.returnTypeRef, substitution)
|
||||
}
|
||||
private fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
||||
return overrideChecker.isOverriddenFunction(overrideCandidate, baseDeclaration)
|
||||
}
|
||||
|
||||
protected open fun isOverriddenPropertyCheck(
|
||||
overrideCandidate: FirCallableMemberDeclaration<*>, // NB: in Java it can be a function which overrides accessor
|
||||
baseDeclaration: FirProperty
|
||||
): Boolean {
|
||||
// TODO: substitutor
|
||||
return overrideCandidate is FirProperty &&
|
||||
sameReceivers(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, ConeSubstitutor.Empty)
|
||||
}
|
||||
|
||||
private fun sameReceivers(memberTypeRef: FirTypeRef?, selfTypeRef: FirTypeRef?, substitution: ConeSubstitutor): Boolean {
|
||||
return when {
|
||||
memberTypeRef != null && selfTypeRef != null -> isEqualTypes(memberTypeRef, selfTypeRef, substitution)
|
||||
else -> memberTypeRef == null && selfTypeRef == null
|
||||
}
|
||||
private fun isOverriddenProperty(overrideCandidate: FirCallableMemberDeclaration<*>, baseDeclaration: FirProperty): Boolean {
|
||||
return overrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration)
|
||||
}
|
||||
|
||||
private fun similarFunctionsOrBothProperties(
|
||||
@@ -73,12 +31,12 @@ abstract class AbstractFirOverrideScope(val session: FirSession) : FirScope() {
|
||||
): Boolean {
|
||||
return when (overrideCandidate) {
|
||||
is FirSimpleFunction -> when (baseDeclaration) {
|
||||
is FirSimpleFunction -> isOverriddenFunCheck(overrideCandidate, baseDeclaration)
|
||||
is FirProperty -> isOverriddenPropertyCheck(overrideCandidate, baseDeclaration)
|
||||
is FirSimpleFunction -> isOverriddenFunction(overrideCandidate, baseDeclaration)
|
||||
is FirProperty -> isOverriddenProperty(overrideCandidate, baseDeclaration)
|
||||
else -> false
|
||||
}
|
||||
is FirConstructor -> false
|
||||
is FirProperty -> baseDeclaration is FirProperty && isOverriddenPropertyCheck(overrideCandidate, baseDeclaration)
|
||||
is FirProperty -> baseDeclaration is FirProperty && isOverriddenProperty(overrideCandidate, baseDeclaration)
|
||||
is FirField -> false
|
||||
else -> error("Unknown fir callable type: $overrideCandidate, $baseDeclaration")
|
||||
}
|
||||
|
||||
+3
-1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
@@ -14,9 +15,10 @@ import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class AbstractFirUseSiteMemberScope(
|
||||
session: FirSession,
|
||||
overrideChecker: FirOverrideChecker,
|
||||
protected val superTypesScope: FirSuperTypeScope,
|
||||
protected val declaredMemberScope: FirScope
|
||||
) : AbstractFirOverrideScope(session) {
|
||||
) : AbstractFirOverrideScope(session, overrideChecker) {
|
||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
||||
if (!declaredMemberScope.processFunctionsByName(name) {
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
|
||||
abstract class FirAbstractOverrideChecker : FirOverrideChecker {
|
||||
|
||||
protected abstract fun isEqualTypes(candidateTypeRef: FirTypeRef, baseTypeRef: FirTypeRef, substitutor: ConeSubstitutor): Boolean
|
||||
|
||||
protected fun getSubstitutorIfTypeParametersAreCompatible(
|
||||
overrideCandidate: FirSimpleFunction,
|
||||
baseDeclaration: FirSimpleFunction
|
||||
): ConeSubstitutor? {
|
||||
if (overrideCandidate.typeParameters.size != baseDeclaration.typeParameters.size) return null
|
||||
|
||||
val types = baseDeclaration.typeParameters.map {
|
||||
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
|
||||
}
|
||||
val substitutor = substitutorByMap(overrideCandidate.typeParameters.map { it.symbol }.zip(types).toMap())
|
||||
if (!overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).all { (a, b) ->
|
||||
a.bounds.size == b.bounds.size && a.bounds.zip(b.bounds).all { (aBound, bBound) ->
|
||||
isEqualTypes(aBound, bBound, substitutor)
|
||||
}
|
||||
}
|
||||
) return null
|
||||
return substitutor
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@ class FirClassUseSiteMemberScope(
|
||||
session: FirSession,
|
||||
superTypesScope: FirSuperTypeScope,
|
||||
declaredMemberScope: FirScope
|
||||
) : AbstractFirUseSiteMemberScope(session, superTypesScope, declaredMemberScope) {
|
||||
) : AbstractFirUseSiteMemberScope(session, FirStandardOverrideChecker(session), superTypesScope, declaredMemberScope) {
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
val seen = mutableSetOf<FirCallableSymbol<*>>()
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeContext
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker.strictEqualTypes
|
||||
|
||||
class FirStandardOverrideChecker(session: FirSession) : FirAbstractOverrideChecker() {
|
||||
|
||||
private val context: ConeTypeContext = session.typeContext
|
||||
|
||||
private fun isEqualTypes(candidateType: ConeKotlinType, baseType: ConeKotlinType, substitutor: ConeSubstitutor) =
|
||||
strictEqualTypes(context, substitutor.substituteOrSelf(candidateType), substitutor.substituteOrSelf(baseType))
|
||||
|
||||
override fun isEqualTypes(candidateTypeRef: FirTypeRef, baseTypeRef: FirTypeRef, substitutor: ConeSubstitutor) =
|
||||
isEqualTypes((candidateTypeRef as FirResolvedTypeRef).type, (baseTypeRef as FirResolvedTypeRef).type, substitutor)
|
||||
|
||||
private fun isEqualReceiverTypes(candidateTypeRef: FirTypeRef?, baseTypeRef: FirTypeRef?, substitutor: ConeSubstitutor): Boolean {
|
||||
return when {
|
||||
candidateTypeRef != null && baseTypeRef != null -> isEqualTypes(candidateTypeRef, baseTypeRef, substitutor)
|
||||
else -> candidateTypeRef == null && baseTypeRef == null
|
||||
}
|
||||
}
|
||||
|
||||
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
||||
if (overrideCandidate.valueParameters.size != baseDeclaration.valueParameters.size) return false
|
||||
|
||||
val substitutor = getSubstitutorIfTypeParametersAreCompatible(overrideCandidate, baseDeclaration) ?: return false
|
||||
|
||||
if (!isEqualReceiverTypes(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, substitutor)) return false
|
||||
|
||||
return overrideCandidate.valueParameters.zip(baseDeclaration.valueParameters).all { (memberParam, selfParam) ->
|
||||
isEqualTypes(memberParam.returnTypeRef, selfParam.returnTypeRef, substitutor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun isOverriddenProperty(
|
||||
overrideCandidate: FirCallableMemberDeclaration<*>,
|
||||
baseDeclaration: FirProperty
|
||||
): Boolean {
|
||||
// TODO: substitutor
|
||||
return overrideCandidate is FirProperty &&
|
||||
isEqualReceiverTypes(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, ConeSubstitutor.Empty)
|
||||
}
|
||||
}
|
||||
@@ -6,16 +6,18 @@
|
||||
package org.jetbrains.kotlin.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FirSuperTypeScope(
|
||||
open class FirSuperTypeScope(
|
||||
session: FirSession,
|
||||
overrideChecker: FirOverrideChecker,
|
||||
val scopes: List<FirScope>
|
||||
) : AbstractFirOverrideScope(session) {
|
||||
) : AbstractFirOverrideScope(session, overrideChecker) {
|
||||
|
||||
private val absentFunctions = mutableSetOf<Name>()
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
fun foo() {
|
||||
val y = listOf("Alpha", "Beta")
|
||||
val x = LinkedHashSet<String>().apply {
|
||||
<!AMBIGUITY!>addAll<!>(y)
|
||||
addAll(y)
|
||||
}
|
||||
|
||||
val z = ArrayList<String>()
|
||||
|
||||
@@ -2,7 +2,7 @@ FILE: addAllOnJavaCollection.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lval y: R|kotlin/collections/List<kotlin/String>| = R|kotlin/collections/listOf|<R|kotlin/String|>(String(Alpha), String(Beta))
|
||||
lval x: R|java/util/LinkedHashSet<kotlin/String>| = R|java/util/LinkedHashSet.LinkedHashSet|<R|kotlin/String|>().R|kotlin/apply|<R|java/util/LinkedHashSet<kotlin/String>|>(<L> = apply@fun R|java/util/LinkedHashSet<kotlin/String>|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
<Ambiguity: addAll, [java/util/AbstractCollection.addAll, kotlin/collections/MutableSet.addAll]>#(R|<local>/y|)
|
||||
this@R|java/util/AbstractCollection|.R|FakeOverride<java/util/AbstractCollection.addAll: R|kotlin/Boolean|>|(R|<local>/y|)
|
||||
}
|
||||
)
|
||||
lval z: R|java/util/ArrayList<kotlin/String>| = R|java/util/ArrayList.ArrayList|<R|kotlin/String|>()
|
||||
|
||||
Reference in New Issue
Block a user