Reformat 'resolution' module according to new codestyle

This commit is contained in:
Dmitry Savvinov
2018-01-17 16:12:58 +03:00
parent e2b83aecd7
commit c704f2de9a
89 changed files with 1941 additions and 1530 deletions
@@ -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()
} }
} }
@@ -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)
} }
@@ -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
@@ -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
@@ -38,6 +38,7 @@ class ContractInterpretationDispatcher {
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
} }
} }
@@ -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")
@@ -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>
} }
@@ -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>
} }
@@ -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)
} }
@@ -48,7 +48,10 @@ internal fun foldConditionsWithOr(list: List<ConditionalEffect>): ESExpression?
/** /**
* 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,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)
} }
@@ -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) {
@@ -42,7 +44,10 @@ class InfoCollector(private val observedEffect: ESEffect) : ESExpressionVisitor<
} }
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) {
@@ -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
} }
@@ -45,12 +45,18 @@ class KotlinCallResolver(
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,7 +66,12 @@ 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)
} }
@@ -79,15 +90,19 @@ 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(
KnownResultProcessor(resolutionCandidates),
TowerResolver.AllCandidatesCollector(), TowerResolver.AllCandidatesCollector(),
useOrder = false) useOrder = false
)
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks) return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
} }
val candidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolutionCandidates), val candidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolutionCandidates),
TowerResolver.SuccessfulResultCollector(), TowerResolver.SuccessfulResultCollector(),
useOrder = true) useOrder = true
)
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates) return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
} }
@@ -111,7 +126,8 @@ class KotlinCallResolver(
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)
} }
@@ -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()
@@ -129,7 +129,12 @@ object NewCommonSuperTypeCalculator {
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)
@@ -160,8 +165,7 @@ 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)
} }
@@ -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
)
} }
} }
} }
@@ -79,10 +79,20 @@ class AdditionalDiagnosticReporter(private val languageVersionSettings: Language
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) {
@@ -48,8 +48,7 @@ class ArgumentsToParametersMapper {
// 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))
} }
@@ -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))
} }
} }
@@ -51,8 +51,7 @@ 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()
} }
@@ -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
@@ -132,8 +133,10 @@ 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)
} }
@@ -172,7 +175,8 @@ class CallableReferencesCandidateFactory(
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>()
@@ -181,16 +185,19 @@ class CallableReferencesCandidateFactory(
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(
candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, defaults, explicitReceiverKind, reflectionCandidateType, defaults,
listOf(NotCallableMemberReference(argument, candidateDescriptor))) listOf(NotCallableMemberReference(argument, candidateDescriptor))
)
} }
diagnostics.addAll(towerCandidate.diagnostics) diagnostics.addAll(towerCandidate.diagnostics)
@@ -201,15 +208,25 @@ class CallableReferencesCandidateFactory(
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(
@@ -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
/** /**
@@ -274,24 +292,32 @@ class CallableReferencesCandidateFactory(
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
} }
} }
@@ -44,7 +44,7 @@ class CallableReferenceOverloadConflictResolver(
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)
@@ -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)
@@ -117,7 +117,8 @@ class CallableReferenceResolver(
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
)
} }
} }
@@ -54,7 +54,13 @@ 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(
@@ -76,8 +82,7 @@ class KotlinCallCompleter(
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts, diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
constraintSystem.asReadOnlyStorage() constraintSystem.asReadOnlyStorage()
) )
} } else {
else {
CallResolutionResult( CallResolutionResult(
CallResolutionResult.Type.PARTIAL, CallResolutionResult.Type.PARTIAL,
candidate.resolvedCall, candidate.resolvedCall,
@@ -101,7 +106,8 @@ class KotlinCallCompleter(
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)
} }
@@ -115,7 +121,12 @@ class KotlinCallCompleter(
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(),
@@ -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
} }
} }
@@ -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) {
@@ -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))
} }
@@ -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> {
@@ -130,7 +139,8 @@ private fun preprocessCallableReference(
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))
} }
@@ -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) }
@@ -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}"
} }
@@ -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(
"Inconsistent call: $kotlinCall. \n" +
"Candidate: $candidateDescriptor, explicitReceiverKind: ${resolvedCall.explicitReceiverKind}.\n" + "Candidate: $candidateDescriptor, explicitReceiverKind: ${resolvedCall.explicitReceiverKind}.\n" +
"Explicit receiver: ${kotlinCall.explicitReceiver}, dispatchReceiverForInvokeExtension: ${kotlinCall.dispatchReceiverForInvokeExtension}") "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) {
@@ -212,7 +228,12 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
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))
} }
@@ -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)
} }
} }
@@ -35,7 +35,7 @@ class TypeArgumentsToParametersMapper {
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)
} }
@@ -47,7 +47,11 @@ interface ConstraintSystemBuilder : ConstraintSystemOperation {
fun buildCurrentSubstitutor(): NewTypeSubstitutor fun buildCurrentSubstitutor(): NewTypeSubstitutor
} }
fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) = fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(
lowerType: UnwrappedType,
upperType: UnwrappedType,
position: ConstraintPosition
) =
runTransaction { runTransaction {
if (!hasContradiction) addSubtypeConstraint(lowerType, upperType, position) if (!hasContradiction) addSubtypeConstraint(lowerType, upperType, position)
!hasContradiction !hasContradiction
@@ -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)
@@ -62,8 +65,8 @@ fun CallableDescriptor.substituteAndApproximateCapturedTypes(substitutor: NewTyp
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
} }
} }
@@ -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
} }
@@ -113,19 +113,27 @@ class ConstraintIncorporator(val typeApproximator: TypeApproximator) {
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)
)
val temporaryCapturedType = NewCapturedType(
CaptureStatus.FOR_INCORPORATION,
newCapturedTypeConstructor, newCapturedTypeConstructor,
lowerType = null) 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()
)
val temporaryCapturedType = NewCapturedType(
CaptureStatus.FOR_INCORPORATION,
newCapturedTypeConstructor, newCapturedTypeConstructor,
lowerType = otherConstraint.type) lowerType = otherConstraint.type
)
baseConstraint.type.substitute(otherVariable, temporaryCapturedType) baseConstraint.type.substitute(otherVariable, temporaryCapturedType)
} }
} }
@@ -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,7 +111,8 @@ 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,
@@ -126,6 +133,7 @@ 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)
@@ -148,14 +156,16 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
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
} }
@@ -193,8 +203,10 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
?: 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"
@@ -43,6 +43,7 @@ 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)
} }
@@ -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
@@ -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)
@@ -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) {
@@ -36,16 +36,17 @@ interface NewTypeSubstitutor {
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 null
} } else {
else {
val lowerBound = substitute(type.lowerBound, keepAnnotation, runCapturedChecks) val lowerBound = substitute(type.lowerBound, keepAnnotation, runCapturedChecks)
val upperBound = substitute(type.upperBound, keepAnnotation, runCapturedChecks) val upperBound = substitute(type.upperBound, keepAnnotation, runCapturedChecks)
if (lowerBound == null && upperBound == null) { if (lowerBound == null && upperBound == null) {
null null
} } else {
else {
// todo discuss lowerIfFlexible and upperIfFlexible // todo discuss lowerIfFlexible and upperIfFlexible
KotlinTypeFactory.flexibleType(lowerBound?.lowerIfFlexible() ?: type.lowerBound, upperBound?.upperIfFlexible() ?: type.upperBound) KotlinTypeFactory.flexibleType(
lowerBound?.lowerIfFlexible() ?: type.lowerBound,
upperBound?.upperIfFlexible() ?: type.upperBound
)
} }
} }
} }
@@ -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(
"Illegal type substitutor: $this, " +
"because for captured type '$type' lower type approximation should be null, but it is: '$lower'," + "because for captured type '$type' lower type approximation should be null, but it is: '$lower'," +
"original lower type: '${capturedType.lowerType}") "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(
"Illegal type substitutor: $this, " +
"because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," + "because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," +
"original supertype: '$supertype'") "original supertype: '$supertype'"
)
} }
} }
@@ -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)
} }
@@ -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,7 +103,10 @@ class ResultTypeResolver(
* *
*/ */
return typeApproximator.approximateToSuperType(adjustedCommonSuperType, TypeApproximatorConfiguration.CapturedTypesApproximation) return typeApproximator.approximateToSuperType(
adjustedCommonSuperType,
TypeApproximatorConfiguration.CapturedTypesApproximation
)
?: adjustedCommonSuperType ?: adjustedCommonSuperType
} }
@@ -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 {
@@ -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
} }
} }
@@ -225,8 +225,11 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
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"
@@ -105,7 +105,10 @@ class TypeVariableDirectionCalculator(
!(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(
startDirection: ResolveDirection,
action: (variable: Variable, direction: ResolveDirection) -> Unit
) =
when (this) { when (this) {
is SimpleType -> visitType(startDirection, action) is SimpleType -> visitType(startDirection, action)
is FlexibleType -> { is FlexibleType -> {
@@ -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"
@@ -28,7 +28,8 @@ 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>
get() {
if (simplifiedConstraints == null) { if (simplifiedConstraints == null) {
simplifiedConstraints = simplifyConstraints() simplifiedConstraints = simplifyConstraints()
} }
@@ -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)
@@ -33,14 +33,13 @@ 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,7 +190,8 @@ class NewConstraintSystemImpl(
} }
// ConstraintInjector.Context // ConstraintInjector.Context
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> get() { override val allTypeVariables: Map<TypeConstructor, NewTypeVariable>
get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.allTypeVariables return storage.allTypeVariables
} }
@@ -191,7 +209,8 @@ class NewConstraintSystemImpl(
} }
// ConstraintInjector.Context, FixationOrderCalculator.Context // ConstraintInjector.Context, FixationOrderCalculator.Context
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> get() { override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints>
get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.notFixedTypeVariables return storage.notFixedTypeVariables
} }
@@ -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
@@ -48,7 +49,8 @@ sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) {
// 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()
} }
@@ -37,7 +37,7 @@ class ReceiverExpressionKotlinCallArgument private constructor(
) : 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
@@ -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"
} }
@@ -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
} }
@@ -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)
} }
@@ -132,7 +133,7 @@ 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)
} }
@@ -49,7 +49,7 @@ 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 {
@@ -86,10 +86,13 @@ 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(
@@ -97,12 +100,17 @@ class SimpleCandidateFactory(
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(
@@ -113,11 +121,20 @@ class SimpleCandidateFactory(
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,16 +162,18 @@ 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
)
} }
} }
@@ -74,6 +74,7 @@ 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?
@@ -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?
get() {
val returnType = candidateDescriptor.returnType ?: return null val returnType = candidateDescriptor.returnType ?: return null
return substitutor.safeSubstitute(returnType.unwrap()) return substitutor.safeSubstitute(returnType.unwrap())
} }
@@ -56,6 +56,7 @@ 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
@@ -106,8 +107,7 @@ class KotlinResolutionCandidate(
if (workStep >= workCount) { if (workStep >= workCount) {
partIndex++ partIndex++
workStep -= workCount workStep -= workCount
} } else {
else {
break break
} }
} }
@@ -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()
} }
@@ -33,7 +33,7 @@ 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
} }
} }
@@ -57,7 +57,8 @@ class FlatSignature<out T> private constructor(
numDefaults: Int, numDefaults: Int,
reflectionType: UnwrappedType reflectionType: UnwrappedType
): FlatSignature<T> { ): FlatSignature<T> {
return FlatSignature(origin, return FlatSignature(
origin,
descriptor.typeParameters, descriptor.typeParameters,
reflectionType.arguments.map { it.type }, // should we drop return type? reflectionType.arguments.map { it.type }, // should we drop return type?
hasExtensionReceiver = false, hasExtensionReceiver = false,
@@ -76,7 +77,8 @@ class FlatSignature<out T> private constructor(
): FlatSignature<T> { ): FlatSignature<T> {
val extensionReceiverType = descriptor.extensionReceiverParameter?.type val extensionReceiverType = descriptor.extensionReceiverParameter?.type
return FlatSignature(origin, return FlatSignature(
origin,
descriptor.typeParameters, descriptor.typeParameters,
valueParameterTypes = valueParameterTypes =
listOfNotNull(extensionReceiverType) + parameterTypes, listOfNotNull(extensionReceiverType) + parameterTypes,
@@ -94,7 +96,8 @@ class FlatSignature<out T> private constructor(
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,
descriptor.typeParameters, descriptor.typeParameters,
valueParameterTypes = descriptor.valueParameters.map { it.argumentValueType }, valueParameterTypes = descriptor.valueParameters.map { it.argumentValueType },
hasExtensionReceiver = false, hasExtensionReceiver = 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)
/** /**
@@ -66,8 +66,7 @@ open class OverloadingConflictResolver<C : Any>(
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,7 +130,7 @@ 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
@@ -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)) {
@@ -185,21 +186,17 @@ open class OverloadingConflictResolver<C : Any>(
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,15 +216,17 @@ 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>,
isNotLessSpecific: (C, C) -> Boolean
): Boolean =
candidates.all { other ->
candidate === other || candidate === other ||
isNotLessSpecific(candidate, other) && !isNotLessSpecific(other, candidate) isNotLessSpecific(candidate, other) && !isNotLessSpecific(other, candidate)
} }
@@ -240,8 +239,11 @@ open class OverloadingConflictResolver<C : Any>(
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
)
} }
/** /**
@@ -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 {
@@ -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
} }
@@ -366,8 +378,7 @@ 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> =
@@ -43,8 +43,7 @@ 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)
@@ -36,7 +36,7 @@ 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
@@ -72,7 +72,9 @@ private class ErrorCandidateContext(
) { ) {
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) {
@@ -92,7 +94,10 @@ private fun ErrorCandidateContext.asClassifierCall(asFunction: Boolean) {
add(ErrorCandidate.Classifier(classifier, kind)) add(ErrorCandidate.Classifier(classifier, kind))
} }
private fun ErrorCandidateContext.getWrongResolutionToClassifier(classifier: ClassifierDescriptor, asFunction: Boolean): WrongResolutionToClassifier? = private fun ErrorCandidateContext.getWrongResolutionToClassifier(
classifier: ClassifierDescriptor,
asFunction: Boolean
): WrongResolutionToClassifier? =
when (classifier) { when (classifier) {
is TypeAliasDescriptor -> classifier.classDescriptor?.let { getWrongResolutionToClassifier(it, asFunction) } is TypeAliasDescriptor -> classifier.classDescriptor?.let { getWrongResolutionToClassifier(it, asFunction) }
@@ -64,7 +64,8 @@ interface CandidateWithBoundDispatchReceiver {
val dispatchReceiver: ReceiverValueWithSmartCastInfo? val dispatchReceiver: ReceiverValueWithSmartCastInfo?
} }
fun getResultApplicability(diagnostics: Collection<KotlinCallDiagnostic>) = diagnostics.maxBy { it.candidateApplicability }?.candidateApplicability fun getResultApplicability(diagnostics: Collection<KotlinCallDiagnostic>) =
diagnostics.maxBy { it.candidateApplicability }?.candidateApplicability
?: RESOLVED ?: RESOLVED
enum class ResolutionCandidateApplicability { enum class ResolutionCandidateApplicability {
@@ -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)
@@ -38,10 +38,9 @@ abstract class AbstractInvokeTowerProcessor<C : Candidate>(
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) }
} }
@@ -104,14 +103,23 @@ class InvokeTowerProcessor<C : Candidate>(
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) =
@@ -136,7 +144,12 @@ class InvokeExtensionTowerProcessor<C : Candidate>(
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>? {
@@ -162,11 +175,23 @@ private class InvokeExtensionScopeTowerProcessor<C : Candidate>(
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()
@@ -204,18 +229,19 @@ fun <C : Candidate> createCallTowerProcessorForExplicitInvoke(
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)
@@ -25,9 +25,8 @@ 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) {}
} }
@@ -47,7 +46,7 @@ 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,17 +144,22 @@ 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(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null)) result.add(
candidateFactory.createCandidate(
towerCandidate,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
extensionReceiver = null
)
)
} }
} }
result result
@@ -146,7 +168,13 @@ private class NoExplicitReceiverScopeTowerProcessor<C: Candidate>(
val result = mutableListOf<C>() val result = mutableListOf<C>()
for (towerCandidate in data.level.collectCandidates(data.implicitReceiver)) { for (towerCandidate in data.level.collectCandidates(data.implicitReceiver)) {
if (towerCandidate.requiresExtensionReceiver) { if (towerCandidate.requiresExtensionReceiver) {
result.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver)) result.add(
candidateFactory.createCandidate(
towerCandidate,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
extensionReceiver = data.implicitReceiver
)
)
} }
} }
result result
@@ -188,8 +216,9 @@ private fun <C : Candidate> createSimpleProcessor(
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
@@ -211,23 +240,26 @@ fun <C : Candidate> createCallableReferenceProcessor(
return SamePriorityCompositeScopeTowerProcessor(variable, function) return SamePriorityCompositeScopeTowerProcessor(variable, function)
} }
fun <C : Candidate> createVariableProcessor(scopeTower: ImplicitScopeTower, name: Name, fun <C : Candidate> createVariableProcessor(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true 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(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true 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(
scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true 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<С>,
@@ -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?)
} }
} }
@@ -43,7 +43,7 @@ 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(
@@ -57,8 +57,7 @@ internal abstract class AbstractScopeTowerLevel(
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)
} }
@@ -83,7 +82,7 @@ internal abstract class AbstractScopeTowerLevel(
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
@@ -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,15 +160,24 @@ 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,7 +192,8 @@ 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)
@@ -191,10 +205,12 @@ internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qual
} }
override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
.getContributedFunctionsAndConstructors(name, .getContributedFunctionsAndConstructors(
name,
location, location,
scopeTower.syntheticScopes, scopeTower.syntheticScopes,
qualifier.staticScope).map { qualifier.staticScope
).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
@@ -209,21 +225,29 @@ internal open class ScopeBasedTowerLevel protected constructor(
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,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver> override fun getObjects(
= resolutionScope.getContributedObjectVariables(name, location).map { name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedObjectVariables(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection<CandidateWithBoundDispatchReceiver> override fun getFunctions(
= resolutionScope.getContributedFunctionsAndConstructors(name, name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedFunctionsAndConstructors(
name,
location, location,
scopeTower.syntheticScopes, scopeTower.syntheticScopes,
resolutionScope).map { resolutionScope
).map {
createCandidateDescriptor(it, dispatchReceiver = null) createCandidateDescriptor(it, dispatchReceiver = null)
} }
@@ -231,19 +255,23 @@ internal open class ScopeBasedTowerLevel protected constructor(
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 {
@@ -267,15 +295,15 @@ internal class SyntheticScopeBasedTowerLevel(
} }
} }
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,
@@ -37,7 +37,7 @@ 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,
@@ -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,19 +81,18 @@ 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>,
@@ -113,9 +112,9 @@ class TowerResolver {
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))
} }
} }
@@ -152,8 +150,7 @@ class TowerResolver {
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)
@@ -203,8 +200,7 @@ class TowerResolver {
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 }
} }
@@ -279,8 +275,7 @@ class TowerResolver {
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
get() =
minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN
} }
} }
@@ -23,7 +23,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastI
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
@@ -21,8 +21,7 @@ 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
@@ -34,23 +34,28 @@ class LexicalChainedScope @JvmOverloads constructor(
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) {
@@ -27,7 +27,7 @@ class LexicalScopeImpl @JvmOverloads constructor(
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)
} }
} }
@@ -37,7 +37,7 @@ 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 {
@@ -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 = ")
@@ -117,7 +117,10 @@ interface ImportingScope : HierarchicalScope {
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()
} }
@@ -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(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> =
emptyList() 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>()
} }
@@ -28,7 +28,7 @@ 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,8 +42,7 @@ 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()
} }
} }
@@ -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,7 +159,7 @@ 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
@@ -160,7 +175,7 @@ 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
@@ -168,18 +183,18 @@ inline fun <T: Any> HierarchicalScope.collectAllFromMeAndParent(
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
} }
@@ -216,7 +230,7 @@ fun LexicalScope.createScopeForDestructuring(newReceiver: ReceiverParameterDescr
) )
} }
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
} }
} }
@@ -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()
} }
@@ -66,9 +66,8 @@ private fun DeclarationDescriptor.getOwnSinceKotlinVersion(): ApiVersion? {
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,22 +96,26 @@ 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
@@ -125,8 +131,7 @@ class TypeApproximator {
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}"
@@ -195,13 +206,20 @@ class TypeApproximator {
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?
@@ -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?
@@ -250,6 +272,7 @@ 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)
@@ -272,7 +295,8 @@ 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"
} }
@@ -299,8 +323,7 @@ class TypeApproximator {
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
@@ -315,14 +338,18 @@ class TypeApproximator {
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)
} }
} }