From e50eb50299c521cdbee5aed289974f2f6db9512b Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 3 Nov 2015 16:23:15 +0300 Subject: [PATCH] Make getNestedTypeVariables() an utility --- .../kotlin/resolve/calls/CallResolverUtil.kt | 1 + .../resolve/calls/GenericCandidateResolver.kt | 4 +- .../calls/inference/ConstraintSystem.kt | 8 --- .../inference/ConstraintSystemBuilderImpl.kt | 12 ++-- .../calls/inference/ConstraintSystemImpl.kt | 8 --- .../inference/constraintIncorporation.kt | 6 +- .../calls/inference/constraintSystemUtils.kt | 55 +++++++++++++++++++ .../calls/tasks/AbstractTracingStrategy.java | 2 +- .../nestedCalls/externalTypeParameter.kt | 6 ++ .../nestedCalls/externalTypeParameter.txt | 11 ++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++ .../org/jetbrains/kotlin/types/TypeUtils.kt | 17 ------ 12 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintSystemUtils.kt create mode 100644 compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.kt create mode 100644 compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt index 8631174ea9f..3342f9ae4c1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt index baac6dab5c4..bae460cd39b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystem.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystem.kt index e52ef4ee25a..c27a4b0aafb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystem.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystem.kt @@ -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 - 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() -} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt index b040f200320..995a1ce6c34 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt @@ -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 { - 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 = + 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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt index 1e5d6e52d19..b9f114acaba 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt @@ -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 { - return type.getNestedArguments().map { typeProjection -> - val descriptor = typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor - descriptor?.let { descriptorToVariable[it] } - }.filterNotNull() - } - override val typeParameterDescriptors: Set get() = descriptorToVariable.keys diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintIncorporation.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintIncorporation.kt index e5d77b5d350..33550ef7b76 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintIncorporation.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintIncorporation.kt @@ -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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintSystemUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintSystemUtils.kt new file mode 100644 index 00000000000..c7719591aa1 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintSystemUtils.kt @@ -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 = + 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 { + val result = ArrayList() + + val stack = ArrayDeque() + 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 { + return getNestedArguments().map { typeProjection -> + typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor + }.filterNotNull() +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/AbstractTracingStrategy.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/AbstractTracingStrategy.java index 95f3c01c644..408c83c363f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/AbstractTracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/AbstractTracingStrategy.java @@ -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; diff --git a/compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.kt b/compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.kt new file mode 100644 index 00000000000..194a5363eef --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.kt @@ -0,0 +1,6 @@ +class A { + fun foo(s: S): S = s + fun bar(s: U): List = null!! + + fun test() = foo(bar("")) +} diff --git a/compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.txt b/compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.txt new file mode 100644 index 00000000000..ee0f817cf17 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nestedCalls/externalTypeParameter.txt @@ -0,0 +1,11 @@ +package + +public final class A { + public constructor A() + public final fun bar(/*0*/ s: U): kotlin.List + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(/*0*/ s: S): S + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(): kotlin.List + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index de05ca5335d..036356135ea 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt index 7f8604524e8..05087c6316f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt @@ -115,23 +115,6 @@ public fun KotlinTypeChecker.equalTypesOrNulls(type1: KotlinType?, type2: Kotlin return equalTypes(type1, type2) } -fun KotlinType.getNestedArguments(): List { - val result = ArrayList() - - val stack = ArrayDeque() - 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.defaultProjections(): List = map { TypeProjectionImpl(it) }