From f2efd30a5d2f7f55ec7f9bda8834729f3cbdeecd Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 6 Oct 2015 22:10:37 +0300 Subject: [PATCH] Added 'NoInfer' and 'Exact' annotations --- compiler/testData/builtin-classes.txt | 8 +++++ .../annotationsForResolve/exactAnnotation.kt | 11 +++++++ .../annotationsForResolve/exactAnnotation.txt | 4 +++ .../noInferAnnotation.kt | 30 +++++++++++++++++++ .../noInferAnnotation.txt | 10 +++++++ .../checkers/JetDiagnosticsTestGenerated.java | 21 +++++++++++++ core/builtins/src/kotlin/Annotations.kt | 14 +++++++++ ...edAsHidden.kt => annotationsForResolve.kt} | 9 ++++++ .../calls/inference/ConstraintSystemImpl.kt | 7 +++++ 9 files changed, 114 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.kt create mode 100644 compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.txt create mode 100644 compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.kt create mode 100644 compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.txt rename core/descriptors/src/org/jetbrains/kotlin/resolve/{isAnnotatedAsHidden.kt => annotationsForResolve.kt} (69%) diff --git a/compiler/testData/builtin-classes.txt b/compiler/testData/builtin-classes.txt index ccdf558b75a..16eedc2303f 100644 --- a/compiler/testData/builtin-classes.txt +++ b/compiler/testData/builtin-classes.txt @@ -456,6 +456,10 @@ public abstract class Enum> : kotlin.Comparable { } } +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.annotation() internal final class Exact : kotlin.Annotation { + /*primary*/ public constructor Exact() +} + @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.MustBeDocumented() @kotlin.annotation.annotation() public final class Extension : kotlin.Annotation { /*primary*/ public constructor Extension() } @@ -1040,6 +1044,10 @@ public interface MutableSet : kotlin.Set, kotlin.MutableCollection): kotlin.Boolean } +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.annotation() internal final class NoInfer : kotlin.Annotation { + /*primary*/ public constructor NoInfer() +} + public final class Nothing { /*primary*/ private constructor Nothing() } diff --git a/compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.kt b/compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.kt new file mode 100644 index 00000000000..378c13a38b7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.kt @@ -0,0 +1,11 @@ +//!DIAGNOSTICS: -UNUSED_VARIABLE + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun List<@Exact T>.firstTyped(): U = throw Exception() + +fun test1(l: List) { + + val i: Int = l.firstTyped() + + val s: String = l.firstTyped() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.txt b/compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.txt new file mode 100644 index 00000000000..712abf2c627 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.txt @@ -0,0 +1,4 @@ +package + +public fun test1(/*0*/ l: kotlin.List): kotlin.Unit +@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun kotlin.List<@kotlin.Exact() T>.firstTyped(): U diff --git a/compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.kt b/compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.kt new file mode 100644 index 00000000000..21fc9a0488f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.kt @@ -0,0 +1,30 @@ +//!DIAGNOSTICS: -UNUSED_PARAMETER + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun test1(t1: T, t2: @NoInfer T): T = t1 + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun @NoInfer T.test2(t1: T): T = t1 + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun test3(t1: @NoInfer T): T = t1 + +fun usage() { + test1(1, "312") + 1.test2("") + test3("") +} + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun List.contains1(e: @NoInfer T): Boolean = true + +fun test(l: List) { + l.contains1("") +} + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun assertEquals1(e1: T, e2: @NoInfer T): Boolean = true + +fun test(s: String) { + assertEquals1(s, 11) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.txt b/compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.txt new file mode 100644 index 00000000000..8740379d18a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.txt @@ -0,0 +1,10 @@ +package + +@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun assertEquals1(/*0*/ e1: T, /*1*/ e2: @kotlin.NoInfer() T): kotlin.Boolean +public fun test(/*0*/ l: kotlin.List): kotlin.Unit +public fun test(/*0*/ s: kotlin.String): kotlin.Unit +@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun test1(/*0*/ t1: T, /*1*/ t2: @kotlin.NoInfer() T): T +@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun test3(/*0*/ t1: @kotlin.NoInfer() T): T +public fun usage(): kotlin.Unit +@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun kotlin.List.contains1(/*0*/ e: @kotlin.NoInfer() T): kotlin.Boolean +@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun @kotlin.NoInfer() T.test2(/*0*/ t1: T): T diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index b10e39ee5c7..aa17e6b8094 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -7293,6 +7293,27 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("compiler/testData/diagnostics/tests/inference/annotationsForResolve") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AnnotationsForResolve extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInAnnotationsForResolve() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/annotationsForResolve"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("exactAnnotation.kt") + public void testExactAnnotation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/annotationsForResolve/exactAnnotation.kt"); + doTest(fileName); + } + + @TestMetadata("noInferAnnotation.kt") + public void testNoInferAnnotation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/annotationsForResolve/noInferAnnotation.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/builtins/src/kotlin/Annotations.kt b/core/builtins/src/kotlin/Annotations.kt index f2a0af18271..2b3664873e9 100644 --- a/core/builtins/src/kotlin/Annotations.kt +++ b/core/builtins/src/kotlin/Annotations.kt @@ -118,3 +118,17 @@ public annotation class HiddenDeclaration @Retention(SOURCE) @MustBeDocumented private annotation class external + +/** + * Specifies that the corresponding type should be ignored during type inference. + */ +@Target(TYPE) +@Retention(SOURCE) +internal annotation class NoInfer + +/** + * Specifies that the constraint built for the type during type inference should be an equality one. + */ +@Target(TYPE) +@Retention(SOURCE) +internal annotation class Exact \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/isAnnotatedAsHidden.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/annotationsForResolve.kt similarity index 69% rename from core/descriptors/src/org/jetbrains/kotlin/resolve/isAnnotatedAsHidden.kt rename to core/descriptors/src/org/jetbrains/kotlin/resolve/annotationsForResolve.kt index e434b8c2027..b27edd07a31 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/isAnnotatedAsHidden.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/annotationsForResolve.kt @@ -17,8 +17,17 @@ package org.jetbrains.kotlin.resolve.descriptorUtil import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.name.FqName private val HIDDEN_ANNOTATION_FQ_NAME = FqName("kotlin.HiddenDeclaration") public fun DeclarationDescriptor.isAnnotatedAsHidden(): Boolean = annotations.findAnnotation(HIDDEN_ANNOTATION_FQ_NAME) != null + +private val NO_INFER_ANNOTATION_FQ_NAME = FqName("kotlin.NoInfer") + +public fun Annotated.hasNoInferAnnotation(): Boolean = annotations.findAnnotation(NO_INFER_ANNOTATION_FQ_NAME) != null + +private val EXACT_ANNOTATION_FQ_NAME = FqName("kotlin.Exact") + +public fun Annotated.hasExactAnnotation(): Boolean = annotations.findAnnotation(EXACT_ANNOTATION_FQ_NAME) != null \ No newline at end of file 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 75d095d25f6..18edd9490f8 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 @@ -29,6 +29,8 @@ 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.scopes.JetScope import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE @@ -286,6 +288,11 @@ public class ConstraintSystemImpl : ConstraintSystem { if (isErrorOrSpecialType(subType, constraintPosition) || isErrorOrSpecialType(superType, constraintPosition)) return if (subType == null || superType == null) return + if (subType.hasNoInferAnnotation() || superType.hasNoInferAnnotation()) return + if ((subType.hasExactAnnotation() || superType.hasExactAnnotation()) && (constraintKind != EQUAL)) { + return doAddConstraint(EQUAL, subType, superType, constraintContext, typeCheckingProcedure) + } + assert(!superType.isFunctionPlaceholder) { "The type for " + constraintPosition + " shouldn't be a placeholder for function type" }