Make getNestedTypeVariables() an utility

This commit is contained in:
Alexander Udalov
2015-11-03 16:23:15 +03:00
parent dd4a7ac6a9
commit e50eb50299
12 changed files with 89 additions and 47 deletions
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.CallTransformer
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.getNestedTypeVariables
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
@@ -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.ConstraintPositionKind.RECEIVER_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.INCOMPLETE_TYPE_INFERENCE
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 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.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.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.TypeSubstitutor
@@ -63,8 +61,6 @@ interface ConstraintSystem {
*/
val currentSubstitutor: TypeSubstitutor
fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor>
fun toBuilder(filterConstraintPosition: (ConstraintPosition) -> Boolean = { true }): Builder
interface Builder {
@@ -101,7 +97,3 @@ interface ConstraintSystem {
fun build(): ConstraintSystem
}
}
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
return toBuilder { !it.derivedFrom(excludePositionKind) }.build()
}
@@ -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.TypeCheckingProcedureCallbacks
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
import org.jetbrains.kotlin.types.typeUtil.isDefaultBound
import java.util.*
@@ -99,11 +98,8 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
type -> type.constructor.declarationDescriptor.let { it is TypeParameterDescriptor && isMyTypeVariable(it) }
}
internal fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor> {
return type.getNestedArguments().map { typeProjection ->
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
}.filterNotNull().filter { if (original) it in descriptorToVariable.keys else isMyTypeVariable(it) }
}
internal fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> =
type.getNestedTypeParameters().filter { isMyTypeVariable(it) }
override fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return
@@ -257,7 +253,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
typeBounds.addBound(bound)
if (!bound.isProper) {
for (dependentTypeVariable in getNestedTypeVariables(bound.constrainingType, original = false)) {
for (dependentTypeVariable in getNestedTypeVariables(bound.constrainingType)) {
val dependentBounds = usedInBounds.getOrPut(dependentTypeVariable) { arrayListOf() }
dependentBounds.add(bound)
}
@@ -359,7 +355,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
if (typeBounds.isFixed) return
typeBounds.setFixed()
val nestedTypeVariables = typeBounds.bounds.flatMap { getNestedTypeVariables(it.constrainingType, original = false) }
val nestedTypeVariables = typeBounds.bounds.flatMap { getNestedTypeVariables(it.constrainingType) }
nestedTypeVariables.forEach { fixVariable(it) }
val value = typeBounds.value ?: return
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isInternalAnnotationForResolv
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import java.util.*
@@ -110,13 +109,6 @@ internal class ConstraintSystemImpl(
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>
get() = descriptorToVariable.keys
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.Variance.INVARIANT
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
import java.util.*
@@ -59,7 +58,7 @@ fun ConstraintSystemBuilderImpl.incorporateBound(newBound: Bound) {
return
}
getNestedTypeVariables(constrainingType, original = true).forEach {
getNestedTypeVariables(constrainingType).forEach {
val boundsForNestedVariable = getTypeBounds(it).bounds
for (index in boundsForNestedVariable.indices) {
generateNewBound(newBound, boundsForNestedVariable[index])
@@ -100,8 +99,7 @@ private fun ConstraintSystemBuilderImpl.generateNewBound(bound: Bound, substitut
fun addNewBound(newConstrainingType: KotlinType, newBoundKind: BoundKind) {
// We don't generate new recursive constraints
val nestedTypeVariables = getNestedTypeVariables(newConstrainingType, original = false)
if (nestedTypeVariables.contains(bound.typeVariable)) return
if (bound.typeVariable in getNestedTypeVariables(newConstrainingType)) return
// We don't generate constraint if a type variable was substituted twice
val derivedFrom = HashSet(bound.derivedFrom + substitution.derivedFrom)
@@ -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()
}
@@ -46,7 +46,7 @@ import java.util.Collection;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
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.types.TypeUtils.noExpectedType;
@@ -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(""))
}
@@ -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);
}
@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")
public void testInferenceForNestedBinaryCall() throws Exception {
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)
}
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)
public fun List<KotlinType>.defaultProjections(): List<TypeProjection> = map { TypeProjectionImpl(it) }