Reformat 'resolution' module according to new codestyle

This commit is contained in:
Dmitry Savvinov
2018-01-17 16:12:58 +03:00
parent e2b83aecd7
commit c704f2de9a
89 changed files with 1941 additions and 1530 deletions
@@ -38,10 +38,10 @@ interface ContractDescriptionElement {
interface EffectDeclaration : ContractDescriptionElement {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitEffectDeclaration(this, data)
contractDescriptionVisitor.visitEffectDeclaration(this, data)
}
interface BooleanExpression : ContractDescriptionElement {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitBooleanExpression(this, data)
contractDescriptionVisitor.visitBooleanExpression(this, data)
}
@@ -74,7 +74,7 @@ class ContractDescriptionRenderer(private val builder: StringBuilder) : Contract
}
private fun ContractDescriptionElement.isAtom(): Boolean =
this is VariableReference || this is ConstantReference || this is IsNullPredicate || this is IsInstancePredicate
this is VariableReference || this is ConstantReference || this is IsNullPredicate || this is IsInstancePredicate
private fun needsBrackets(parent: ContractDescriptionElement, child: ContractDescriptionElement): Boolean {
if (child.isAtom()) return false
@@ -87,8 +87,7 @@ class ContractDescriptionRenderer(private val builder: StringBuilder) : Contract
builder.append("(")
block()
builder.append(")")
}
else {
} else {
block()
}
}
@@ -25,7 +25,10 @@ interface ContractDescriptionVisitor<out R, in D> {
// Effects
fun visitEffectDeclaration(effectDeclaration: EffectDeclaration, data: D): R = visitContractDescriptionElement(effectDeclaration, data)
fun visitConditionalEffectDeclaration(conditionalEffect: ConditionalEffectDeclaration, data: D): R = visitEffectDeclaration(conditionalEffect, data)
fun visitConditionalEffectDeclaration(conditionalEffect: ConditionalEffectDeclaration, data: D): R =
visitEffectDeclaration(conditionalEffect, data)
fun visitReturnsEffectDeclaration(returnsEffect: ReturnsEffectDeclaration, data: D): R = visitEffectDeclaration(returnsEffect, data)
fun visitCallsEffectDeclaration(callsEffect: CallsEffectDeclaration, data: D): R = visitEffectDeclaration(callsEffect, data)
@@ -43,7 +46,10 @@ interface ContractDescriptionVisitor<out R, in D> {
fun visitValue(value: ContractDescriptionValue, data: D): R = visitContractDescriptionElement(value, data)
fun visitConstantDescriptor(constantReference: ConstantReference, data: D): R = visitValue(constantReference, data)
fun visitBooleanConstantDescriptor(booleanConstantDescriptor: BooleanConstantReference, data: D): R = visitConstantDescriptor(booleanConstantDescriptor, data)
fun visitBooleanConstantDescriptor(booleanConstantDescriptor: BooleanConstantReference, data: D): R =
visitConstantDescriptor(booleanConstantDescriptor, data)
fun visitVariableReference(variableReference: VariableReference, data: D): R = visitValue(variableReference, data)
fun visitBooleanVariableReference(booleanVariableReference: BooleanVariableReference, data: D): R = visitVariableReference(booleanVariableReference, data)
fun visitBooleanVariableReference(booleanVariableReference: BooleanVariableReference, data: D): R =
visitVariableReference(booleanVariableReference, data)
}
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.contracts.description.expressions.VariableReference
*/
class ConditionalEffectDeclaration(val effect: EffectDeclaration, val condition: BooleanExpression) : EffectDeclaration {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitConditionalEffectDeclaration(this, data)
contractDescriptionVisitor.visitConditionalEffectDeclaration(this, data)
}
@@ -44,7 +44,7 @@ class ConditionalEffectDeclaration(val effect: EffectDeclaration, val condition:
*/
class ReturnsEffectDeclaration(val value: ConstantReference) : EffectDeclaration {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitReturnsEffectDeclaration(this, data)
contractDescriptionVisitor.visitReturnsEffectDeclaration(this, data)
}
@@ -55,7 +55,7 @@ class ReturnsEffectDeclaration(val value: ConstantReference) : EffectDeclaration
*/
class CallsEffectDeclaration(val variableReference: VariableReference, val kind: InvocationKind) : EffectDeclaration {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitCallsEffectDeclaration(this, data)
contractDescriptionVisitor.visitCallsEffectDeclaration(this, data)
}
enum class InvocationKind {
@@ -46,7 +46,7 @@ class LazyContractProvider(private val computation: () -> Any?) : ContractProvid
companion object {
fun createInitialized(contract: ContractDescription?): LazyContractProvider =
LazyContractProvider({}).apply { setContractDescription(contract) }
LazyContractProvider({}).apply { setContractDescription(contract) }
}
}
@@ -21,15 +21,15 @@ import org.jetbrains.kotlin.contracts.description.ContractDescriptionVisitor
class LogicalOr(val left: BooleanExpression, val right: BooleanExpression) : BooleanExpression {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitLogicalOr(this, data)
contractDescriptionVisitor.visitLogicalOr(this, data)
}
class LogicalAnd(val left: BooleanExpression, val right: BooleanExpression) : BooleanExpression {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitLogicalAnd(this, data)
contractDescriptionVisitor.visitLogicalAnd(this, data)
}
class LogicalNot(val arg: BooleanExpression) : BooleanExpression {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitLogicalNot(this, data)
contractDescriptionVisitor.visitLogicalNot(this, data)
}
@@ -22,14 +22,14 @@ import org.jetbrains.kotlin.types.KotlinType
class IsInstancePredicate(val arg: VariableReference, val type: KotlinType, val isNegated: Boolean) : BooleanExpression {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitIsInstancePredicate(this, data)
contractDescriptionVisitor.visitIsInstancePredicate(this, data)
fun negated(): IsInstancePredicate = IsInstancePredicate(arg, type, isNegated.not())
}
class IsNullPredicate(val arg: VariableReference, val isNegated: Boolean) : BooleanExpression {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitIsNullPredicate(this, data)
contractDescriptionVisitor.visitIsNullPredicate(this, data)
fun negated(): IsNullPredicate = IsNullPredicate(arg, isNegated.not())
}
@@ -24,12 +24,12 @@ import org.jetbrains.kotlin.descriptors.ParameterDescriptor
interface ContractDescriptionValue : ContractDescriptionElement {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitValue(this, data)
contractDescriptionVisitor.visitValue(this, data)
}
open class ConstantReference(val name: String) : ContractDescriptionValue {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitConstantDescriptor(this, data)
contractDescriptionVisitor.visitConstantDescriptor(this, data)
companion object {
val NULL = ConstantReference("NULL")
@@ -40,7 +40,7 @@ open class ConstantReference(val name: String) : ContractDescriptionValue {
class BooleanConstantReference(name: String) : ConstantReference(name), BooleanExpression {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitBooleanConstantDescriptor(this, data)
contractDescriptionVisitor.visitBooleanConstantDescriptor(this, data)
companion object {
val TRUE = BooleanConstantReference("TRUE")
@@ -50,10 +50,10 @@ class BooleanConstantReference(name: String) : ConstantReference(name), BooleanE
open class VariableReference(val descriptor: ParameterDescriptor) : ContractDescriptionValue {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D) =
contractDescriptionVisitor.visitVariableReference(this, data)
contractDescriptionVisitor.visitVariableReference(this, data)
}
class BooleanVariableReference(descriptor: ParameterDescriptor) : VariableReference(descriptor), BooleanExpression {
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
contractDescriptionVisitor.visitBooleanVariableReference(this, data)
contractDescriptionVisitor.visitBooleanVariableReference(this, data)
}
@@ -22,7 +22,8 @@ import org.jetbrains.kotlin.contracts.model.ESExpression
import org.jetbrains.kotlin.contracts.model.functors.IsFunctor
import org.jetbrains.kotlin.contracts.model.structure.*
internal class ConditionInterpreter(private val dispatcher: ContractInterpretationDispatcher) : ContractDescriptionVisitor<ESExpression?, Unit> {
internal class ConditionInterpreter(private val dispatcher: ContractInterpretationDispatcher) :
ContractDescriptionVisitor<ESExpression?, Unit> {
override fun visitLogicalOr(logicalOr: LogicalOr, data: Unit): ESExpression? {
val left = logicalOr.left.accept(this, data) ?: return null
val right = logicalOr.right.accept(this, data) ?: return null
@@ -51,8 +52,8 @@ internal class ConditionInterpreter(private val dispatcher: ContractInterpretati
}
override fun visitBooleanConstantDescriptor(booleanConstantDescriptor: BooleanConstantReference, data: Unit): ESExpression? =
dispatcher.interpretConstant(booleanConstantDescriptor)
dispatcher.interpretConstant(booleanConstantDescriptor)
override fun visitBooleanVariableReference(booleanVariableReference: BooleanVariableReference, data: Unit): ESExpression? =
dispatcher.interpretVariable(booleanVariableReference)
dispatcher.interpretVariable(booleanVariableReference)
}
@@ -25,7 +25,7 @@ internal class ConstantValuesInterpreter {
fun interpretConstant(constantReference: ConstantReference): ESConstant? = when (constantReference) {
BooleanConstantReference.TRUE -> true.lift()
BooleanConstantReference.FALSE -> false.lift()
ConstantReference.NULL-> ESConstant.NULL
ConstantReference.NULL -> ESConstant.NULL
ConstantReference.NOT_NULL -> ESConstant.NOT_NULL
ConstantReference.WILDCARD -> ESConstant.WILDCARD
else -> null
@@ -35,9 +35,10 @@ class ContractInterpretationDispatcher {
private val conditionInterpreter = ConditionInterpreter(this)
private val conditionalEffectInterpreter = ConditionalEffectInterpreter(this)
private val effectsInterpreters: List<EffectDeclarationInterpreter> = listOf(
ReturnsEffectInterpreter(this),
CallsEffectInterpreter(this)
ReturnsEffectInterpreter(this),
CallsEffectInterpreter(this)
)
fun resolveFunctor(functionDescriptor: FunctionDescriptor): Functor? {
val contractDescriptor = functionDescriptor.getUserData(ContractProviderKey)?.getContractDescription() ?: return null
return convertContractDescriptorToFunctor(contractDescriptor)
@@ -47,8 +48,7 @@ class ContractInterpretationDispatcher {
val resultingClauses = contractDescription.effects.map { effect ->
if (effect is ConditionalEffectDeclaration) {
conditionalEffectInterpreter.interpret(effect) ?: return null
}
else {
} else {
effectsInterpreters.mapNotNull { it.tryInterpret(effect) }.singleOrNull() ?: return null
}
}
@@ -62,10 +62,10 @@ class ContractInterpretationDispatcher {
}
internal fun interpretConstant(constantReference: ConstantReference): ESConstant? =
constantsInterpreter.interpretConstant(constantReference)
constantsInterpreter.interpretConstant(constantReference)
internal fun interpretCondition(booleanExpression: BooleanExpression): ESExpression? =
booleanExpression.accept(conditionInterpreter, Unit)
booleanExpression.accept(conditionInterpreter, Unit)
internal fun interpretVariable(variableReference: VariableReference): ESVariable? = ESVariable(variableReference.descriptor)
}
@@ -29,20 +29,20 @@ import org.jetbrains.kotlin.types.KotlinType
* Also, it's abstracted away from PSI
*/
class MutableContextInfo private constructor(
val firedEffects: MutableList<ESEffect>,
val subtypes: MutableMap<ESValue, MutableSet<KotlinType>>,
val notSubtypes: MutableMap<ESValue, MutableSet<KotlinType>>,
val equalValues: MutableMap<ESValue, MutableSet<ESValue>>,
val notEqualValues: MutableMap<ESValue, MutableSet<ESValue>>
val firedEffects: MutableList<ESEffect>,
val subtypes: MutableMap<ESValue, MutableSet<KotlinType>>,
val notSubtypes: MutableMap<ESValue, MutableSet<KotlinType>>,
val equalValues: MutableMap<ESValue, MutableSet<ESValue>>,
val notEqualValues: MutableMap<ESValue, MutableSet<ESValue>>
) {
companion object {
val EMPTY: MutableContextInfo
get() = MutableContextInfo(
firedEffects = mutableListOf(),
subtypes = mutableMapOf(),
notSubtypes = mutableMapOf(),
equalValues = mutableMapOf(),
notEqualValues = mutableMapOf()
firedEffects = mutableListOf(),
subtypes = mutableMapOf(),
notSubtypes = mutableMapOf(),
equalValues = mutableMapOf(),
notEqualValues = mutableMapOf()
)
}
@@ -63,19 +63,19 @@ class MutableContextInfo private constructor(
fun fire(effect: ESEffect) = apply { firedEffects += effect }
fun or(other: MutableContextInfo): MutableContextInfo = MutableContextInfo(
firedEffects = firedEffects.intersect(other.firedEffects).toMutableList(),
subtypes = subtypes.intersect(other.subtypes),
notSubtypes = notSubtypes.intersect(other.notSubtypes),
equalValues = equalValues.intersect(other.equalValues),
notEqualValues = notEqualValues.intersect(other.notEqualValues)
firedEffects = firedEffects.intersect(other.firedEffects).toMutableList(),
subtypes = subtypes.intersect(other.subtypes),
notSubtypes = notSubtypes.intersect(other.notSubtypes),
equalValues = equalValues.intersect(other.equalValues),
notEqualValues = notEqualValues.intersect(other.notEqualValues)
)
fun and(other: MutableContextInfo): MutableContextInfo = MutableContextInfo(
firedEffects = firedEffects.union(other.firedEffects).toMutableList(),
subtypes = subtypes.union(other.subtypes),
notSubtypes = notSubtypes.union(other.notSubtypes),
equalValues = equalValues.union(other.equalValues),
notEqualValues = notEqualValues.union(other.notEqualValues)
firedEffects = firedEffects.union(other.firedEffects).toMutableList(),
subtypes = subtypes.union(other.subtypes),
notSubtypes = notSubtypes.union(other.notSubtypes),
equalValues = equalValues.union(other.equalValues),
notEqualValues = notEqualValues.union(other.notEqualValues)
)
private fun <D> MutableMap<ESValue, MutableSet<D>>.intersect(that: MutableMap<ESValue, MutableSet<D>>): MutableMap<ESValue, MutableSet<D>> {
@@ -120,7 +120,7 @@ class MutableContextInfo private constructor(
}
append("Fired effects: ")
append(info.firedEffects.joinToString(separator = ", " ))
append(info.firedEffects.joinToString(separator = ", "))
appendln("")
subtypes.printMapEntriesWithSeparator("is")
@@ -56,5 +56,8 @@ abstract class AbstractBinaryFunctor : AbstractReducingFunctor() {
}
protected abstract fun invokeWithConstant(computation: Computation, constant: ESConstant): List<ESEffect>
protected abstract fun invokeWithReturningEffects(left: List<ConditionalEffect>, right: List<ConditionalEffect>): List<ConditionalEffect>
protected abstract fun invokeWithReturningEffects(
left: List<ConditionalEffect>,
right: List<ConditionalEffect>
): List<ConditionalEffect>
}
@@ -30,5 +30,5 @@ abstract class AbstractReducingFunctor : Functor {
override fun invokeWithArguments(arguments: List<Computation>): List<ESEffect> = reducer.reduceEffects(doInvocation(arguments))
abstract protected fun doInvocation(arguments: List<Computation>): List<ESEffect>
protected abstract fun doInvocation(arguments: List<Computation>): List<ESEffect>
}
@@ -30,7 +30,7 @@ class AndFunctor : AbstractBinaryFunctor() {
ESConstant.TRUE -> computation.effects
ESConstant.FALSE -> emptyList()
// This means that expression isn't typechecked properly
// This means that expression isn't typechecked properly
else -> computation.effects
}
@@ -84,7 +84,11 @@ class EqualsFunctor(val isNegated: Boolean) : AbstractReducingFunctor() {
resultingClauses.add(trueClause)
}
if (effect.simpleEffect.value != constant && effect.simpleEffect.value is ESConstant && isSafeToProduceFalse(call, effect.simpleEffect.value, constant)) {
if (effect.simpleEffect.value != constant && effect.simpleEffect.value is ESConstant && isSafeToProduceFalse(
call,
effect.simpleEffect.value,
constant
)) {
val falseClause = ConditionalEffect(effect.condition, ESReturns(isNegated.lift()))
resultingClauses.add(falseClause)
}
@@ -96,10 +100,10 @@ class EqualsFunctor(val isNegated: Boolean) : AbstractReducingFunctor() {
// It is safe to produce false if we're comparing types which are isomorphic to Boolean. For such types we can be sure, that
// if leftConstant != rightConstant, then this is the only way to produce 'false'.
private fun isSafeToProduceFalse(leftCall: Computation, leftConstant: ESConstant, rightConstant: ESConstant): Boolean = when {
// Comparison of Boolean
// Comparison of Boolean
KotlinBuiltIns.isBoolean(rightConstant.type) && leftCall.type != null && KotlinBuiltIns.isBoolean(leftCall.type!!) -> true
// Comparison of NULL/NOT_NULL, which is essentially Boolean
// Comparison of NULL/NOT_NULL, which is essentially Boolean
leftConstant.isNullConstant() && rightConstant.isNullConstant() -> true
else -> false
@@ -107,8 +111,8 @@ class EqualsFunctor(val isNegated: Boolean) : AbstractReducingFunctor() {
private fun equateValues(left: ESValue, right: ESValue): List<ESEffect> {
return listOf(
ConditionalEffect(ESEqual(left, right, isNegated), ESReturns(true.lift())),
ConditionalEffect(ESEqual(left, right, isNegated.not()), ESReturns(false.lift()))
ConditionalEffect(ESEqual(left, right, isNegated), ESReturns(true.lift())),
ConditionalEffect(ESEqual(left, right, isNegated.not()), ESReturns(false.lift()))
)
}
}
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.contracts.model.ESExpression
* Applies [operation] to [first] and [second] if both not-null, otherwise returns null
*/
internal fun <F, S, R> applyIfBothNotNull(first: F?, second: S?, operation: (F, S) -> R): R? =
if (first == null || second == null) null else operation(first, second)
if (first == null || second == null) null else operation(first, second)
/**
* If both [first] and [second] are null, then return null
@@ -40,15 +40,18 @@ internal fun <F : R, S : R, R> applyWithDefault(first: F?, second: S?, operation
}
internal fun foldConditionsWithOr(list: List<ConditionalEffect>): ESExpression? =
if (list.isEmpty())
null
else
list.map { it.condition }.reduce { acc, condition -> ESOr(acc, condition) }
if (list.isEmpty())
null
else
list.map { it.condition }.reduce { acc, condition -> ESOr(acc, condition) }
/**
* Places all clauses that equal to `firstModel` into first list, and all clauses that equal to `secondModel` into second list
*/
internal fun List<ConditionalEffect>.strictPartition(firstModel: ESEffect, secondModel: ESEffect): Pair<List<ConditionalEffect>, List<ConditionalEffect>> {
internal fun List<ConditionalEffect>.strictPartition(
firstModel: ESEffect,
secondModel: ESEffect
): Pair<List<ConditionalEffect>, List<ConditionalEffect>> {
val first = mutableListOf<ConditionalEffect>()
val second = mutableListOf<ConditionalEffect>()
@@ -30,7 +30,7 @@ class OrFunctor : AbstractBinaryFunctor() {
ESConstant.FALSE -> computation.effects
ESConstant.TRUE -> emptyList()
// This means that expression isn't typechecked properly
// This means that expression isn't typechecked properly
else -> computation.effects
}
@@ -30,11 +30,13 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.utils.addIfNotNull
class SubstitutingFunctor(private val basicEffects: List<ESEffect>, private val ownerFunction: FunctionDescriptor) : AbstractReducingFunctor() {
class SubstitutingFunctor(private val basicEffects: List<ESEffect>, private val ownerFunction: FunctionDescriptor) :
AbstractReducingFunctor() {
override fun doInvocation(arguments: List<Computation>): List<ESEffect> {
if (basicEffects.isEmpty()) return emptyList()
val receiver = listOfNotNull(ownerFunction.dispatchReceiverParameter?.toESVariable(), ownerFunction.extensionReceiverParameter?.toESVariable())
val receiver =
listOfNotNull(ownerFunction.dispatchReceiverParameter?.toESVariable(), ownerFunction.extensionReceiverParameter?.toESVariable())
val parameters = receiver + ownerFunction.valueParameters.map { it.toESVariable() }
assert(parameters.size == arguments.size) {
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.contracts.model.ESEffect
import org.jetbrains.kotlin.contracts.model.ESValue
import org.jetbrains.kotlin.contracts.model.SimpleEffect
data class ESCalls(val callable: ESValue, val kind: InvocationKind): SimpleEffect() {
data class ESCalls(val callable: ESValue, val kind: InvocationKind) : SimpleEffect() {
override fun isImplies(other: ESEffect): Boolean? {
if (other !is ESCalls) return null
@@ -33,7 +33,7 @@ data class ESCalls(val callable: ESValue, val kind: InvocationKind): SimpleEffec
}
data class ESReturns(val value: ESValue): SimpleEffect() {
data class ESReturns(val value: ESValue) : SimpleEffect() {
override fun isImplies(other: ESEffect): Boolean? {
if (other !is ESReturns) return null
@@ -22,28 +22,28 @@ import org.jetbrains.kotlin.contracts.model.ESOperator
import org.jetbrains.kotlin.contracts.model.ESValue
import org.jetbrains.kotlin.contracts.model.functors.*
class ESAnd(val left: ESExpression, val right: ESExpression): ESOperator {
class ESAnd(val left: ESExpression, val right: ESExpression) : ESOperator {
override val functor: AndFunctor = AndFunctor()
override fun <T> accept(visitor: ESExpressionVisitor<T>): T = visitor.visitAnd(this)
}
class ESOr(val left: ESExpression, val right: ESExpression): ESOperator {
class ESOr(val left: ESExpression, val right: ESExpression) : ESOperator {
override val functor: OrFunctor = OrFunctor()
override fun <T> accept(visitor: ESExpressionVisitor<T>): T = visitor.visitOr(this)
}
class ESNot(val arg: ESExpression): ESOperator {
class ESNot(val arg: ESExpression) : ESOperator {
override val functor = NotFunctor()
override fun <T> accept(visitor: ESExpressionVisitor<T>): T = visitor.visitNot(this)
}
class ESIs(val left: ESValue, override val functor: IsFunctor): ESOperator {
class ESIs(val left: ESValue, override val functor: IsFunctor) : ESOperator {
val type = functor.type
override fun <T> accept(visitor: ESExpressionVisitor<T>): T = visitor.visitIs(this)
}
class ESEqual(val left: ESValue, val right: ESValue, isNegated: Boolean): ESOperator {
class ESEqual(val left: ESValue, val right: ESValue, isNegated: Boolean) : ESOperator {
override val functor: EqualsFunctor = EqualsFunctor(isNegated)
override fun <T> accept(visitor: ESExpressionVisitor<T>): T = visitor.visitEqual(this)
}
@@ -24,7 +24,9 @@ class InfoCollector(private val observedEffect: ESEffect) : ESExpressionVisitor<
private var isInverted: Boolean = false
fun collectFromSchema(schema: List<ESEffect>): MutableContextInfo =
schema.mapNotNull { collectFromEffect(it) }.fold(MutableContextInfo.EMPTY, { resultingInfo, clauseInfo -> resultingInfo.and(clauseInfo) })
schema.mapNotNull { collectFromEffect(it) }.fold(
MutableContextInfo.EMPTY,
{ resultingInfo, clauseInfo -> resultingInfo.and(clauseInfo) })
private fun collectFromEffect(effect: ESEffect): MutableContextInfo? {
if (effect !is ConditionalEffect) {
@@ -33,16 +35,19 @@ class InfoCollector(private val observedEffect: ESEffect) : ESExpressionVisitor<
// Check for information from conditional effects
return when (observedEffect.isImplies(effect.simpleEffect)) {
// observed effect implies clause's effect => clause's effect was fired => clause's condition is true
// observed effect implies clause's effect => clause's effect was fired => clause's condition is true
true -> effect.condition.accept(this)
// Observed effect *may* or *doesn't* implies clause's - no useful information
// Observed effect *may* or *doesn't* implies clause's - no useful information
null, false -> null
}
}
override fun visitIs(isOperator: ESIs): MutableContextInfo = with(isOperator) {
if (functor.isNegated != isInverted) MutableContextInfo.EMPTY.notSubtype(left, type) else MutableContextInfo.EMPTY.subtype(left, type)
if (functor.isNegated != isInverted) MutableContextInfo.EMPTY.notSubtype(left, type) else MutableContextInfo.EMPTY.subtype(
left,
type
)
}
override fun visitEqual(equal: ESEqual): MutableContextInfo = with(equal) {
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
*/
class Reducer : ESExpressionVisitor<ESExpression?> {
fun reduceEffects(schema: List<ESEffect>): List<ESEffect> =
schema.mapNotNull { reduceEffect(it) }
schema.mapNotNull { reduceEffect(it) }
private fun reduceEffect(effect: ESEffect): ESEffect? {
when (effect) {
@@ -54,8 +54,7 @@ class Substitutor(private val substitutions: Map<ESVariable, Computation>) : ESE
return CallComputation(DefaultBuiltIns.Instance.booleanType, or.functor.invokeWithArguments(left, right))
}
override fun visitVariable(esVariable: ESVariable): Computation?
= substitutions[esVariable] ?: esVariable
override fun visitVariable(esVariable: ESVariable): Computation? = substitutions[esVariable] ?: esVariable
override fun visitConstant(esConstant: ESConstant): Computation? = esConstant
}
@@ -28,29 +28,35 @@ import java.lang.UnsupportedOperationException
class KotlinCallResolver(
private val towerResolver: TowerResolver,
private val kotlinCallCompleter: KotlinCallCompleter,
private val overloadingConflictResolver: NewOverloadingConflictResolver,
private val callComponents: KotlinCallComponents
private val towerResolver: TowerResolver,
private val kotlinCallCompleter: KotlinCallCompleter,
private val overloadingConflictResolver: NewOverloadingConflictResolver,
private val callComponents: KotlinCallComponents
) {
fun resolveCall(
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
expectedType: UnwrappedType?,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<KotlinResolutionCandidate>,
collectAllCandidates: Boolean
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
expectedType: UnwrappedType?,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<KotlinResolutionCandidate>,
collectAllCandidates: Boolean
): CallResolutionResult {
kotlinCall.checkCallInvariants()
val candidateFactory = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall)
val processor = when(kotlinCall.callKind) {
val processor = when (kotlinCall.callKind) {
KotlinCallKind.VARIABLE -> {
createVariableAndObjectProcessor(scopeTower, kotlinCall.name, candidateFactory, kotlinCall.explicitReceiver?.receiver)
}
KotlinCallKind.FUNCTION -> {
createFunctionProcessor(scopeTower, kotlinCall.name, candidateFactory, factoryProviderForInvoke, kotlinCall.explicitReceiver?.receiver)
createFunctionProcessor(
scopeTower,
kotlinCall.name,
candidateFactory,
factoryProviderForInvoke,
kotlinCall.explicitReceiver?.receiver
)
}
KotlinCallKind.UNSUPPORTED -> throw UnsupportedOperationException()
}
@@ -60,18 +66,23 @@ class KotlinCallResolver(
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
}
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kotlinCall.callKind != KotlinCallKind.UNSUPPORTED, name = kotlinCall.name)
val candidates = towerResolver.runResolve(
scopeTower,
processor,
useOrder = kotlinCall.callKind != KotlinCallKind.UNSUPPORTED,
name = kotlinCall.name
)
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
}
fun resolveGivenCandidates(
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
expectedType: UnwrappedType?,
givenCandidates: Collection<GivenCandidate>,
collectAllCandidates: Boolean
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
expectedType: UnwrappedType?,
givenCandidates: Collection<GivenCandidate>,
collectAllCandidates: Boolean
): CallResolutionResult {
kotlinCall.checkCallInvariants()
val candidateFactory = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall)
@@ -79,23 +90,27 @@ class KotlinCallResolver(
val resolutionCandidates = givenCandidates.map { candidateFactory.createCandidate(it).forceResolution() }
if (collectAllCandidates) {
val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolutionCandidates),
TowerResolver.AllCandidatesCollector(),
useOrder = false)
val allCandidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolutionCandidates),
TowerResolver.AllCandidatesCollector(),
useOrder = false
)
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
}
val candidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolutionCandidates),
TowerResolver.SuccessfulResultCollector(),
useOrder = true)
val candidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolutionCandidates),
TowerResolver.SuccessfulResultCollector(),
useOrder = true
)
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
}
private fun choseMostSpecific(
candidateFactory: SimpleCandidateFactory,
resolutionCallbacks: KotlinResolutionCallbacks,
expectedType: UnwrappedType?,
candidates: Collection<KotlinResolutionCandidate>
candidateFactory: SimpleCandidateFactory,
resolutionCallbacks: KotlinResolutionCallbacks,
expectedType: UnwrappedType?,
candidates: Collection<KotlinResolutionCandidate>
): CallResolutionResult {
val isDebuggerContext = candidateFactory.scopeTower.isDebuggerContext
@@ -108,10 +123,11 @@ class KotlinCallResolver(
}
val maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates(
refinedCandidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = true, // todo
isDebuggerContext = isDebuggerContext)
refinedCandidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = true, // todo
isDebuggerContext = isDebuggerContext
)
return kotlinCallCompleter.runCompletion(candidateFactory, maximallySpecificCandidates, expectedType, resolutionCallbacks)
}
@@ -89,7 +89,7 @@ object NewCommonSuperTypeCalculator {
private fun commonSuperTypeForNotNullTypes(types: List<SimpleType>, depth: Int): SimpleType {
val uniqueTypes = types.uniquify()
val filteredType = uniqueTypes.filterNot { type ->
uniqueTypes.any { other -> type != other && NewKotlinTypeChecker.isSubtypeOf(type, other)}
uniqueTypes.any { other -> type != other && NewKotlinTypeChecker.isSubtypeOf(type, other) }
}
// seems like all types are equal
if (filteredType.isEmpty()) return uniqueTypes.first()
@@ -125,11 +125,16 @@ object NewCommonSuperTypeCalculator {
}
private fun superTypeWithGivenConstructor(
types: List<SimpleType>,
constructor: TypeConstructor,
depth: Int
types: List<SimpleType>,
constructor: TypeConstructor,
depth: Int
): SimpleType {
if (constructor.parameters.isEmpty()) return KotlinTypeFactory.simpleType(Annotations.EMPTY, constructor, emptyList(), nullable = false)
if (constructor.parameters.isEmpty()) return KotlinTypeFactory.simpleType(
Annotations.EMPTY,
constructor,
emptyList(),
nullable = false
)
val typeCheckerContext = TypeCheckerContext(false)
@@ -158,12 +163,11 @@ object NewCommonSuperTypeCalculator {
}
val argument =
if (thereIsStar || typeProjections.isEmpty()) {
StarProjectionImpl(parameter)
}
else {
calculateArgument(parameter, typeProjections, depth)
}
if (thereIsStar || typeProjections.isEmpty()) {
StarProjectionImpl(parameter)
} else {
calculateArgument(parameter, typeProjections, depth)
}
arguments.add(argument)
}
@@ -185,20 +189,17 @@ object NewCommonSuperTypeCalculator {
val asOut: Boolean
if (parameter.variance != Variance.INVARIANT) {
asOut = parameter.variance == Variance.OUT_VARIANCE
}
else {
} else {
val thereIsOut = arguments.any { it.projectionKind == Variance.OUT_VARIANCE }
val thereIsIn = arguments.any { it.projectionKind == Variance.IN_VARIANCE }
if (thereIsOut) {
if (thereIsIn) {
// CS(Inv<out X>, Inv<in Y>) = Inv<*>
return StarProjectionImpl(parameter)
}
else {
} else {
asOut = true
}
}
else {
} else {
asOut = !thereIsIn
}
}
@@ -207,11 +208,16 @@ object NewCommonSuperTypeCalculator {
// CS(In<X>, In<Y>) = In<X & Y>
if (asOut) {
val type = commonSuperType(arguments.map { it.type.unwrap() }, depth + 1)
return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl(Variance.OUT_VARIANCE, type)
}
else {
return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl(
Variance.OUT_VARIANCE,
type
)
} else {
val type = intersectTypes(arguments.map { it.type.unwrap() })
return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl(Variance.IN_VARIANCE, type)
return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl(
Variance.IN_VARIANCE,
type
)
}
}
}
@@ -29,18 +29,18 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
class AdditionalDiagnosticReporter(private val languageVersionSettings: LanguageVersionSettings) {
fun reportAdditionalDiagnostics(
candidate: ResolvedCallAtom,
resultingDescriptor: CallableDescriptor,
kotlinDiagnosticsHolder: KotlinDiagnosticsHolder,
diagnostics: Collection<KotlinCallDiagnostic>
candidate: ResolvedCallAtom,
resultingDescriptor: CallableDescriptor,
kotlinDiagnosticsHolder: KotlinDiagnosticsHolder,
diagnostics: Collection<KotlinCallDiagnostic>
) {
reportSmartCasts(candidate, resultingDescriptor, kotlinDiagnosticsHolder, diagnostics)
}
private fun createSmartCastDiagnostic(
candidate: ResolvedCallAtom,
argument: KotlinCallArgument,
expectedResultType: UnwrappedType
candidate: ResolvedCallAtom,
argument: KotlinCallArgument,
expectedResultType: UnwrappedType
): SmartCastDiagnostic? {
if (argument !is ExpressionKotlinCallArgument) return null
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(argument.receiver.receiverValue.type, expectedResultType)) {
@@ -50,10 +50,10 @@ class AdditionalDiagnosticReporter(private val languageVersionSettings: Language
}
private fun reportSmartCastOnReceiver(
candidate: ResolvedCallAtom,
receiver: SimpleKotlinCallArgument?,
parameter: ReceiverParameterDescriptor?,
diagnostics: Collection<KotlinCallDiagnostic>
candidate: ResolvedCallAtom,
receiver: SimpleKotlinCallArgument?,
parameter: ReceiverParameterDescriptor?,
diagnostics: Collection<KotlinCallDiagnostic>
): SmartCastDiagnostic? {
if (receiver == null || parameter == null) return null
val expectedType = parameter.type.unwrap().let { if (receiver.isSafeCall) it.makeNullableAsSpecified(true) else it }
@@ -65,24 +65,34 @@ class AdditionalDiagnosticReporter(private val languageVersionSettings: Language
diagnostics.filterIsInstance<UnsafeCallError>().none {
it.receiver == receiver
}
&&
diagnostics.filterIsInstance<UnstableSmartCast>().none {
it.argument == receiver
}
&&
diagnostics.filterIsInstance<UnstableSmartCast>().none {
it.argument == receiver
}
}
}
private fun reportSmartCasts(
candidate: ResolvedCallAtom,
resultingDescriptor: CallableDescriptor,
kotlinDiagnosticsHolder: KotlinDiagnosticsHolder,
diagnostics: Collection<KotlinCallDiagnostic>
candidate: ResolvedCallAtom,
resultingDescriptor: CallableDescriptor,
kotlinDiagnosticsHolder: KotlinDiagnosticsHolder,
diagnostics: Collection<KotlinCallDiagnostic>
) {
kotlinDiagnosticsHolder.addDiagnosticIfNotNull(
reportSmartCastOnReceiver(candidate, candidate.extensionReceiverArgument, resultingDescriptor.extensionReceiverParameter, diagnostics)
reportSmartCastOnReceiver(
candidate,
candidate.extensionReceiverArgument,
resultingDescriptor.extensionReceiverParameter,
diagnostics
)
)
kotlinDiagnosticsHolder.addDiagnosticIfNotNull(
reportSmartCastOnReceiver(candidate, candidate.dispatchReceiverArgument, resultingDescriptor.dispatchReceiverParameter, diagnostics)
reportSmartCastOnReceiver(
candidate,
candidate.dispatchReceiverArgument,
resultingDescriptor.dispatchReceiverParameter,
diagnostics
)
)
for (parameter in resultingDescriptor.valueParameters) {
@@ -27,29 +27,28 @@ import java.util.*
class ArgumentsToParametersMapper {
data class ArgumentMapping(
// This map should be ordered by arguments as written, e.g.:
// fun foo(a: Int, b: Int) {}
// foo(b = bar(), a = qux())
// parameterToCallArgumentMap.values() should be [ 'bar()', 'foo()' ]
val parameterToCallArgumentMap: Map<ValueParameterDescriptor, ResolvedCallArgument>,
val diagnostics: List<KotlinCallDiagnostic>
// This map should be ordered by arguments as written, e.g.:
// fun foo(a: Int, b: Int) {}
// foo(b = bar(), a = qux())
// parameterToCallArgumentMap.values() should be [ 'bar()', 'foo()' ]
val parameterToCallArgumentMap: Map<ValueParameterDescriptor, ResolvedCallArgument>,
val diagnostics: List<KotlinCallDiagnostic>
)
val EmptyArgumentMapping = ArgumentMapping(emptyMap(), emptyList())
fun mapArguments(call: KotlinCall, descriptor: CallableDescriptor): ArgumentMapping =
mapArguments(call.argumentsInParenthesis, call.externalArgument, descriptor)
mapArguments(call.argumentsInParenthesis, call.externalArgument, descriptor)
fun mapArguments(
argumentsInParenthesis: List<KotlinCallArgument>,
externalArgument: KotlinCallArgument?,
descriptor: CallableDescriptor
argumentsInParenthesis: List<KotlinCallArgument>,
externalArgument: KotlinCallArgument?,
descriptor: CallableDescriptor
): ArgumentMapping {
// optimization for case of variable
if (argumentsInParenthesis.isEmpty() && externalArgument == null && descriptor.valueParameters.isEmpty()) {
return EmptyArgumentMapping
}
else {
} else {
val processor = CallArgumentProcessor(descriptor)
processor.processArgumentsInParenthesis(argumentsInParenthesis)
@@ -171,8 +170,7 @@ class ArgumentsToParametersMapper {
return valueParameter
}
}
}
else {
} else {
parameter.getOverriddenParameterWithOtherName()?.let {
addDiagnostic(NameForAmbiguousParameter(argument, parameter, it))
}
@@ -209,7 +207,7 @@ class ArgumentsToParametersMapper {
completeVarargPositionArguments()
}
}
fun processExternalArgument(externalArgument: KotlinCallArgument) {
val lastParameter = parameters.lastOrNull()
if (lastParameter == null) {
@@ -237,8 +235,7 @@ class ArgumentsToParametersMapper {
if (!parameter.isVararg) {
if (resolvedArgument !is ResolvedCallArgument.SimpleArgument) {
error("Incorrect resolved argument for parameter $parameter :$resolvedArgument")
}
else {
} else {
if (resolvedArgument.callArgument.isSpread) {
addDiagnostic(NonVarargSpread(resolvedArgument.callArgument))
}
@@ -250,11 +247,9 @@ class ArgumentsToParametersMapper {
if (!result.containsKey(parameter.original)) {
if (parameter.hasDefaultValue()) {
result[parameter.original] = ResolvedCallArgument.DefaultArgument
}
else if (parameter.isVararg) {
} else if (parameter.isVararg) {
result[parameter.original] = ResolvedCallArgument.VarargArgument(emptyList())
}
else {
} else {
addDiagnostic(NoValueForParameter(parameter, descriptor))
}
}
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal fun unexpectedArgument(argument: KotlinCallArgument): Nothing =
error("Unexpected argument type: $argument, ${argument.javaClass.canonicalName}.")
error("Unexpected argument type: $argument, ${argument.javaClass.canonicalName}.")
// if expression is not stable and has smart casts, then we create this type
internal val ReceiverValueWithSmartCastInfo.unstableType: UnwrappedType?
@@ -49,19 +49,18 @@ internal val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType
}
internal fun KotlinCallArgument.getExpectedType(parameter: ParameterDescriptor, languageVersionSettings: LanguageVersionSettings) =
if (this.isSpread || this.isArrayAssignedAsNamedArgumentInAnnotation(parameter, languageVersionSettings)) {
parameter.type.unwrap()
}
else {
parameter.safeAs<ValueParameterDescriptor>()?.varargElementType?.unwrap() ?: parameter.type.unwrap()
}
if (this.isSpread || this.isArrayAssignedAsNamedArgumentInAnnotation(parameter, languageVersionSettings)) {
parameter.type.unwrap()
} else {
parameter.safeAs<ValueParameterDescriptor>()?.varargElementType?.unwrap() ?: parameter.type.unwrap()
}
val ValueParameterDescriptor.isVararg: Boolean get() = varargElementType != null
val ParameterDescriptor.isVararg: Boolean get() = this.safeAs<ValueParameterDescriptor>()?.isVararg ?: false
private fun KotlinCallArgument.isArrayAssignedAsNamedArgumentInAnnotation(
parameter: ParameterDescriptor,
languageVersionSettings: LanguageVersionSettings
parameter: ParameterDescriptor,
languageVersionSettings: LanguageVersionSettings
): Boolean {
if (!languageVersionSettings.supportsFeature(LanguageFeature.AssigningArraysToVarargsInNamedFormInAnnotations)) return false
@@ -46,7 +46,8 @@ sealed class CallableReceiver(val receiver: ReceiverValueWithSmartCastInfo) {
class UnboundReference(val qualifier: QualifierReceiver, receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
class BoundValueReference(val qualifier: QualifierReceiver, receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
class ScopeReceiver(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
class ExplicitValueReceiver(val lhsArgument: SimpleKotlinCallArgument, receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
class ExplicitValueReceiver(val lhsArgument: SimpleKotlinCallArgument, receiver: ReceiverValueWithSmartCastInfo) :
CallableReceiver(receiver)
}
// todo investigate similar code in CheckVisibility
@@ -62,13 +63,13 @@ private val CallableReceiver.asReceiverValueForVisibilityChecks: ReceiverValue
* For class B with companion object B::companionM dispatchReceiver = BoundValueReference
*/
class CallableReferenceCandidate(
val candidate: CallableDescriptor,
val dispatchReceiver: CallableReceiver?,
val extensionReceiver: CallableReceiver?,
val explicitReceiverKind: ExplicitReceiverKind,
val reflectionCandidateType: UnwrappedType,
val numDefaults: Int,
val diagnostics: List<KotlinCallDiagnostic>
val candidate: CallableDescriptor,
val dispatchReceiver: CallableReceiver?,
val extensionReceiver: CallableReceiver?,
val explicitReceiverKind: ExplicitReceiverKind,
val reflectionCandidateType: UnwrappedType,
val numDefaults: Int,
val diagnostics: List<KotlinCallDiagnostic>
) : Candidate {
override val resultingApplicability = getResultApplicability(diagnostics)
override val isSuccessful get() = resultingApplicability.isSuccess
@@ -113,13 +114,13 @@ fun createCallableReferenceProcessor(factory: CallableReferencesCandidateFactory
}
fun ConstraintSystemOperation.checkCallableReference(
argument: CallableReferenceKotlinCallArgument,
dispatchReceiver: CallableReceiver?,
extensionReceiver: CallableReceiver?,
candidateDescriptor: CallableDescriptor,
reflectionCandidateType: UnwrappedType,
expectedType: UnwrappedType?,
ownerDescriptor: DeclarationDescriptor
argument: CallableReferenceKotlinCallArgument,
dispatchReceiver: CallableReceiver?,
extensionReceiver: CallableReceiver?,
candidateDescriptor: CallableDescriptor,
reflectionCandidateType: UnwrappedType,
expectedType: UnwrappedType?,
ownerDescriptor: DeclarationDescriptor
): Pair<FreshVariableNewTypeSubstitutor, KotlinCallDiagnostic?> {
val position = ArgumentConstraintPosition(argument)
@@ -132,17 +133,19 @@ fun ConstraintSystemOperation.checkCallableReference(
addReceiverConstraint(toFreshSubstitutor, dispatchReceiver, candidateDescriptor.dispatchReceiverParameter, position)
addReceiverConstraint(toFreshSubstitutor, extensionReceiver, candidateDescriptor.extensionReceiverParameter, position)
val invisibleMember = Visibilities.findInvisibleMember(dispatchReceiver?.asReceiverValueForVisibilityChecks,
candidateDescriptor, ownerDescriptor)
val invisibleMember = Visibilities.findInvisibleMember(
dispatchReceiver?.asReceiverValueForVisibilityChecks,
candidateDescriptor, ownerDescriptor
)
return toFreshSubstitutor to invisibleMember?.let(::VisibilityError)
}
private fun ConstraintSystemOperation.addReceiverConstraint(
toFreshSubstitutor: FreshVariableNewTypeSubstitutor,
receiverArgument: CallableReceiver?,
receiverParameter: ReceiverParameterDescriptor?,
position: ArgumentConstraintPosition
toFreshSubstitutor: FreshVariableNewTypeSubstitutor,
receiverArgument: CallableReceiver?,
receiverParameter: ReceiverParameterDescriptor?,
position: ArgumentConstraintPosition
) {
if (receiverArgument == null || receiverParameter == null) {
assert(receiverArgument == null) { "Receiver argument should be null if parameter is: $receiverArgument" }
@@ -156,41 +159,45 @@ private fun ConstraintSystemOperation.addReceiverConstraint(
}
class CallableReferencesCandidateFactory(
val argument: CallableReferenceKotlinCallArgument,
val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower,
val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit,
val expectedType: UnwrappedType?
val argument: CallableReferenceKotlinCallArgument,
val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower,
val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit,
val expectedType: UnwrappedType?
) : CandidateFactory<CallableReferenceCandidate> {
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) =
createCallableReferenceProcessor(scopeTower, argument.rhsName, this, explicitReceiver)
createCallableReferenceProcessor(scopeTower, argument.rhsName, this, explicitReceiver)
override fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValueWithSmartCastInfo?
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): CallableReferenceCandidate {
val dispatchCallableReceiver = towerCandidate.dispatchReceiver?.let { toCallableReceiver(it, explicitReceiverKind == DISPATCH_RECEIVER) }
val dispatchCallableReceiver =
towerCandidate.dispatchReceiver?.let { toCallableReceiver(it, explicitReceiverKind == DISPATCH_RECEIVER) }
val extensionCallableReceiver = extensionReceiver?.let { toCallableReceiver(it, explicitReceiverKind == EXTENSION_RECEIVER) }
val candidateDescriptor = towerCandidate.descriptor
val diagnostics = SmartList<KotlinCallDiagnostic>()
val (reflectionCandidateType, defaults) = buildReflectionType(
candidateDescriptor,
dispatchCallableReceiver,
extensionCallableReceiver,
expectedType)
candidateDescriptor,
dispatchCallableReceiver,
extensionCallableReceiver,
expectedType
)
if (defaults != 0) {
diagnostics.add(CallableReferencesDefaultArgumentUsed(argument, candidateDescriptor, defaults))
}
if (candidateDescriptor !is CallableMemberDescriptor) {
return CallableReferenceCandidate(candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, defaults,
listOf(NotCallableMemberReference(argument, candidateDescriptor)))
return CallableReferenceCandidate(
candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, defaults,
listOf(NotCallableMemberReference(argument, candidateDescriptor))
)
}
diagnostics.addAll(towerCandidate.diagnostics)
@@ -200,22 +207,32 @@ class CallableReferencesCandidateFactory(
if (it.hasContradiction) return@compatibilityChecker
val (_, visibilityError) = it.checkCallableReference(
argument, dispatchCallableReceiver, extensionCallableReceiver, candidateDescriptor,
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor)
argument, dispatchCallableReceiver, extensionCallableReceiver, candidateDescriptor,
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor
)
diagnostics.addIfNotNull(visibilityError)
if (it.hasContradiction) diagnostics.add(CallableReferenceNotCompatible(argument, candidateDescriptor, expectedType, reflectionCandidateType))
if (it.hasContradiction) diagnostics.add(
CallableReferenceNotCompatible(
argument,
candidateDescriptor,
expectedType,
reflectionCandidateType
)
)
}
return CallableReferenceCandidate(candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, defaults, diagnostics)
return CallableReferenceCandidate(
candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, defaults, diagnostics
)
}
private fun getArgumentAndReturnTypeUseMappingByExpectedType(
descriptor: FunctionDescriptor,
expectedType: UnwrappedType?,
unboundReceiverCount: Int
descriptor: FunctionDescriptor,
expectedType: UnwrappedType?,
unboundReceiverCount: Int
): Triple<Array<KotlinType>, CoercionStrategy, Int>? {
val functionType = getFunctionTypeFromCallableReferenceExpectedType(expectedType) ?: return null
@@ -223,7 +240,8 @@ class CallableReferencesCandidateFactory(
if (expectedArgumentCount < 0) return null
val fakeArguments = (0..(expectedArgumentCount - 1)).map { FakeKotlinCallArgumentForCallableReference(it) }
val argumentMapping = callComponents.argumentsToParametersMapper.mapArguments(fakeArguments, externalArgument = null, descriptor = descriptor)
val argumentMapping =
callComponents.argumentsToParametersMapper.mapArguments(fakeArguments, externalArgument = null, descriptor = descriptor)
if (argumentMapping.diagnostics.any { !it.candidateApplicability.isSuccess }) return null
/**
@@ -253,10 +271,10 @@ class CallableReferencesCandidateFactory(
}
private fun buildReflectionType(
descriptor: CallableDescriptor,
dispatchReceiver: CallableReceiver?,
extensionReceiver: CallableReceiver?,
expectedType: UnwrappedType?
descriptor: CallableDescriptor,
dispatchReceiver: CallableReceiver?,
extensionReceiver: CallableReceiver?,
expectedType: UnwrappedType?
): Pair<UnwrappedType, /*defaults*/ Int> {
val argumentsAndReceivers = ArrayList<KotlinType>(descriptor.valueParameters.size + 2)
@@ -268,30 +286,38 @@ class CallableReferencesCandidateFactory(
}
val descriptorReturnType = descriptor.returnType
?: ErrorUtils.createErrorType("Error return type for descriptor: $descriptor")
?: ErrorUtils.createErrorType("Error return type for descriptor: $descriptor")
when (descriptor) {
is PropertyDescriptor -> {
val mutable = descriptor.isVar && run {
val setter = descriptor.setter
setter == null || Visibilities.isVisible(dispatchReceiver?.asReceiverValueForVisibilityChecks, setter,
scopeTower.lexicalScope.ownerDescriptor)
setter == null || Visibilities.isVisible(
dispatchReceiver?.asReceiverValueForVisibilityChecks, setter,
scopeTower.lexicalScope.ownerDescriptor
)
}
return callComponents.reflectionTypes.getKPropertyType(Annotations.EMPTY, argumentsAndReceivers, descriptorReturnType, mutable) to 0
return callComponents.reflectionTypes.getKPropertyType(
Annotations.EMPTY,
argumentsAndReceivers,
descriptorReturnType,
mutable
) to 0
}
is FunctionDescriptor -> {
val returnType: KotlinType
val defaults: Int
val argumentsAndExpectedTypeCoercion = getArgumentAndReturnTypeUseMappingByExpectedType(descriptor, expectedType,
unboundReceiverCount = argumentsAndReceivers.size)
val argumentsAndExpectedTypeCoercion = getArgumentAndReturnTypeUseMappingByExpectedType(
descriptor, expectedType,
unboundReceiverCount = argumentsAndReceivers.size
)
if (argumentsAndExpectedTypeCoercion == null) {
descriptor.valueParameters.mapTo(argumentsAndReceivers) { it.type }
returnType = descriptorReturnType
defaults = 0
}
else {
} else {
val (arguments, coercion) = argumentsAndExpectedTypeCoercion
defaults = argumentsAndExpectedTypeCoercion.third
argumentsAndReceivers.addAll(arguments)
@@ -299,8 +325,10 @@ class CallableReferencesCandidateFactory(
returnType = if (coercion == CoercionStrategy.COERCION_TO_UNIT) descriptor.builtIns.unitType else descriptorReturnType
}
return callComponents.reflectionTypes.getKFunctionType(Annotations.EMPTY, null, argumentsAndReceivers, null,
returnType, descriptor.builtIns) to defaults
return callComponents.reflectionTypes.getKFunctionType(
Annotations.EMPTY, null, argumentsAndReceivers, null,
returnType, descriptor.builtIns
) to defaults
}
else -> error("Unsupported descriptor type: $descriptor")
}
@@ -315,8 +343,7 @@ class CallableReferencesCandidateFactory(
is LHSResult.Type -> {
if (lhsResult.qualifier.classValueReceiver?.type == receiver.receiverValue.type) {
CallableReceiver.BoundValueReference(lhsResult.qualifier, receiver)
}
else {
} else {
CallableReceiver.UnboundReference(lhsResult.qualifier, receiver)
}
}
@@ -331,11 +358,9 @@ fun getFunctionTypeFromCallableReferenceExpectedType(expectedType: UnwrappedType
return if (expectedType.isFunctionType) {
expectedType
}
else if (ReflectionTypes.isNumberedKFunction(expectedType)) {
} else if (ReflectionTypes.isNumberedKFunction(expectedType)) {
expectedType.immediateSupertypes().first { it.isFunctionType }.unwrap()
}
else {
} else {
null
}
}
@@ -32,36 +32,36 @@ import org.jetbrains.kotlin.types.UnwrappedType
class CallableReferenceOverloadConflictResolver(
builtIns: KotlinBuiltIns,
specificityComparator: TypeSpecificityComparator,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector
builtIns: KotlinBuiltIns,
specificityComparator: TypeSpecificityComparator,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector
) : OverloadingConflictResolver<CallableReferenceCandidate>(
builtIns,
specificityComparator,
{ it.candidate },
{ SimpleConstraintSystemImpl(constraintInjector, builtIns) },
Companion::createFlatSignature,
{ null },
{ statelessCallbacks.isDescriptorFromSource(it) }
) {
builtIns,
specificityComparator,
{ it.candidate },
{ SimpleConstraintSystemImpl(constraintInjector, builtIns) },
Companion::createFlatSignature,
{ null },
{ statelessCallbacks.isDescriptorFromSource(it) }
) {
companion object {
private fun createFlatSignature(candidate: CallableReferenceCandidate) =
FlatSignature.createFromReflectionType(candidate, candidate.candidate, candidate.numDefaults, candidate.reflectionCandidateType)
FlatSignature.createFromReflectionType(candidate, candidate.candidate, candidate.numDefaults, candidate.reflectionCandidateType)
}
}
class CallableReferenceResolver(
private val towerResolver: TowerResolver,
private val callableReferenceOverloadConflictResolver: CallableReferenceOverloadConflictResolver,
private val callComponents: KotlinCallComponents
private val towerResolver: TowerResolver,
private val callableReferenceOverloadConflictResolver: CallableReferenceOverloadConflictResolver,
private val callComponents: KotlinCallComponents
) {
fun processCallableReferenceArgument(
csBuilder: ConstraintSystemBuilder,
resolvedAtom: ResolvedCallableReferenceAtom,
diagnosticsHolder: KotlinDiagnosticsHolder
csBuilder: ConstraintSystemBuilder,
resolvedAtom: ResolvedCallableReferenceAtom,
diagnosticsHolder: KotlinDiagnosticsHolder
) {
val argument = resolvedAtom.atom
val expectedType = resolvedAtom.expectedType?.let { csBuilder.buildCurrentSubstitutor().safeSubstitute(it) }
@@ -73,17 +73,17 @@ class CallableReferenceResolver(
val chosenCandidate = candidates.singleOrNull()
if (chosenCandidate != null) {
val (toFreshSubstitutor, diagnostic) = with(chosenCandidate) {
csBuilder.checkCallableReference(argument, dispatchReceiver, extensionReceiver, candidate,
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor)
csBuilder.checkCallableReference(
argument, dispatchReceiver, extensionReceiver, candidate,
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor
)
}
diagnosticsHolder.addDiagnosticIfNotNull(diagnostic)
chosenCandidate.freshSubstitutor = toFreshSubstitutor
}
else {
} else {
if (candidates.isEmpty()) {
diagnosticsHolder.addDiagnostic(NoneCallableReferenceCandidates(argument))
}
else {
} else {
diagnosticsHolder.addDiagnostic(CallableReferenceCandidatesAmbiguity(argument, candidates))
}
}
@@ -97,7 +97,7 @@ class CallableReferenceResolver(
private fun buildResolvedKtArgument(lhsResult: LHSResult): ResolvedAtom? {
if (lhsResult !is LHSResult.Expression) return null
val lshCallArgument = lhsResult.lshCallArgument
return when(lshCallArgument) {
return when (lshCallArgument) {
is SubKotlinCallArgument -> lshCallArgument.callResult
is ExpressionKotlinCallArgument -> ResolvedExpressionAtom(lshCallArgument)
else -> unexpectedArgument(lshCallArgument)
@@ -105,19 +105,20 @@ class CallableReferenceResolver(
}
private fun runRHSResolution(
scopeTower: ImplicitScopeTower,
callableReference: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?, // this type can have not fixed type variable inside
compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be rolled back
scopeTower: ImplicitScopeTower,
callableReference: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?, // this type can have not fixed type variable inside
compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be rolled back
): Set<CallableReferenceCandidate> {
val factory = CallableReferencesCandidateFactory(callableReference, callComponents, scopeTower, compatibilityChecker, expectedType)
val processor = createCallableReferenceProcessor(factory)
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true, name = callableReference.rhsName)
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
candidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = false, // we can't specify generics explicitly for callable references
isDebuggerContext = scopeTower.isDebuggerContext)
candidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = false, // we can't specify generics explicitly for callable references
isDebuggerContext = scopeTower.isDebuggerContext
)
}
}
@@ -38,11 +38,11 @@ interface KotlinResolutionStatelessCallbacks {
// This components hold state (trace). Work with this carefully.
interface KotlinResolutionCallbacks {
fun analyzeAndGetLambdaReturnArguments(
lambdaArgument: LambdaKotlinCallArgument,
isSuspend: Boolean,
receiverType: UnwrappedType?,
parameters: List<UnwrappedType>,
expectedReturnType: UnwrappedType? // null means, that return type is not proper i.e. it depends on some type variables
lambdaArgument: LambdaKotlinCallArgument,
isSuspend: Boolean,
receiverType: UnwrappedType?,
parameters: List<UnwrappedType>,
expectedReturnType: UnwrappedType? // null means, that return type is not proper i.e. it depends on some type variables
): List<SimpleKotlinCallArgument>
fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom)
@@ -27,15 +27,15 @@ import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.UnwrappedType
class KotlinCallCompleter(
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter
) {
fun runCompletion(
factory: SimpleCandidateFactory,
candidates: Collection<KotlinResolutionCandidate>,
expectedType: UnwrappedType?,
resolutionCallbacks: KotlinResolutionCallbacks
factory: SimpleCandidateFactory,
candidates: Collection<KotlinResolutionCandidate>,
expectedType: UnwrappedType?,
resolutionCallbacks: KotlinResolutionCallbacks
): CallResolutionResult {
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
if (candidates.isEmpty()) {
@@ -54,14 +54,20 @@ class KotlinCallCompleter(
if (candidate == null || candidate.csBuilder.hasContradiction) {
val candidateForCompletion = candidate ?: factory.createErrorCandidate().forceResolution()
candidateForCompletion.prepareForCompletion(expectedType, resolutionCallbacks)
runCompletion(candidateForCompletion.resolvedCall, ConstraintSystemCompletionMode.FULL, diagnosticHolder, candidateForCompletion.getSystem(), resolutionCallbacks)
runCompletion(
candidateForCompletion.resolvedCall,
ConstraintSystemCompletionMode.FULL,
diagnosticHolder,
candidateForCompletion.getSystem(),
resolutionCallbacks
)
val systemStorage = candidate?.getSystem()?.asReadOnlyStorage() ?: ConstraintStorage.Empty
return CallResolutionResult(
CallResolutionResult.Type.ERROR,
candidate?.resolvedCall,
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
systemStorage
CallResolutionResult.Type.ERROR,
candidate?.resolvedCall,
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
systemStorage
)
}
@@ -71,57 +77,62 @@ class KotlinCallCompleter(
return if (completionType == ConstraintSystemCompletionMode.FULL) {
CallResolutionResult(
CallResolutionResult.Type.COMPLETED,
candidate.resolvedCall,
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
constraintSystem.asReadOnlyStorage()
CallResolutionResult.Type.COMPLETED,
candidate.resolvedCall,
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
constraintSystem.asReadOnlyStorage()
)
}
else {
} else {
CallResolutionResult(
CallResolutionResult.Type.PARTIAL,
candidate.resolvedCall,
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
constraintSystem.asReadOnlyStorage()
CallResolutionResult.Type.PARTIAL,
candidate.resolvedCall,
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
constraintSystem.asReadOnlyStorage()
)
}
}
fun createAllCandidatesResult(
candidates: Collection<KotlinResolutionCandidate>,
expectedType: UnwrappedType?,
resolutionCallbacks: KotlinResolutionCallbacks
candidates: Collection<KotlinResolutionCandidate>,
expectedType: UnwrappedType?,
resolutionCallbacks: KotlinResolutionCallbacks
): CallResolutionResult {
val diagnosticsHolder = KotlinDiagnosticsHolder.SimpleHolder()
for (candidate in candidates) {
candidate.prepareForCompletion(expectedType, resolutionCallbacks)
runCompletion(
candidate.resolvedCall,
ConstraintSystemCompletionMode.FULL,
diagnosticsHolder,
candidate.getSystem(),
resolutionCallbacks,
skipPostponedArguments = true)
candidate.resolvedCall,
ConstraintSystemCompletionMode.FULL,
diagnosticsHolder,
candidate.getSystem(),
resolutionCallbacks,
skipPostponedArguments = true
)
}
return CallResolutionResult(CallResolutionResult.Type.ALL_CANDIDATES, null, emptyList(), ConstraintStorage.Empty, candidates)
}
private fun runCompletion(
resolvedCallAtom: ResolvedCallAtom,
completionMode: ConstraintSystemCompletionMode,
diagnosticsHolder: KotlinDiagnosticsHolder,
constraintSystem: NewConstraintSystem,
resolutionCallbacks: KotlinResolutionCallbacks,
skipPostponedArguments: Boolean = false
private fun runCompletion(
resolvedCallAtom: ResolvedCallAtom,
completionMode: ConstraintSystemCompletionMode,
diagnosticsHolder: KotlinDiagnosticsHolder,
constraintSystem: NewConstraintSystem,
resolutionCallbacks: KotlinResolutionCallbacks,
skipPostponedArguments: Boolean = false
) {
val returnType = resolvedCallAtom.freshReturnType ?: constraintSystem.builtIns.unitType
kotlinConstraintSystemCompleter.runCompletion(constraintSystem.asConstraintSystemCompleterContext(), completionMode, resolvedCallAtom, returnType) {
kotlinConstraintSystemCompleter.runCompletion(
constraintSystem.asConstraintSystemCompleterContext(),
completionMode,
resolvedCallAtom,
returnType
) {
if (!skipPostponedArguments) {
postponedArgumentsAnalyzer.analyze(
constraintSystem.asPostponedArgumentsAnalyzerContext(),
resolutionCallbacks,
it,
diagnosticsHolder
constraintSystem.asPostponedArgumentsAnalyzerContext(),
resolutionCallbacks,
it,
diagnosticsHolder
)
}
}
@@ -132,8 +143,8 @@ class KotlinCallCompleter(
// true if we should complete this call
private fun KotlinResolutionCandidate.prepareForCompletion(
expectedType: UnwrappedType?,
resolutionCallbacks: KotlinResolutionCallbacks
expectedType: UnwrappedType?,
resolutionCallbacks: KotlinResolutionCallbacks
): ConstraintSystemCompletionMode {
val unsubstitutedReturnType = resolvedCall.candidateDescriptor.returnType?.unwrap() ?: return ConstraintSystemCompletionMode.PARTIAL
val withSmartCastInfo = resolutionCallbacks.createReceiverWithSmartCastInfo(resolvedCall)
@@ -141,14 +152,16 @@ class KotlinCallCompleter(
val actualType = withSmartCastInfo?.stableType ?: unsubstitutedReturnType
val returnType = resolvedCall.substitutor.substituteKeepAnnotations(actualType)
if (expectedType != null && !TypeUtils.noExpectedType(expectedType) && !resolutionCallbacks.isCompileTimeConstant(resolvedCall, expectedType)) {
if (expectedType != null && !TypeUtils.noExpectedType(expectedType) && !resolutionCallbacks.isCompileTimeConstant(
resolvedCall,
expectedType
)) {
csBuilder.addSubtypeConstraint(returnType, expectedType, ExpectedTypeConstraintPosition(resolvedCall.atom))
}
return if (expectedType != null || csBuilder.isProperType(returnType)) {
ConstraintSystemCompletionMode.FULL
}
else {
} else {
ConstraintSystemCompletionMode.PARTIAL
}
}
@@ -28,21 +28,21 @@ import org.jetbrains.kotlin.types.KotlinType
import java.util.*
class NewOverloadingConflictResolver(
builtIns: KotlinBuiltIns,
specificityComparator: TypeSpecificityComparator,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector
builtIns: KotlinBuiltIns,
specificityComparator: TypeSpecificityComparator,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector
) : OverloadingConflictResolver<KotlinResolutionCandidate>(
builtIns,
specificityComparator,
{
// todo investigate
it.resolvedCall.candidateDescriptor
},
{ SimpleConstraintSystemImpl(constraintInjector, builtIns) },
Companion::createFlatSignature,
{ it.variableCandidateIfInvoke },
{ statelessCallbacks.isDescriptorFromSource(it) }
builtIns,
specificityComparator,
{
// todo investigate
it.resolvedCall.candidateDescriptor
},
{ SimpleConstraintSystemImpl(constraintInjector, builtIns) },
Companion::createFlatSignature,
{ it.variableCandidateIfInvoke },
{ statelessCallbacks.isDescriptorFromSource(it) }
) {
companion object {
@@ -57,8 +57,7 @@ class NewOverloadingConflictResolver(
for ((valueParameter, resolvedValueArgument) in resolvedCall.argumentMappingByOriginal) {
if (resolvedValueArgument is ResolvedCallArgument.DefaultArgument) {
numDefaults++
}
else {
} else {
val originalValueParameter = originalValueParameters[valueParameter.index]
val parameterType = originalValueParameter.argumentValueType
for (valueArgument in resolvedValueArgument.arguments) {
@@ -71,7 +70,7 @@ class NewOverloadingConflictResolver(
originalDescriptor,
numDefaults,
resolvedCall.atom.argumentsInParenthesis.map { valueArgumentToParameterType[it] } +
listOfNotNull(resolvedCall.atom.externalArgument?.let { valueArgumentToParameterType[it] })
listOfNotNull(resolvedCall.atom.externalArgument?.let { valueArgumentToParameterType[it] })
)
}
@@ -27,11 +27,11 @@ import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun resolveKtPrimitive(
csBuilder: ConstraintSystemBuilder,
argument: KotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
csBuilder: ConstraintSystemBuilder,
argument: KotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
): ResolvedAtom = when (argument) {
is SimpleKotlinCallArgument -> checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
is LambdaKotlinCallArgument -> preprocessLambdaArgument(csBuilder, argument, expectedType)
@@ -43,10 +43,10 @@ fun resolveKtPrimitive(
// if expected type isn't function type, then may be it is Function<R>, Any or just `T`
private fun preprocessLambdaArgument(
csBuilder: ConstraintSystemBuilder,
argument: LambdaKotlinCallArgument,
expectedType: UnwrappedType?,
forceResolution: Boolean = false
csBuilder: ConstraintSystemBuilder,
argument: LambdaKotlinCallArgument,
expectedType: UnwrappedType?,
forceResolution: Boolean = false
): ResolvedAtom {
if (expectedType != null && !forceResolution && csBuilder.isTypeVariable(expectedType)) {
return LambdaWithTypeVariableAsExpectedTypeAtom(argument, expectedType)
@@ -55,8 +55,10 @@ private fun preprocessLambdaArgument(
val resolvedArgument = extractLambdaInfoFromFunctionalType(expectedType, argument) ?: extraLambdaInfo(expectedType, argument, csBuilder)
if (expectedType != null) {
val lambdaType = createFunctionType(csBuilder.builtIns, Annotations.EMPTY, resolvedArgument.receiver,
resolvedArgument.parameters, null, resolvedArgument.returnType, resolvedArgument.isSuspend)
val lambdaType = createFunctionType(
csBuilder.builtIns, Annotations.EMPTY, resolvedArgument.receiver,
resolvedArgument.parameters, null, resolvedArgument.returnType, resolvedArgument.isSuspend
)
csBuilder.addSubtypeConstraint(lambdaType, expectedType, ArgumentConstraintPosition(argument))
}
@@ -64,9 +66,9 @@ private fun preprocessLambdaArgument(
}
private fun extraLambdaInfo(
expectedType: UnwrappedType?,
argument: LambdaKotlinCallArgument,
csBuilder: ConstraintSystemBuilder
expectedType: UnwrappedType?,
argument: LambdaKotlinCallArgument,
csBuilder: ConstraintSystemBuilder
): ResolvedLambdaAtom {
val builtIns = csBuilder.builtIns
val isSuspend = expectedType?.isSuspendFunctionType ?: false
@@ -77,9 +79,9 @@ private fun extraLambdaInfo(
val typeVariable = TypeVariableForLambdaReturnType(argument, builtIns, "_L")
val receiverType = argumentAsFunctionExpression?.receiverType
val returnType = argumentAsFunctionExpression?.returnType ?:
expectedType?.arguments?.singleOrNull()?.type?.unwrap()?.takeIf { isFunctionSupertype } ?:
typeVariable.defaultType
val returnType =
argumentAsFunctionExpression?.returnType ?: expectedType?.arguments?.singleOrNull()?.type?.unwrap()?.takeIf { isFunctionSupertype }
?: typeVariable.defaultType
val parameters = argument.parametersTypes?.map { it ?: builtIns.nothingType } ?: emptyList()
@@ -97,7 +99,14 @@ private fun extractLambdaInfoFromFunctionalType(expectedType: UnwrappedType?, ar
val receiverType = argumentAsFunctionExpression?.receiverType ?: expectedType.getReceiverTypeFromFunctionType()?.unwrap()
val returnType = argumentAsFunctionExpression?.returnType ?: expectedType.getReturnTypeFromFunctionType().unwrap()
return ResolvedLambdaAtom(argument, expectedType.isSuspendFunctionType, receiverType, parameters, returnType, typeVariableForLambdaReturnType = null)
return ResolvedLambdaAtom(
argument,
expectedType.isSuspendFunctionType,
receiverType,
parameters,
returnType,
typeVariableForLambdaReturnType = null
)
}
private fun extractLambdaParameters(expectedType: UnwrappedType, argument: LambdaKotlinCallArgument): List<UnwrappedType> {
@@ -122,15 +131,16 @@ fun LambdaWithTypeVariableAsExpectedTypeAtom.transformToResolvedLambda(csBuilder
}
private fun preprocessCallableReference(
csBuilder: ConstraintSystemBuilder,
argument: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder
csBuilder: ConstraintSystemBuilder,
argument: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder
): ResolvedAtom {
val result = ResolvedCallableReferenceAtom(argument, expectedType)
if (expectedType == null) return result
val notCallableTypeConstructor = csBuilder.getProperSuperTypeConstructors(expectedType).firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it) }
val notCallableTypeConstructor =
csBuilder.getProperSuperTypeConstructors(expectedType).firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it) }
if (notCallableTypeConstructor != null) {
diagnosticsHolder.addDiagnostic(NotCallableExpectedType(argument, expectedType, notCallableTypeConstructor))
}
@@ -138,8 +148,8 @@ private fun preprocessCallableReference(
}
private fun preprocessCollectionLiteralArgument(
collectionLiteralArgument: CollectionLiteralKotlinCallArgument,
expectedType: UnwrappedType?
collectionLiteralArgument: CollectionLiteralKotlinCallArgument,
expectedType: UnwrappedType?
): ResolvedAtom {
// todo add some checks about expected type
return ResolvedCollectionLiteralAtom(collectionLiteralArgument, expectedType)
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.typeUtil.builtIns
class PostponedArgumentsAnalyzer(
private val callableReferenceResolver: CallableReferenceResolver
private val callableReferenceResolver: CallableReferenceResolver
) {
interface Context {
fun buildCurrentSubstitutor(): NewTypeSubstitutor
@@ -36,10 +36,16 @@ class PostponedArgumentsAnalyzer(
// mutable operations
fun addOtherSystem(otherSystem: ConstraintStorage)
fun getBuilder(): ConstraintSystemBuilder
}
fun analyze(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, argument: ResolvedAtom, diagnosticsHolder: KotlinDiagnosticsHolder) {
fun analyze(
c: Context,
resolutionCallbacks: KotlinResolutionCallbacks,
argument: ResolvedAtom,
diagnosticsHolder: KotlinDiagnosticsHolder
) {
when (argument) {
is ResolvedLambdaAtom ->
analyzeLambda(c, resolutionCallbacks, argument, diagnosticsHolder)
@@ -56,7 +62,12 @@ class PostponedArgumentsAnalyzer(
}
}
private fun analyzeLambda(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, lambda: ResolvedLambdaAtom, diagnosticHolder: KotlinDiagnosticsHolder) {
private fun analyzeLambda(
c: Context,
resolutionCallbacks: KotlinResolutionCallbacks,
lambda: ResolvedLambdaAtom,
diagnosticHolder: KotlinDiagnosticsHolder
) {
val currentSubstitutor = c.buildCurrentSubstitutor()
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
@@ -64,7 +75,8 @@ class PostponedArgumentsAnalyzer(
val parameters = lambda.parameters.map(::substitute)
val expectedType = lambda.returnType.takeIf { c.canBeProper(it) }?.let(::substitute)
val returnArguments = resolutionCallbacks.analyzeAndGetLambdaReturnArguments(lambda.atom, lambda.isSuspend, receiver, parameters, expectedType)
val returnArguments =
resolutionCallbacks.analyzeAndGetLambdaReturnArguments(lambda.atom, lambda.isSuspend, receiver, parameters, expectedType)
returnArguments.forEach { c.addSubsystemFromArgument(it) }
@@ -55,12 +55,19 @@ internal object CheckVisibility : ResolutionPart() {
if (scopeTower.isDebuggerContext) return
val receiverValue = dispatchReceiverArgument?.receiver?.receiverValue ?: Visibilities.ALWAYS_SUITABLE_RECEIVER
val invisibleMember = Visibilities.findInvisibleMember(receiverValue, resolvedCall.candidateDescriptor, containingDescriptor) ?: return
val invisibleMember =
Visibilities.findInvisibleMember(receiverValue, resolvedCall.candidateDescriptor, containingDescriptor) ?: return
if (dispatchReceiverArgument is ExpressionKotlinCallArgument) {
val smartCastReceiver = getReceiverValueWithSmartCast(receiverValue, dispatchReceiverArgument.receiver.stableType)
if (Visibilities.findInvisibleMember(smartCastReceiver, candidateDescriptor, containingDescriptor) == null) {
addDiagnostic(SmartCastDiagnostic(dispatchReceiverArgument, dispatchReceiverArgument.receiver.stableType, resolvedCall.atom))
addDiagnostic(
SmartCastDiagnostic(
dispatchReceiverArgument,
dispatchReceiverArgument.receiver.stableType,
resolvedCall.atom
)
)
return
}
}
@@ -147,16 +154,23 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
val knownTypeArgument = knownTypeParametersResultingSubstitutor?.substitute(typeParameter.defaultType)
if (knownTypeArgument != null) {
csBuilder.addEqualityConstraint(freshVariable.defaultType, knownTypeArgument.unwrap(), KnownTypeParameterConstraintPosition(knownTypeArgument))
csBuilder.addEqualityConstraint(
freshVariable.defaultType,
knownTypeArgument.unwrap(),
KnownTypeParameterConstraintPosition(knownTypeArgument)
)
continue
}
val typeArgument = resolvedCall.typeArgumentMappingByOriginal.getTypeArgument(typeParameter)
if (typeArgument is SimpleTypeArgument) {
csBuilder.addEqualityConstraint(freshVariable.defaultType, typeArgument.type, ExplicitTypeParameterConstraintPosition(typeArgument))
}
else {
csBuilder.addEqualityConstraint(
freshVariable.defaultType,
typeArgument.type,
ExplicitTypeParameterConstraintPosition(typeArgument)
)
} else {
assert(typeArgument == TypeArgumentPlaceholder) {
"Unexpected typeArgument: $typeArgument, ${typeArgument.javaClass.canonicalName}"
}
@@ -165,8 +179,8 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
}
fun createToFreshVariableSubstitutorAndAddInitialConstraints(
candidateDescriptor: CallableDescriptor,
csBuilder: ConstraintSystemOperation
candidateDescriptor: CallableDescriptor,
csBuilder: ConstraintSystemOperation
): FreshVariableNewTypeSubstitutor {
val typeParameters = candidateDescriptor.typeParameters
@@ -193,9 +207,11 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
internal object CheckExplicitReceiverKindConsistency : ResolutionPart() {
private fun KotlinResolutionCandidate.hasError(): Nothing =
error("Inconsistent call: $kotlinCall. \n" +
"Candidate: $candidateDescriptor, explicitReceiverKind: ${resolvedCall.explicitReceiverKind}.\n" +
"Explicit receiver: ${kotlinCall.explicitReceiver}, dispatchReceiverForInvokeExtension: ${kotlinCall.dispatchReceiverForInvokeExtension}")
error(
"Inconsistent call: $kotlinCall. \n" +
"Candidate: $candidateDescriptor, explicitReceiverKind: ${resolvedCall.explicitReceiverKind}.\n" +
"Explicit receiver: ${kotlinCall.explicitReceiver}, dispatchReceiverForInvokeExtension: ${kotlinCall.dispatchReceiverForInvokeExtension}"
)
override fun KotlinResolutionCandidate.process(workIndex: Int) {
when (resolvedCall.explicitReceiverKind) {
@@ -207,20 +223,25 @@ internal object CheckExplicitReceiverKindConsistency : ResolutionPart() {
}
private fun KotlinResolutionCandidate.resolveKotlinArgument(
argument: KotlinCallArgument,
candidateParameter: ParameterDescriptor?,
isReceiver: Boolean
argument: KotlinCallArgument,
candidateParameter: ParameterDescriptor?,
isReceiver: Boolean
) {
val expectedType = candidateParameter?.let {
resolvedCall.substitutor.substituteKeepAnnotations(argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings))
resolvedCall.substitutor.substituteKeepAnnotations(
argument.getExpectedType(
candidateParameter,
callComponents.languageVersionSettings
)
)
}
addResolvedKtPrimitive(resolveKtPrimitive(csBuilder, argument, expectedType, this, isReceiver))
}
internal object CheckReceivers : ResolutionPart() {
private fun KotlinResolutionCandidate.checkReceiver(
receiverArgument: SimpleKotlinCallArgument?,
receiverParameter: ReceiverParameterDescriptor?
receiverArgument: SimpleKotlinCallArgument?,
receiverParameter: ReceiverParameterDescriptor?
) {
if ((receiverArgument == null) != (receiverParameter == null)) {
error("Inconsistency receiver state for call $kotlinCall and candidate descriptor: $candidateDescriptor")
@@ -33,11 +33,11 @@ import org.jetbrains.kotlin.types.upperIfFlexible
fun checkSimpleArgument(
csBuilder: ConstraintSystemBuilder,
argument: SimpleKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
csBuilder: ConstraintSystemBuilder,
argument: SimpleKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
): ResolvedAtom = when (argument) {
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
@@ -45,11 +45,11 @@ fun checkSimpleArgument(
}
private fun checkExpressionArgument(
csBuilder: ConstraintSystemBuilder,
expressionArgument: ExpressionKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
csBuilder: ConstraintSystemBuilder,
expressionArgument: ExpressionKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
): ResolvedAtom {
val resolvedKtExpression = ResolvedExpressionAtom(expressionArgument)
if (expectedType == null) return resolvedKtExpression
@@ -58,7 +58,7 @@ private fun checkExpressionArgument(
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.receiver.stableType, expectedType)
fun unstableSmartCastOrSubtypeError(
unstableType: UnwrappedType?, actualExpectedType: UnwrappedType, position: ConstraintPosition
unstableType: UnwrappedType?, actualExpectedType: UnwrappedType, position: ConstraintPosition
): KotlinCallDiagnostic? {
if (unstableType != null) {
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, actualExpectedType, position)) {
@@ -74,25 +74,30 @@ private fun checkExpressionArgument(
if (expressionArgument.isSafeCall) {
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
diagnosticsHolder.addDiagnosticIfNotNull(
unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedNullableType, position))
unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedNullableType, position)
)
}
return resolvedKtExpression
}
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
if (!isReceiver) {
diagnosticsHolder.addDiagnosticIfNotNull(unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedType, position))
diagnosticsHolder.addDiagnosticIfNotNull(
unstableSmartCastOrSubtypeError(
expressionArgument.receiver.unstableType,
expectedType,
position
)
)
return resolvedKtExpression
}
val unstableType = expressionArgument.receiver.unstableType
if (unstableType != null && csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
diagnosticsHolder.addDiagnostic(UnstableSmartCast(expressionArgument, unstableType))
}
else if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
} else if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
diagnosticsHolder.addDiagnostic(UnsafeCallError(expressionArgument))
}
else {
} else {
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
}
}
@@ -122,7 +127,7 @@ private fun captureFromTypeParameterUpperBoundIfNeeded(argumentType: UnwrappedTy
if (argumentType.lowerIfFlexible().constructor.declarationDescriptor is TypeParameterDescriptor) {
val chosenSupertype = argumentType.lowerIfFlexible().supertypes().singleOrNull {
it.constructor.declarationDescriptor is ClassifierDescriptorWithTypeParameters &&
it.unwrap().hasSupertypeWithGivenTypeConstructor(expectedTypeConstructor)
it.unwrap().hasSupertypeWithGivenTypeConstructor(expectedTypeConstructor)
}
if (chosenSupertype != null) {
return captureFromExpression(chosenSupertype.unwrap()) ?: argumentType
@@ -133,11 +138,11 @@ private fun captureFromTypeParameterUpperBoundIfNeeded(argumentType: UnwrappedTy
}
private fun checkSubCallArgument(
csBuilder: ConstraintSystemBuilder,
subCallArgument: SubKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
csBuilder: ConstraintSystemBuilder,
subCallArgument: SubKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean
): ResolvedAtom {
val subCallResult = subCallArgument.callResult
@@ -156,7 +161,7 @@ private fun checkSubCallArgument(
if (isReceiver && !csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedType, position) &&
csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedNullableType, position)
) {
) {
diagnosticsHolder.addDiagnostic(UnsafeCallError(subCallArgument))
return subCallResult
}
@@ -29,15 +29,15 @@ class TypeArgumentsToParametersMapper {
object NoExplicitArguments : TypeArgumentsMapping(emptyList()) {
override fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument =
TypeArgumentPlaceholder
TypeArgumentPlaceholder
}
class TypeArgumentsMappingImpl(
diagnostics: List<KotlinCallDiagnostic>,
private val typeParameterToArgumentMap: Map<TypeParameterDescriptor, TypeArgument>
): TypeArgumentsMapping(diagnostics) {
diagnostics: List<KotlinCallDiagnostic>,
private val typeParameterToArgumentMap: Map<TypeParameterDescriptor, TypeArgument>
) : TypeArgumentsMapping(diagnostics) {
override fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument =
typeParameterToArgumentMap[typeParameterDescriptor] ?: TypeArgumentPlaceholder
typeParameterToArgumentMap[typeParameterDescriptor] ?: TypeArgumentPlaceholder
}
}
@@ -48,9 +48,9 @@ class TypeArgumentsToParametersMapper {
if (call.typeArguments.size != descriptor.typeParameters.size) {
return TypeArgumentsMapping.TypeArgumentsMappingImpl(
listOf(WrongCountOfTypeArguments(descriptor, call.typeArguments.size)), emptyMap())
}
else {
listOf(WrongCountOfTypeArguments(descriptor, call.typeArguments.size)), emptyMap()
)
} else {
val typeParameterToArgumentMap = descriptor.typeParameters.zip(call.typeArguments).associate { it }
return TypeArgumentsMapping.TypeArgumentsMappingImpl(listOf(), typeParameterToArgumentMap)
}
@@ -47,11 +47,15 @@ interface ConstraintSystemBuilder : ConstraintSystemOperation {
fun buildCurrentSubstitutor(): NewTypeSubstitutor
}
fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) =
runTransaction {
if (!hasContradiction) addSubtypeConstraint(lowerType, upperType, position)
!hasContradiction
}
fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(
lowerType: UnwrappedType,
upperType: UnwrappedType,
position: ConstraintPosition
) =
runTransaction {
if (!hasContradiction) addSubtypeConstraint(lowerType, upperType, position)
!hasContradiction
}
fun PostponedArgumentsAnalyzer.Context.addSubsystemFromArgument(argument: KotlinCallArgument?) {
@@ -33,7 +33,10 @@ fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor {
it.key to it.value
}
val uninferredSubstitutorMap = notFixedTypeVariables.entries.associate { (freshTypeConstructor, typeVariable) ->
freshTypeConstructor to ErrorUtils.createErrorTypeWithCustomConstructor("Uninferred type", typeVariable.typeVariable.freshTypeConstructor)
freshTypeConstructor to ErrorUtils.createErrorTypeWithCustomConstructor(
"Uninferred type",
typeVariable.typeVariable.freshTypeConstructor
)
}
return NewTypeSubstitutorByConstructorMap(currentSubstitutorMap + uninferredSubstitutorMap)
@@ -61,10 +64,10 @@ fun CallableDescriptor.substituteAndApproximateCapturedTypes(substitutor: NewTyp
override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) =
substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType ->
TypeApproximator().approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedTypesApproximation) ?:
substitutedType
}
substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType ->
TypeApproximator().approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedTypesApproximation)
?: substitutedType
}
}
return substitute(TypeSubstitutor.create(wrappedSubstitution))
@@ -32,6 +32,7 @@ interface NewConstraintSystem {
// after this method we shouldn't mutate system via ConstraintSystemBuilder
fun asReadOnlyStorage(): ConstraintStorage
fun asConstraintSystemCompleterContext(): KotlinConstraintSystemCompleter.Context
fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzer.Context
}
@@ -102,30 +102,38 @@ class ConstraintIncorporator(val typeApproximator: TypeApproximator) {
}
private fun generateNewConstraint(
c: Context,
targetVariable: NewTypeVariable,
baseConstraint: Constraint,
otherVariable: NewTypeVariable,
otherConstraint: Constraint
c: Context,
targetVariable: NewTypeVariable,
baseConstraint: Constraint,
otherVariable: NewTypeVariable,
otherConstraint: Constraint
) {
val typeForApproximation = when (otherConstraint.kind) {
ConstraintKind.EQUALITY -> {
baseConstraint.type.substitute(otherVariable, otherConstraint.type)
}
ConstraintKind.UPPER -> {
val newCapturedTypeConstructor = NewCapturedTypeConstructor(TypeProjectionImpl(Variance.OUT_VARIANCE, otherConstraint.type),
listOf(otherConstraint.type))
val temporaryCapturedType = NewCapturedType(CaptureStatus.FOR_INCORPORATION,
newCapturedTypeConstructor,
lowerType = null)
val newCapturedTypeConstructor = NewCapturedTypeConstructor(
TypeProjectionImpl(Variance.OUT_VARIANCE, otherConstraint.type),
listOf(otherConstraint.type)
)
val temporaryCapturedType = NewCapturedType(
CaptureStatus.FOR_INCORPORATION,
newCapturedTypeConstructor,
lowerType = null
)
baseConstraint.type.substitute(otherVariable, temporaryCapturedType)
}
ConstraintKind.LOWER -> {
val newCapturedTypeConstructor = NewCapturedTypeConstructor(TypeProjectionImpl(Variance.IN_VARIANCE, otherConstraint.type),
emptyList())
val temporaryCapturedType = NewCapturedType(CaptureStatus.FOR_INCORPORATION,
newCapturedTypeConstructor,
lowerType = otherConstraint.type)
val newCapturedTypeConstructor = NewCapturedTypeConstructor(
TypeProjectionImpl(Variance.IN_VARIANCE, otherConstraint.type),
emptyList()
)
val temporaryCapturedType = NewCapturedType(
CaptureStatus.FOR_INCORPORATION,
newCapturedTypeConstructor,
lowerType = otherConstraint.type
)
baseConstraint.type.substitute(otherVariable, temporaryCapturedType)
}
}
@@ -145,8 +153,8 @@ class ConstraintIncorporator(val typeApproximator: TypeApproximator) {
}
private fun approximateCapturedTypes(type: UnwrappedType, toSuper: Boolean): UnwrappedType =
if (toSuper) typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type
else typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type
if (toSuper) typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type
else typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type
}
@@ -63,7 +63,12 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
}
private fun addSubTypeConstraintAndIncorporateIt(c: Context, lowerType: UnwrappedType, upperType: UnwrappedType, incorporatePosition: IncorporationConstraintPosition) {
private fun addSubTypeConstraintAndIncorporateIt(
c: Context,
lowerType: UnwrappedType,
upperType: UnwrappedType,
incorporatePosition: IncorporationConstraintPosition
) {
val possibleNewConstraints = Stack<Pair<NewTypeVariable, Constraint>>()
val typeCheckerContext = TypeCheckerContext(c, incorporatePosition, lowerType, upperType, possibleNewConstraints)
typeCheckerContext.runIsSubtypeOf(lowerType, upperType)
@@ -72,7 +77,8 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
val (typeVariable, constraint) = possibleNewConstraints.pop()
if (c.shouldWeSkipConstraint(typeVariable, constraint)) continue
val constraints = c.notFixedTypeVariables[typeVariable.freshTypeConstructor] ?: typeCheckerContext.fixedTypeVariable(typeVariable)
val constraints =
c.notFixedTypeVariables[typeVariable.freshTypeConstructor] ?: typeCheckerContext.fixedTypeVariable(typeVariable)
// it is important, that we add constraint here(not inside TypeCheckerContext), because inside incorporation we read constraints
constraints.addConstraint(constraint)?.let {
@@ -105,14 +111,15 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
return false
}
private fun Context.isAllowedType(type: UnwrappedType) = type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION
private fun Context.isAllowedType(type: UnwrappedType) =
type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION
private inner class TypeCheckerContext(
val c: Context,
val position: IncorporationConstraintPosition,
val baseLowerType: UnwrappedType,
val baseUpperType: UnwrappedType,
val possibleNewConstraints: MutableList<Pair<NewTypeVariable, Constraint>>
val c: Context,
val position: IncorporationConstraintPosition,
val baseLowerType: UnwrappedType,
val baseUpperType: UnwrappedType,
val possibleNewConstraints: MutableList<Pair<NewTypeVariable, Constraint>>
) : TypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context {
fun runIsSubtypeOf(lowerType: UnwrappedType, upperType: UnwrappedType) {
@@ -126,36 +133,39 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
// from TypeCheckerContextForConstraintSystem
override fun isMyTypeVariable(type: SimpleType): Boolean = c.allTypeVariables.containsKey(type.constructor)
override fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType) =
addConstraint(typeVariable, superType, UPPER)
addConstraint(typeVariable, superType, UPPER)
override fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType) =
addConstraint(typeVariable, subType, LOWER)
addConstraint(typeVariable, subType, LOWER)
private fun isCapturedTypeFromSubtyping(type: UnwrappedType) =
when ((type as? NewCapturedType)?.captureStatus) {
null, CaptureStatus.FROM_EXPRESSION -> false
CaptureStatus.FOR_SUBTYPING -> true
CaptureStatus.FOR_INCORPORATION ->
error("Captured type for incorporation shouldn't escape from incorporation: $type\n" + renderBaseConstraint())
}
when ((type as? NewCapturedType)?.captureStatus) {
null, CaptureStatus.FROM_EXPRESSION -> false
CaptureStatus.FOR_SUBTYPING -> true
CaptureStatus.FOR_INCORPORATION ->
error("Captured type for incorporation shouldn't escape from incorporation: $type\n" + renderBaseConstraint())
}
private fun addConstraint(typeVariableConstructor: TypeConstructor, type: UnwrappedType, kind: ConstraintKind) {
val typeVariable = c.allTypeVariables[typeVariableConstructor]
?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}")
?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}")
var targetType = type
if (type.contains(this::isCapturedTypeFromSubtyping)) {
// TypeVariable <: type -> if TypeVariable <: subType => TypeVariable <: type
if (kind == UPPER) {
val subType = typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
val subType =
typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
if (subType != null && !KotlinBuiltIns.isNothingOrNullableNothing(subType)) {
targetType = subType
}
}
if (kind == LOWER) {
val superType = typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
val superType =
typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
if (superType != null && !KotlinBuiltIns.isAnyOrNullableAny(superType)) { // todo rethink error reporting for Any cases
targetType = superType
}
@@ -189,12 +199,14 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
}
override fun getConstraintsForVariable(typeVariable: NewTypeVariable) =
c.notFixedTypeVariables[typeVariable.freshTypeConstructor]?.constraints
?: fixedTypeVariable(typeVariable)
c.notFixedTypeVariables[typeVariable.freshTypeConstructor]?.constraints
?: fixedTypeVariable(typeVariable)
fun fixedTypeVariable(variable: NewTypeVariable): Nothing {
error("Type variable $variable should not be fixed!\n" +
renderBaseConstraint())
error(
"Type variable $variable should not be fixed!\n" +
renderBaseConstraint()
)
}
private fun renderBaseConstraint() = "Base constraint: $baseLowerType <: $baseUpperType from position: $position"
@@ -27,8 +27,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class KotlinConstraintSystemCompleter(
private val resultTypeResolver: ResultTypeResolver,
private val variableFixationFinder: VariableFixationFinder
private val resultTypeResolver: ResultTypeResolver,
private val variableFixationFinder: VariableFixationFinder
) {
enum class ConstraintSystemCompletionMode {
FULL,
@@ -43,15 +43,16 @@ class KotlinConstraintSystemCompleter(
// mutable operations
fun addError(error: KotlinCallDiagnostic)
fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType)
}
fun runCompletion(
c: Context,
completionMode: ConstraintSystemCompletionMode,
topLevelPrimitive: ResolvedAtom,
topLevelType: UnwrappedType,
analyze: (PostponedResolvedAtom) -> Unit
c: Context,
completionMode: ConstraintSystemCompletionMode,
topLevelPrimitive: ResolvedAtom,
topLevelType: UnwrappedType,
analyze: (PostponedResolvedAtom) -> Unit
) {
while (true) {
if (analyzePostponeArgumentIfPossible(c, topLevelPrimitive, analyze)) continue
@@ -59,7 +60,8 @@ class KotlinConstraintSystemCompleter(
val allTypeVariables = getOrderedAllTypeVariables(c, topLevelPrimitive)
val postponedKtPrimitives = getOrderedNotAnalyzedPostponedArguments(topLevelPrimitive)
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
c, allTypeVariables, postponedKtPrimitives, completionMode, topLevelType)
c, allTypeVariables, postponedKtPrimitives, completionMode, topLevelType
)
if (shouldForceCallableReferenceOrLambdaResolution(completionMode, variableForFixation)) {
if (forcePostponedAtomResolution<ResolvedCallableReferenceAtom>(topLevelPrimitive, analyze)) continue
@@ -88,8 +90,8 @@ class KotlinConstraintSystemCompleter(
}
private fun shouldForceCallableReferenceOrLambdaResolution(
completionMode: ConstraintSystemCompletionMode,
variableForFixation: VariableFixationFinder.VariableForFixation?
completionMode: ConstraintSystemCompletionMode,
variableForFixation: VariableFixationFinder.VariableForFixation?
): Boolean {
if (completionMode == ConstraintSystemCompletionMode.PARTIAL) return false
if (variableForFixation != null && variableForFixation.hasProperConstraint) return false
@@ -98,7 +100,11 @@ class KotlinConstraintSystemCompleter(
}
// true if we do analyze
private fun analyzePostponeArgumentIfPossible(c: Context, topLevelPrimitive: ResolvedAtom, analyze: (PostponedResolvedAtom) -> Unit): Boolean {
private fun analyzePostponeArgumentIfPossible(
c: Context,
topLevelPrimitive: ResolvedAtom,
analyze: (PostponedResolvedAtom) -> Unit
): Boolean {
for (argument in getOrderedNotAnalyzedPostponedArguments(topLevelPrimitive)) {
if (canWeAnalyzeIt(c, argument)) {
analyze(argument)
@@ -110,8 +116,8 @@ class KotlinConstraintSystemCompleter(
// true if we find some callable reference and run resolution for it. Note that such resolution can be unsuccessful
private inline fun <reified T : PostponedResolvedAtom> forcePostponedAtomResolution(
topLevelPrimitive: ResolvedAtom,
analyze: (PostponedResolvedAtom) -> Unit
topLevelPrimitive: ResolvedAtom,
analyze: (PostponedResolvedAtom) -> Unit
): Boolean {
val postponedArgument = getOrderedNotAnalyzedPostponedArguments(topLevelPrimitive).firstIsInstanceOrNull<T>() ?: return false
analyze(postponedArgument)
@@ -129,7 +135,7 @@ class KotlinConstraintSystemCompleter(
return arrayListOf<PostponedResolvedAtom>().apply { topLevelPrimitive.process(this) }
}
private fun getOrderedAllTypeVariables(c: Context, topLevelPrimitive: ResolvedAtom) : List<TypeConstructor> {
private fun getOrderedAllTypeVariables(c: Context, topLevelPrimitive: ResolvedAtom): List<TypeConstructor> {
fun ResolvedAtom.process(to: MutableList<TypeConstructor>) {
val typeVariables = when (this) {
is ResolvedCallAtom -> substitutor.freshVariables
@@ -146,6 +152,7 @@ class KotlinConstraintSystemCompleter(
subResolvedAtoms.forEach { it.process(to) }
}
}
val result = arrayListOf<TypeConstructor>().apply { topLevelPrimitive.process(this) }
assert(result.size == c.notFixedTypeVariables.size) {
@@ -164,10 +171,10 @@ class KotlinConstraintSystemCompleter(
}
private fun fixVariable(
c: Context,
topLevelType: UnwrappedType,
variableWithConstraints: VariableWithConstraints,
postponedResolveKtPrimitives: List<PostponedResolvedAtom>
c: Context,
topLevelType: UnwrappedType,
variableWithConstraints: VariableWithConstraints,
postponedResolveKtPrimitives: List<PostponedResolvedAtom>
) {
val direction = TypeVariableDirectionCalculator(c, postponedResolveKtPrimitives, topLevelType).getDirection(variableWithConstraints)
@@ -29,26 +29,27 @@ interface NewTypeSubstitutor {
fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type, runCapturedChecks = true, keepAnnotation = false) ?: type
fun substituteKeepAnnotations(type: UnwrappedType): UnwrappedType =
substitute(type, runCapturedChecks = true, keepAnnotation = true) ?: type
substitute(type, runCapturedChecks = true, keepAnnotation = true) ?: type
private fun substitute(type: UnwrappedType, keepAnnotation: Boolean, runCapturedChecks: Boolean): UnwrappedType? =
when (type) {
is SimpleType -> substitute(type, keepAnnotation, runCapturedChecks)
is FlexibleType -> if (type is DynamicType || type is RawType) {
when (type) {
is SimpleType -> substitute(type, keepAnnotation, runCapturedChecks)
is FlexibleType -> if (type is DynamicType || type is RawType) {
null
} else {
val lowerBound = substitute(type.lowerBound, keepAnnotation, runCapturedChecks)
val upperBound = substitute(type.upperBound, keepAnnotation, runCapturedChecks)
if (lowerBound == null && upperBound == null) {
null
}
else {
val lowerBound = substitute(type.lowerBound, keepAnnotation, runCapturedChecks)
val upperBound = substitute(type.upperBound, keepAnnotation, runCapturedChecks)
if (lowerBound == null && upperBound == null) {
null
}
else {
// todo discuss lowerIfFlexible and upperIfFlexible
KotlinTypeFactory.flexibleType(lowerBound?.lowerIfFlexible() ?: type.lowerBound, upperBound?.upperIfFlexible() ?: type.upperBound)
}
} else {
// todo discuss lowerIfFlexible and upperIfFlexible
KotlinTypeFactory.flexibleType(
lowerBound?.lowerIfFlexible() ?: type.lowerBound,
upperBound?.upperIfFlexible() ?: type.upperBound
)
}
}
}
private fun substitute(type: SimpleType, keepAnnotation: Boolean, runCapturedChecks: Boolean): UnwrappedType? {
if (type.isError) return null
@@ -57,10 +58,11 @@ interface NewTypeSubstitutor {
val substitutedExpandedType = substitute(type.expandedType, keepAnnotation, runCapturedChecks)
val substitutedAbbreviation = substitute(type.abbreviation, keepAnnotation, runCapturedChecks)
if (substitutedExpandedType is SimpleType? && substitutedAbbreviation is SimpleType?) {
return AbbreviatedType(substitutedExpandedType ?: type.expandedType,
substitutedAbbreviation ?: type.abbreviation)
}
else {
return AbbreviatedType(
substitutedExpandedType ?: type.expandedType,
substitutedAbbreviation ?: type.abbreviation
)
} else {
return substitutedExpandedType
}
}
@@ -74,21 +76,26 @@ interface NewTypeSubstitutor {
if (typeConstructor is NewCapturedTypeConstructor) {
if (!runCapturedChecks) return null
assert(type is NewCapturedType || (type is DefinitelyNotNullType && type.original is NewCapturedType)) { // KT-16147
assert(type is NewCapturedType || (type is DefinitelyNotNullType && type.original is NewCapturedType)) {
// KT-16147
"Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " +
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
}
val capturedType = if (type is DefinitelyNotNullType) type.original as NewCapturedType else type as NewCapturedType
val lower = capturedType.lowerType?.let { substitute(it, keepAnnotation, runCapturedChecks = false) }
if (lower != null) throw IllegalStateException("Illegal type substitutor: $this, " +
"because for captured type '$type' lower type approximation should be null, but it is: '$lower'," +
"original lower type: '${capturedType.lowerType}")
if (lower != null) throw IllegalStateException(
"Illegal type substitutor: $this, " +
"because for captured type '$type' lower type approximation should be null, but it is: '$lower'," +
"original lower type: '${capturedType.lowerType}"
)
typeConstructor.supertypes.forEach { supertype ->
substitute(supertype, keepAnnotation, runCapturedChecks = false)?.let {
throw IllegalStateException("Illegal type substitutor: $this, " +
"because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," +
"original supertype: '$supertype'")
throw IllegalStateException(
"Illegal type substitutor: $this, " +
"because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," +
"original supertype: '$supertype'"
)
}
}
@@ -120,9 +127,9 @@ interface NewTypeSubstitutor {
}
private fun substituteParametrizedType(
type: SimpleType,
keepAnnotation: Boolean,
runCapturedChecks: Boolean
type: SimpleType,
keepAnnotation: Boolean,
runCapturedChecks: Boolean
): UnwrappedType? {
val parameters = type.constructor.parameters
val arguments = type.arguments
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.types.checker.intersectTypes
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
class ResultTypeResolver(
val typeApproximator: TypeApproximator
val typeApproximator: TypeApproximator
) {
interface Context {
fun isProperType(type: UnwrappedType): Boolean
@@ -49,8 +49,7 @@ class ResultTypeResolver(
val superType = findSuperType(c, variableWithConstraints)
val result = if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) {
c.resultType(subType, superType, variableWithConstraints)
}
else {
} else {
c.resultType(superType, subType, variableWithConstraints)
}
@@ -58,9 +57,9 @@ class ResultTypeResolver(
}
private fun Context.resultType(
firstCandidate: UnwrappedType?,
secondCandidate: UnwrappedType?,
variableWithConstraints: VariableWithConstraints
firstCandidate: UnwrappedType?,
secondCandidate: UnwrappedType?,
variableWithConstraints: VariableWithConstraints
): UnwrappedType? {
if (firstCandidate == null || secondCandidate == null) return firstCandidate ?: secondCandidate
@@ -68,8 +67,7 @@ class ResultTypeResolver(
if (isSuitableType(secondCandidate, variableWithConstraints)) {
return secondCandidate
}
else {
} else {
return firstCandidate
}
}
@@ -105,8 +103,11 @@ class ResultTypeResolver(
*
*/
return typeApproximator.approximateToSuperType(adjustedCommonSuperType, TypeApproximatorConfiguration.CapturedTypesApproximation)
?: adjustedCommonSuperType
return typeApproximator.approximateToSuperType(
adjustedCommonSuperType,
TypeApproximatorConfiguration.CapturedTypesApproximation
)
?: adjustedCommonSuperType
}
return null
@@ -150,9 +151,9 @@ class ResultTypeResolver(
}
fun findResultIfThereIsEqualsConstraint(
c: Context,
variableWithConstraints: VariableWithConstraints,
allowedFixToNotProperType: Boolean = false
c: Context,
variableWithConstraints: VariableWithConstraints,
allowedFixToNotProperType: Boolean = false
): UnwrappedType? {
val properEqualsConstraint = variableWithConstraints.constraints.filter {
it.kind == ConstraintKind.EQUALITY && c.isProperType(it.type)
@@ -160,7 +161,7 @@ class ResultTypeResolver(
if (properEqualsConstraint.isNotEmpty()) {
return properEqualsConstraint.map { it.type }.singleBestRepresentative()?.unwrap()
?: properEqualsConstraint.first().type // seems like constraint system has contradiction
?: properEqualsConstraint.first().type // seems like constraint system has contradiction
}
if (!allowedFixToNotProperType) return null
@@ -31,6 +31,7 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
// super and sub type isSingleClassifierType
abstract fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType)
abstract fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType)
override fun getLowerCapturedTypePolicy(subType: SimpleType, superType: NewCapturedType) = when {
@@ -65,10 +66,10 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
}
private fun UnwrappedType.isTypeVariableWithExact() =
anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasExactAnnotation()
anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasExactAnnotation()
private fun UnwrappedType.isTypeVariableWithNoInfer() =
anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasNoInferAnnotation()
anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasNoInferAnnotation()
private fun internalAddSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType): Boolean? {
assertInputTypes(subType, superType)
@@ -81,8 +82,7 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
if (subType.anyBound(this::isMyTypeVariable)) {
return simplifyUpperConstraint(subType, superType) && (answer ?: true)
}
else {
} else {
return simplifyConstraintForPossibleIntersectionSubType(subType, superType) ?: answer
}
}
@@ -174,7 +174,7 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
if (typeVariable.isMarkedNullable) {
// here is important that superType is singleClassifierType
return superType.anyBound(this::isMyTypeVariable) ||
isSubtypeOfByTypeChecker(typeVariable.builtIns.nullableNothingType, superType)
isSubtypeOfByTypeChecker(typeVariable.builtIns.nullableNothingType, superType)
}
return true
@@ -222,11 +222,14 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
}
private fun isSubtypeOfByTypeChecker(subType: UnwrappedType, superType: UnwrappedType) =
with(NewKotlinTypeChecker) { this@TypeCheckerContextForConstraintSystem.isSubtypeOf(subType, superType) }
with(NewKotlinTypeChecker) { this@TypeCheckerContextForConstraintSystem.isSubtypeOf(subType, superType) }
private fun assertInputTypes(subType: UnwrappedType, superType: UnwrappedType) {
fun correctSubType(subType: SimpleType) = subType.isSingleClassifierType || subType.isIntersectionType || isMyTypeVariable(subType) || subType.isError
fun correctSuperType(superType: SimpleType) = superType.isSingleClassifierType || superType.isIntersectionType || isMyTypeVariable(superType) || superType.isError
fun correctSubType(subType: SimpleType) =
subType.isSingleClassifierType || subType.isIntersectionType || isMyTypeVariable(subType) || subType.isError
fun correctSuperType(superType: SimpleType) =
superType.isSingleClassifierType || superType.isIntersectionType || isMyTypeVariable(superType) || superType.isError
assert(subType.bothBounds(::correctSubType)) {
"Not singleClassifierType and not intersection subType: $subType"
@@ -24,9 +24,9 @@ import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.utils.SmartSet
class TypeVariableDependencyInformationProvider(
private val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>,
private val postponedKtPrimitives: List<PostponedResolvedAtom>,
private val topLevelType: UnwrappedType?
private val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>,
private val postponedKtPrimitives: List<PostponedResolvedAtom>,
private val topLevelType: UnwrappedType?
) {
// not oriented edges
private val constrainEdges: MutableMap<TypeConstructor, MutableSet<TypeConstructor>> = hashMapOf()
@@ -32,9 +32,9 @@ import org.jetbrains.kotlin.utils.SmartList
private typealias Variable = VariableWithConstraints
class TypeVariableDirectionCalculator(
private val c: VariableFixationFinder.Context,
private val postponedKtPrimitives: List<PostponedResolvedAtom>,
topLevelType: UnwrappedType
private val c: VariableFixationFinder.Context,
private val postponedKtPrimitives: List<PostponedResolvedAtom>,
topLevelType: UnwrappedType
) {
enum class ResolveDirection {
TO_SUBTYPE,
@@ -45,7 +45,7 @@ class TypeVariableDirectionCalculator(
data class NodeWithDirection(val variableWithConstraints: VariableWithConstraints, val direction: ResolveDirection) {
override fun toString() = "$variableWithConstraints to $direction"
}
private val directions = HashMap<Variable, ResolveDirection>()
init {
@@ -53,7 +53,7 @@ class TypeVariableDirectionCalculator(
}
fun getDirection(typeVariable: Variable): ResolveDirection =
directions.getOrDefault(typeVariable, ResolveDirection.UNKNOWN)
directions.getOrDefault(typeVariable, ResolveDirection.UNKNOWN)
private fun setupDirections(topReturnType: UnwrappedType) {
topReturnType.visitType(ResolveDirection.TO_SUBTYPE) { variableWithConstraints, direction ->
@@ -87,32 +87,35 @@ class TypeVariableDirectionCalculator(
}
private fun getConstraintDependencies(
variable: Variable,
direction: ResolveDirection
variable: Variable,
direction: ResolveDirection
): List<NodeWithDirection> =
SmartList<NodeWithDirection>().also { result ->
for (constraint in variable.constraints) {
if (!isInterestingConstraint(direction, constraint)) continue
SmartList<NodeWithDirection>().also { result ->
for (constraint in variable.constraints) {
if (!isInterestingConstraint(direction, constraint)) continue
constraint.type.visitType(direction) { nodeVariable, nodeDirection ->
result.add(NodeWithDirection(nodeVariable, nodeDirection))
}
constraint.type.visitType(direction) { nodeVariable, nodeDirection ->
result.add(NodeWithDirection(nodeVariable, nodeDirection))
}
}
}
private fun isInterestingConstraint(direction: ResolveDirection, constraint: Constraint): Boolean =
!(direction == ResolveDirection.TO_SUBTYPE && constraint.kind == ConstraintKind.UPPER) &&
!(direction == ResolveDirection.TO_SUPERTYPE && constraint.kind == ConstraintKind.LOWER)
!(direction == ResolveDirection.TO_SUBTYPE && constraint.kind == ConstraintKind.UPPER) &&
!(direction == ResolveDirection.TO_SUPERTYPE && constraint.kind == ConstraintKind.LOWER)
private fun UnwrappedType.visitType(startDirection: ResolveDirection, action: (variable: Variable, direction: ResolveDirection) -> Unit) =
when (this) {
is SimpleType -> visitType(startDirection, action)
is FlexibleType -> {
lowerBound.visitType(startDirection, action)
upperBound.visitType(startDirection, action)
}
private fun UnwrappedType.visitType(
startDirection: ResolveDirection,
action: (variable: Variable, direction: ResolveDirection) -> Unit
) =
when (this) {
is SimpleType -> visitType(startDirection, action)
is FlexibleType -> {
lowerBound.visitType(startDirection, action)
upperBound.visitType(startDirection, action)
}
}
private fun SimpleType.visitType(startDirection: ResolveDirection, action: (variable: Variable, direction: ResolveDirection) -> Unit) {
if (isIntersectionType) {
@@ -34,11 +34,11 @@ class VariableFixationFinder {
data class VariableForFixation(val variable: TypeConstructor, val hasProperConstraint: Boolean)
fun findFirstVariableForFixation(
c: Context,
allTypeVariables: List<TypeConstructor>,
postponedKtPrimitives: List<PostponedResolvedAtom>,
completionMode: ConstraintSystemCompletionMode,
topLevelType: UnwrappedType
c: Context,
allTypeVariables: List<TypeConstructor>,
postponedKtPrimitives: List<PostponedResolvedAtom>,
completionMode: ConstraintSystemCompletionMode,
topLevelType: UnwrappedType
): VariableForFixation? = c.findTypeVariableForFixation(allTypeVariables, postponedKtPrimitives, completionMode, topLevelType)
private enum class TypeVariableFixationReadiness {
@@ -50,11 +50,11 @@ class VariableFixationFinder {
}
private fun Context.getTypeVariableReadiness(
variable: TypeConstructor,
dependencyProvider: TypeVariableDependencyInformationProvider
variable: TypeConstructor,
dependencyProvider: TypeVariableDependencyInformationProvider
): TypeVariableFixationReadiness = when {
!notFixedTypeVariables.contains(variable) ||
dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN
dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN
!variableHasProperArgumentConstraints(variable) -> TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT
hasDependencyToOtherTypeVariables(variable) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY
dependencyProvider.isVariableRelatedToAnyOutputType(variable) -> TypeVariableFixationReadiness.RELATED_TO_ANY_OUTPUT_TYPE
@@ -62,10 +62,10 @@ class VariableFixationFinder {
}
private fun Context.findTypeVariableForFixation(
allTypeVariables: List<TypeConstructor>,
postponedKtPrimitives: List<PostponedResolvedAtom>,
completionMode: ConstraintSystemCompletionMode,
topLevelType: UnwrappedType
allTypeVariables: List<TypeConstructor>,
postponedKtPrimitives: List<PostponedResolvedAtom>,
completionMode: ConstraintSystemCompletionMode,
topLevelType: UnwrappedType
): VariableForFixation? {
val dependencyProvider = TypeVariableDependencyInformationProvider(notFixedTypeVariables, postponedKtPrimitives,
topLevelType.takeIf { completionMode == PARTIAL })
@@ -89,12 +89,12 @@ class VariableFixationFinder {
}
private fun Context.variableHasProperArgumentConstraints(variable: TypeConstructor): Boolean =
notFixedTypeVariables[variable]?.constraints?.any { isProperArgumentConstraint(it) } ?: false
notFixedTypeVariables[variable]?.constraints?.any { isProperArgumentConstraint(it) } ?: false
private fun Context.isProperArgumentConstraint(c: Constraint) =
isProperType(c.type) && c.position.initialConstraint.position !is DeclaredUpperBoundConstraintPosition
isProperType(c.type) && c.position.initialConstraint.position !is DeclaredUpperBoundConstraintPosition
private fun Context.isProperType(type: UnwrappedType): Boolean =
!type.contains { notFixedTypeVariables.containsKey(it.constructor) }
!type.contains { notFixedTypeVariables.containsKey(it.constructor) }
}
@@ -30,12 +30,15 @@ sealed class ConstraintPosition
class ExplicitTypeParameterConstraintPosition(val typeArgument: SimpleTypeArgument) : ConstraintPosition() {
override fun toString() = "TypeParameter $typeArgument"
}
class ExpectedTypeConstraintPosition(val topLevelCall: KotlinCall) : ConstraintPosition() {
override fun toString() = "ExpectedType for call $topLevelCall"
}
class DeclaredUpperBoundConstraintPosition(val typeParameterDescriptor: TypeParameterDescriptor) : ConstraintPosition() {
override fun toString() = "DeclaredUpperBound ${typeParameterDescriptor.name} from ${typeParameterDescriptor.containingDeclaration}"
}
class ArgumentConstraintPosition(val argument: KotlinCallArgument) : ConstraintPosition() {
override fun toString() = "Argument $argument"
}
@@ -47,9 +50,11 @@ class ReceiverConstraintPosition(val argument: KotlinCallArgument) : ConstraintP
class FixVariableConstraintPosition(val variable: NewTypeVariable) : ConstraintPosition() {
override fun toString() = "Fix variable $variable"
}
class KnownTypeParameterConstraintPosition(val typeArgument: KotlinType) : ConstraintPosition() {
override fun toString() = "TypeArgument $typeArgument"
}
class LambdaArgumentConstraintPosition(val lambda: ResolvedLambdaAtom) : ConstraintPosition() {
override fun toString(): String {
return "LambdaArgument $lambda"
@@ -68,15 +73,15 @@ abstract class ConstraintSystemCallDiagnostic(applicability: ResolutionCandidate
}
class NewConstraintError(
val lowerType: UnwrappedType,
val upperType: UnwrappedType,
val position: IncorporationConstraintPosition
val lowerType: UnwrappedType,
val upperType: UnwrappedType,
val position: IncorporationConstraintPosition
) : ConstraintSystemCallDiagnostic(if (position.from is ReceiverConstraintPosition) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE)
class CapturedTypeFromSubtyping(
val typeVariable: NewTypeVariable,
val constraintType: UnwrappedType,
val position: ConstraintPosition
val typeVariable: NewTypeVariable,
val constraintType: UnwrappedType,
val position: ConstraintPosition
) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
class NotEnoughInformationForTypeParameter(val typeVariable: NewTypeVariable) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
@@ -70,10 +70,10 @@ enum class ConstraintKind {
}
class Constraint(
val kind: ConstraintKind,
val type: UnwrappedType, // flexible types here is allowed
val position: IncorporationConstraintPosition,
val typeHashCode: Int = type.hashCode()
val kind: ConstraintKind,
val type: UnwrappedType, // flexible types here is allowed
val position: IncorporationConstraintPosition,
val typeHashCode: Int = type.hashCode()
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -100,18 +100,18 @@ interface VariableWithConstraints {
}
class InitialConstraint(
val a: UnwrappedType,
val b: UnwrappedType,
val constraintKind: ConstraintKind, // see [checkConstraint]
val position: ConstraintPosition
val a: UnwrappedType,
val b: UnwrappedType,
val constraintKind: ConstraintKind, // see [checkConstraint]
val position: ConstraintPosition
) {
override fun toString(): String {
val sign =
when (constraintKind) {
ConstraintKind.EQUALITY -> "=="
ConstraintKind.LOWER -> ":>"
ConstraintKind.UPPER -> "<:"
}
when (constraintKind) {
ConstraintKind.EQUALITY -> "=="
ConstraintKind.LOWER -> ":>"
ConstraintKind.UPPER -> "<:"
}
return "$a $sign $b from $position"
}
}
@@ -25,15 +25,16 @@ import kotlin.collections.ArrayList
class MutableVariableWithConstraints(
override val typeVariable: NewTypeVariable,
constraints: Collection<Constraint> = emptyList()
override val typeVariable: NewTypeVariable,
constraints: Collection<Constraint> = emptyList()
) : VariableWithConstraints {
override val constraints: List<Constraint> get() {
if (simplifiedConstraints == null) {
simplifiedConstraints = simplifyConstraints()
override val constraints: List<Constraint>
get() {
if (simplifiedConstraints == null) {
simplifiedConstraints = simplifyConstraints()
}
return simplifiedConstraints!!
}
return simplifiedConstraints!!
}
private val mutableConstraints = ArrayList(constraints)
private var simplifiedConstraints: List<Constraint>? = null
@@ -49,8 +50,7 @@ class MutableVariableWithConstraints(
val actualConstraint = if (previousConstraintWithSameType.isNotEmpty()) {
// i.e. previous is LOWER and new is UPPER or opposite situation
Constraint(ConstraintKind.EQUALITY, constraint.type, constraint.position, constraint.typeHashCode)
}
else {
} else {
constraint
}
mutableConstraints.add(actualConstraint)
@@ -72,16 +72,16 @@ class MutableVariableWithConstraints(
}
private fun newConstraintIsUseless(oldKind: ConstraintKind, newKind: ConstraintKind) =
when (oldKind) {
ConstraintKind.EQUALITY -> true
ConstraintKind.LOWER -> newKind == ConstraintKind.LOWER
ConstraintKind.UPPER -> newKind == ConstraintKind.UPPER
}
when (oldKind) {
ConstraintKind.EQUALITY -> true
ConstraintKind.LOWER -> newKind == ConstraintKind.LOWER
ConstraintKind.UPPER -> newKind == ConstraintKind.UPPER
}
private fun simplifyConstraints(): List<Constraint> {
val equalityConstraints = mutableConstraints
.filter { it.kind == ConstraintKind.EQUALITY }
.groupBy { it.typeHashCode }
.filter { it.kind == ConstraintKind.EQUALITY }
.groupBy { it.typeHashCode }
return mutableConstraints.filter { isUsefulConstraint(it, equalityConstraints) }
}
@@ -31,16 +31,15 @@ import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.utils.SmartList
class NewConstraintSystemImpl(
private val constraintInjector: ConstraintInjector,
override val builtIns: KotlinBuiltIns
):
NewConstraintSystem,
ConstraintSystemBuilder,
ConstraintInjector.Context,
ResultTypeResolver.Context,
KotlinConstraintSystemCompleter.Context,
PostponedArgumentsAnalyzer.Context
{
private val constraintInjector: ConstraintInjector,
override val builtIns: KotlinBuiltIns
) :
NewConstraintSystem,
ConstraintSystemBuilder,
ConstraintInjector.Context,
ResultTypeResolver.Context,
KotlinConstraintSystemCompleter.Context,
PostponedArgumentsAnalyzer.Context {
private val storage = MutableConstraintStorage()
private var state = State.BUILDING
private val typeVariablesTransaction: MutableList<NewTypeVariable> = SmartList()
@@ -83,10 +82,20 @@ class NewConstraintSystemImpl(
}
override fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) =
constraintInjector.addInitialSubtypeConstraint(apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, lowerType, upperType, position)
constraintInjector.addInitialSubtypeConstraint(
apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) },
lowerType,
upperType,
position
)
override fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) =
constraintInjector.addInitialEqualityConstraint(apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, a, b, position)
constraintInjector.addInitialEqualityConstraint(
apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) },
a,
b,
position
)
override fun getProperSuperTypeConstructors(type: UnwrappedType): List<TypeConstructor> {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
@@ -146,7 +155,14 @@ class NewConstraintSystemImpl(
// ConstraintSystemBuilder, KotlinConstraintSystemCompleter.Context
override val hasContradiction: Boolean
get() = diagnostics.any { !it.candidateApplicability.isSuccess }.apply { checkState(State.FREEZED, State.BUILDING, State.COMPLETION, State.TRANSACTION) }
get() = diagnostics.any { !it.candidateApplicability.isSuccess }.apply {
checkState(
State.FREEZED,
State.BUILDING,
State.COMPLETION,
State.TRANSACTION
)
}
override fun addOtherSystem(otherSystem: ConstraintStorage) {
storage.allTypeVariables.putAll(otherSystem.allTypeVariables)
@@ -154,7 +170,8 @@ class NewConstraintSystemImpl(
notFixedTypeVariables[variable] = MutableVariableWithConstraints(constraints.typeVariable, constraints.constraints)
}
storage.initialConstraints.addAll(otherSystem.initialConstraints)
storage.maxTypeDepthFromInitialConstraints = Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints)
storage.maxTypeDepthFromInitialConstraints =
Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints)
storage.errors.addAll(otherSystem.errors)
storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables)
}
@@ -173,10 +190,11 @@ class NewConstraintSystemImpl(
}
// ConstraintInjector.Context
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.allTypeVariables
}
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable>
get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.allTypeVariables
}
override var maxTypeDepthFromInitialConstraints: Int
get() = storage.maxTypeDepthFromInitialConstraints
@@ -191,10 +209,11 @@ class NewConstraintSystemImpl(
}
// ConstraintInjector.Context, FixationOrderCalculator.Context
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.notFixedTypeVariables
}
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints>
get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.notFixedTypeVariables
}
// ConstraintInjector.Context, KotlinConstraintSystemCompleter.Context
override fun addError(error: KotlinCallDiagnostic) {
@@ -29,7 +29,8 @@ import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debugName: String): TypeConstructor, NewTypeVariableConstructor {
class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debugName: String) : TypeConstructor,
NewTypeVariableConstructor {
override fun getParameters(): List<TypeParameterDescriptor> = emptyList()
override fun getSupertypes(): Collection<KotlinType> = emptyList()
override fun isFinal(): Boolean = false
@@ -47,18 +48,19 @@ sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) {
// member scope is used if we have receiver with type TypeVariable(T)
// todo add to member scope methods from supertypes for type variable
val defaultType: SimpleType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY, freshTypeConstructor, arguments = emptyList(),
nullable = false, memberScope = builtIns.any.unsubstitutedMemberScope)
Annotations.EMPTY, freshTypeConstructor, arguments = emptyList(),
nullable = false, memberScope = builtIns.any.unsubstitutedMemberScope
)
override fun toString() = freshTypeConstructor.toString()
}
class TypeVariableFromCallableDescriptor(
val originalTypeParameter: TypeParameterDescriptor
val originalTypeParameter: TypeParameterDescriptor
) : NewTypeVariable(originalTypeParameter.builtIns, originalTypeParameter.name.identifier)
class TypeVariableForLambdaReturnType(
val lambdaArgument: LambdaKotlinCallArgument,
builtIns: KotlinBuiltIns,
name: String
val lambdaArgument: LambdaKotlinCallArgument,
builtIns: KotlinBuiltIns,
name: String
) : NewTypeVariable(builtIns, name)
@@ -24,27 +24,27 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.prepareReceiverRegardingCap
class FakeKotlinCallArgumentForCallableReference(
val index: Int
val index: Int
) : KotlinCallArgument {
override val isSpread: Boolean get() = false
override val argumentName: Name? get() = null
}
class ReceiverExpressionKotlinCallArgument private constructor(
override val receiver: ReceiverValueWithSmartCastInfo,
override val isSafeCall: Boolean = false,
val isVariableReceiverForInvoke: Boolean = false
override val receiver: ReceiverValueWithSmartCastInfo,
override val isSafeCall: Boolean = false,
val isVariableReceiverForInvoke: Boolean = false
) : ExpressionKotlinCallArgument {
override val isSpread: Boolean get() = false
override val argumentName: Name? get() = null
override fun toString() = "$receiver" + if(isSafeCall) "?" else ""
override fun toString() = "$receiver" + if (isSafeCall) "?" else ""
companion object {
// we create ReceiverArgument and fix capture types
operator fun invoke(
receiver: ReceiverValueWithSmartCastInfo,
isSafeCall: Boolean = false,
isVariableReceiverForInvoke: Boolean = false
receiver: ReceiverValueWithSmartCastInfo,
isSafeCall: Boolean = false,
isVariableReceiverForInvoke: Boolean = false
) = ReceiverExpressionKotlinCallArgument(receiver.prepareReceiverRegardingCaptureTypes(), isSafeCall, isVariableReceiverForInvoke)
}
}
@@ -78,8 +78,7 @@ fun KotlinCall.checkCallInvariants() {
assert(dispatchReceiverForInvokeExtension == null) {
"Dispatch receiver for invoke should be null for not function call: $dispatchReceiverForInvokeExtension"
}
}
else {
} else {
assert(externalArgument == null || !externalArgument!!.isSpread) {
"External argument cannot nave spread element: $externalArgument"
}
@@ -88,7 +88,7 @@ interface FunctionExpression : LambdaKotlinCallArgument {
* D.E::foo <-> Expression
*/
sealed class LHSResult {
class Type(val qualifier: QualifierReceiver, resolvedType: UnwrappedType): LHSResult() {
class Type(val qualifier: QualifierReceiver, resolvedType: UnwrappedType) : LHSResult() {
val unboundDetailedReceiver: ReceiverValueWithSmartCastInfo
init {
@@ -101,7 +101,7 @@ sealed class LHSResult {
}
}
class Object(val qualifier: QualifierReceiver): LHSResult() {
class Object(val qualifier: QualifierReceiver) : LHSResult() {
val objectValueReceiver: ReceiverValueWithSmartCastInfo
init {
@@ -111,12 +111,13 @@ sealed class LHSResult {
objectValueReceiver = qualifier.classValueReceiverWithSmartCastInfo ?: error("class value should be not null for $qualifier")
}
}
class Expression(val lshCallArgument: SimpleKotlinCallArgument): LHSResult()
class Expression(val lshCallArgument: SimpleKotlinCallArgument) : LHSResult()
// todo this case is forbid for now
object Empty: LHSResult()
object Empty : LHSResult()
object Error: LHSResult()
object Error : LHSResult()
}
interface CallableReferenceKotlinCallArgument : PostponableKotlinCallArgument {
@@ -135,6 +136,6 @@ interface TypeArgument
// todo allow '_' in frontend
object TypeArgumentPlaceholder : TypeArgument
interface SimpleTypeArgument: TypeArgument {
interface SimpleTypeArgument : TypeArgument {
val type: UnwrappedType
}
@@ -31,7 +31,8 @@ abstract class InapplicableArgumentDiagnostic : KotlinCallDiagnostic(INAPPLICABL
}
// ArgumentsToParameterMapper
class TooManyArguments(val argument: KotlinCallArgument, val descriptor: CallableDescriptor) : KotlinCallDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR) {
class TooManyArguments(val argument: KotlinCallArgument, val descriptor: CallableDescriptor) :
KotlinCallDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
}
@@ -50,54 +51,54 @@ class NameNotFound(val argument: KotlinCallArgument, val descriptor: CallableDes
}
class NoValueForParameter(
val parameterDescriptor: ValueParameterDescriptor,
val descriptor: CallableDescriptor
val parameterDescriptor: ValueParameterDescriptor,
val descriptor: CallableDescriptor
) : KotlinCallDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR) {
override fun report(reporter: DiagnosticReporter) = reporter.onCall(this)
}
class ArgumentPassedTwice(
val argument: KotlinCallArgument,
val parameterDescriptor: ValueParameterDescriptor,
val firstOccurrence: ResolvedCallArgument
val argument: KotlinCallArgument,
val parameterDescriptor: ValueParameterDescriptor,
val firstOccurrence: ResolvedCallArgument
) : KotlinCallDiagnostic(INAPPLICABLE) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgumentName(argument, this)
}
class VarargArgumentOutsideParentheses(
override val argument: KotlinCallArgument,
val parameterDescriptor: ValueParameterDescriptor
override val argument: KotlinCallArgument,
val parameterDescriptor: ValueParameterDescriptor
) : InapplicableArgumentDiagnostic()
class NameForAmbiguousParameter(
val argument: KotlinCallArgument,
val parameterDescriptor: ValueParameterDescriptor,
val overriddenParameterWithOtherName: ValueParameterDescriptor
val argument: KotlinCallArgument,
val parameterDescriptor: ValueParameterDescriptor,
val overriddenParameterWithOtherName: ValueParameterDescriptor
) : KotlinCallDiagnostic(CONVENTION_ERROR) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgumentName(argument, this)
}
class NamedArgumentReference(
val argument: KotlinCallArgument,
val parameterDescriptor: ValueParameterDescriptor
val argument: KotlinCallArgument,
val parameterDescriptor: ValueParameterDescriptor
) : KotlinCallDiagnostic(RESOLVED) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgumentName(argument, this)
}
// TypeArgumentsToParameterMapper
class WrongCountOfTypeArguments(
val descriptor: CallableDescriptor,
val currentCount: Int
val descriptor: CallableDescriptor,
val currentCount: Int
) : KotlinCallDiagnostic(INAPPLICABLE) {
override fun report(reporter: DiagnosticReporter) = reporter.onTypeArguments(this)
}
// Callable reference resolution
class CallableReferenceNotCompatible(
override val argument: CallableReferenceKotlinCallArgument,
val candidate: CallableMemberDescriptor,
val expectedType: UnwrappedType?,
val callableReverenceType: UnwrappedType
override val argument: CallableReferenceKotlinCallArgument,
val candidate: CallableMemberDescriptor,
val expectedType: UnwrappedType?,
val callableReverenceType: UnwrappedType
) : InapplicableArgumentDiagnostic()
// supported by FE but not supported by BE now
@@ -110,35 +111,35 @@ class CallableReferencesDefaultArgumentUsed(
}
class NotCallableMemberReference(
override val argument: CallableReferenceKotlinCallArgument,
val candidate: CallableDescriptor
override val argument: CallableReferenceKotlinCallArgument,
val candidate: CallableDescriptor
) : InapplicableArgumentDiagnostic()
class NoneCallableReferenceCandidates(override val argument: CallableReferenceKotlinCallArgument) : InapplicableArgumentDiagnostic()
class CallableReferenceCandidatesAmbiguity(
override val argument: CallableReferenceKotlinCallArgument,
val candidates: Collection<CallableReferenceCandidate>
override val argument: CallableReferenceKotlinCallArgument,
val candidates: Collection<CallableReferenceCandidate>
) : InapplicableArgumentDiagnostic()
class NotCallableExpectedType(
override val argument: CallableReferenceKotlinCallArgument,
val expectedType: UnwrappedType,
val notCallableTypeConstructor: TypeConstructor
override val argument: CallableReferenceKotlinCallArgument,
val expectedType: UnwrappedType,
val notCallableTypeConstructor: TypeConstructor
) : InapplicableArgumentDiagnostic()
// SmartCasts
class SmartCastDiagnostic(
val argument: ExpressionKotlinCallArgument,
val smartCastType: UnwrappedType,
val kotlinCall: KotlinCall?
): KotlinCallDiagnostic(RESOLVED) {
val argument: ExpressionKotlinCallArgument,
val smartCastType: UnwrappedType,
val kotlinCall: KotlinCall?
) : KotlinCallDiagnostic(RESOLVED) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
}
class UnstableSmartCast(
val argument: ExpressionKotlinCallArgument,
val targetType: UnwrappedType
val argument: ExpressionKotlinCallArgument,
val targetType: UnwrappedType
) : KotlinCallDiagnostic(MAY_THROW_RUNTIME_ERROR) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
}
@@ -172,8 +173,8 @@ class NoneCandidatesCallDiagnostic(val kotlinCall: KotlinCall) : KotlinCallDiagn
}
class ManyCandidatesCallDiagnostic(
val kotlinCall: KotlinCall,
val candidates: Collection<KotlinResolutionCandidate>
val kotlinCall: KotlinCall,
val candidates: Collection<KotlinResolutionCandidate>
) : KotlinCallDiagnostic(INAPPLICABLE) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCall(this)
@@ -36,20 +36,20 @@ import org.jetbrains.kotlin.types.isDynamic
class KotlinCallComponents(
val statelessCallbacks: KotlinResolutionStatelessCallbacks,
val argumentsToParametersMapper: ArgumentsToParametersMapper,
val typeArgumentsToParametersMapper: TypeArgumentsToParametersMapper,
val constraintInjector: ConstraintInjector,
val reflectionTypes: ReflectionTypes,
val builtIns: KotlinBuiltIns,
val languageVersionSettings: LanguageVersionSettings
val statelessCallbacks: KotlinResolutionStatelessCallbacks,
val argumentsToParametersMapper: ArgumentsToParametersMapper,
val typeArgumentsToParametersMapper: TypeArgumentsToParametersMapper,
val constraintInjector: ConstraintInjector,
val reflectionTypes: ReflectionTypes,
val builtIns: KotlinBuiltIns,
val languageVersionSettings: LanguageVersionSettings
)
class SimpleCandidateFactory(
val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower,
val kotlinCall: KotlinCall
): CandidateFactory<KotlinResolutionCandidate> {
val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower,
val kotlinCall: KotlinCall
) : CandidateFactory<KotlinResolutionCandidate> {
val baseSystem: ConstraintStorage
init {
@@ -66,11 +66,11 @@ class SimpleCandidateFactory(
// todo: try something else, because current method is ugly and unstable
private fun createReceiverArgument(
explicitReceiver: ReceiverKotlinCallArgument?,
fromResolution: ReceiverValueWithSmartCastInfo?
explicitReceiver: ReceiverKotlinCallArgument?,
fromResolution: ReceiverValueWithSmartCastInfo?
): SimpleKotlinCallArgument? =
explicitReceiver as? SimpleKotlinCallArgument ?: // qualifier receiver cannot be safe
fromResolution?.let { ReceiverExpressionKotlinCallArgument(it, isSafeCall = false) } // todo smartcast implicit this
explicitReceiver as? SimpleKotlinCallArgument ?: // qualifier receiver cannot be safe
fromResolution?.let { ReceiverExpressionKotlinCallArgument(it, isSafeCall = false) } // todo smartcast implicit this
private fun KotlinCall.getExplicitDispatchReceiver(explicitReceiverKind: ExplicitReceiverKind) = when (explicitReceiverKind) {
ExplicitReceiverKind.DISPATCH_RECEIVER -> explicitReceiver
@@ -86,38 +86,55 @@ class SimpleCandidateFactory(
fun createCandidate(givenCandidate: GivenCandidate): KotlinResolutionCandidate {
val isSafeCall = (kotlinCall.explicitReceiver as? SimpleKotlinCallArgument)?.isSafeCall ?: false
val explicitReceiverKind = if (givenCandidate.dispatchReceiver == null) ExplicitReceiverKind.NO_EXPLICIT_RECEIVER else ExplicitReceiverKind.DISPATCH_RECEIVER
val explicitReceiverKind =
if (givenCandidate.dispatchReceiver == null) ExplicitReceiverKind.NO_EXPLICIT_RECEIVER else ExplicitReceiverKind.DISPATCH_RECEIVER
val dispatchArgumentReceiver = givenCandidate.dispatchReceiver?.let { ReceiverExpressionKotlinCallArgument(it, isSafeCall) }
return createCandidate(givenCandidate.descriptor, explicitReceiverKind, dispatchArgumentReceiver, null,
listOf(), givenCandidate.knownTypeParametersResultingSubstitutor)
return createCandidate(
givenCandidate.descriptor, explicitReceiverKind, dispatchArgumentReceiver, null,
listOf(), givenCandidate.knownTypeParametersResultingSubstitutor
)
}
override fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValueWithSmartCastInfo?
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): KotlinResolutionCandidate {
val dispatchArgumentReceiver = createReceiverArgument(kotlinCall.getExplicitDispatchReceiver(explicitReceiverKind),
towerCandidate.dispatchReceiver)
val extensionArgumentReceiver = createReceiverArgument(kotlinCall.getExplicitExtensionReceiver(explicitReceiverKind), extensionReceiver)
val dispatchArgumentReceiver = createReceiverArgument(
kotlinCall.getExplicitDispatchReceiver(explicitReceiverKind),
towerCandidate.dispatchReceiver
)
val extensionArgumentReceiver =
createReceiverArgument(kotlinCall.getExplicitExtensionReceiver(explicitReceiverKind), extensionReceiver)
return createCandidate(towerCandidate.descriptor, explicitReceiverKind, dispatchArgumentReceiver,
extensionArgumentReceiver, towerCandidate.diagnostics, knownSubstitutor = null)
return createCandidate(
towerCandidate.descriptor, explicitReceiverKind, dispatchArgumentReceiver,
extensionArgumentReceiver, towerCandidate.diagnostics, knownSubstitutor = null
)
}
private fun createCandidate(
descriptor: CallableDescriptor,
explicitReceiverKind: ExplicitReceiverKind,
dispatchArgumentReceiver: SimpleKotlinCallArgument?,
extensionArgumentReceiver: SimpleKotlinCallArgument?,
initialDiagnostics: Collection<KotlinCallDiagnostic>,
knownSubstitutor: TypeSubstitutor?
descriptor: CallableDescriptor,
explicitReceiverKind: ExplicitReceiverKind,
dispatchArgumentReceiver: SimpleKotlinCallArgument?,
extensionArgumentReceiver: SimpleKotlinCallArgument?,
initialDiagnostics: Collection<KotlinCallDiagnostic>,
knownSubstitutor: TypeSubstitutor?
): KotlinResolutionCandidate {
val resolvedKtCall = MutableResolvedCallAtom(kotlinCall, descriptor, explicitReceiverKind,
dispatchArgumentReceiver, extensionArgumentReceiver)
val resolvedKtCall = MutableResolvedCallAtom(
kotlinCall, descriptor, explicitReceiverKind,
dispatchArgumentReceiver, extensionArgumentReceiver
)
if (ErrorUtils.isError(descriptor)) {
return KotlinResolutionCandidate(callComponents, scopeTower, baseSystem, resolvedKtCall, knownSubstitutor, listOf(ErrorDescriptorResolutionPart))
return KotlinResolutionCandidate(
callComponents,
scopeTower,
baseSystem,
resolvedKtCall,
knownSubstitutor,
listOf(ErrorDescriptorResolutionPart)
)
}
val candidate = KotlinResolutionCandidate(callComponents, scopeTower, baseSystem, resolvedKtCall, knownSubstitutor)
@@ -145,45 +162,47 @@ class SimpleCandidateFactory(
val errorScope = ErrorUtils.createErrorScope("Error resolution candidate for call $kotlinCall")
val errorDescriptor = if (kotlinCall.callKind == KotlinCallKind.VARIABLE) {
errorScope.getContributedVariables(kotlinCall.name, scopeTower.location)
}
else {
} else {
errorScope.getContributedFunctions(kotlinCall.name, scopeTower.location)
}.first()
val dispatchReceiver = createReceiverArgument(kotlinCall.explicitReceiver, fromResolution = null)
val explicitReceiverKind = if (dispatchReceiver == null) ExplicitReceiverKind.NO_EXPLICIT_RECEIVER else ExplicitReceiverKind.DISPATCH_RECEIVER
val explicitReceiverKind =
if (dispatchReceiver == null) ExplicitReceiverKind.NO_EXPLICIT_RECEIVER else ExplicitReceiverKind.DISPATCH_RECEIVER
return createCandidate(errorDescriptor, explicitReceiverKind, dispatchReceiver, extensionArgumentReceiver = null,
initialDiagnostics = listOf(), knownSubstitutor = null)
return createCandidate(
errorDescriptor, explicitReceiverKind, dispatchReceiver, extensionArgumentReceiver = null,
initialDiagnostics = listOf(), knownSubstitutor = null
)
}
}
enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
VARIABLE(
CheckVisibility,
CheckInfixResolutionPart,
CheckOperatorResolutionPart,
CheckSuperExpressionCallPart,
NoTypeArguments,
NoArguments,
CreateFreshVariablesSubstitutor,
CheckExplicitReceiverKindConsistency,
CheckReceivers
CheckVisibility,
CheckInfixResolutionPart,
CheckOperatorResolutionPart,
CheckSuperExpressionCallPart,
NoTypeArguments,
NoArguments,
CreateFreshVariablesSubstitutor,
CheckExplicitReceiverKindConsistency,
CheckReceivers
),
FUNCTION(
CheckInstantiationOfAbstractClass,
CheckVisibility,
CheckInfixResolutionPart,
CheckSuperExpressionCallPart,
MapTypeArguments,
MapArguments,
ArgumentsToCandidateParameterDescriptor,
CreateFreshVariablesSubstitutor,
CheckExplicitReceiverKindConsistency,
CheckReceivers,
CheckArguments,
CheckExternalArgument
CheckInstantiationOfAbstractClass,
CheckVisibility,
CheckInfixResolutionPart,
CheckSuperExpressionCallPart,
MapTypeArguments,
MapArguments,
ArgumentsToCandidateParameterDescriptor,
CreateFreshVariablesSubstitutor,
CheckExplicitReceiverKindConsistency,
CheckReceivers,
CheckArguments,
CheckExternalArgument
),
UNSUPPORTED();
@@ -191,8 +210,8 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
}
class GivenCandidate(
val descriptor: FunctionDescriptor,
val dispatchReceiver: ReceiverValueWithSmartCastInfo?,
val knownTypeParametersResultingSubstitutor: TypeSubstitutor?
val descriptor: FunctionDescriptor,
val dispatchReceiver: ReceiverValueWithSmartCastInfo?,
val knownTypeParametersResultingSubstitutor: TypeSubstitutor?
)
@@ -74,14 +74,15 @@ class ResolvedExpressionAtom(override val atom: ExpressionKotlinCallArgument) :
setAnalyzedResults(listOf())
}
}
sealed class PostponedResolvedAtom : ResolvedAtom() {
abstract val inputTypes: Collection<UnwrappedType>
abstract val outputType: UnwrappedType?
}
class LambdaWithTypeVariableAsExpectedTypeAtom(
override val atom: LambdaKotlinCallArgument,
val expectedType: UnwrappedType
override val atom: LambdaKotlinCallArgument,
val expectedType: UnwrappedType
) : PostponedResolvedAtom() {
override val inputTypes: Collection<UnwrappedType> get() = listOf(expectedType)
override val outputType: UnwrappedType? get() = null
@@ -92,19 +93,19 @@ class LambdaWithTypeVariableAsExpectedTypeAtom(
}
class ResolvedLambdaAtom(
override val atom: LambdaKotlinCallArgument,
val isSuspend: Boolean,
val receiver: UnwrappedType?,
val parameters: List<UnwrappedType>,
val returnType: UnwrappedType,
val typeVariableForLambdaReturnType: TypeVariableForLambdaReturnType?
override val atom: LambdaKotlinCallArgument,
val isSuspend: Boolean,
val receiver: UnwrappedType?,
val parameters: List<UnwrappedType>,
val returnType: UnwrappedType,
val typeVariableForLambdaReturnType: TypeVariableForLambdaReturnType?
) : PostponedResolvedAtom() {
lateinit var resultArguments: List<KotlinCallArgument>
private set
fun setAnalyzedResults(
resultArguments: List<KotlinCallArgument>,
subResolvedAtoms: List<ResolvedAtom>
resultArguments: List<KotlinCallArgument>,
subResolvedAtoms: List<ResolvedAtom>
) {
this.resultArguments = resultArguments
setAnalyzedResults(subResolvedAtoms)
@@ -115,15 +116,15 @@ class ResolvedLambdaAtom(
}
class ResolvedCallableReferenceAtom(
override val atom: CallableReferenceKotlinCallArgument,
val expectedType: UnwrappedType?
override val atom: CallableReferenceKotlinCallArgument,
val expectedType: UnwrappedType?
) : PostponedResolvedAtom() {
var candidate: CallableReferenceCandidate? = null
private set
fun setAnalyzedResults(
candidate: CallableReferenceCandidate?,
subResolvedAtoms: List<ResolvedAtom>
candidate: CallableReferenceCandidate?,
subResolvedAtoms: List<ResolvedAtom>
) {
this.candidate = candidate
setAnalyzedResults(subResolvedAtoms)
@@ -145,8 +146,8 @@ class ResolvedCallableReferenceAtom(
}
class ResolvedCollectionLiteralAtom(
override val atom: CollectionLiteralKotlinCallArgument,
val expectedType: UnwrappedType?
override val atom: CollectionLiteralKotlinCallArgument,
val expectedType: UnwrappedType?
) : ResolvedAtom() {
init {
setAnalyzedResults(listOf())
@@ -154,11 +155,11 @@ class ResolvedCollectionLiteralAtom(
}
class CallResolutionResult(
val type: Type,
val resultCallAtom: ResolvedCallAtom?,
val diagnostics: List<KotlinCallDiagnostic>,
val constraintSystem: ConstraintStorage,
val allCandidates: Collection<KotlinResolutionCandidate>? = null
val type: Type,
val resultCallAtom: ResolvedCallAtom?,
val diagnostics: List<KotlinCallDiagnostic>,
val constraintSystem: ConstraintStorage,
val allCandidates: Collection<KotlinResolutionCandidate>? = null
) : ResolvedAtom() {
override val atom: ResolutionAtom? get() = null
@@ -176,7 +177,8 @@ class CallResolutionResult(
override fun toString() = "$type, resultCallAtom = $resultCallAtom, (${diagnostics.joinToString()})"
}
val ResolvedCallAtom.freshReturnType: UnwrappedType? get() {
val returnType = candidateDescriptor.returnType ?: return null
return substitutor.safeSubstitute(returnType.unwrap())
}
val ResolvedCallAtom.freshReturnType: UnwrappedType?
get() {
val returnType = candidateDescriptor.returnType ?: return null
return substitutor.safeSubstitute(returnType.unwrap())
}
@@ -56,17 +56,18 @@ interface KotlinDiagnosticsHolder {
fun KotlinDiagnosticsHolder.addDiagnosticIfNotNull(diagnostic: KotlinCallDiagnostic?) {
diagnostic?.let { addDiagnostic(it) }
}
/**
* baseSystem contains all information from arguments, i.e. it is union of all system of arguments
* Also by convention we suppose that baseSystem has no contradiction
*/
class KotlinResolutionCandidate(
val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower,
private val baseSystem: ConstraintStorage,
val resolvedCall: MutableResolvedCallAtom,
val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null,
private val resolutionSequence: List<ResolutionPart> = resolvedCall.atom.callKind.resolutionSequence
val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower,
private val baseSystem: ConstraintStorage,
val resolvedCall: MutableResolvedCallAtom,
val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null,
private val resolutionSequence: List<ResolutionPart> = resolvedCall.atom.callKind.resolutionSequence
) : Candidate, KotlinDiagnosticsHolder {
val diagnosticsFromResolutionParts = arrayListOf<KotlinCallDiagnostic>() // TODO: this is mutable list, take diagnostics only once!
private var newSystem: NewConstraintSystemImpl? = null
@@ -106,8 +107,7 @@ class KotlinResolutionCandidate(
if (workStep >= workCount) {
partIndex++
workStep -= workCount
}
else {
} else {
break
}
}
@@ -165,11 +165,11 @@ class KotlinResolutionCandidate(
}
class MutableResolvedCallAtom(
override val atom: KotlinCall,
override val candidateDescriptor: CallableDescriptor, // original candidate descriptor
override val explicitReceiverKind: ExplicitReceiverKind,
override val dispatchReceiverArgument: SimpleKotlinCallArgument?,
override val extensionReceiverArgument: SimpleKotlinCallArgument?
override val atom: KotlinCall,
override val candidateDescriptor: CallableDescriptor, // original candidate descriptor
override val explicitReceiverKind: ExplicitReceiverKind,
override val dispatchReceiverArgument: SimpleKotlinCallArgument?,
override val extensionReceiverArgument: SimpleKotlinCallArgument?
) : ResolvedCallAtom() {
override lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
override lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
@@ -26,11 +26,11 @@ sealed class ResolvedCallArgument {
}
class SimpleArgument(val callArgument: KotlinCallArgument): ResolvedCallArgument() {
class SimpleArgument(val callArgument: KotlinCallArgument) : ResolvedCallArgument() {
override val arguments: List<KotlinCallArgument>
get() = listOf(callArgument)
}
class VarargArgument(override val arguments: List<KotlinCallArgument>): ResolvedCallArgument()
class VarargArgument(override val arguments: List<KotlinCallArgument>) : ResolvedCallArgument()
}
@@ -33,76 +33,79 @@ interface SpecificityComparisonCallbacks {
interface TypeSpecificityComparator {
fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType): Boolean
object NONE: TypeSpecificityComparator {
object NONE : TypeSpecificityComparator {
override fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType) = false
}
}
class FlatSignature<out T> private constructor(
val origin: T,
val typeParameters: Collection<TypeParameterDescriptor>,
val valueParameterTypes: List<KotlinType?>,
val hasExtensionReceiver: Boolean,
val hasVarargs: Boolean,
val numDefaults: Int,
val isExpect: Boolean,
val isSyntheticMember: Boolean
val origin: T,
val typeParameters: Collection<TypeParameterDescriptor>,
val valueParameterTypes: List<KotlinType?>,
val hasExtensionReceiver: Boolean,
val hasVarargs: Boolean,
val numDefaults: Int,
val isExpect: Boolean,
val isSyntheticMember: Boolean
) {
val isGeneric = typeParameters.isNotEmpty()
companion object {
fun <T> createFromReflectionType(
origin: T,
descriptor: CallableDescriptor,
numDefaults: Int,
reflectionType: UnwrappedType
origin: T,
descriptor: CallableDescriptor,
numDefaults: Int,
reflectionType: UnwrappedType
): FlatSignature<T> {
return FlatSignature(origin,
descriptor.typeParameters,
reflectionType.arguments.map { it.type }, // should we drop return type?
hasExtensionReceiver = false,
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
numDefaults = numDefaults,
isExpect = descriptor is MemberDescriptor && descriptor.isExpect,
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
)
return FlatSignature(
origin,
descriptor.typeParameters,
reflectionType.arguments.map { it.type }, // should we drop return type?
hasExtensionReceiver = false,
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
numDefaults = numDefaults,
isExpect = descriptor is MemberDescriptor && descriptor.isExpect,
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
)
}
fun <T> create(
origin: T,
descriptor: CallableDescriptor,
numDefaults: Int,
parameterTypes: List<KotlinType?>
origin: T,
descriptor: CallableDescriptor,
numDefaults: Int,
parameterTypes: List<KotlinType?>
): FlatSignature<T> {
val extensionReceiverType = descriptor.extensionReceiverParameter?.type
return FlatSignature(origin,
descriptor.typeParameters,
valueParameterTypes =
listOfNotNull(extensionReceiverType) + parameterTypes,
hasExtensionReceiver = extensionReceiverType != null,
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
numDefaults = numDefaults,
isExpect = descriptor is MemberDescriptor && descriptor.isExpect,
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
return FlatSignature(
origin,
descriptor.typeParameters,
valueParameterTypes =
listOfNotNull(extensionReceiverType) + parameterTypes,
hasExtensionReceiver = extensionReceiverType != null,
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
numDefaults = numDefaults,
isExpect = descriptor is MemberDescriptor && descriptor.isExpect,
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
)
}
fun <D : CallableDescriptor> createFromCallableDescriptor(
descriptor: D
descriptor: D
): FlatSignature<D> =
create(descriptor, descriptor, numDefaults = 0, parameterTypes = descriptor.valueParameters.map { it.argumentValueType })
create(descriptor, descriptor, numDefaults = 0, parameterTypes = descriptor.valueParameters.map { it.argumentValueType })
fun <D : CallableDescriptor> createForPossiblyShadowedExtension(descriptor: D): FlatSignature<D> =
FlatSignature(descriptor,
descriptor.typeParameters,
valueParameterTypes = descriptor.valueParameters.map { it.argumentValueType },
hasExtensionReceiver = false,
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
numDefaults = descriptor.valueParameters.count { it.hasDefaultValue() },
isExpect = descriptor is MemberDescriptor && descriptor.isExpect,
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
)
FlatSignature(
descriptor,
descriptor.typeParameters,
valueParameterTypes = descriptor.valueParameters.map { it.argumentValueType },
hasExtensionReceiver = false,
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
numDefaults = descriptor.valueParameters.count { it.hasDefaultValue() },
isExpect = descriptor is MemberDescriptor && descriptor.isExpect,
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
)
val ValueParameterDescriptor.argumentValueType get() = varargElementType ?: type
}
@@ -119,10 +122,10 @@ interface SimpleConstraintSystem {
}
fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
specific: FlatSignature<T>,
general: FlatSignature<T>,
callbacks: SpecificityComparisonCallbacks,
specificityComparator: TypeSpecificityComparator
specific: FlatSignature<T>,
general: FlatSignature<T>,
callbacks: SpecificityComparisonCallbacks,
specificityComparator: TypeSpecificityComparator
): Boolean {
if (specific.hasExtensionReceiver != general.hasExtensionReceiver) return false
if (specific.valueParameterTypes.size != general.valueParameterTypes.size) return false
@@ -143,8 +146,7 @@ fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
return false
}
}
}
else {
} else {
val substitutedGeneralType = typeSubstitutor.safeSubstitute(generalType, Variance.INVARIANT)
/**
@@ -33,41 +33,40 @@ import org.jetbrains.kotlin.types.TypeUtils
import java.util.*
open class OverloadingConflictResolver<C : Any>(
private val builtIns: KotlinBuiltIns,
private val specificityComparator: TypeSpecificityComparator,
private val getResultingDescriptor: (C) -> CallableDescriptor,
private val createEmptyConstraintSystem: () -> SimpleConstraintSystem,
private val createFlatSignature: (C) -> FlatSignature<C>,
private val getVariableCandidates: (C) -> C?, // for variable WithInvoke
private val isFromSources: (CallableDescriptor) -> Boolean
private val builtIns: KotlinBuiltIns,
private val specificityComparator: TypeSpecificityComparator,
private val getResultingDescriptor: (C) -> CallableDescriptor,
private val createEmptyConstraintSystem: () -> SimpleConstraintSystem,
private val createFlatSignature: (C) -> FlatSignature<C>,
private val getVariableCandidates: (C) -> C?, // for variable WithInvoke
private val isFromSources: (CallableDescriptor) -> Boolean
) {
private val resolvedCallHashingStrategy = object : TObjectHashingStrategy<C> {
override fun equals(call1: C?, call2: C?): Boolean =
if (call1 != null && call2 != null)
call1.resultingDescriptor == call2.resultingDescriptor
else
call1 == call2
if (call1 != null && call2 != null)
call1.resultingDescriptor == call2.resultingDescriptor
else
call1 == call2
override fun computeHashCode(call: C?): Int =
call?.resultingDescriptor?.hashCode() ?: 0
call?.resultingDescriptor?.hashCode() ?: 0
}
private val C.resultingDescriptor: CallableDescriptor get() = getResultingDescriptor(this)
// if result contains only one element -- it is maximally specific; otherwise we have ambiguity
fun chooseMaximallySpecificCandidates(
candidates: Collection<C>,
checkArgumentsMode: CheckArgumentTypesMode,
discriminateGenerics: Boolean,
isDebuggerContext: Boolean
candidates: Collection<C>,
checkArgumentsMode: CheckArgumentTypesMode,
discriminateGenerics: Boolean,
isDebuggerContext: Boolean
): Set<C> {
candidates.setIfOneOrEmpty()?.let { return it }
val fixedCandidates = if (getVariableCandidates(candidates.first()) != null) {
findMaximallySpecificVariableAsFunctionCalls(candidates, isDebuggerContext) ?: return LinkedHashSet(candidates)
}
else {
} else {
candidates
}
@@ -131,35 +130,35 @@ open class OverloadingConflictResolver<C : Any>(
return result
}
private fun Collection<C>.setIfOneOrEmpty() = when(size) {
private fun Collection<C>.setIfOneOrEmpty() = when (size) {
0 -> emptySet()
1 -> setOf(single())
else -> null
}
private fun findMaximallySpecific(
candidates: Set<C>,
checkArgumentsMode: CheckArgumentTypesMode,
discriminateGenerics: Boolean,
isDebuggerContext: Boolean
candidates: Set<C>,
checkArgumentsMode: CheckArgumentTypesMode,
discriminateGenerics: Boolean,
isDebuggerContext: Boolean
): C? =
if (candidates.size <= 1)
candidates.firstOrNull()
else when (checkArgumentsMode) {
CheckArgumentTypesMode.CHECK_CALLABLE_TYPE ->
uniquifyCandidatesSet(candidates).singleOrNull {
isDefinitelyMostSpecific(it, candidates) { call1, call2 ->
isNotLessSpecificCallableReference(call1.resultingDescriptor, call2.resultingDescriptor)
}
if (candidates.size <= 1)
candidates.firstOrNull()
else when (checkArgumentsMode) {
CheckArgumentTypesMode.CHECK_CALLABLE_TYPE ->
uniquifyCandidatesSet(candidates).singleOrNull {
isDefinitelyMostSpecific(it, candidates) { call1, call2 ->
isNotLessSpecificCallableReference(call1.resultingDescriptor, call2.resultingDescriptor)
}
}
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
findMaximallySpecificCall(candidates, discriminateGenerics, isDebuggerContext)
?: findMaximallySpecificCall(
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
findMaximallySpecificCall(candidates, discriminateGenerics, isDebuggerContext)
?: findMaximallySpecificCall(
candidates.filterNotTo(mutableSetOf()) { createFlatSignature(it).isSyntheticMember },
discriminateGenerics, isDebuggerContext
)
}
)
}
// null means ambiguity between variables
private fun findMaximallySpecificVariableAsFunctionCalls(candidates: Collection<C>, isDebuggerContext: Boolean): Set<C>? {
@@ -167,8 +166,10 @@ open class OverloadingConflictResolver<C : Any>(
getVariableCandidates(it) ?: throw AssertionError("Regular call among variable-as-function calls: $it")
}
val maxSpecificVariableCalls = chooseMaximallySpecificCandidates(variableCalls, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
isDebuggerContext = isDebuggerContext, discriminateGenerics = false)
val maxSpecificVariableCalls = chooseMaximallySpecificCandidates(
variableCalls, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
isDebuggerContext = isDebuggerContext, discriminateGenerics = false
)
val maxSpecificVariableCall = maxSpecificVariableCalls.singleOrNull() ?: return null
return candidates.filterTo(newResolvedCallSet(2)) {
@@ -177,29 +178,25 @@ open class OverloadingConflictResolver<C : Any>(
}
private fun findMaximallySpecificCall(
candidates: Set<C>,
discriminateGenerics: Boolean,
isDebuggerContext: Boolean
candidates: Set<C>,
discriminateGenerics: Boolean,
isDebuggerContext: Boolean
): C? {
val filteredCandidates = uniquifyCandidatesSet(candidates)
if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
val conflictingCandidates = filteredCandidates.map {
candidateCall ->
val conflictingCandidates = filteredCandidates.map { candidateCall ->
createFlatSignature(candidateCall)
}
val bestCandidatesByParameterTypes = conflictingCandidates.filter {
candidate ->
isMostSpecific(candidate, conflictingCandidates) {
call1, call2 ->
val bestCandidatesByParameterTypes = conflictingCandidates.filter { candidate ->
isMostSpecific(candidate, conflictingCandidates) { call1, call2 ->
isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenerics)
}
}
return bestCandidatesByParameterTypes.exactMaxWith {
call1, call2 ->
return bestCandidatesByParameterTypes.exactMaxWith { call1, call2 ->
isOfNotLessSpecificShape(call1, call2) && isOfNotLessSpecificVisibilityForDebugger(call1, call2, isDebuggerContext)
}?.origin
}
@@ -219,29 +216,34 @@ open class OverloadingConflictResolver<C : Any>(
}
private inline fun <C> isMostSpecific(candidate: C, candidates: Collection<C>, isNotLessSpecific: (C, C) -> Boolean): Boolean =
candidates.all {
other ->
candidate === other ||
isNotLessSpecific(candidate, other)
}
candidates.all { other ->
candidate === other ||
isNotLessSpecific(candidate, other)
}
private inline fun <C> isDefinitelyMostSpecific(candidate: C, candidates: Collection<C>, isNotLessSpecific: (C, C) -> Boolean): Boolean =
candidates.all {
other ->
candidate === other ||
isNotLessSpecific(candidate, other) && !isNotLessSpecific(other, candidate)
}
private inline fun <C> isDefinitelyMostSpecific(
candidate: C,
candidates: Collection<C>,
isNotLessSpecific: (C, C) -> Boolean
): Boolean =
candidates.all { other ->
candidate === other ||
isNotLessSpecific(candidate, other) && !isNotLessSpecific(other, candidate)
}
/**
* `call1` is not less specific than `call2`
*/
private fun isNotLessSpecificCallWithArgumentMapping(
call1: FlatSignature<C>,
call2: FlatSignature<C>,
discriminateGenerics: Boolean
call1: FlatSignature<C>,
call2: FlatSignature<C>,
discriminateGenerics: Boolean
): Boolean {
return tryCompareDescriptorsFromScripts(call1.candidateDescriptor(), call2.candidateDescriptor()) ?:
compareCallsByUsedArguments(call1, call2, discriminateGenerics)
return tryCompareDescriptorsFromScripts(call1.candidateDescriptor(), call2.candidateDescriptor()) ?: compareCallsByUsedArguments(
call1,
call2,
discriminateGenerics
)
}
/**
@@ -249,9 +251,9 @@ open class OverloadingConflictResolver<C : Any>(
* `false` otherwise.
*/
private fun compareCallsByUsedArguments(
call1: FlatSignature<C>,
call2: FlatSignature<C>,
discriminateGenerics: Boolean
call1: FlatSignature<C>,
call2: FlatSignature<C>,
discriminateGenerics: Boolean
): Boolean {
if (discriminateGenerics) {
val isGeneric1 = call1.isGeneric
@@ -266,7 +268,12 @@ open class OverloadingConflictResolver<C : Any>(
if (!call1.isExpect && call2.isExpect) return true
if (call1.isExpect && !call2.isExpect) return false
return createEmptyConstraintSystem().isSignatureNotLessSpecific(call1, call2, SpecificityComparisonWithNumerics, specificityComparator)
return createEmptyConstraintSystem().isSignatureNotLessSpecific(
call1,
call2,
SpecificityComparisonWithNumerics,
specificityComparator
)
}
private val SpecificityComparisonWithNumerics = object : SpecificityComparisonCallbacks {
@@ -295,8 +302,8 @@ open class OverloadingConflictResolver<C : Any>(
}
private fun isOfNotLessSpecificShape(
call1: FlatSignature<C>,
call2: FlatSignature<C>
call1: FlatSignature<C>,
call2: FlatSignature<C>
): Boolean {
val hasVarargs1 = call1.hasVarargs
val hasVarargs2 = call2.hasVarargs
@@ -311,9 +318,9 @@ open class OverloadingConflictResolver<C : Any>(
}
private fun isOfNotLessSpecificVisibilityForDebugger(
call1: FlatSignature<C>,
call2: FlatSignature<C>,
isDebuggerContext: Boolean
call1: FlatSignature<C>,
call2: FlatSignature<C>,
isDebuggerContext: Boolean
): Boolean {
if (isDebuggerContext) {
val isMoreVisible1 = Visibilities.compare(call1.descriptorVisibility(), call2.descriptorVisibility())
@@ -352,7 +359,12 @@ open class OverloadingConflictResolver<C : Any>(
val fSignature = FlatSignature.createFromCallableDescriptor(f)
val gSignature = FlatSignature.createFromCallableDescriptor(g)
if (!createEmptyConstraintSystem().isSignatureNotLessSpecific(fSignature, gSignature, SpecificityComparisonWithNumerics, specificityComparator)) {
if (!createEmptyConstraintSystem().isSignatureNotLessSpecific(
fSignature,
gSignature,
SpecificityComparisonWithNumerics,
specificityComparator
)) {
return false
}
@@ -365,20 +377,19 @@ open class OverloadingConflictResolver<C : Any>(
}
private fun isNotLessSpecificCallableReference(f: CallableDescriptor, g: CallableDescriptor): Boolean =
// TODO should we "discriminate generic descriptors" for callable references?
tryCompareDescriptorsFromScripts(f, g) ?:
isNotLessSpecificCallableReferenceDescriptor(f, g)
// TODO should we "discriminate generic descriptors" for callable references?
tryCompareDescriptorsFromScripts(f, g) ?: isNotLessSpecificCallableReferenceDescriptor(f, g)
// Different smart casts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects
private fun uniquifyCandidatesSet(candidates: Collection<C>): Set<C> =
THashSet(candidates.size, resolvedCallHashingStrategy).apply { addAll(candidates) }
THashSet(candidates.size, resolvedCallHashingStrategy).apply { addAll(candidates) }
private fun newResolvedCallSet(expectedSize: Int): MutableSet<C> =
THashSet(expectedSize, resolvedCallHashingStrategy)
THashSet(expectedSize, resolvedCallHashingStrategy)
private fun FlatSignature<C>.candidateDescriptor() =
origin.resultingDescriptor.original
origin.resultingDescriptor.original
private fun FlatSignature<C>.descriptorVisibility() =
candidateDescriptor().visibility
candidateDescriptor().visibility
}
@@ -20,8 +20,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
fun getReceiverValueWithSmartCast(
receiverArgument: ReceiverValue?,
smartCastType: KotlinType?
receiverArgument: ReceiverValue?,
smartCastType: KotlinType?
) = smartCastType?.let(::SmartCastReceiverValue) ?: receiverArgument
private class SmartCastReceiverValue(private val type: KotlinType) : ReceiverValue {
@@ -43,17 +43,16 @@ fun createSynthesizedInvokes(functions: Collection<FunctionDescriptor>): Collect
val containerClassId = (invoke.containingDeclaration as ClassDescriptor).classId
val synthesized = if (containerClassId != null && isBuiltinFunctionClass(containerClassId)) {
createSynthesizedFunctionWithFirstParameterAsReceiver(invoke)
}
else {
} else {
val invokeDeclaration = invoke.overriddenDescriptors.singleOrNull()
?: error("No single overridden invoke for $invoke: ${invoke.overriddenDescriptors}")
?: error("No single overridden invoke for $invoke: ${invoke.overriddenDescriptors}")
val synthesizedSuperFun = createSynthesizedFunctionWithFirstParameterAsReceiver(invokeDeclaration)
val fakeOverride = synthesizedSuperFun.copy(
invoke.containingDeclaration,
synthesizedSuperFun.modality,
synthesizedSuperFun.visibility,
CallableMemberDescriptor.Kind.FAKE_OVERRIDE,
/* copyOverrides = */ false
invoke.containingDeclaration,
synthesizedSuperFun.modality,
synthesizedSuperFun.visibility,
CallableMemberDescriptor.Kind.FAKE_OVERRIDE,
/* copyOverrides = */ false
)
fakeOverride.setSingleOverridden(synthesizedSuperFun)
fakeOverride
@@ -69,9 +68,9 @@ private fun createSynthesizedFunctionWithFirstParameterAsReceiver(descriptor: Fu
descriptor.original.newCopyBuilder().apply {
setExtensionReceiverType(descriptor.original.valueParameters.first().type)
setValueParameters(
descriptor.original.valueParameters
.drop(1)
.map { p -> p.copy(descriptor.original, Name.identifier("p${p.index + 1}"), p.index - 1) }
descriptor.original.valueParameters
.drop(1)
.map { p -> p.copy(descriptor.original, Name.identifier("p${p.index + 1}"), p.index - 1) }
)
}.build()!!
@@ -85,5 +84,5 @@ fun isSynthesizedInvoke(descriptor: DeclarationDescriptor): Boolean {
}
return real.kind == CallableMemberDescriptor.Kind.SYNTHESIZED &&
real.containingDeclaration.getFunctionalClassKind() != null
real.containingDeclaration.getFunctionalClassKind() != null
}
@@ -36,19 +36,19 @@ enum class WrongResolutionToClassifier(val message: (Name) -> String) {
OBJECT_AS_FUNCTION({ "Function 'invoke()' is not found in object $it" })
}
sealed class ErrorCandidate<out D: DeclarationDescriptor>(val descriptor: D) {
sealed class ErrorCandidate<out D : DeclarationDescriptor>(val descriptor: D) {
class Classifier(
classifierDescriptor: ClassifierDescriptor,
val kind: WrongResolutionToClassifier
classifierDescriptor: ClassifierDescriptor,
val kind: WrongResolutionToClassifier
) : ErrorCandidate<ClassifierDescriptor>(classifierDescriptor) {
val errorMessage = kind.message(descriptor.name)
}
}
fun collectErrorCandidatesForFunction(
scopeTower: ImplicitScopeTower,
name: Name,
explicitReceiver: DetailedReceiver?
scopeTower: ImplicitScopeTower,
name: Name,
explicitReceiver: DetailedReceiver?
): Collection<ErrorCandidate<*>> {
val context = ErrorCandidateContext(scopeTower, name, explicitReceiver)
context.asClassifierCall(asFunction = true)
@@ -56,9 +56,9 @@ fun collectErrorCandidatesForFunction(
}
fun collectErrorCandidatesForVariable(
scopeTower: ImplicitScopeTower,
name: Name,
explicitReceiver: DetailedReceiver?
scopeTower: ImplicitScopeTower,
name: Name,
explicitReceiver: DetailedReceiver?
): Collection<ErrorCandidate<*>> {
val context = ErrorCandidateContext(scopeTower, name, explicitReceiver)
context.asClassifierCall(asFunction = false)
@@ -66,54 +66,59 @@ fun collectErrorCandidatesForVariable(
}
private class ErrorCandidateContext(
val scopeTower: ImplicitScopeTower,
val name: Name,
val explicitReceiver: DetailedReceiver?
val scopeTower: ImplicitScopeTower,
val name: Name,
val explicitReceiver: DetailedReceiver?
) {
val result = SmartList<ErrorCandidate<*>>()
fun add(errorCandidate: ErrorCandidate<*>) { result.add(errorCandidate) }
fun add(errorCandidate: ErrorCandidate<*>) {
result.add(errorCandidate)
}
}
private fun ErrorCandidateContext.asClassifierCall(asFunction: Boolean) {
val classifier =
when (explicitReceiver) {
is ReceiverValueWithSmartCastInfo -> {
explicitReceiver.receiverValue.type.memberScope.getContributedClassifier(name, scopeTower.location)
}
is QualifierReceiver -> {
explicitReceiver.staticScope.getContributedClassifier(name, scopeTower.location)
}
else -> scopeTower.lexicalScope.findClassifier(name, scopeTower.location)
} ?: return
when (explicitReceiver) {
is ReceiverValueWithSmartCastInfo -> {
explicitReceiver.receiverValue.type.memberScope.getContributedClassifier(name, scopeTower.location)
}
is QualifierReceiver -> {
explicitReceiver.staticScope.getContributedClassifier(name, scopeTower.location)
}
else -> scopeTower.lexicalScope.findClassifier(name, scopeTower.location)
} ?: return
val kind = getWrongResolutionToClassifier(classifier, asFunction) ?: return
add(ErrorCandidate.Classifier(classifier, kind))
}
private fun ErrorCandidateContext.getWrongResolutionToClassifier(classifier: ClassifierDescriptor, asFunction: Boolean): WrongResolutionToClassifier? =
when (classifier) {
is TypeAliasDescriptor -> classifier.classDescriptor?.let { getWrongResolutionToClassifier(it, asFunction) }
private fun ErrorCandidateContext.getWrongResolutionToClassifier(
classifier: ClassifierDescriptor,
asFunction: Boolean
): WrongResolutionToClassifier? =
when (classifier) {
is TypeAliasDescriptor -> classifier.classDescriptor?.let { getWrongResolutionToClassifier(it, asFunction) }
is TypeParameterDescriptor -> if (asFunction) TYPE_PARAMETER_AS_FUNCTION else TYPE_PARAMETER_AS_VALUE
is TypeParameterDescriptor -> if (asFunction) TYPE_PARAMETER_AS_FUNCTION else TYPE_PARAMETER_AS_VALUE
is ClassDescriptor -> {
when (classifier.kind) {
ClassKind.INTERFACE -> if (asFunction) INTERFACE_AS_FUNCTION else INTERFACE_AS_VALUE
is ClassDescriptor -> {
when (classifier.kind) {
ClassKind.INTERFACE -> if (asFunction) INTERFACE_AS_FUNCTION else INTERFACE_AS_VALUE
ClassKind.OBJECT -> if (asFunction) OBJECT_AS_FUNCTION else null
ClassKind.CLASS -> when {
asFunction && explicitReceiver is QualifierReceiver? && classifier.isInner -> INNER_CLASS_CONSTRUCTOR_NO_RECEIVER
asFunction && classifier.isExpect -> EXPECT_CLASS_AS_FUNCTION
!asFunction -> CLASS_AS_VALUE
else -> null
}
ClassKind.OBJECT -> if (asFunction) OBJECT_AS_FUNCTION else null
ClassKind.CLASS -> when {
asFunction && explicitReceiver is QualifierReceiver? && classifier.isInner -> INNER_CLASS_CONSTRUCTOR_NO_RECEIVER
asFunction && classifier.isExpect -> EXPECT_CLASS_AS_FUNCTION
!asFunction -> CLASS_AS_VALUE
else -> null
}
}
else -> null
else -> null
}
}
else -> null
}
@@ -64,8 +64,9 @@ interface CandidateWithBoundDispatchReceiver {
val dispatchReceiver: ReceiverValueWithSmartCastInfo?
}
fun getResultApplicability(diagnostics: Collection<KotlinCallDiagnostic>) = diagnostics.maxBy { it.candidateApplicability }?.candidateApplicability
?: RESOLVED
fun getResultApplicability(diagnostics: Collection<KotlinCallDiagnostic>) =
diagnostics.maxBy { it.candidateApplicability }?.candidateApplicability
?: RESOLVED
enum class ResolutionCandidateApplicability {
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
@@ -80,30 +81,31 @@ enum class ResolutionCandidateApplicability {
HIDDEN, // removed from resolve
}
abstract class ResolutionDiagnostic(candidateApplicability: ResolutionCandidateApplicability): KotlinCallDiagnostic(candidateApplicability) {
abstract class ResolutionDiagnostic(candidateApplicability: ResolutionCandidateApplicability) :
KotlinCallDiagnostic(candidateApplicability) {
override fun report(reporter: DiagnosticReporter) {
// do nothing
}
}
// todo error for this access from nested class
class VisibilityError(val invisibleMember: DeclarationDescriptorWithVisibility): ResolutionDiagnostic(RUNTIME_ERROR) {
class VisibilityError(val invisibleMember: DeclarationDescriptorWithVisibility) : ResolutionDiagnostic(RUNTIME_ERROR) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCall(this)
}
}
class NestedClassViaInstanceReference(val classDescriptor: ClassDescriptor): ResolutionDiagnostic(IMPOSSIBLE_TO_GENERATE)
class InnerClassViaStaticReference(val classDescriptor: ClassDescriptor): ResolutionDiagnostic(IMPOSSIBLE_TO_GENERATE)
class UnsupportedInnerClassCall(val message: String): ResolutionDiagnostic(IMPOSSIBLE_TO_GENERATE)
class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType): ResolutionDiagnostic(RESOLVED)
class NestedClassViaInstanceReference(val classDescriptor: ClassDescriptor) : ResolutionDiagnostic(IMPOSSIBLE_TO_GENERATE)
class InnerClassViaStaticReference(val classDescriptor: ClassDescriptor) : ResolutionDiagnostic(IMPOSSIBLE_TO_GENERATE)
class UnsupportedInnerClassCall(val message: String) : ResolutionDiagnostic(IMPOSSIBLE_TO_GENERATE)
class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType) : ResolutionDiagnostic(RESOLVED)
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED) // todo discuss and change to INAPPLICABLE
object LowPriorityDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED_LOW_PRIORITY)
object DynamicDescriptorDiagnostic: ResolutionDiagnostic(RESOLVED_LOW_PRIORITY)
object UnstableSmartCastDiagnostic: ResolutionDiagnostic(MAY_THROW_RUNTIME_ERROR)
object HiddenExtensionRelatedToDynamicTypes: ResolutionDiagnostic(HIDDEN)
object HiddenDescriptor: ResolutionDiagnostic(HIDDEN)
object DynamicDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED_LOW_PRIORITY)
object UnstableSmartCastDiagnostic : ResolutionDiagnostic(MAY_THROW_RUNTIME_ERROR)
object HiddenExtensionRelatedToDynamicTypes : ResolutionDiagnostic(HIDDEN)
object HiddenDescriptor : ResolutionDiagnostic(HIDDEN)
object InvokeConventionCallNoOperatorModifier : ResolutionDiagnostic(CONVENTION_ERROR)
object InfixCallNoInfixModifier : ResolutionDiagnostic(CONVENTION_ERROR)
@@ -26,8 +26,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
abstract class AbstractInvokeTowerProcessor<C : Candidate>(
protected val factoryProviderForInvoke: CandidateFactoryProviderForInvoke<C>,
protected val variableProcessor: ScopeTowerProcessor<C>
protected val factoryProviderForInvoke: CandidateFactoryProviderForInvoke<C>,
protected val variableProcessor: ScopeTowerProcessor<C>
) : ScopeTowerProcessor<C> {
// todo optimize it
private val previousData = ArrayList<TowerData>()
@@ -36,14 +36,13 @@ abstract class AbstractInvokeTowerProcessor<C : Candidate>(
protected fun hasInvokeProcessors() = invokeProcessors.isNotEmpty()
private inner class VariableInvokeProcessor(
var variableCandidate: C,
val invokeProcessor: ScopeTowerProcessor<C>
): ScopeTowerProcessor<C> {
var variableCandidate: C,
val invokeProcessor: ScopeTowerProcessor<C>
) : ScopeTowerProcessor<C> {
override fun process(data: TowerData)
= invokeProcessor.process(data).map { candidateGroup ->
candidateGroup.map { factoryProviderForInvoke.transformCandidate(variableCandidate, it) }
}
override fun process(data: TowerData) = invokeProcessor.process(data).map { candidateGroup ->
candidateGroup.map { factoryProviderForInvoke.transformCandidate(variableCandidate, it) }
}
override fun recordLookups(skippedData: Collection<TowerData>, name: Name) {
invokeProcessor.recordLookups(skippedData, name)
@@ -51,7 +50,7 @@ abstract class AbstractInvokeTowerProcessor<C : Candidate>(
}
private fun createVariableInvokeProcessor(variableCandidate: C): VariableInvokeProcessor? =
createInvokeProcessor(variableCandidate)?.let { VariableInvokeProcessor(variableCandidate, it) }
createInvokeProcessor(variableCandidate)?.let { VariableInvokeProcessor(variableCandidate, it) }
protected abstract fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C>?
@@ -98,24 +97,33 @@ abstract class AbstractInvokeTowerProcessor<C : Candidate>(
// todo KT-9522 Allow invoke convention for synthetic property
class InvokeTowerProcessor<C : Candidate>(
val scopeTower: ImplicitScopeTower,
val name: Name,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<C>,
explicitReceiver: DetailedReceiver?
val scopeTower: ImplicitScopeTower,
val name: Name,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<C>,
explicitReceiver: DetailedReceiver?
) : AbstractInvokeTowerProcessor<C>(
factoryProviderForInvoke,
createVariableAndObjectProcessor(scopeTower, name, factoryProviderForInvoke.factoryForVariable(stripExplicitReceiver = false), explicitReceiver)
factoryProviderForInvoke,
createVariableAndObjectProcessor(
scopeTower,
name,
factoryProviderForInvoke.factoryForVariable(stripExplicitReceiver = false),
explicitReceiver
)
) {
// todo filter by operator
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C>? {
val (variableReceiver, invokeContext) = factoryProviderForInvoke.factoryForInvoke(variableCandidate, useExplicitReceiver = false)
?: return null
return ExplicitReceiverScopeTowerProcessor(scopeTower, invokeContext, variableReceiver) { getFunctions(OperatorNameConventions.INVOKE, it) }
?: return null
return ExplicitReceiverScopeTowerProcessor(
scopeTower,
invokeContext,
variableReceiver
) { getFunctions(OperatorNameConventions.INVOKE, it) }
}
override fun mayDataBeApplicable(data: TowerData) =
data == TowerData.Empty || data is TowerData.TowerLevel
data == TowerData.Empty || data is TowerData.TowerLevel
override fun recordLookups(skippedData: Collection<TowerData>, name: Name) {
variableProcessor.recordLookups(skippedData, name)
@@ -130,20 +138,25 @@ class InvokeTowerProcessor<C : Candidate>(
}
class InvokeExtensionTowerProcessor<C : Candidate>(
val scopeTower: ImplicitScopeTower,
val name: Name,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<C>,
private val explicitReceiver: ReceiverValueWithSmartCastInfo?
val scopeTower: ImplicitScopeTower,
val name: Name,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<C>,
private val explicitReceiver: ReceiverValueWithSmartCastInfo?
) : AbstractInvokeTowerProcessor<C>(
factoryProviderForInvoke,
createVariableAndObjectProcessor(scopeTower, name, factoryProviderForInvoke.factoryForVariable(stripExplicitReceiver = true), explicitReceiver = null)
factoryProviderForInvoke,
createVariableAndObjectProcessor(
scopeTower,
name,
factoryProviderForInvoke.factoryForVariable(stripExplicitReceiver = true),
explicitReceiver = null
)
) {
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C>? {
val (variableReceiver, invokeContext) = factoryProviderForInvoke.factoryForInvoke(variableCandidate, useExplicitReceiver = true)
?: return null
?: return null
val invokeDescriptor = scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
?: return null
?: return null
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
}
@@ -155,18 +168,30 @@ class InvokeExtensionTowerProcessor<C : Candidate>(
}
private class InvokeExtensionScopeTowerProcessor<C : Candidate>(
context: CandidateFactory<C>,
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver,
private val explicitReceiver: ReceiverValueWithSmartCastInfo?
context: CandidateFactory<C>,
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver,
private val explicitReceiver: ReceiverValueWithSmartCastInfo?
) : AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> {
if (explicitReceiver != null && data == TowerData.Empty) {
return listOf(candidateFactory.createCandidate(invokeCandidateDescriptor, ExplicitReceiverKind.BOTH_RECEIVERS, explicitReceiver))
return listOf(
candidateFactory.createCandidate(
invokeCandidateDescriptor,
ExplicitReceiverKind.BOTH_RECEIVERS,
explicitReceiver
)
)
}
if (explicitReceiver == null && data is TowerData.OnlyImplicitReceiver) {
return listOf(candidateFactory.createCandidate(invokeCandidateDescriptor, ExplicitReceiverKind.DISPATCH_RECEIVER, data.implicitReceiver))
return listOf(
candidateFactory.createCandidate(
invokeCandidateDescriptor,
ExplicitReceiverKind.DISPATCH_RECEIVER,
data.implicitReceiver
)
)
}
return emptyList()
@@ -178,7 +203,7 @@ private class InvokeExtensionScopeTowerProcessor<C : Candidate>(
// todo debug info
private fun ImplicitScopeTower.getExtensionInvokeCandidateDescriptor(
extensionFunctionReceiver: ReceiverValueWithSmartCastInfo
extensionFunctionReceiver: ReceiverValueWithSmartCastInfo
): CandidateWithBoundDispatchReceiver? {
val type = extensionFunctionReceiver.receiverValue.type
if (!type.isBuiltinExtensionFunctionalType) return null // todo: missing smart cast?
@@ -186,7 +211,7 @@ private fun ImplicitScopeTower.getExtensionInvokeCandidateDescriptor(
val invokeDescriptor = type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single()
val synthesizedInvokes = createSynthesizedInvokes(listOf(invokeDescriptor))
val synthesizedInvoke = synthesizedInvokes.singleOrNull()
?: error("No single synthesized invoke for $invokeDescriptor: $synthesizedInvokes")
?: error("No single synthesized invoke for $invokeDescriptor: $synthesizedInvokes")
// here we don't add SynthesizedDescriptor diagnostic because it should has priority as member
return CandidateWithBoundDispatchReceiverImpl(extensionFunctionReceiver, synthesizedInvoke, listOf())
@@ -194,31 +219,32 @@ private fun ImplicitScopeTower.getExtensionInvokeCandidateDescriptor(
// case 1.(foo())() or (foo())()
fun <C : Candidate> createCallTowerProcessorForExplicitInvoke(
scopeTower: ImplicitScopeTower,
functionContext: CandidateFactory<C>,
expressionForInvoke: ReceiverValueWithSmartCastInfo,
explicitReceiver: ReceiverValueWithSmartCastInfo?
scopeTower: ImplicitScopeTower,
functionContext: CandidateFactory<C>,
expressionForInvoke: ReceiverValueWithSmartCastInfo,
explicitReceiver: ReceiverValueWithSmartCastInfo?
): ScopeTowerProcessor<C> {
val invokeExtensionDescriptor = scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
if (explicitReceiver != null) {
return if (invokeExtensionDescriptor == null) {
// case 1.(foo())(), where foo() isn't extension function
KnownResultProcessor(emptyList())
}
else {
} else {
InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
}
}
else {
val usualInvoke = ExplicitReceiverScopeTowerProcessor(scopeTower, functionContext, expressionForInvoke) { getFunctions(OperatorNameConventions.INVOKE, it) } // todo operator
} else {
val usualInvoke = ExplicitReceiverScopeTowerProcessor(
scopeTower,
functionContext,
expressionForInvoke
) { getFunctions(OperatorNameConventions.INVOKE, it) } // todo operator
return if (invokeExtensionDescriptor == null) {
usualInvoke
}
else {
} else {
PrioritizedCompositeScopeTowerProcessor(
usualInvoke,
InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = null)
usualInvoke,
InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = null)
)
}
}
@@ -24,17 +24,16 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastI
class KnownResultProcessor<out C>(
val result: Collection<C>
): ScopeTowerProcessor<C> {
override fun process(data: TowerData)
= if (data == TowerData.Empty) listOfNotNull(result.takeIf { it.isNotEmpty() }) else emptyList()
val result: Collection<C>
) : ScopeTowerProcessor<C> {
override fun process(data: TowerData) = if (data == TowerData.Empty) listOfNotNull(result.takeIf { it.isNotEmpty() }) else emptyList()
override fun recordLookups(skippedData: Collection<TowerData>, name: Name) {}
}
// use this if processors priority is important
class PrioritizedCompositeScopeTowerProcessor<out C>(
vararg val processors: ScopeTowerProcessor<C>
vararg val processors: ScopeTowerProcessor<C>
) : ScopeTowerProcessor<C> {
override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) }
@@ -46,8 +45,8 @@ class PrioritizedCompositeScopeTowerProcessor<out C>(
// use this if all processors has same priority
class SamePriorityCompositeScopeTowerProcessor<out C>(
private vararg val processors: SimpleScopeTowerProcessor<C>
): SimpleScopeTowerProcessor<C> {
private vararg val processors: SimpleScopeTowerProcessor<C>
) : SimpleScopeTowerProcessor<C> {
override fun simpleProcess(data: TowerData): Collection<C> = processors.flatMap { it.simpleProcess(data) }
override fun recordLookups(skippedData: Collection<TowerData>, name: Name) {
processors.forEach { it.recordLookups(skippedData, name) }
@@ -55,19 +54,19 @@ class SamePriorityCompositeScopeTowerProcessor<out C>(
}
internal abstract class AbstractSimpleScopeTowerProcessor<C: Candidate>(
val candidateFactory: CandidateFactory<C>
internal abstract class AbstractSimpleScopeTowerProcessor<C : Candidate>(
val candidateFactory: CandidateFactory<C>
) : SimpleScopeTowerProcessor<C>
private typealias CandidatesCollector =
ScopeTowerLevel.(extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection<CandidateWithBoundDispatchReceiver>
ScopeTowerLevel.(extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection<CandidateWithBoundDispatchReceiver>
internal class ExplicitReceiverScopeTowerProcessor<C: Candidate>(
val scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
val explicitReceiver: ReceiverValueWithSmartCastInfo,
val collectCandidates: CandidatesCollector
): AbstractSimpleScopeTowerProcessor<C>(context) {
internal class ExplicitReceiverScopeTowerProcessor<C : Candidate>(
val scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
val explicitReceiver: ReceiverValueWithSmartCastInfo,
val collectCandidates: CandidatesCollector
) : AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> {
return when (data) {
TowerData.Empty -> resolveAsMember()
@@ -80,7 +79,13 @@ internal class ExplicitReceiverScopeTowerProcessor<C: Candidate>(
val members = mutableListOf<C>()
for (memberCandidate in MemberScopeTowerLevel(scopeTower, explicitReceiver).collectCandidates(null)) {
if (!memberCandidate.requiresExtensionReceiver) {
members.add(candidateFactory.createCandidate(memberCandidate, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null))
members.add(
candidateFactory.createCandidate(
memberCandidate,
ExplicitReceiverKind.DISPATCH_RECEIVER,
extensionReceiver = null
)
)
}
}
return members
@@ -90,7 +95,13 @@ internal class ExplicitReceiverScopeTowerProcessor<C: Candidate>(
val extensions = mutableListOf<C>()
for (extensionCandidate in level.collectCandidates(explicitReceiver)) {
if (extensionCandidate.requiresExtensionReceiver) {
extensions.add(candidateFactory.createCandidate(extensionCandidate, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver))
extensions.add(
candidateFactory.createCandidate(
extensionCandidate,
ExplicitReceiverKind.EXTENSION_RECEIVER,
extensionReceiver = explicitReceiver
)
)
}
}
return extensions
@@ -105,19 +116,25 @@ internal class ExplicitReceiverScopeTowerProcessor<C: Candidate>(
}
}
private class QualifierScopeTowerProcessor<C: Candidate>(
val scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
val qualifier: QualifierReceiver,
val collectCandidates: CandidatesCollector
): AbstractSimpleScopeTowerProcessor<C>(context) {
private class QualifierScopeTowerProcessor<C : Candidate>(
val scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
val qualifier: QualifierReceiver,
val collectCandidates: CandidatesCollector
) : AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> {
if (data != TowerData.Empty) return emptyList()
val staticMembers = mutableListOf<C>()
for (towerCandidate in QualifierScopeTowerLevel(scopeTower, qualifier).collectCandidates(null)) {
if (!towerCandidate.requiresExtensionReceiver) {
staticMembers.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null))
staticMembers.add(
candidateFactory.createCandidate(
towerCandidate,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
extensionReceiver = null
)
)
}
}
return staticMembers
@@ -127,32 +144,43 @@ private class QualifierScopeTowerProcessor<C: Candidate>(
override fun recordLookups(skippedData: Collection<TowerData>, name: Name) {}
}
private class NoExplicitReceiverScopeTowerProcessor<C: Candidate>(
context: CandidateFactory<C>,
val collectCandidates: CandidatesCollector
private class NoExplicitReceiverScopeTowerProcessor<C : Candidate>(
context: CandidateFactory<C>,
val collectCandidates: CandidatesCollector
) : AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C>
= when(data) {
is TowerData.TowerLevel -> {
val result = mutableListOf<C>()
for (towerCandidate in data.level.collectCandidates(null)) {
if (!towerCandidate.requiresExtensionReceiver) {
result.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null))
}
}
result
override fun simpleProcess(data: TowerData): Collection<C> = when (data) {
is TowerData.TowerLevel -> {
val result = mutableListOf<C>()
for (towerCandidate in data.level.collectCandidates(null)) {
if (!towerCandidate.requiresExtensionReceiver) {
result.add(
candidateFactory.createCandidate(
towerCandidate,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
extensionReceiver = null
)
)
}
is TowerData.BothTowerLevelAndImplicitReceiver -> {
val result = mutableListOf<C>()
for (towerCandidate in data.level.collectCandidates(data.implicitReceiver)) {
if (towerCandidate.requiresExtensionReceiver) {
result.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver))
}
}
result
}
else -> emptyList()
}
result
}
is TowerData.BothTowerLevelAndImplicitReceiver -> {
val result = mutableListOf<C>()
for (towerCandidate in data.level.collectCandidates(data.implicitReceiver)) {
if (towerCandidate.requiresExtensionReceiver) {
result.add(
candidateFactory.createCandidate(
towerCandidate,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
extensionReceiver = data.implicitReceiver
)
)
}
}
result
}
else -> emptyList()
}
override fun recordLookups(skippedData: Collection<TowerData>, name: Name) {
for (data in skippedData) {
@@ -166,73 +194,77 @@ private class NoExplicitReceiverScopeTowerProcessor<C: Candidate>(
}
private fun <C : Candidate> createSimpleProcessorWithoutClassValueReceiver(
scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?,
collectCandidates: CandidatesCollector
scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?,
collectCandidates: CandidatesCollector
): SimpleScopeTowerProcessor<C> =
when (explicitReceiver) {
is ReceiverValueWithSmartCastInfo -> ExplicitReceiverScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
is QualifierReceiver -> QualifierScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
else -> {
assert(explicitReceiver == null) {
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!::class.java.simpleName})"
}
NoExplicitReceiverScopeTowerProcessor(context, collectCandidates)
when (explicitReceiver) {
is ReceiverValueWithSmartCastInfo -> ExplicitReceiverScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
is QualifierReceiver -> QualifierScopeTowerProcessor(scopeTower, context, explicitReceiver, collectCandidates)
else -> {
assert(explicitReceiver == null) {
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!::class.java.simpleName})"
}
NoExplicitReceiverScopeTowerProcessor(context, collectCandidates)
}
}
private fun <C : Candidate> createSimpleProcessor(
scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?,
classValueReceiver: Boolean,
collectCandidates: CandidatesCollector
) : ScopeTowerProcessor<C> {
val withoutClassValueProcessor = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver, collectCandidates)
scopeTower: ImplicitScopeTower,
context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?,
classValueReceiver: Boolean,
collectCandidates: CandidatesCollector
): ScopeTowerProcessor<C> {
val withoutClassValueProcessor =
createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver, collectCandidates)
if (classValueReceiver && explicitReceiver is QualifierReceiver) {
val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return withoutClassValueProcessor
return PrioritizedCompositeScopeTowerProcessor(
withoutClassValueProcessor,
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
withoutClassValueProcessor,
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
)
}
return withoutClassValueProcessor
}
fun <C : Candidate> createCallableReferenceProcessor(
scopeTower: ImplicitScopeTower,
name: Name, context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?
scopeTower: ImplicitScopeTower,
name: Name, context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?
): SimpleScopeTowerProcessor<C> {
val variable = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getVariables(name, it) }
val function = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getFunctions(name, it) }
return SamePriorityCompositeScopeTowerProcessor(variable, function)
}
fun <C : Candidate> createVariableProcessor(scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
fun <C : Candidate> createVariableProcessor(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getVariables(name, it) }
fun <C : Candidate> createVariableAndObjectProcessor(scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
fun <C : Candidate> createVariableAndObjectProcessor(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = PrioritizedCompositeScopeTowerProcessor(
createVariableProcessor(scopeTower, name, context, explicitReceiver),
createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getObjects(name, it) }
createVariableProcessor(scopeTower, name, context, explicitReceiver),
createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getObjects(name, it) }
)
fun <C : Candidate> createSimpleFunctionProcessor(scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
fun <C : Candidate> createSimpleFunctionProcessor(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getFunctions(name, it) }
fun <С: Candidate> createFunctionProcessor(
scopeTower: ImplicitScopeTower,
name: Name,
simpleContext: CandidateFactory<С>,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<С>,
explicitReceiver: DetailedReceiver?
fun <С : Candidate> createFunctionProcessor(
scopeTower: ImplicitScopeTower,
name: Name,
simpleContext: CandidateFactory<С>,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<С>,
explicitReceiver: DetailedReceiver?
): PrioritizedCompositeScopeTowerProcessor<С> {
// a.foo() -- simple function call
@@ -250,15 +282,14 @@ fun <С: Candidate> createFunctionProcessor(
}
fun <C: Candidate> createProcessorWithReceiverValueOrEmpty(
explicitReceiver: DetailedReceiver?,
create: (ReceiverValueWithSmartCastInfo?) -> ScopeTowerProcessor<C>
fun <C : Candidate> createProcessorWithReceiverValueOrEmpty(
explicitReceiver: DetailedReceiver?,
create: (ReceiverValueWithSmartCastInfo?) -> ScopeTowerProcessor<C>
): ScopeTowerProcessor<C> {
return if (explicitReceiver is QualifierReceiver) {
explicitReceiver.classValueReceiverWithSmartCastInfo?.let(create)
?: KnownResultProcessor<C>(listOf())
}
else {
?: KnownResultProcessor<C>(listOf())
} else {
create(explicitReceiver as ReceiverValueWithSmartCastInfo?)
}
}
@@ -42,23 +42,22 @@ import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
internal abstract class AbstractScopeTowerLevel(
protected val scopeTower: ImplicitScopeTower
): ScopeTowerLevel {
protected val scopeTower: ImplicitScopeTower
) : ScopeTowerLevel {
protected val location: LookupLocation get() = scopeTower.location
protected fun createCandidateDescriptor(
descriptor: CallableDescriptor,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
specialError: ResolutionDiagnostic? = null,
dispatchReceiverSmartCastType: KotlinType? = null
descriptor: CallableDescriptor,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
specialError: ResolutionDiagnostic? = null,
dispatchReceiverSmartCastType: KotlinType? = null
): CandidateWithBoundDispatchReceiver {
val diagnostics = SmartList<ResolutionDiagnostic>()
diagnostics.addIfNotNull(specialError)
if (ErrorUtils.isError(descriptor)) {
diagnostics.add(ErrorDescriptorDiagnostic)
}
else {
} else {
if (descriptor.hasLowPriorityInOverloadResolution() || descriptor.isLowPriorityFromStdlibJre7Or8()) {
diagnostics.add(LowPriorityDescriptorDiagnostic)
}
@@ -67,9 +66,9 @@ internal abstract class AbstractScopeTowerLevel(
val shouldSkipVisibilityCheck = scopeTower.isDebuggerContext || scopeTower.isNewInferenceEnabled
if (!shouldSkipVisibilityCheck) {
Visibilities.findInvisibleMember(
getReceiverValueWithSmartCast(dispatchReceiver?.receiverValue, dispatchReceiverSmartCastType),
descriptor,
scopeTower.lexicalScope.ownerDescriptor
getReceiverValueWithSmartCast(dispatchReceiver?.receiverValue, dispatchReceiverSmartCastType),
descriptor,
scopeTower.lexicalScope.ownerDescriptor
)?.let { diagnostics.add(VisibilityError(it)) }
}
}
@@ -81,15 +80,15 @@ internal abstract class AbstractScopeTowerLevel(
// todo KT-9538 Unresolved inner class via subclass reference
// todo add static methods & fields with error
internal class MemberScopeTowerLevel(
scopeTower: ImplicitScopeTower,
val dispatchReceiver: ReceiverValueWithSmartCastInfo
): AbstractScopeTowerLevel(scopeTower) {
scopeTower: ImplicitScopeTower,
val dispatchReceiver: ReceiverValueWithSmartCastInfo
) : AbstractScopeTowerLevel(scopeTower) {
private val syntheticScopes = scopeTower.syntheticScopes
private val isNewInferenceEnabled = scopeTower.isNewInferenceEnabled
private fun collectMembers(
getMembers: ResolutionScope.(KotlinType?) -> Collection<CallableDescriptor>
getMembers: ResolutionScope.(KotlinType?) -> Collection<CallableDescriptor>
): Collection<CandidateWithBoundDispatchReceiver> {
val result = ArrayList<CandidateWithBoundDispatchReceiver>(0)
val receiverValue = dispatchReceiver.receiverValue
@@ -103,9 +102,9 @@ internal class MemberScopeTowerLevel(
for (possibleType in dispatchReceiver.possibleTypes) {
possibleType.memberScope.getMembers(possibleType).mapTo(unstableCandidates ?: result) {
createCandidateDescriptor(
it,
dispatchReceiver.smartCastReceiver(possibleType),
unstableError, dispatchReceiverSmartCastType = possibleType
it,
dispatchReceiver.smartCastReceiver(possibleType),
unstableError, dispatchReceiverSmartCastType = possibleType
)
}
}
@@ -113,8 +112,7 @@ internal class MemberScopeTowerLevel(
if (dispatchReceiver.possibleTypes.isNotEmpty()) {
if (unstableCandidates == null) {
result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor.approximateCapturedTypes() })
}
else {
} else {
result.addAll(unstableCandidates.selectMostSpecificInEachOverridableGroup { descriptor.approximateCapturedTypes() })
}
}
@@ -142,8 +140,14 @@ internal class MemberScopeTowerLevel(
override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = when (position) {
Variance.INVARIANT -> null
Variance.OUT_VARIANCE -> approximator.approximateToSuperType(topLevelType.unwrap(), TypeApproximatorConfiguration.CapturedTypesApproximation)
Variance.IN_VARIANCE -> approximator.approximateToSubType(topLevelType.unwrap(), TypeApproximatorConfiguration.CapturedTypesApproximation)
Variance.OUT_VARIANCE -> approximator.approximateToSuperType(
topLevelType.unwrap(),
TypeApproximatorConfiguration.CapturedTypesApproximation
)
Variance.IN_VARIANCE -> approximator.approximateToSubType(
topLevelType.unwrap(),
TypeApproximatorConfiguration.CapturedTypesApproximation
)
} ?: topLevelType
}
return substitute(TypeSubstitutor.create(wrappedSubstitution))
@@ -156,18 +160,27 @@ internal class MemberScopeTowerLevel(
return ReceiverValueWithSmartCastInfo(newReceiverValue, possibleTypes, isStable)
}
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver> {
override fun getVariables(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> {
return collectMembers { getContributedVariables(name, location) }
}
override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver> {
override fun getObjects(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> {
return emptyList()
}
override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver> {
override fun getFunctions(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> {
return collectMembers {
getContributedFunctions(name, location) + it.getInnerConstructors(name, location) +
syntheticScopes.collectSyntheticMemberFunctions(listOfNotNull(it), name, location)
syntheticScopes.collectSyntheticMemberFunctions(listOfNotNull(it), name, location)
}
}
@@ -179,71 +192,86 @@ internal class MemberScopeTowerLevel(
}
}
internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qualifier: QualifierReceiver) : AbstractScopeTowerLevel(scopeTower) {
internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qualifier: QualifierReceiver) :
AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
.getContributedVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
.getContributedVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
.getContributedObjectVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
.getContributedObjectVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
.getContributedFunctionsAndConstructors(name,
location,
scopeTower.syntheticScopes,
qualifier.staticScope).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
.getContributedFunctionsAndConstructors(
name,
location,
scopeTower.syntheticScopes,
qualifier.staticScope
).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun recordLookup(name: Name) {}
}
// KT-3335 Creating imported super class' inner class fails in codegen
internal open class ScopeBasedTowerLevel protected constructor(
scopeTower: ImplicitScopeTower,
private val resolutionScope: ResolutionScope
scopeTower: ImplicitScopeTower,
private val resolutionScope: ResolutionScope
) : AbstractScopeTowerLevel(scopeTower) {
internal constructor(scopeTower: ImplicitScopeTower, lexicalScope: LexicalScope) : this(scopeTower, lexicalScope as ResolutionScope)
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver>
= resolutionScope.getContributedVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getVariables(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver>
= resolutionScope.getContributedObjectVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getObjects(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedObjectVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver>
= resolutionScope.getContributedFunctionsAndConstructors(name,
location,
scopeTower.syntheticScopes,
resolutionScope).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getFunctions(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedFunctionsAndConstructors(
name,
location,
scopeTower.syntheticScopes,
resolutionScope
).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun recordLookup(name: Name) {
resolutionScope.recordLookup(name, location)
}
}
internal class ImportingScopeBasedTowerLevel(
scopeTower: ImplicitScopeTower,
importingScope: ImportingScope
): ScopeBasedTowerLevel(scopeTower, importingScope)
scopeTower: ImplicitScopeTower,
importingScope: ImportingScope
) : ScopeBasedTowerLevel(scopeTower, importingScope)
internal class SyntheticScopeBasedTowerLevel(
scopeTower: ImplicitScopeTower,
private val syntheticScopes: SyntheticScopes
): AbstractScopeTowerLevel(scopeTower) {
scopeTower: ImplicitScopeTower,
private val syntheticScopes: SyntheticScopes
) : AbstractScopeTowerLevel(scopeTower) {
private val ReceiverValueWithSmartCastInfo.allTypes: Set<KotlinType>
get() = possibleTypes + receiverValue.type
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver> {
override fun getVariables(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> {
if (extensionReceiver == null) return emptyList()
return syntheticScopes.collectSyntheticExtensionProperties(extensionReceiver.allTypes, name, location).map {
@@ -252,43 +280,43 @@ internal class SyntheticScopeBasedTowerLevel(
}
override fun getObjects(
name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?
name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> =
emptyList()
emptyList()
override fun getFunctions(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> =
emptyList()
emptyList()
override fun recordLookup(name: Name) {
}
}
internal class HidesMembersTowerLevel(scopeTower: ImplicitScopeTower): AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?)
= getCandidates(name, extensionReceiver, LexicalScope::collectVariables)
internal class HidesMembersTowerLevel(scopeTower: ImplicitScopeTower) : AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) =
getCandidates(name, extensionReceiver, LexicalScope::collectVariables)
override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?)
= emptyList<CandidateWithBoundDispatchReceiver>()
override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) =
emptyList<CandidateWithBoundDispatchReceiver>()
override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?)
= getCandidates(name, extensionReceiver, LexicalScope::collectFunctions)
override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) =
getCandidates(name, extensionReceiver, LexicalScope::collectFunctions)
private fun getCandidates(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?,
collectCandidates: LexicalScope.(Name, LookupLocation) -> Collection<CallableDescriptor>
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?,
collectCandidates: LexicalScope.(Name, LookupLocation) -> Collection<CallableDescriptor>
): Collection<CandidateWithBoundDispatchReceiver> {
if (extensionReceiver == null || name !in HIDES_MEMBERS_NAME_LIST) return emptyList()
return scopeTower.lexicalScope.collectCandidates(name, location).filter {
it.extensionReceiverParameter != null && it.hasHidesMembersAnnotation()
}.map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
createCandidateDescriptor(it, dispatchReceiver = null)
}
}
override fun recordLookup(name: Name) {}
@@ -309,10 +337,10 @@ private fun KotlinType?.getInnerConstructors(name: Name, location: LookupLocatio
}
private fun ResolutionScope.getContributedFunctionsAndConstructors(
name: Name,
location: LookupLocation,
syntheticScopes: SyntheticScopes,
scope: ResolutionScope
name: Name,
location: LookupLocation,
syntheticScopes: SyntheticScopes,
scope: ResolutionScope
): Collection<FunctionDescriptor> {
val result = ArrayList<FunctionDescriptor>(getContributedFunctions(name, location))
@@ -338,27 +366,27 @@ private fun ResolutionScope.getContributedObjectVariables(name: Name, location:
}
fun getFakeDescriptorForObject(classifier: ClassifierDescriptor?): FakeCallableDescriptorForObject? =
when (classifier) {
is TypeAliasDescriptor ->
classifier.classDescriptor?.let { classDescriptor ->
if (classDescriptor.hasClassValueDescriptor)
FakeCallableDescriptorForTypeAliasObject(classifier)
else
null
}
is ClassDescriptor ->
if (classifier.hasClassValueDescriptor)
FakeCallableDescriptorForObject(classifier)
when (classifier) {
is TypeAliasDescriptor ->
classifier.classDescriptor?.let { classDescriptor ->
if (classDescriptor.hasClassValueDescriptor)
FakeCallableDescriptorForTypeAliasObject(classifier)
else
null
else -> null
}
}
is ClassDescriptor ->
if (classifier.hasClassValueDescriptor)
FakeCallableDescriptorForObject(classifier)
else
null
else -> null
}
private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDescriptor? =
if (classifier !is ClassDescriptor || !classifier.canHaveCallableConstructors)
null
else
classifier
if (classifier !is ClassDescriptor || !classifier.canHaveCallableConstructors)
null
else
classifier
private val ClassDescriptor.canHaveCallableConstructors: Boolean
get() = !ErrorUtils.isError(this) && !kind.isSingleton
@@ -37,11 +37,11 @@ interface Candidate {
val resultingApplicability: ResolutionCandidateApplicability
}
interface CandidateFactory<out C: Candidate> {
interface CandidateFactory<out C : Candidate> {
fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValueWithSmartCastInfo?
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): C
}
@@ -59,7 +59,7 @@ interface CandidateFactoryProviderForInvoke<C : Candidate> {
sealed class TowerData {
object Empty : TowerData()
class OnlyImplicitReceiver(val implicitReceiver: ReceiverValueWithSmartCastInfo): TowerData()
class OnlyImplicitReceiver(val implicitReceiver: ReceiverValueWithSmartCastInfo) : TowerData()
class TowerLevel(val level: ScopeTowerLevel) : TowerData()
class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValueWithSmartCastInfo) : TowerData()
// Has the same meaning as BothTowerLevelAndImplicitReceiver, but it's only used for names lookup, so it doesn't need implicit receiver
@@ -81,41 +81,40 @@ interface SimpleScopeTowerProcessor<out C> : ScopeTowerProcessor<C> {
}
class TowerResolver {
fun <C: Candidate> runResolve(
scopeTower: ImplicitScopeTower,
processor: ScopeTowerProcessor<C>,
useOrder: Boolean,
name: Name
fun <C : Candidate> runResolve(
scopeTower: ImplicitScopeTower,
processor: ScopeTowerProcessor<C>,
useOrder: Boolean,
name: Name
): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector(), useOrder, name)
fun <C: Candidate> collectAllCandidates(
scopeTower: ImplicitScopeTower,
processor: ScopeTowerProcessor<C>,
name: Name
): Collection<C>
= scopeTower.run(processor, AllCandidatesCollector(), false, name)
fun <C : Candidate> collectAllCandidates(
scopeTower: ImplicitScopeTower,
processor: ScopeTowerProcessor<C>,
name: Name
): Collection<C> = scopeTower.run(processor, AllCandidatesCollector(), false, name)
fun <C : Candidate> ImplicitScopeTower.run(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean,
name: Name
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean,
name: Name
): Collection<C> = Task(this, processor, resultCollector, useOrder, name).run()
private inner class Task<out C : Candidate>(
private val implicitScopeTower: ImplicitScopeTower,
private val processor: ScopeTowerProcessor<C>,
private val resultCollector: ResultCollector<C>,
private val useOrder: Boolean,
private val name: Name
private val implicitScopeTower: ImplicitScopeTower,
private val processor: ScopeTowerProcessor<C>,
private val resultCollector: ResultCollector<C>,
private val useOrder: Boolean,
private val name: Name
) {
private val isNameForHidesMember = name in HIDES_MEMBERS_NAME_LIST
private val skippedDataForLookup = mutableListOf<TowerData>()
private val localLevels: Collection<ScopeTowerLevel> by lazy(LazyThreadSafetyMode.NONE) {
implicitScopeTower.lexicalScope.parentsWithSelf.
filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }.
map { ScopeBasedTowerLevel(implicitScopeTower, it) }.toList()
implicitScopeTower.lexicalScope.parentsWithSelf.filterIsInstance<LexicalScope>()
.filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }.map { ScopeBasedTowerLevel(implicitScopeTower, it) }
.toList()
}
private val nonLocalLevels: Collection<ScopeTowerLevel> by lazy(LazyThreadSafetyMode.NONE) {
@@ -131,8 +130,7 @@ class TowerResolver {
fun addLevel(scopeTowerLevel: ScopeTowerLevel, mayFitForName: Boolean) {
if (mayFitForName) {
mainResult.add(scopeTowerLevel)
}
else {
} else {
skippedDataForLookup.add(TowerData.ForLookupForNoExplicitReceiver(scopeTowerLevel))
}
}
@@ -141,22 +139,21 @@ class TowerResolver {
if (scope is LexicalScope) {
if (!scope.kind.withLocalDescriptors) {
addLevel(
ScopeBasedTowerLevel(this@createNonLocalLevels, scope),
scope.mayFitForName(name)
ScopeBasedTowerLevel(this@createNonLocalLevels, scope),
scope.mayFitForName(name)
)
}
getImplicitReceiver(scope)?.let {
addLevel(
MemberScopeTowerLevel(this@createNonLocalLevels, it),
it.mayFitForName(name)
MemberScopeTowerLevel(this@createNonLocalLevels, it),
it.mayFitForName(name)
)
}
}
else {
} else {
addLevel(
ImportingScopeBasedTowerLevel(this@createNonLocalLevels, scope as ImportingScope),
scope.mayFitForName(name)
ImportingScopeBasedTowerLevel(this@createNonLocalLevels, scope as ImportingScope),
scope.mayFitForName(name)
)
}
}
@@ -197,16 +194,15 @@ class TowerResolver {
// statics
if (!scope.kind.withLocalDescriptors) {
TowerData.TowerLevel(ScopeBasedTowerLevel(implicitScopeTower, scope))
.process(scope.mayFitForName(name))?.let { return it }
.process(scope.mayFitForName(name))?.let { return it }
}
implicitScopeTower.getImplicitReceiver(scope)
?.let(this::processImplicitReceiver)
?.let { return it }
}
else {
?.let(this::processImplicitReceiver)
?.let { return it }
} else {
TowerData.TowerLevel(ImportingScopeBasedTowerLevel(implicitScopeTower, scope as ImportingScope))
.process(scope.mayFitForName(name))?.let { return it }
.process(scope.mayFitForName(name))?.let { return it }
}
}
@@ -223,7 +219,7 @@ class TowerResolver {
// members of implicit receiver or member extension for explicit receiver
TowerData.TowerLevel(MemberScopeTowerLevel(implicitScopeTower, implicitReceiver))
.process(implicitReceiver.mayFitForName(name))?.let { return it }
.process(implicitReceiver.mayFitForName(name))?.let { return it }
// synthetic properties
TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver).process()?.let { return it }
@@ -255,32 +251,31 @@ class TowerResolver {
}
private fun KotlinType.mayFitForName(name: Name) =
isDynamic() ||
!memberScope.definitelyDoesNotContainName(name) ||
!memberScope.definitelyDoesNotContainName(OperatorNameConventions.INVOKE)
isDynamic() ||
!memberScope.definitelyDoesNotContainName(name) ||
!memberScope.definitelyDoesNotContainName(OperatorNameConventions.INVOKE)
private fun ResolutionScope.mayFitForName(name: Name) =
!definitelyDoesNotContainName(name) || !definitelyDoesNotContainName(OperatorNameConventions.INVOKE)
!definitelyDoesNotContainName(name) || !definitelyDoesNotContainName(OperatorNameConventions.INVOKE)
}
fun <C : Candidate> runWithEmptyTowerData(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean
): Collection<C> = processTowerData(processor, resultCollector, useOrder, TowerData.Empty) ?: resultCollector.getFinalCandidates()
private fun <C : Candidate> processTowerData(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean,
towerData: TowerData
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean,
towerData: TowerData
): Collection<C>? {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val candidatesGroups = if (useOrder) {
processor.process(towerData)
}
else {
} else {
listOf(processor.process(towerData).flatMap { it })
}
@@ -301,7 +296,7 @@ class TowerResolver {
abstract fun pushCandidates(candidates: Collection<C>)
}
class AllCandidatesCollector<C : Candidate>: ResultCollector<C>() {
class AllCandidatesCollector<C : Candidate> : ResultCollector<C>() {
private val allCandidates = ArrayList<C>()
override fun getSuccessfulCandidates(): Collection<C>? = null
@@ -352,7 +347,8 @@ class TowerResolver {
return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability }
}
private val Collection<C>.groupApplicability get() =
minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN
private val Collection<C>.groupApplicability
get() =
minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN
}
}
@@ -21,9 +21,10 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
private val INAPPLICABLE_STATUSES = setOf(
ResolutionCandidateApplicability.INAPPLICABLE,
ResolutionCandidateApplicability.INAPPLICABLE_ARGUMENTS_MAPPING_ERROR,
ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER)
ResolutionCandidateApplicability.INAPPLICABLE,
ResolutionCandidateApplicability.INAPPLICABLE_ARGUMENTS_MAPPING_ERROR,
ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
)
val ResolutionCandidateApplicability.isSuccess: Boolean
get() = this <= ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
@@ -38,9 +39,9 @@ val ResolutionCandidateApplicability.isInapplicable: Boolean
get() = this in INAPPLICABLE_STATUSES
internal class CandidateWithBoundDispatchReceiverImpl(
override val dispatchReceiver: ReceiverValueWithSmartCastInfo?,
override val descriptor: CallableDescriptor,
override val diagnostics: List<ResolutionDiagnostic>
override val dispatchReceiver: ReceiverValueWithSmartCastInfo?,
override val descriptor: CallableDescriptor,
override val diagnostics: List<ResolutionDiagnostic>
) : CandidateWithBoundDispatchReceiver
fun <C : Candidate> C.forceResolution(): C {
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor
import java.util.*
open class FakeCallableDescriptorForObject(
val classDescriptor: ClassDescriptor
val classDescriptor: ClassDescriptor
) : DeclarationDescriptorWithVisibility by classDescriptor.getClassObjectReferenceTarget(), VariableDescriptor {
init {
@@ -20,16 +20,15 @@ import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.impl.DescriptorDerivedFromTypeAlias
class FakeCallableDescriptorForTypeAliasObject(override val typeAliasDescriptor: TypeAliasDescriptor) :
FakeCallableDescriptorForObject(typeAliasDescriptor.classDescriptor!!),
DescriptorDerivedFromTypeAlias
{
FakeCallableDescriptorForObject(typeAliasDescriptor.classDescriptor!!),
DescriptorDerivedFromTypeAlias {
override fun getReferencedDescriptor() =
typeAliasDescriptor
typeAliasDescriptor
override fun equals(other: Any?): Boolean =
other is FakeCallableDescriptorForTypeAliasObject &&
typeAliasDescriptor == other.typeAliasDescriptor
other is FakeCallableDescriptorForTypeAliasObject &&
typeAliasDescriptor == other.typeAliasDescriptor
override fun hashCode(): Int =
typeAliasDescriptor.hashCode()
typeAliasDescriptor.hashCode()
}
@@ -28,16 +28,16 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjection
fun createValueParametersForInvokeInFunctionType(
functionDescriptor: FunctionDescriptor, parameterTypes: List<TypeProjection>
functionDescriptor: FunctionDescriptor, parameterTypes: List<TypeProjection>
): List<ValueParameterDescriptor> {
return parameterTypes.mapIndexed { i, typeProjection ->
ValueParameterDescriptorImpl(
functionDescriptor, null, i, Annotations.EMPTY,
Name.identifier("p${i + 1}"), typeProjection.type,
/* declaresDefaultValue = */ false,
/* isCrossinline = */ false,
/* isNoinline = */ false,
null, SourceElement.NO_SOURCE
functionDescriptor, null, i, Annotations.EMPTY,
Name.identifier("p${i + 1}"), typeProjection.type,
/* declaresDefaultValue = */ false,
/* isCrossinline = */ false,
/* isNoinline = */ false,
null, SourceElement.NO_SOURCE
)
}
}
@@ -46,10 +46,10 @@ fun CallableDescriptor.isLowPriorityFromStdlibJre7Or8(): Boolean {
if (!packageFqName.startsWith(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) return false
val isFromStdlibJre7Or8 =
packageFqName == kotlin && name == use ||
packageFqName == kotlinText && name == get ||
packageFqName == kotlinCollections && (name == getOrDefault || name == remove) ||
packageFqName == kotlinStreams
packageFqName == kotlin && name == use ||
packageFqName == kotlinText && name == get ||
packageFqName == kotlinCollections && (name == getOrDefault || name == remove) ||
packageFqName == kotlinStreams
if (!isFromStdlibJre7Or8) return false
@@ -26,31 +26,36 @@ import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes
import org.jetbrains.kotlin.utils.Printer
class LexicalChainedScope @JvmOverloads constructor(
parent: LexicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceiver: ReceiverParameterDescriptor?,
override val kind: LexicalScopeKind,
private val memberScopes: List<MemberScope>,
@Deprecated("This value is temporary hack for resolve -- don't use it!")
val isStaticScope: Boolean = false
): LexicalScope {
parent: LexicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceiver: ReceiverParameterDescriptor?,
override val kind: LexicalScopeKind,
private val memberScopes: List<MemberScope>,
@Deprecated("This value is temporary hack for resolve -- don't use it!")
val isStaticScope: Boolean = false
) : LexicalScope {
override val parent = parent.takeSnapshot()
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= getFromAllScopes(memberScopes) { it.getContributedDescriptors() }
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) =
getFromAllScopes(memberScopes) { it.getContributedDescriptors() }
override fun getContributedClassifier(name: Name, location: LookupLocation) = getFirstClassifierDiscriminateHeaders(memberScopes) { it.getContributedClassifier(name, location) }
override fun getContributedClassifier(name: Name, location: LookupLocation) =
getFirstClassifierDiscriminateHeaders(memberScopes) { it.getContributedClassifier(name, location) }
override fun getContributedVariables(name: Name, location: LookupLocation) = getFromAllScopes(memberScopes) { it.getContributedVariables(name, location) }
override fun getContributedVariables(name: Name, location: LookupLocation) =
getFromAllScopes(memberScopes) { it.getContributedVariables(name, location) }
override fun getContributedFunctions(name: Name, location: LookupLocation) = getFromAllScopes(memberScopes) { it.getContributedFunctions(name, location) }
override fun getContributedFunctions(name: Name, location: LookupLocation) =
getFromAllScopes(memberScopes) { it.getContributedFunctions(name, location) }
override fun toString(): String = kind.toString()
override fun printStructure(p: Printer) {
p.println(this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {")
p.println(
this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {"
)
p.pushIndent()
for (scope in memberScopes) {
@@ -20,14 +20,14 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.utils.Printer
class LexicalScopeImpl @JvmOverloads constructor(
parent: HierarchicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceiver: ReceiverParameterDescriptor?,
override val kind: LexicalScopeKind,
redeclarationChecker: LocalRedeclarationChecker = LocalRedeclarationChecker.DO_NOTHING,
initialize: LexicalScopeImpl.InitializeHandler.() -> Unit = {}
): LexicalScope, LexicalScopeStorage(parent, redeclarationChecker) {
parent: HierarchicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceiver: ReceiverParameterDescriptor?,
override val kind: LexicalScopeKind,
redeclarationChecker: LocalRedeclarationChecker = LocalRedeclarationChecker.DO_NOTHING,
initialize: LexicalScopeImpl.InitializeHandler.() -> Unit = {}
) : LexicalScope, LexicalScopeStorage(parent, redeclarationChecker) {
init {
InitializeHandler().initialize()
@@ -36,8 +36,10 @@ class LexicalScopeImpl @JvmOverloads constructor(
override fun toString(): String = kind.toString()
override fun printStructure(p: Printer) {
p.println(this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {")
p.println(
this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {"
)
p.pushIndent()
p.print("parent = ")
@@ -49,14 +51,14 @@ class LexicalScopeImpl @JvmOverloads constructor(
inner class InitializeHandler() {
fun addVariableDescriptor(variableDescriptor: VariableDescriptor): Unit
= this@LexicalScopeImpl.addVariableOrClassDescriptor(variableDescriptor)
fun addVariableDescriptor(variableDescriptor: VariableDescriptor): Unit =
this@LexicalScopeImpl.addVariableOrClassDescriptor(variableDescriptor)
fun addFunctionDescriptor(functionDescriptor: FunctionDescriptor): Unit
= this@LexicalScopeImpl.addFunctionDescriptorInternal(functionDescriptor)
fun addFunctionDescriptor(functionDescriptor: FunctionDescriptor): Unit =
this@LexicalScopeImpl.addFunctionDescriptorInternal(functionDescriptor)
fun addClassifierDescriptor(classifierDescriptor: ClassifierDescriptor): Unit
= this@LexicalScopeImpl.addVariableOrClassDescriptor(classifierDescriptor)
fun addClassifierDescriptor(classifierDescriptor: ClassifierDescriptor): Unit =
this@LexicalScopeImpl.addVariableOrClassDescriptor(classifierDescriptor)
}
}
@@ -35,9 +35,9 @@ interface LocalRedeclarationChecker {
}
abstract class LexicalScopeStorage(
parent: HierarchicalScope,
val redeclarationChecker: LocalRedeclarationChecker
): LexicalScope {
parent: HierarchicalScope,
val redeclarationChecker: LocalRedeclarationChecker
) : LexicalScope {
override val parent = parent.takeSnapshot()
protected val addedDescriptors: MutableList<DeclarationDescriptor> = SmartList()
@@ -45,13 +45,15 @@ abstract class LexicalScopeStorage(
private var functionsByName: MutableMap<Name, IntList>? = null
private var variablesAndClassifiersByName: MutableMap<Name, IntList>? = null
override fun getContributedClassifier(name: Name, location: LookupLocation) = variableOrClassDescriptorByName(name) as? ClassifierDescriptor
override fun getContributedVariables(name: Name, location: LookupLocation) = listOfNotNull(variableOrClassDescriptorByName(name) as? VariableDescriptor)
override fun getContributedClassifier(name: Name, location: LookupLocation) =
variableOrClassDescriptorByName(name) as? ClassifierDescriptor
override fun getContributedVariables(name: Name, location: LookupLocation) =
listOfNotNull(variableOrClassDescriptorByName(name) as? VariableDescriptor)
override fun getContributedFunctions(name: Name, location: LookupLocation) = functionsByName(name)
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= addedDescriptors
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = addedDescriptors
protected fun addVariableOrClassDescriptor(descriptor: DeclarationDescriptor) {
val name = descriptor.name
@@ -115,7 +117,7 @@ abstract class LexicalScopeStorage(
private operator fun IntList?.plus(value: Int) = IntList(value, this)
private fun <TDescriptor: DeclarationDescriptor> IntList.toDescriptors(): List<TDescriptor> {
private fun <TDescriptor : DeclarationDescriptor> IntList.toDescriptors(): List<TDescriptor> {
val result = ArrayList<TDescriptor>(1)
var rest: IntList? = this
do {
@@ -126,5 +128,5 @@ abstract class LexicalScopeStorage(
}
override fun definitelyDoesNotContainName(name: Name) =
functionsByName?.get(name) == null && variablesAndClassifiersByName?.get(name) == null
functionsByName?.get(name) == null && variablesAndClassifiersByName?.get(name) == null
}
@@ -22,11 +22,11 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.Printer
class LexicalWritableScope(
parent: LexicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
redeclarationChecker: LocalRedeclarationChecker,
override val kind: LexicalScopeKind
parent: LexicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
redeclarationChecker: LocalRedeclarationChecker,
override val kind: LexicalScopeKind
) : LexicalScopeStorage(parent, redeclarationChecker) {
override val implicitReceiver: ReceiverParameterDescriptor?
@@ -68,11 +68,14 @@ class LexicalWritableScope(
}
private inner class Snapshot(val descriptorLimit: Int) : LexicalScope by this {
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= addedDescriptors.subList(0, descriptorLimit)
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) =
addedDescriptors.subList(0, descriptorLimit)
override fun getContributedClassifier(name: Name, location: LookupLocation) = variableOrClassDescriptorByName(name, descriptorLimit) as? ClassifierDescriptor
override fun getContributedVariables(name: Name, location: LookupLocation) = listOfNotNull(variableOrClassDescriptorByName(name, descriptorLimit) as? VariableDescriptor)
override fun getContributedClassifier(name: Name, location: LookupLocation) =
variableOrClassDescriptorByName(name, descriptorLimit) as? ClassifierDescriptor
override fun getContributedVariables(name: Name, location: LookupLocation) =
listOfNotNull(variableOrClassDescriptorByName(name, descriptorLimit) as? VariableDescriptor)
override fun getContributedFunctions(name: Name, location: LookupLocation) = functionsByName(name, descriptorLimit)
@@ -88,8 +91,10 @@ class LexicalWritableScope(
override fun toString(): String = kind.toString()
override fun printStructure(p: Printer) {
p.println(this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {")
p.println(
this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {"
)
p.pushIndent()
p.print("parent = ")
@@ -40,8 +40,8 @@ interface LexicalScope : HierarchicalScope {
val kind: LexicalScopeKind
class Base(
parent: HierarchicalScope,
override val ownerDescriptor: DeclarationDescriptor
parent: HierarchicalScope,
override val ownerDescriptor: DeclarationDescriptor
) : BaseHierarchicalScope(parent), LexicalScope {
override val parent: HierarchicalScope
get() = super.parent!!
@@ -112,12 +112,15 @@ interface ImportingScope : HierarchicalScope {
fun getContributedPackage(name: Name): PackageViewDescriptor?
fun getContributedDescriptors(
kindFilter: DescriptorKindFilter = DescriptorKindFilter.ALL,
nameFilter: (Name) -> Boolean = MemberScope.ALL_NAME_FILTER,
changeNamesForAliased: Boolean
kindFilter: DescriptorKindFilter = DescriptorKindFilter.ALL,
nameFilter: (Name) -> Boolean = MemberScope.ALL_NAME_FILTER,
changeNamesForAliased: Boolean
): Collection<DeclarationDescriptor>
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
return getContributedDescriptors(kindFilter, nameFilter, changeNamesForAliased = false)
}
@@ -135,7 +138,10 @@ interface ImportingScope : HierarchicalScope {
}
abstract class BaseHierarchicalScope(override val parent: HierarchicalScope?) : HierarchicalScope {
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> = emptyList()
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> = emptyList()
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null
@@ -150,10 +156,16 @@ abstract class BaseImportingScope(parent: ImportingScope?) : BaseHierarchicalSco
override fun getContributedPackage(name: Name): PackageViewDescriptor? = null
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
return getContributedDescriptors(kindFilter, nameFilter, changeNamesForAliased = false)
}
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, changeNamesForAliased: Boolean): Collection<DeclarationDescriptor>
= emptyList()
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
changeNamesForAliased: Boolean
): Collection<DeclarationDescriptor> = emptyList()
}
@@ -27,9 +27,9 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.Printer
class SubpackagesImportingScope(
override val parent: ImportingScope?,
moduleDescriptor: ModuleDescriptor,
fqName: FqName
override val parent: ImportingScope?,
moduleDescriptor: ModuleDescriptor,
fqName: FqName
) : SubpackagesScope(moduleDescriptor, fqName), ImportingScope by ImportingScope.Empty {
override fun getContributedPackage(name: Name): PackageViewDescriptor? = getPackage(name)
@@ -42,11 +42,18 @@ class SubpackagesImportingScope(
//TODO: kept old behavior, but it seems very strange (super call seems more applicable)
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> =
emptyList()
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> =
emptyList()
//TODO: kept old behavior, but it seems very strange (super call seems more applicable)
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, changeNamesForAliased: Boolean): Collection<DeclarationDescriptor>
= emptyList()
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
changeNamesForAliased: Boolean
): Collection<DeclarationDescriptor> = emptyList()
override fun computeImportedNames() = emptySet<Name>()
}
@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.types.checker.prepareArgumentTypeRegardingCaptureTyp
interface DetailedReceiver
class ReceiverValueWithSmartCastInfo(
val receiverValue: ReceiverValue,
val possibleTypes: Set<KotlinType>, // doesn't include receiver.type
val isStable: Boolean
): DetailedReceiver {
val receiverValue: ReceiverValue,
val possibleTypes: Set<KotlinType>, // doesn't include receiver.type
val isStable: Boolean
) : DetailedReceiver {
override fun toString() = receiverValue.toString()
}
@@ -42,17 +42,16 @@ fun LexicalScope.getImplicitReceiversHierarchy(): List<ReceiverParameterDescript
fun LexicalScope.getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = collectAllFromMeAndParent {
if (it is LexicalScope && it.isOwnerDescriptorAccessibleByLabel && it.ownerDescriptor.name == labelName) {
listOf(it.ownerDescriptor)
}
else {
} else {
listOf()
}
}
// Result is guaranteed to be filtered by kind and name.
fun HierarchicalScope.collectDescriptorsFiltered(
kindFilter: DescriptorKindFilter = DescriptorKindFilter.ALL,
nameFilter: (Name) -> Boolean = { true },
changeNamesForAliased: Boolean = false
kindFilter: DescriptorKindFilter = DescriptorKindFilter.ALL,
nameFilter: (Name) -> Boolean = { true },
changeNamesForAliased: Boolean = false
): Collection<DeclarationDescriptor> {
if (kindFilter.kindMask == 0) return listOf()
return collectAllFromMeAndParent {
@@ -63,38 +62,49 @@ fun HierarchicalScope.collectDescriptorsFiltered(
}.filter { kindFilter.accepts(it) && nameFilter(it.name) }
}
@Deprecated("Use getContributedProperties instead") fun LexicalScope.findLocalVariable(name: Name): VariableDescriptor? {
@Deprecated("Use getContributedProperties instead")
fun LexicalScope.findLocalVariable(name: Name): VariableDescriptor? {
return findFirstFromMeAndParent {
when {
it is LexicalScopeWrapper -> it.delegate.findLocalVariable(name)
it !is ImportingScope && it !is LexicalChainedScope -> it.getContributedVariables(name, NoLookupLocation.WHEN_GET_LOCAL_VARIABLE).singleOrNull() /* todo check this*/
it !is ImportingScope && it !is LexicalChainedScope -> it.getContributedVariables(
name,
NoLookupLocation.WHEN_GET_LOCAL_VARIABLE
).singleOrNull() /* todo check this*/
else -> null
}
}
}
fun HierarchicalScope.findClassifier(name: Name, location: LookupLocation): ClassifierDescriptor?
= findFirstFromMeAndParent { it.getContributedClassifier(name, location) }
fun HierarchicalScope.findClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? =
findFirstFromMeAndParent { it.getContributedClassifier(name, location) }
fun HierarchicalScope.findPackage(name: Name): PackageViewDescriptor?
= findFirstFromImportingScopes { it.getContributedPackage(name) }
fun HierarchicalScope.findPackage(name: Name): PackageViewDescriptor? = findFirstFromImportingScopes { it.getContributedPackage(name) }
fun HierarchicalScope.collectVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor>
= collectAllFromMeAndParent { it.getContributedVariables(name, location) }
fun HierarchicalScope.collectVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> =
collectAllFromMeAndParent { it.getContributedVariables(name, location) }
fun HierarchicalScope.collectFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor>
= collectAllFromMeAndParent { it.getContributedFunctions(name, location) }
fun HierarchicalScope.collectFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> =
collectAllFromMeAndParent { it.getContributedFunctions(name, location) }
fun HierarchicalScope.findVariable(name: Name, location: LookupLocation, predicate: (VariableDescriptor) -> Boolean = { true }): VariableDescriptor? {
fun HierarchicalScope.findVariable(
name: Name,
location: LookupLocation,
predicate: (VariableDescriptor) -> Boolean = { true }
): VariableDescriptor? {
processForMeAndParent {
it.getContributedVariables(name, location).firstOrNull(predicate)?.let { return it }
}
return null
}
fun HierarchicalScope.findFunction(name: Name, location: LookupLocation, predicate: (FunctionDescriptor) -> Boolean = { true }): FunctionDescriptor? {
fun HierarchicalScope.findFunction(
name: Name,
location: LookupLocation,
predicate: (FunctionDescriptor) -> Boolean = { true }
): FunctionDescriptor? {
processForMeAndParent {
it.getContributedFunctions(name, location).firstOrNull(predicate)?.let { return it }
}
@@ -103,13 +113,18 @@ fun HierarchicalScope.findFunction(name: Name, location: LookupLocation, predica
fun HierarchicalScope.takeSnapshot(): HierarchicalScope = if (this is LexicalWritableScope) takeSnapshot() else this
@JvmOverloads fun MemberScope.memberScopeAsImportingScope(parentScope: ImportingScope? = null): ImportingScope = MemberScopeToImportingScopeAdapter(parentScope, this)
@JvmOverloads
fun MemberScope.memberScopeAsImportingScope(parentScope: ImportingScope? = null): ImportingScope =
MemberScopeToImportingScopeAdapter(parentScope, this)
private class MemberScopeToImportingScopeAdapter(override val parent: ImportingScope?, val memberScope: MemberScope) : ImportingScope {
override fun getContributedPackage(name: Name): PackageViewDescriptor? = null
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, changeNamesForAliased: Boolean)
= memberScope.getContributedDescriptors(kindFilter, nameFilter)
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
changeNamesForAliased: Boolean
) = memberScope.getContributedDescriptors(kindFilter, nameFilter)
override fun getContributedClassifier(name: Name, location: LookupLocation) = memberScope.getContributedClassifier(name, location)
@@ -144,8 +159,8 @@ inline fun HierarchicalScope.processForMeAndParent(process: (HierarchicalScope)
}
}
private inline fun <T: Any> HierarchicalScope.collectFromMeAndParent(
collect: (HierarchicalScope) -> T?
private inline fun <T : Any> HierarchicalScope.collectFromMeAndParent(
collect: (HierarchicalScope) -> T?
): List<T> {
var result: MutableList<T>? = null
processForMeAndParent {
@@ -160,26 +175,26 @@ private inline fun <T: Any> HierarchicalScope.collectFromMeAndParent(
return result ?: emptyList()
}
inline fun <T: Any> HierarchicalScope.collectAllFromMeAndParent(
collect: (HierarchicalScope) -> Collection<T>
inline fun <T : Any> HierarchicalScope.collectAllFromMeAndParent(
collect: (HierarchicalScope) -> Collection<T>
): Collection<T> {
var result: Collection<T>? = null
processForMeAndParent { result = result.concat(collect(it)) }
return result ?: emptySet()
}
inline fun <T: Any> HierarchicalScope.findFirstFromMeAndParent(fetch: (HierarchicalScope) -> T?): T? {
inline fun <T : Any> HierarchicalScope.findFirstFromMeAndParent(fetch: (HierarchicalScope) -> T?): T? {
processForMeAndParent { fetch(it)?.let { return it } }
return null
}
inline fun <T: Any> HierarchicalScope.collectAllFromImportingScopes(
collect: (ImportingScope) -> Collection<T>
inline fun <T : Any> HierarchicalScope.collectAllFromImportingScopes(
collect: (ImportingScope) -> Collection<T>
): Collection<T> {
return collectAllFromMeAndParent { if (it is ImportingScope) collect(it) else emptyList() }
}
inline fun <T: Any> HierarchicalScope.findFirstFromImportingScopes(fetch: (ImportingScope) -> T?): T? {
inline fun <T : Any> HierarchicalScope.findFirstFromImportingScopes(fetch: (ImportingScope) -> T?): T? {
return findFirstFromMeAndParent { if (it is ImportingScope) fetch(it) else null }
}
@@ -190,11 +205,10 @@ fun LexicalScope.addImportingScopes(importScopes: List<ImportingScope>): Lexical
return replaceImportingScopes(newFirstImporting)
}
fun LexicalScope.addImportingScope(importScope: ImportingScope): LexicalScope
= addImportingScopes(listOf(importScope))
fun LexicalScope.addImportingScope(importScope: ImportingScope): LexicalScope = addImportingScopes(listOf(importScope))
fun ImportingScope.withParent(newParent: ImportingScope?): ImportingScope {
return object: ImportingScope by this {
return object : ImportingScope by this {
override val parent: ImportingScope?
get() = newParent
}
@@ -210,13 +224,13 @@ fun LexicalScope.replaceImportingScopes(importingScopeChain: ImportingScope?): L
fun LexicalScope.createScopeForDestructuring(newReceiver: ReceiverParameterDescriptor?): LexicalScope {
return LexicalScopeImpl(
parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel,
newReceiver,
LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING
parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel,
newReceiver,
LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING
)
}
private class LexicalScopeWrapper(val delegate: LexicalScope, val newImportingScopeChain: ImportingScope): LexicalScope by delegate {
private class LexicalScopeWrapper(val delegate: LexicalScope, val newImportingScopeChain: ImportingScope) : LexicalScope by delegate {
init {
assert(delegate !is LexicalScopeWrapper) {
"Do not wrap again to avoid performance issues"
@@ -229,8 +243,7 @@ private class LexicalScopeWrapper(val delegate: LexicalScope, val newImportingSc
val parent = delegate.parent
if (parent is LexicalScope) {
parent.replaceImportingScopes(newImportingScopeChain)
}
else {
} else {
newImportingScopeChain
}
}
@@ -240,10 +253,10 @@ private class LexicalScopeWrapper(val delegate: LexicalScope, val newImportingSc
fun chainImportingScopes(scopes: List<ImportingScope>, tail: ImportingScope? = null): ImportingScope? {
return scopes.asReversed()
.fold(tail) { current, scope ->
assert(scope.parent == null)
scope.withParent(current)
}
.fold(tail) { current, scope ->
assert(scope.parent == null)
scope.withParent(current)
}
}
class ErrorLexicalScope : LexicalScope {
@@ -260,7 +273,10 @@ class ErrorLexicalScope : LexicalScope {
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> = emptySet()
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> = emptySet()
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> = emptySet()
}
override fun printStructure(p: Printer) {
@@ -278,5 +294,8 @@ class ErrorLexicalScope : LexicalScope {
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> = emptySet()
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> = emptySet()
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> = emptySet()
}
@@ -30,12 +30,12 @@ val SINCE_KOTLIN_FQ_NAME = FqName("kotlin.SinceKotlin")
* callback is called with the version specified in the [SinceKotlin] annotation if the descriptor is inaccessible.
*/
fun DeclarationDescriptor.checkSinceKotlinVersionAccessibility(
languageVersionSettings: LanguageVersionSettings,
actionIfInaccessible: ((ApiVersion) -> Unit)? = null
languageVersionSettings: LanguageVersionSettings,
actionIfInaccessible: ((ApiVersion) -> Unit)? = null
): Boolean {
val version =
if (this is CallableMemberDescriptor && !kind.isReal) getSinceKotlinVersionByOverridden(this)
else getOwnSinceKotlinVersion()
if (this is CallableMemberDescriptor && !kind.isReal) getSinceKotlinVersionByOverridden(this)
else getOwnSinceKotlinVersion()
// Allow access in the following cases:
// 1) There's no @SinceKotlin annotation for this descriptor
@@ -59,16 +59,15 @@ private fun getSinceKotlinVersionByOverridden(descriptor: CallableMemberDescript
private fun DeclarationDescriptor.getOwnSinceKotlinVersion(): ApiVersion? {
// TODO: use-site targeted annotations
fun DeclarationDescriptor.loadAnnotationValue(): ApiVersion? =
(annotations.findAnnotation(SINCE_KOTLIN_FQ_NAME)?.allValueArguments?.values?.singleOrNull()?.value as? String)
?.let(ApiVersion.Companion::parse)
(annotations.findAnnotation(SINCE_KOTLIN_FQ_NAME)?.allValueArguments?.values?.singleOrNull()?.value as? String)
?.let(ApiVersion.Companion::parse)
val ownVersion = loadAnnotationValue()
val ctorClass = (this as? ConstructorDescriptor)?.containingDeclaration?.loadAnnotationValue()
val property = (this as? PropertyAccessorDescriptor)?.correspondingProperty?.loadAnnotationValue()
val typeAliasDescriptor = (this as? TypeAliasDescriptor) ?:
(this as? TypeAliasConstructorDescriptor)?.typeAliasDescriptor ?:
(this as? FakeCallableDescriptorForTypeAliasObject)?.typeAliasDescriptor
val typeAliasDescriptor = (this as? TypeAliasDescriptor) ?: (this as? TypeAliasConstructorDescriptor)?.typeAliasDescriptor
?: (this as? FakeCallableDescriptorForTypeAliasObject)?.typeAliasDescriptor
val typeAlias = typeAliasDescriptor?.loadAnnotationValue()
@@ -35,6 +35,7 @@ open class TypeApproximatorConfiguration {
TO_FIRST,
TO_COMMON_SUPERTYPE
}
open val flexible get() = false // simple flexible types (FlexibleTypeImpl)
open val dynamic get() = false // DynamicType
open val rawType get() = false // RawTypeImpl
@@ -65,7 +66,8 @@ open class TypeApproximatorConfiguration {
override val definitelyNotNullType get() = false
}
abstract class AbstractCapturedTypesApproximation(val approximatedCapturedStatus: CaptureStatus): TypeApproximatorConfiguration.AllFlexibleSameValue() {
abstract class AbstractCapturedTypesApproximation(val approximatedCapturedStatus: CaptureStatus) :
TypeApproximatorConfiguration.AllFlexibleSameValue() {
override val allFlexible get() = true
override val errorType get() = true
@@ -94,39 +96,42 @@ class TypeApproximator {
// null means that this input type is the result, i.e. input type not contains not-allowed kind of types
// type <: resultType
fun approximateToSuperType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
approximateToSuperType(type, conf, - type.typeDepth())
approximateToSuperType(type, conf, -type.typeDepth())
// resultType <: type
fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
approximateToSubType(type, conf, - type.typeDepth())
approximateToSubType(type, conf, -type.typeDepth())
private fun approximateToSuperType(type: UnwrappedType, conf: TypeApproximatorConfiguration, depth: Int): UnwrappedType? {
if (type is TypeUtils.SpecialType) return null
return approximateTo(NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::upperBound,
referenceApproximateToSuperType, depth)
return approximateTo(
NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::upperBound,
referenceApproximateToSuperType, depth
)
}
private fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration, depth: Int): UnwrappedType? {
if (type is TypeUtils.SpecialType) return null
return approximateTo(NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::lowerBound,
referenceApproximateToSubType, depth)
return approximateTo(
NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::lowerBound,
referenceApproximateToSubType, depth
)
}
// comments for case bound = upperBound, approximateTo = toSuperType
private fun approximateTo(
type: UnwrappedType,
conf: TypeApproximatorConfiguration,
bound: FlexibleType.() -> SimpleType,
approximateTo: (SimpleType, TypeApproximatorConfiguration, depth: Int) -> UnwrappedType?,
depth: Int
type: UnwrappedType,
conf: TypeApproximatorConfiguration,
bound: FlexibleType.() -> SimpleType,
approximateTo: (SimpleType, TypeApproximatorConfiguration, depth: Int) -> UnwrappedType?,
depth: Int
): UnwrappedType? {
when (type) {
is SimpleType -> return approximateTo(type, conf, depth)
is FlexibleType -> {
if (type is DynamicType) {
return if (conf.dynamic) null else type.bound()
}
else if (type is RawType) {
} else if (type is RawType) {
return if (conf.rawType) null else type.bound()
}
@@ -157,17 +162,23 @@ class TypeApproximator {
*
* If U_1 <: U_2.lower .. U_2.upper, then we know only that U_1 <: U_2.upper.
*/
return KotlinTypeFactory.flexibleType(lowerResult?.lowerIfFlexible() ?: type.lowerBound,
upperResult?.upperIfFlexible() ?: type.upperBound)
}
else {
return KotlinTypeFactory.flexibleType(
lowerResult?.lowerIfFlexible() ?: type.lowerBound,
upperResult?.upperIfFlexible() ?: type.upperBound
)
} else {
return type.bound().let { approximateTo(it, conf, depth) ?: it }
}
}
}
}
private fun approximateIntersectionType(type: SimpleType, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int): UnwrappedType? {
private fun approximateIntersectionType(
type: SimpleType,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): UnwrappedType? {
val typeConstructor = type.constructor
assert(typeConstructor is IntersectionTypeConstructor) {
"Should be intersection type: $type, typeConstructor class: ${typeConstructor::class.java.canonicalName}"
@@ -194,35 +205,42 @@ class TypeApproximator {
val baseResult = when (conf.intersection) {
ALLOWED -> if (!thereIsApproximation) return null else intersectTypes(newTypes)
TO_FIRST -> if (toSuper) newTypes.first() else return type.defaultResult(toSuper = false)
// commonSupertypeCalculator should handle flexible types correctly
TO_COMMON_SUPERTYPE -> if (toSuper) NewCommonSuperTypeCalculator.commonSuperType(newTypes) else return type.defaultResult(toSuper = false)
// commonSupertypeCalculator should handle flexible types correctly
TO_COMMON_SUPERTYPE -> if (toSuper) NewCommonSuperTypeCalculator.commonSuperType(newTypes) else return type.defaultResult(
toSuper = false
)
}
return if (type.isMarkedNullable) baseResult.makeNullableAsSpecified(true) else baseResult
}
private fun approximateCapturedType(type: NewCapturedType, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int): UnwrappedType? {
private fun approximateCapturedType(
type: NewCapturedType,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): UnwrappedType? {
val supertypes = type.constructor.supertypes
val baseSuperType = when (supertypes.size) {
0 -> type.builtIns.nullableAnyType // Let C = in Int, then superType for C and C? is Any?
1 -> supertypes.single()
// Consider the following example:
// A.getA()::class.java, where `getA()` returns some class from Java
// From `::class` we are getting type KClass<Cap<out A!>>, where Cap<out A!> have two supertypes:
// - Any (from declared upper bound of type parameter for KClass)
// - (A..A?) -- from A!, projection type of captured type
// Consider the following example:
// A.getA()::class.java, where `getA()` returns some class from Java
// From `::class` we are getting type KClass<Cap<out A!>>, where Cap<out A!> have two supertypes:
// - Any (from declared upper bound of type parameter for KClass)
// - (A..A?) -- from A!, projection type of captured type
// Now, after approximation we were getting type `KClass<out A>`, because { Any & (A..A?) } = A,
// but in old inference type was equal to `KClass<out A!>`.
// Now, after approximation we were getting type `KClass<out A>`, because { Any & (A..A?) } = A,
// but in old inference type was equal to `KClass<out A!>`.
// Important note that from the point of type system first type is more specific:
// Here, approximation of KClass<Cap<out A!>> is a type KClass<T> such that KClass<Cap<out A!>> <: KClass<out T> =>
// So, the the more specific type for T would be "some non-null (because of declared upper bound type) subtype of A", which is `out A`
// Important note that from the point of type system first type is more specific:
// Here, approximation of KClass<Cap<out A!>> is a type KClass<T> such that KClass<Cap<out A!>> <: KClass<out T> =>
// So, the the more specific type for T would be "some non-null (because of declared upper bound type) subtype of A", which is `out A`
// But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass<out A!>`
// But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass<out A!>`
// Once NI will be more stabilized, we'll use more specific type
// Once NI will be more stabilized, we'll use more specific type
else -> type.constructor.projection.type.unwrap()
}
@@ -241,7 +259,11 @@ class TypeApproximator {
return null
}
}
val baseResult = if (toSuper) approximateToSuperType(baseSuperType, conf, depth) ?: baseSuperType else approximateToSubType(baseSubType, conf, depth) ?: baseSubType
val baseResult = if (toSuper) approximateToSuperType(baseSuperType, conf, depth) ?: baseSuperType else approximateToSubType(
baseSubType,
conf,
depth
) ?: baseSubType
// C = in Int, Int <: C => Int? <: C?
// C = out Number, C <: Number => C? <: Number?
@@ -249,9 +271,10 @@ class TypeApproximator {
}
private fun approximateSimpleToSuperType(type: SimpleType, conf: TypeApproximatorConfiguration, depth: Int) =
approximateTo(type, conf, toSuper = true, depth = depth)
approximateTo(type, conf, toSuper = true, depth = depth)
private fun approximateSimpleToSubType(type: SimpleType, conf: TypeApproximatorConfiguration, depth: Int) =
approximateTo(type, conf, toSuper = false, depth = depth)
approximateTo(type, conf, toSuper = false, depth = depth)
private fun approximateTo(type: SimpleType, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int): UnwrappedType? {
if (type.isError) {
@@ -272,9 +295,10 @@ class TypeApproximator {
val typeConstructor = type.constructor
if (typeConstructor is NewCapturedTypeConstructor) {
assert(type is NewCapturedType) { // KT-16147
assert(type is NewCapturedType) {
// KT-16147
"Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " +
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
}
return approximateCapturedType(type as NewCapturedType, conf, toSuper, depth)
}
@@ -291,16 +315,15 @@ class TypeApproximator {
}
private fun approximateDefinitelyNotNullType(
type: DefinitelyNotNullType,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
type: DefinitelyNotNullType,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): UnwrappedType? {
val approximatedOriginalType = approximateTo(type.original, conf, toSuper, depth)
return if (conf.definitelyNotNullType) {
approximatedOriginalType?.makeDefinitelyNotNullOrNotNull()
}
else {
} else {
if (toSuper)
(approximatedOriginalType ?: type.original).makeNullableAsSpecified(false)
else
@@ -309,20 +332,24 @@ class TypeApproximator {
}
private fun isApproximateDirectionToSuper(effectiveVariance: Variance, toSuper: Boolean) =
when (effectiveVariance) {
Variance.OUT_VARIANCE -> toSuper
Variance.IN_VARIANCE -> !toSuper
Variance.INVARIANT -> throw AssertionError("Incorrect variance $effectiveVariance")
}
when (effectiveVariance) {
Variance.OUT_VARIANCE -> toSuper
Variance.IN_VARIANCE -> !toSuper
Variance.INVARIANT -> throw AssertionError("Incorrect variance $effectiveVariance")
}
private fun approximateParametrizedType(type: SimpleType, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int): SimpleType? {
private fun approximateParametrizedType(
type: SimpleType,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): SimpleType? {
val parameters = type.constructor.parameters
val arguments = type.arguments
if (parameters.size != arguments.size) {
return if (conf.errorType) {
ErrorUtils.createErrorType("Inconsistent type: $type (parameters.size = ${parameters.size}, arguments.size = ${arguments.size})")
}
else type.defaultResult(toSuper)
} else type.defaultResult(toSuper)
}
val newArguments = arrayOfNulls<TypeProjection?>(arguments.size)
@@ -338,8 +365,10 @@ class TypeApproximator {
when (effectiveVariance) {
null -> {
return if (conf.errorType) {
ErrorUtils.createErrorType("Inconsistent type: $type ($index parameter has declared variance: ${parameter.variance}, " +
"but argument variance is ${argument.projectionKind})")
ErrorUtils.createErrorType(
"Inconsistent type: $type ($index parameter has declared variance: ${parameter.variance}, " +
"but argument variance is ${argument.projectionKind})"
)
} else type.defaultResult(toSuper)
}
Variance.OUT_VARIANCE, Variance.IN_VARIANCE -> {
@@ -353,8 +382,7 @@ class TypeApproximator {
val approximatedArgument = argumentType.let {
if (isApproximateDirectionToSuper(effectiveVariance, toSuper)) {
approximateToSuperType(it, conf, depth)
}
else {
} else {
approximateToSubType(it, conf, depth)
}
} ?: continue@loop
@@ -397,9 +425,11 @@ class TypeApproximator {
}
}
val approximatedSuperType = approximateToSuperType(argumentType, conf, depth) ?: continue@loop // null means that this type we can leave as is
val approximatedSuperType =
approximateToSuperType(argumentType, conf, depth) ?: continue@loop // null means that this type we can leave as is
if (approximatedSuperType.isTrivialSuper()) {
val approximatedSubType = approximateToSubType(argumentType, conf, depth) ?: continue@loop // seems like this is never null
val approximatedSubType =
approximateToSubType(argumentType, conf, depth) ?: continue@loop // seems like this is never null
if (!approximatedSubType.isTrivialSub()) {
newArguments[index] = TypeProjectionImpl(Variance.IN_VARIANCE, approximatedSubType)
continue@loop
@@ -408,8 +438,7 @@ class TypeApproximator {
if (NewKotlinTypeChecker.equalTypes(argumentType, approximatedSuperType)) {
newArguments[index] = approximatedSuperType.asTypeProjection()
}
else {
} else {
newArguments[index] = TypeProjectionImpl(Variance.OUT_VARIANCE, approximatedSuperType)
}
}
@@ -434,10 +463,10 @@ class TypeApproximator {
}
internal fun UnwrappedType.typeDepth() =
when (this) {
is SimpleType -> typeDepth()
is FlexibleType -> Math.max(lowerBound.typeDepth(), upperBound.typeDepth())
}
when (this) {
is SimpleType -> typeDepth()
is FlexibleType -> Math.max(lowerBound.typeDepth(), upperBound.typeDepth())
}
internal fun SimpleType.typeDepth(): Int {
if (this is TypeUtils.SpecialType) return 0