Typechecker and visibility utils for fake overrides

This commit is contained in:
Alexander Gorshenev
2020-05-12 13:36:31 +03:00
parent 789efc7c3a
commit 2828aa9ce8
3 changed files with 101 additions and 1 deletions
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
class IrTypeCheckerContext(override val irBuiltIns: IrBuiltIns) : IrTypeSystemContext, AbstractTypeCheckerContext() {
open class IrTypeCheckerContext(override val irBuiltIns: IrBuiltIns) : IrTypeSystemContext, AbstractTypeCheckerContext() {
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
require(type is IrSimpleType)
@@ -0,0 +1,34 @@
package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.types.IrTypeCheckerContext
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
open class IrTypeCheckerContextWithAdditionalAxioms(
override val irBuiltIns: IrBuiltIns,
firstParameters: List<IrTypeParameter>,
secondParameters: List<IrTypeParameter>
) : IrTypeCheckerContext(irBuiltIns) {
init {
assert(firstParameters.size == secondParameters.size) {
"different length of type parameter lists: $firstParameters vs $secondParameters"
}
}
private val firstTypeParameterConstructors = firstParameters.map { it.symbol }
private val secondTypeParameterConstructors = secondParameters.map { it.symbol }
private val matchingTypeConstructors = firstTypeParameterConstructors.zip(secondTypeParameterConstructors).toMap()
override fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean {
if (super.isEqualTypeConstructors(a, b)) return true
if (matchingTypeConstructors[a] == b || matchingTypeConstructors[b] == a) return true
return false
}
override fun isEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
if (super.isEqualTypeConstructors(c1, c2)) return true
if (matchingTypeConstructors[c1] == c2 || matchingTypeConstructors[c2] == c1) return true
return false
}
}
@@ -0,0 +1,66 @@
package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.lower.parents
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility
import org.jetbrains.kotlin.ir.declarations.IrOverridableMember
import org.jetbrains.kotlin.ir.util.module
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
// The contents of this file is from VisibilityUtil.kt adapted to IR.
// TODO: The code would better be commonized for descriptors, ir and fir.
private fun findInvisibleMember(
receiver: ReceiverValue?,
what: IrDeclarationWithVisibility,
from: IrDeclaration
): IrDeclarationWithVisibility? {
// TODO: We need the proper code for IR,
// but that requires many of Visibilities.java available in IR.
// So for now we stick to a quick hack serving the needs
// of fake override construction algorithm.
val parentsWithSelf = sequenceOf(what) + what.parents
parentsWithSelf.forEach {
if (it !is IrDeclarationWithVisibility) return null
if (it.visibility == Visibilities.INTERNAL &&
(from.module != it.module)
) {
return it
}
}
return null
}
fun isVisibleIgnoringReceiver(
what: IrDeclarationWithVisibility,
from: IrDeclaration
): Boolean {
return findInvisibleMember(Visibilities.ALWAYS_SUITABLE_RECEIVER, what, from) == null
}
fun isVisibleForOverride(
overriding: IrOverridableMember,
fromSuper: IrOverridableMember
): Boolean {
return !Visibilities.isPrivate((fromSuper as IrDeclarationWithVisibility).visibility) &&
isVisibleIgnoringReceiver(fromSuper, overriding)
}
fun findMemberWithMaxVisibility(members: Collection<IrOverridableMember>): IrOverridableMember {
assert(members.isNotEmpty())
var member: IrOverridableMember? = null
for (candidate in members) {
if (member == null) {
member = candidate
continue
}
val result = Visibilities.compare(member.visibility, candidate.visibility)
if (result != null && result < 0) {
member = candidate
}
}
return member ?: error("Could not find a visible member")
}