Reformat 'resolution' module according to new codestyle
This commit is contained in:
+2
-2
@@ -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)
|
||||
}
|
||||
+2
-3
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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)
|
||||
}
|
||||
+2
-2
@@ -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())
|
||||
}
|
||||
|
||||
+5
-5
@@ -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)
|
||||
}
|
||||
+4
-3
@@ -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)
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
|
||||
+6
-6
@@ -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)
|
||||
}
|
||||
+21
-21
@@ -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")
|
||||
|
||||
+4
-1
@@ -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>
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+9
-5
@@ -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()))
|
||||
)
|
||||
}
|
||||
}
|
||||
+9
-6
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -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)
|
||||
}
|
||||
|
||||
+9
-4
@@ -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) {
|
||||
|
||||
+1
-2
@@ -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)
|
||||
}
|
||||
|
||||
+27
-21
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
-21
@@ -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) {
|
||||
|
||||
+16
-21
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
+8
-9
@@ -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
|
||||
|
||||
|
||||
+92
-67
@@ -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
|
||||
}
|
||||
}
|
||||
+35
-34
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -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)
|
||||
|
||||
+60
-47
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+16
-17
@@ -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] })
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
+35
-25
@@ -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)
|
||||
|
||||
+16
-4
@@ -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) }
|
||||
|
||||
|
||||
+38
-17
@@ -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")
|
||||
|
||||
+29
-24
@@ -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
|
||||
}
|
||||
|
||||
+8
-8
@@ -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)
|
||||
}
|
||||
|
||||
+9
-5
@@ -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?) {
|
||||
|
||||
+8
-5
@@ -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))
|
||||
|
||||
+1
@@ -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
|
||||
}
|
||||
+25
-17
@@ -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
|
||||
|
||||
|
||||
}
|
||||
+35
-23
@@ -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"
|
||||
|
||||
+25
-18
@@ -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)
|
||||
|
||||
|
||||
+37
-30
@@ -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
|
||||
|
||||
+15
-14
@@ -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
|
||||
|
||||
|
||||
+11
-8
@@ -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"
|
||||
|
||||
+3
-3
@@ -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()
|
||||
|
||||
+25
-22
@@ -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) {
|
||||
|
||||
+15
-15
@@ -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) }
|
||||
|
||||
}
|
||||
+11
-6
@@ -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)
|
||||
+13
-13
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
+16
-16
@@ -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) }
|
||||
}
|
||||
|
||||
|
||||
+41
-22
@@ -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) {
|
||||
|
||||
+9
-7
@@ -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"
|
||||
}
|
||||
|
||||
+7
-6
@@ -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
|
||||
}
|
||||
|
||||
+35
-34
@@ -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)
|
||||
|
||||
+83
-64
@@ -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?
|
||||
)
|
||||
|
||||
|
||||
+27
-25
@@ -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())
|
||||
}
|
||||
+13
-13
@@ -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>
|
||||
|
||||
+2
-2
@@ -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()
|
||||
}
|
||||
+54
-52
@@ -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)
|
||||
|
||||
/**
|
||||
|
||||
+93
-82
@@ -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
|
||||
}
|
||||
|
||||
+2
-2
@@ -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 {
|
||||
|
||||
+11
-12
@@ -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
|
||||
}
|
||||
|
||||
+44
-39
@@ -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
|
||||
}
|
||||
|
||||
+14
-12
@@ -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)
|
||||
|
||||
+73
-47
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+123
-92
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+6
-7
@@ -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()
|
||||
}
|
||||
|
||||
+7
-7
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
|
||||
+21
-16
@@ -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
|
||||
}
|
||||
|
||||
+16
-11
@@ -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()
|
||||
}
|
||||
|
||||
+14
-7
@@ -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>()
|
||||
}
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user