From 9dbcd8b55ff113c2fee1d800ecc74a85dfb97f79 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 19 Jan 2015 16:52:21 +0300 Subject: [PATCH] Approximate captured types only when necessary --- .../resolve/FunctionDescriptorUtil.java | 5 ---- .../notApproximateWhenCopyDescriptors.kt | 7 +++++ .../notApproximateWhenCopyDescriptors.txt | 26 +++++++++++++++++++ .../checkers/JetDiagnosticsTestGenerated.java | 6 +++++ .../calls/inference/ConstraintSystemImpl.kt | 15 +++++++++-- .../kotlin/types/CapturedTypeApproximation.kt | 5 +--- .../types/CompositeTypeSubstitution.java | 10 ++++++- .../kotlin/types/DescriptorSubstitutor.java | 5 ++++ .../kotlin/types/TypeSubstitution.java | 15 ++++++++--- .../kotlin/types/TypeSubstitutor.java | 5 +++- 10 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.kt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java index 81bc3620ac3..96549fef823 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java @@ -39,11 +39,6 @@ public class FunctionDescriptorUtil { return null; } - @Override - public boolean isEmpty() { - return false; - } - @Override public String toString() { return "FunctionDescriptorUtil.MAKE_TYPE_PARAMETERS_FRESH"; diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.kt new file mode 100644 index 00000000000..7b4046ca94a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.kt @@ -0,0 +1,7 @@ +class Bar + +fun Bar.foo() = 42 + +object MyObject { + fun foo(bar: Bar) = bar.foo() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.txt new file mode 100644 index 00000000000..332ac19e4b0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.txt @@ -0,0 +1,26 @@ +package + +internal fun Bar.foo(): kotlin.Int + +internal final class Bar { + public constructor Bar() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal object MyObject { + private constructor MyObject() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + internal final fun foo(/*0*/ bar: Bar): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public class object : MyObject { + private constructor () + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + internal final override /*1*/ /*fake_override*/ fun foo(/*0*/ bar: Bar): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 0d68588a63e..c624e33b5db 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -5208,6 +5208,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("notApproximateWhenCopyDescriptors.kt") + public void testNotApproximateWhenCopyDescriptors() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.kt"); + doTest(fileName); + } + @TestMetadata("overApproximationForInCaptured.kt") public void testOverApproximationForInCaptured() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/overApproximationForInCaptured.kt"); 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 e1fd463afc2..5dfef831073 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 @@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.CompoundC import org.jetbrains.kotlin.types.getCustomTypeVariable import org.jetbrains.kotlin.types.isFlexible import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound +import org.jetbrains.kotlin.types.TypeSubstitution public class ConstraintSystemImpl : ConstraintSystem { @@ -437,9 +438,9 @@ public class ConstraintSystemImpl : ConstraintSystem { return if (typeParameterDescriptor != null && isMyTypeVariable(typeParameterDescriptor)) typeParameterDescriptor else null } - override fun getResultingSubstitutor() = replaceUninferredBySpecialErrorType() + override fun getResultingSubstitutor() = replaceUninferredBySpecialErrorType().setApproximateCapturedTypes() - override fun getCurrentSubstitutor() = replaceUninferredBy(TypeUtils.DONT_CARE) + override fun getCurrentSubstitutor() = replaceUninferredBy(TypeUtils.DONT_CARE).setApproximateCapturedTypes() private fun createCorrespondingExtensionFunctionType(functionType: JetType, receiverType: JetType): JetType { assert(KotlinBuiltIns.isFunctionType(functionType)) @@ -461,3 +462,13 @@ public class ConstraintSystemImpl : ConstraintSystem { return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType) } } + +private fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor { + return TypeSubstitutor.create(SubstitutionWithCapturedTypeApproximation(getSubstitution())) +} + +private class SubstitutionWithCapturedTypeApproximation(val substitution: TypeSubstitution) : TypeSubstitution() { + override fun get(key: TypeConstructor?) = substitution[key] + override fun isEmpty() = substitution.isEmpty() + override fun approximateCapturedTypes() = true +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt b/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt index a89eb9c4743..61c2cb60aa0 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt @@ -74,8 +74,6 @@ public fun approximateCapturedTypesIfNecessary(typeProjection: TypeProjection?): if (typeProjection == null) return null val type = typeProjection.getType() - //todo temporary hack to compile 'kotlin' - if (type is LazyType) return typeProjection if (!TypeUtils.containsSpecialType(type, { it.isCaptured() })) { return typeProjection } @@ -89,11 +87,10 @@ public fun approximateCapturedTypesIfNecessary(typeProjection: TypeProjection?): } private fun substituteCapturedTypes(typeProjection: TypeProjection): TypeProjection? { - val typeSubstitutor = TypeSubstitutor.create(object : TypeSubstitution { + val typeSubstitutor = TypeSubstitutor.create(object : TypeSubstitution() { override fun get(typeConstructor: TypeConstructor?): TypeProjection? { return (typeConstructor as? CapturedTypeConstructor)?.typeProjection } - override fun isEmpty() = false }) return typeSubstitutor.substituteWithoutApproximation(typeProjection) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/CompositeTypeSubstitution.java b/core/descriptors/src/org/jetbrains/kotlin/types/CompositeTypeSubstitution.java index 4067ac3e43e..2e6aaab36f3 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/CompositeTypeSubstitution.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/CompositeTypeSubstitution.java @@ -18,7 +18,7 @@ package org.jetbrains.kotlin.types; import org.jetbrains.annotations.NotNull; -public class CompositeTypeSubstitution implements TypeSubstitution { +public class CompositeTypeSubstitution extends TypeSubstitution { private final TypeSubstitution[] inner; public CompositeTypeSubstitution(@NotNull TypeSubstitution... inner) { @@ -42,6 +42,14 @@ public class CompositeTypeSubstitution implements TypeSubstitution { return true; } + @Override + public boolean approximateCapturedTypes() { + for (TypeSubstitution substitution : inner) { + if (substitution.approximateCapturedTypes()) return true; + } + return false; + } + @Override public String toString() { StringBuilder builder = new StringBuilder(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java b/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java index 7878ba8a247..8e2f40e0d58 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java @@ -53,6 +53,11 @@ public class DescriptorSubstitutor { return originalSubstitutor.isEmpty() && mutableSubstitution.isEmpty(); } + @Override + public boolean approximateCapturedTypes() { + return originalSubstitutor.getSubstitution().approximateCapturedTypes(); + } + @Override public String toString() { return "DescriptorSubstitutor.substituteTypeParameters(" + mutableSubstitution + " / " + originalSubstitutor.getSubstitution() + ")"; diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.java index e619330d8d3..cabf947aa4d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.java @@ -18,8 +18,8 @@ package org.jetbrains.kotlin.types; import org.jetbrains.annotations.Nullable; -public interface TypeSubstitution { - TypeSubstitution EMPTY = new TypeSubstitution() { +public abstract class TypeSubstitution { + public static final TypeSubstitution EMPTY = new TypeSubstitution() { @Override public TypeProjection get(TypeConstructor key) { return null; @@ -37,6 +37,13 @@ public interface TypeSubstitution { }; @Nullable - TypeProjection get(TypeConstructor key); - boolean isEmpty(); + public abstract TypeProjection get(TypeConstructor key); + + public boolean isEmpty() { + return false; + } + + public boolean approximateCapturedTypes() { + return false; + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java index bf9eb472fcb..7401fc67e87 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java @@ -31,7 +31,7 @@ public class TypeSubstitutor { private static final int MAX_RECURSION_DEPTH = 100; - public static class MapToTypeSubstitutionAdapter implements TypeSubstitution { + public static class MapToTypeSubstitutionAdapter extends TypeSubstitution { private final @NotNull Map substitutionContext; public MapToTypeSubstitutionAdapter(@NotNull Map substitutionContext) { @@ -142,6 +142,9 @@ public class TypeSubstitutor { @Nullable public TypeProjection substitute(@NotNull TypeProjection typeProjection) { TypeProjection substitutedTypeProjection = substituteWithoutApproximation(typeProjection); + if (!substitution.approximateCapturedTypes()) { + return substitutedTypeProjection; + } return TypesApproximationPackage.approximateCapturedTypesIfNecessary(substitutedTypeProjection); }