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.declarations.FirJavaMethod
|
||||||
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
|
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
|
||||||
import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteMemberScope
|
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.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
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.scopes.impl.declaredMemberScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
@@ -109,7 +109,7 @@ class JavaSymbolProvider(
|
|||||||
}
|
}
|
||||||
JavaClassUseSiteMemberScope(
|
JavaClassUseSiteMemberScope(
|
||||||
regularClass, useSiteSession,
|
regularClass, useSiteSession,
|
||||||
FirSuperTypeScope(useSiteSession, superTypeEnhancementScopes), declaredScope
|
JavaSuperTypeScope(regularClass, useSiteSession, superTypeEnhancementScopes), declaredScope
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-85
@@ -5,24 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.java.scopes
|
package org.jetbrains.kotlin.fir.java.scopes
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
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.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
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.AbstractFirUseSiteMemberScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope
|
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.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class JavaClassUseSiteMemberScope(
|
class JavaClassUseSiteMemberScope(
|
||||||
@@ -30,84 +24,14 @@ class JavaClassUseSiteMemberScope(
|
|||||||
session: FirSession,
|
session: FirSession,
|
||||||
superTypesScope: FirSuperTypeScope,
|
superTypesScope: FirSuperTypeScope,
|
||||||
declaredMemberScope: FirScope
|
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
|
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) {
|
internal fun bindOverrides(name: Name) {
|
||||||
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
||||||
declaredMemberScope.processFunctionsByName(name) {
|
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.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
|
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||||
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.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
|
||||||
@@ -86,7 +83,11 @@ fun FirClass<*>.buildDefaultUseSiteMemberScope(useSiteSession: FirSession, build
|
|||||||
null
|
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.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
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
|
//base symbol as key, overridden as value
|
||||||
val overrideByBase = mutableMapOf<FirCallableSymbol<*>, FirCallableSymbol<*>?>()
|
val overrideByBase = mutableMapOf<FirCallableSymbol<*>, FirCallableSymbol<*>?>()
|
||||||
|
|
||||||
protected val context: ConeTypeContext = session.typeContext
|
private fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
||||||
|
return overrideChecker.isOverriddenFunction(overrideCandidate, baseDeclaration)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun isOverriddenPropertyCheck(
|
private fun isOverriddenProperty(overrideCandidate: FirCallableMemberDeclaration<*>, baseDeclaration: FirProperty): Boolean {
|
||||||
overrideCandidate: FirCallableMemberDeclaration<*>, // NB: in Java it can be a function which overrides accessor
|
return overrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration)
|
||||||
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 similarFunctionsOrBothProperties(
|
private fun similarFunctionsOrBothProperties(
|
||||||
@@ -73,12 +31,12 @@ abstract class AbstractFirOverrideScope(val session: FirSession) : FirScope() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
return when (overrideCandidate) {
|
return when (overrideCandidate) {
|
||||||
is FirSimpleFunction -> when (baseDeclaration) {
|
is FirSimpleFunction -> when (baseDeclaration) {
|
||||||
is FirSimpleFunction -> isOverriddenFunCheck(overrideCandidate, baseDeclaration)
|
is FirSimpleFunction -> isOverriddenFunction(overrideCandidate, baseDeclaration)
|
||||||
is FirProperty -> isOverriddenPropertyCheck(overrideCandidate, baseDeclaration)
|
is FirProperty -> isOverriddenProperty(overrideCandidate, baseDeclaration)
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
is FirConstructor -> false
|
is FirConstructor -> false
|
||||||
is FirProperty -> baseDeclaration is FirProperty && isOverriddenPropertyCheck(overrideCandidate, baseDeclaration)
|
is FirProperty -> baseDeclaration is FirProperty && isOverriddenProperty(overrideCandidate, baseDeclaration)
|
||||||
is FirField -> false
|
is FirField -> false
|
||||||
else -> error("Unknown fir callable type: $overrideCandidate, $baseDeclaration")
|
else -> error("Unknown fir callable type: $overrideCandidate, $baseDeclaration")
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.scopes.impl
|
package org.jetbrains.kotlin.fir.scopes.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
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.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||||
@@ -14,9 +15,10 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
|
|
||||||
abstract class AbstractFirUseSiteMemberScope(
|
abstract class AbstractFirUseSiteMemberScope(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
|
overrideChecker: FirOverrideChecker,
|
||||||
protected val superTypesScope: FirSuperTypeScope,
|
protected val superTypesScope: FirSuperTypeScope,
|
||||||
protected val declaredMemberScope: FirScope
|
protected val declaredMemberScope: FirScope
|
||||||
) : AbstractFirOverrideScope(session) {
|
) : AbstractFirOverrideScope(session, overrideChecker) {
|
||||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||||
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
||||||
if (!declaredMemberScope.processFunctionsByName(name) {
|
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,
|
session: FirSession,
|
||||||
superTypesScope: FirSuperTypeScope,
|
superTypesScope: FirSuperTypeScope,
|
||||||
declaredMemberScope: FirScope
|
declaredMemberScope: FirScope
|
||||||
) : AbstractFirUseSiteMemberScope(session, superTypesScope, declaredMemberScope) {
|
) : AbstractFirUseSiteMemberScope(session, FirStandardOverrideChecker(session), superTypesScope, declaredMemberScope) {
|
||||||
|
|
||||||
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||||
val seen = mutableSetOf<FirCallableSymbol<*>>()
|
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
|
package org.jetbrains.kotlin.fir.scopes.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
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.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class FirSuperTypeScope(
|
open class FirSuperTypeScope(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
|
overrideChecker: FirOverrideChecker,
|
||||||
val scopes: List<FirScope>
|
val scopes: List<FirScope>
|
||||||
) : AbstractFirOverrideScope(session) {
|
) : AbstractFirOverrideScope(session, overrideChecker) {
|
||||||
|
|
||||||
private val absentFunctions = mutableSetOf<Name>()
|
private val absentFunctions = mutableSetOf<Name>()
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
fun foo() {
|
fun foo() {
|
||||||
val y = listOf("Alpha", "Beta")
|
val y = listOf("Alpha", "Beta")
|
||||||
val x = LinkedHashSet<String>().apply {
|
val x = LinkedHashSet<String>().apply {
|
||||||
<!AMBIGUITY!>addAll<!>(y)
|
addAll(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
val z = ArrayList<String>()
|
val z = ArrayList<String>()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ FILE: addAllOnJavaCollection.kt
|
|||||||
public final fun foo(): R|kotlin/Unit| {
|
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 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> {
|
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|>()
|
lval z: R|java/util/ArrayList<kotlin/String>| = R|java/util/ArrayList.ArrayList|<R|kotlin/String|>()
|
||||||
|
|||||||
Reference in New Issue
Block a user