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