Make getNestedTypeVariables() an utility
This commit is contained in:
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||||
|
|||||||
+3
-1
@@ -37,6 +37,8 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeParameters
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE
|
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.OTHER_ERROR
|
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.OTHER_ERROR
|
||||||
@@ -165,7 +167,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
|||||||
val candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidateDescriptor)
|
val candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidateDescriptor)
|
||||||
val conversion = candidateDescriptor.typeParameters.zip(candidateWithFreshVariables.typeParameters).toMap()
|
val conversion = candidateDescriptor.typeParameters.zip(candidateWithFreshVariables.typeParameters).toMap()
|
||||||
|
|
||||||
val freshVariables = nestedTypeVariables.map { conversion[argumentConstraintSystem.variableToDescriptor(it)] }.filterNotNull()
|
val freshVariables = returnType.getNestedTypeParameters().map { conversion[it] }.filterNotNull()
|
||||||
builder.registerTypeVariables(freshVariables, external = true)
|
builder.registerTypeVariables(freshVariables, external = true)
|
||||||
|
|
||||||
builder.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition)
|
builder.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition)
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ package org.jetbrains.kotlin.resolve.calls.inference
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFrom
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
@@ -63,8 +61,6 @@ interface ConstraintSystem {
|
|||||||
*/
|
*/
|
||||||
val currentSubstitutor: TypeSubstitutor
|
val currentSubstitutor: TypeSubstitutor
|
||||||
|
|
||||||
fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor>
|
|
||||||
|
|
||||||
fun toBuilder(filterConstraintPosition: (ConstraintPosition) -> Boolean = { true }): Builder
|
fun toBuilder(filterConstraintPosition: (ConstraintPosition) -> Boolean = { true }): Builder
|
||||||
|
|
||||||
interface Builder {
|
interface Builder {
|
||||||
@@ -101,7 +97,3 @@ interface ConstraintSystem {
|
|||||||
fun build(): ConstraintSystem
|
fun build(): ConstraintSystem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
|
|
||||||
return toBuilder { !it.derivedFrom(excludePositionKind) }.build()
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-8
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
|||||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
||||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks
|
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isDefaultBound
|
import org.jetbrains.kotlin.types.typeUtil.isDefaultBound
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -99,11 +98,8 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
type -> type.constructor.declarationDescriptor.let { it is TypeParameterDescriptor && isMyTypeVariable(it) }
|
type -> type.constructor.declarationDescriptor.let { it is TypeParameterDescriptor && isMyTypeVariable(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor> {
|
internal fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> =
|
||||||
return type.getNestedArguments().map { typeProjection ->
|
type.getNestedTypeParameters().filter { isMyTypeVariable(it) }
|
||||||
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
|
||||||
}.filterNotNull().filter { if (original) it in descriptorToVariable.keys else isMyTypeVariable(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
override fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
||||||
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return
|
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return
|
||||||
@@ -257,7 +253,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
typeBounds.addBound(bound)
|
typeBounds.addBound(bound)
|
||||||
|
|
||||||
if (!bound.isProper) {
|
if (!bound.isProper) {
|
||||||
for (dependentTypeVariable in getNestedTypeVariables(bound.constrainingType, original = false)) {
|
for (dependentTypeVariable in getNestedTypeVariables(bound.constrainingType)) {
|
||||||
val dependentBounds = usedInBounds.getOrPut(dependentTypeVariable) { arrayListOf() }
|
val dependentBounds = usedInBounds.getOrPut(dependentTypeVariable) { arrayListOf() }
|
||||||
dependentBounds.add(bound)
|
dependentBounds.add(bound)
|
||||||
}
|
}
|
||||||
@@ -359,7 +355,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
if (typeBounds.isFixed) return
|
if (typeBounds.isFixed) return
|
||||||
typeBounds.setFixed()
|
typeBounds.setFixed()
|
||||||
|
|
||||||
val nestedTypeVariables = typeBounds.bounds.flatMap { getNestedTypeVariables(it.constrainingType, original = false) }
|
val nestedTypeVariables = typeBounds.bounds.flatMap { getNestedTypeVariables(it.constrainingType) }
|
||||||
nestedTypeVariables.forEach { fixVariable(it) }
|
nestedTypeVariables.forEach { fixVariable(it) }
|
||||||
|
|
||||||
val value = typeBounds.value ?: return
|
val value = typeBounds.value ?: return
|
||||||
|
|||||||
-8
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isInternalAnnotationForResolv
|
|||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -110,13 +109,6 @@ internal class ConstraintSystemImpl(
|
|||||||
return SubstitutionFilteringInternalResolveAnnotations(substitution).buildSubstitutor()
|
return SubstitutionFilteringInternalResolveAnnotations(substitution).buildSubstitutor()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> {
|
|
||||||
return type.getNestedArguments().map { typeProjection ->
|
|
||||||
val descriptor = typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
|
||||||
descriptor?.let { descriptorToVariable[it] }
|
|
||||||
}.filterNotNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
|
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
|
||||||
get() = descriptorToVariable.keys
|
get() = descriptorToVariable.keys
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.types.TypeProjectionImpl
|
|||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
||||||
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
|
||||||
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -59,7 +58,7 @@ fun ConstraintSystemBuilderImpl.incorporateBound(newBound: Bound) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
getNestedTypeVariables(constrainingType, original = true).forEach {
|
getNestedTypeVariables(constrainingType).forEach {
|
||||||
val boundsForNestedVariable = getTypeBounds(it).bounds
|
val boundsForNestedVariable = getTypeBounds(it).bounds
|
||||||
for (index in boundsForNestedVariable.indices) {
|
for (index in boundsForNestedVariable.indices) {
|
||||||
generateNewBound(newBound, boundsForNestedVariable[index])
|
generateNewBound(newBound, boundsForNestedVariable[index])
|
||||||
@@ -100,8 +99,7 @@ private fun ConstraintSystemBuilderImpl.generateNewBound(bound: Bound, substitut
|
|||||||
|
|
||||||
fun addNewBound(newConstrainingType: KotlinType, newBoundKind: BoundKind) {
|
fun addNewBound(newConstrainingType: KotlinType, newBoundKind: BoundKind) {
|
||||||
// We don't generate new recursive constraints
|
// We don't generate new recursive constraints
|
||||||
val nestedTypeVariables = getNestedTypeVariables(newConstrainingType, original = false)
|
if (bound.typeVariable in getNestedTypeVariables(newConstrainingType)) return
|
||||||
if (nestedTypeVariables.contains(bound.typeVariable)) return
|
|
||||||
|
|
||||||
// We don't generate constraint if a type variable was substituted twice
|
// We don't generate constraint if a type variable was substituted twice
|
||||||
val derivedFrom = HashSet(bound.derivedFrom + substitution.derivedFrom)
|
val derivedFrom = HashSet(bound.derivedFrom + substitution.derivedFrom)
|
||||||
|
|||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.calls.inference
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFrom
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjection
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun ConstraintSystem.getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> =
|
||||||
|
type.getNestedTypeParameters().filter { it in typeParameterDescriptors }.map { descriptorToVariable(it) }
|
||||||
|
|
||||||
|
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
|
||||||
|
return toBuilder { !it.derivedFrom(excludePositionKind) }.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinType.getNestedArguments(): List<TypeProjection> {
|
||||||
|
val result = ArrayList<TypeProjection>()
|
||||||
|
|
||||||
|
val stack = ArrayDeque<TypeProjection>()
|
||||||
|
stack.push(TypeProjectionImpl(this))
|
||||||
|
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
val typeProjection = stack.pop()
|
||||||
|
if (typeProjection.isStarProjection) continue
|
||||||
|
|
||||||
|
result.add(typeProjection)
|
||||||
|
|
||||||
|
typeProjection.type.arguments.forEach { stack.add(it) }
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinType.getNestedTypeParameters(): List<TypeParameterDescriptor> {
|
||||||
|
return getNestedArguments().map { typeProjection ->
|
||||||
|
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||||
|
}.filterNotNull()
|
||||||
|
}
|
||||||
+1
-1
@@ -46,7 +46,7 @@ import java.util.Collection;
|
|||||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
|
import static org.jetbrains.kotlin.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqNameFromTopLevelClass;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqNameFromTopLevelClass;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemKt.filterConstraintsOut;
|
import static org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemUtilsKt.filterConstraintsOut;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION;
|
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION;
|
||||||
import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
|
import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
|
||||||
|
|
||||||
|
|||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
class A<T> {
|
||||||
|
fun <S> foo(s: S): S = s
|
||||||
|
fun <U> bar(<!UNUSED_PARAMETER!>s<!>: U): List<T> = null!!
|
||||||
|
|
||||||
|
fun test() = foo(bar(""))
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class A</*0*/ T> {
|
||||||
|
public constructor A</*0*/ T>()
|
||||||
|
public final fun </*0*/ U> bar(/*0*/ s: U): kotlin.List<T>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun </*0*/ S> foo(/*0*/ s: S): S
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun test(): kotlin.List<T>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -7955,6 +7955,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalTypeParameter.kt")
|
||||||
|
public void testExternalTypeParameter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inferenceForNestedBinaryCall.kt")
|
@TestMetadata("inferenceForNestedBinaryCall.kt")
|
||||||
public void testInferenceForNestedBinaryCall() throws Exception {
|
public void testInferenceForNestedBinaryCall() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/nestedCalls/inferenceForNestedBinaryCall.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/nestedCalls/inferenceForNestedBinaryCall.kt");
|
||||||
|
|||||||
@@ -115,23 +115,6 @@ public fun KotlinTypeChecker.equalTypesOrNulls(type1: KotlinType?, type2: Kotlin
|
|||||||
return equalTypes(type1, type2)
|
return equalTypes(type1, type2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KotlinType.getNestedArguments(): List<TypeProjection> {
|
|
||||||
val result = ArrayList<TypeProjection>()
|
|
||||||
|
|
||||||
val stack = ArrayDeque<TypeProjection>()
|
|
||||||
stack.push(TypeProjectionImpl(this))
|
|
||||||
|
|
||||||
while (!stack.isEmpty()) {
|
|
||||||
val typeProjection = stack.pop()
|
|
||||||
if (typeProjection.isStarProjection()) continue
|
|
||||||
|
|
||||||
result.add(typeProjection)
|
|
||||||
|
|
||||||
typeProjection.getType().getArguments().forEach { stack.add(it) }
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun KotlinType.containsError() = ErrorUtils.containsErrorType(this)
|
fun KotlinType.containsError() = ErrorUtils.containsErrorType(this)
|
||||||
|
|
||||||
public fun List<KotlinType>.defaultProjections(): List<TypeProjection> = map { TypeProjectionImpl(it) }
|
public fun List<KotlinType>.defaultProjections(): List<TypeProjection> = map { TypeProjectionImpl(it) }
|
||||||
|
|||||||
Reference in New Issue
Block a user