From 667f6269e4365d799397b41137fee7159bbe5f18 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 19 Oct 2015 20:09:39 +0300 Subject: [PATCH] Filter internal annotations for resolve in type substitutor to avoid having List<@NoInfer Int> as a result type of function invocation (the function returns List<@NoInfer T>) --- .../kotlin/resolve/calls/CandidateResolver.kt | 4 ++-- .../internalAnnotationsOnTypes.kt | 13 +++++++++++++ .../internalAnnotationsOnTypes.txt | 6 ++++++ ...JetDiagnosticsTestWithStdLibGenerated.java | 6 ++++++ .../kotlin/resolve/annotationsForResolve.kt | 9 +++++++-- .../calls/inference/ConstraintSystemImpl.kt | 19 ++++++++++++------- .../DisjointKeysUnionTypeSubstitution.kt | 4 +++- .../kotlin/types/TypeSubstitution.kt | 15 +++++++++++++++ .../kotlin/types/TypeSubstitutor.java | 14 ++++++-------- 9 files changed, 70 insertions(+), 20 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index 557044010c4..b584543d397 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnExpress import org.jetbrains.kotlin.resolve.calls.callUtil.isExplicitSafeCall import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker import org.jetbrains.kotlin.resolve.calls.context.* +import org.jetbrains.kotlin.resolve.calls.inference.SubstitutionFilteringInternalResolveAnnotations import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall @@ -43,7 +44,6 @@ import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.* import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionTask -import org.jetbrains.kotlin.resolve.calls.tasks.isSynthesizedInvoke import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue @@ -127,7 +127,7 @@ public class CandidateResolver( "Explicit type argument expected for " + candidateDescriptor.getTypeParameters().get(index).getName())) } val substitution = FunctionDescriptorUtil.createSubstitution(candidateDescriptor as FunctionDescriptor, typeArguments) - val substitutor = TypeSubstitutor.create(substitution) + val substitutor = TypeSubstitutor.create(SubstitutionFilteringInternalResolveAnnotations(substitution)) if (expectedTypeArgumentCount != jetTypeArguments.size()) { candidateCall.addStatus(OTHER_ERROR) diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.kt b/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.kt new file mode 100644 index 00000000000..59e5422611d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.kt @@ -0,0 +1,13 @@ +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun Iterable<*>.filterIsInstance1(): List<@kotlin.internal.NoInfer R> = throw Exception() + +fun test(list: List) { + list.filterIsInstance1().map { it * 2} +} + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun foo(t: R): List<@kotlin.internal.NoInfer R> = throw Exception("$t") + +fun test() { + foo(1).map { it * 2} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.txt b/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.txt new file mode 100644 index 00000000000..bb3a67f8a10 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.txt @@ -0,0 +1,6 @@ +package + +@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun foo(/*0*/ t: R): kotlin.List +public fun test(): kotlin.Unit +public fun test(/*0*/ list: kotlin.List): kotlin.Unit +@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun kotlin.Iterable<*>.filterIsInstance1(): kotlin.List diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestWithStdLibGenerated.java index 20624878f4b..0cdb26ff94a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestWithStdLibGenerated.java @@ -696,6 +696,12 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic doTest(fileName); } + @TestMetadata("internalAnnotationsOnTypes.kt") + public void testInternalAnnotationsOnTypes() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/internalAnnotationsOnTypes.kt"); + doTest(fileName); + } + @TestMetadata("noInferAnnotation.kt") public void testNoInferAnnotation() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/noInferAnnotation.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/annotationsForResolve.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/annotationsForResolve.kt index b8948cec71b..09b469e2449 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/annotationsForResolve.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/annotationsForResolve.kt @@ -18,17 +18,22 @@ package org.jetbrains.kotlin.resolve.descriptorUtil import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.types.KtType private val NO_INFER_ANNOTATION_FQ_NAME = FqName("kotlin.internal.NoInfer") +private val EXACT_ANNOTATION_FQ_NAME = FqName("kotlin.internal.Exact") public fun KtType.hasNoInferAnnotation(): Boolean = annotations.hasAnnotation(NO_INFER_ANNOTATION_FQ_NAME) -private val EXACT_ANNOTATION_FQ_NAME = FqName("kotlin.internal.Exact") - public fun KtType.hasExactAnnotation(): Boolean = annotations.hasAnnotation(EXACT_ANNOTATION_FQ_NAME) +public fun Annotations.hasInternalAnnotationForResolve(): Boolean = + hasAnnotation(NO_INFER_ANNOTATION_FQ_NAME) || hasAnnotation(EXACT_ANNOTATION_FQ_NAME) + +public fun FqName.isInternalAnnotationForResolve() = this == NO_INFER_ANNOTATION_FQ_NAME || this == EXACT_ANNOTATION_FQ_NAME + private val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME = FqName("kotlin.internal.LowPriorityInOverloadResolution") public fun CallableDescriptor.hasLowPriorityInOverloadResolution(): Boolean = annotations.hasAnnotation(LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME) diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt index a3ecc64d5c5..c3863626641 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.EQUAL import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound @@ -29,9 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFrom -import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation -import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation -import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation +import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.scopes.KtScope import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE @@ -137,7 +136,8 @@ public class ConstraintSystemImpl : ConstraintSystem { substituteOriginal: Boolean ): TypeSubstitutor { val parameterToInferredValueMap = getParameterToInferredValueMap(allTypeParameterBounds, getDefaultValue, substituteOriginal) - return TypeConstructorSubstitution.createByParametersMap(parameterToInferredValueMap).buildSubstitutor() + val substitution = TypeConstructorSubstitution.createByParametersMap(parameterToInferredValueMap) + return SubstitutionFilteringInternalResolveAnnotations(substitution).buildSubstitutor() } override fun getStatus(): ConstraintSystemStatus = constraintSystemStatus @@ -546,12 +546,17 @@ private fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor { return TypeSubstitutor.create(SubstitutionWithCapturedTypeApproximation(getSubstitution())) } -private class SubstitutionWithCapturedTypeApproximation(val substitution: TypeSubstitution) : TypeSubstitution() { - override fun get(key: KtType) = substitution[key] - override fun isEmpty() = substitution.isEmpty() +private class SubstitutionWithCapturedTypeApproximation(substitution: TypeSubstitution) : DelegatedTypeSubstitution(substitution) { override fun approximateCapturedTypes() = true } +class SubstitutionFilteringInternalResolveAnnotations(substitution: TypeSubstitution) : DelegatedTypeSubstitution(substitution) { + override fun filterAnnotations(annotations: Annotations): Annotations { + if (!annotations.hasInternalAnnotationForResolve()) return annotations + return FilteredAnnotations(annotations) { !it.isInternalAnnotationForResolve() } + } +} + public fun ConstraintSystemImpl.registerTypeVariables(typeVariables: Map) { registerTypeVariables(typeVariables.keySet(), { typeVariables[it]!! }, { it }) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/DisjointKeysUnionTypeSubstitution.kt b/core/descriptors/src/org/jetbrains/kotlin/types/DisjointKeysUnionTypeSubstitution.kt index 9abec61ee37..2fba5aad778 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/DisjointKeysUnionTypeSubstitution.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/DisjointKeysUnionTypeSubstitution.kt @@ -16,7 +16,7 @@ package org.jetbrains.kotlin.types; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.descriptors.annotations.Annotations public class DisjointKeysUnionTypeSubstitution private constructor( private val first: TypeSubstitution, @@ -37,4 +37,6 @@ public class DisjointKeysUnionTypeSubstitution private constructor( override fun isEmpty() = false override fun approximateCapturedTypes() = first.approximateCapturedTypes() || second.approximateCapturedTypes() + + override fun filterAnnotations(annotations: Annotations) = second.filterAnnotations(first.filterAnnotations(annotations)) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt index 81978e1bf8b..a5def888ad0 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotations public abstract class TypeSubstitution { companion object { @@ -34,6 +35,8 @@ public abstract class TypeSubstitution { public open fun approximateCapturedTypes(): Boolean = false + public open fun filterAnnotations(annotations: Annotations) = annotations + public fun buildSubstitutor(): TypeSubstitutor = TypeSubstitutor.create(this) } @@ -123,4 +126,16 @@ private class CompositeTypeSubstitution( override fun isEmpty() = first.isEmpty() && second.isEmpty() // override fun approximateCapturedTypes() = first.approximateCapturedTypes() || second.approximateCapturedTypes() + + override fun filterAnnotations(annotations: Annotations): Annotations = second.filterAnnotations(first.filterAnnotations(annotations)) +} + +public open class DelegatedTypeSubstitution(val substitution: TypeSubstitution): TypeSubstitution() { + override fun get(key: KtType) = substitution.get(key) + + override fun isEmpty() = substitution.isEmpty() + + override fun approximateCapturedTypes() = substitution.approximateCapturedTypes() + + override fun filterAnnotations(annotations: Annotations) = substitution.filterAnnotations(annotations) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java index d32896b517f..f6f600adb63 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java @@ -30,7 +30,10 @@ import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope; import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; public class TypeSubstitutor { @@ -183,7 +186,7 @@ public class TypeSubstitutor { // substitutionType.annotations = replacement.annotations ++ type.annotations if (!type.getAnnotations().isEmpty()) { - Annotations typeAnnotations = filterOutUnsafeVariance(type.getAnnotations()); + Annotations typeAnnotations = filterOutUnsafeVariance(substitution.filterAnnotations(type.getAnnotations())); substitutedType = TypeUtilsKt.replaceAnnotations( substitutedType, new CompositeAnnotations(substitutedType.getAnnotations(), typeAnnotations) @@ -227,7 +230,7 @@ public class TypeSubstitutor { // Only type parameters of the corresponding class (or captured type parameters of outer declaration) are substituted // e.g. for return type Foo of 'add(..)' in 'class Foo { fun add(bar: Bar): Foo }' R shouldn't be substituted in the scope - TypeSubstitution substitutionFilteringTypeParameters = new TypeSubstitution() { + TypeSubstitution substitutionFilteringTypeParameters = new DelegatedTypeSubstitution(substitution) { private final Collection containedOrCapturedTypeParameters = TypeUtilsKt.getContainedAndCapturedTypeParameterConstructors(type); @@ -236,11 +239,6 @@ public class TypeSubstitutor { public TypeProjection get(@NotNull KtType key) { return containedOrCapturedTypeParameters.contains(key.getConstructor()) ? substitution.get(key) : null; } - - @Override - public boolean isEmpty() { - return substitution.isEmpty(); - } }; KtType substitutedType = KtTypeImpl.create(type.getAnnotations(), // Old annotations. This is questionable type.getConstructor(), // The same constructor