Added 'OnlyInputTypes' annotation

This commit is contained in:
Svetlana Isakova
2015-10-16 15:49:46 +03:00
parent 082469aee4
commit a6ec5cecc0
11 changed files with 91 additions and 6 deletions
@@ -493,6 +493,7 @@ public interface Errors {
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_CANNOT_CAPTURE_TYPES = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> TYPE_INFERENCE_INCORPORATION_ERROR = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<PsiElement, TypeParameterDescriptor> TYPE_INFERENCE_ONLY_INPUT_TYPES = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<JetExpression, JetType, JetType> TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
@@ -610,6 +610,8 @@ public class DefaultErrorMessages {
MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Type inference failed: {0}", TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER);
MAP.put(TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR, "Type inference failed: {0}", TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR_RENDERER);
MAP.put(TYPE_INFERENCE_INCORPORATION_ERROR, "Type inference failed. Please try to specify type arguments explicitly.");
MAP.put(TYPE_INFERENCE_ONLY_INPUT_TYPES, "Type inference failed. The value of the type parameter {0} should be mentioned in input types " +
"(argument types, receiver type or expected type). Try to specify it explicitly.", NAME);
MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER);
MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: found: {1} required: {0}", RENDER_TYPE, RENDER_TYPE);
@@ -242,6 +242,10 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
else if (status.hasTypeInferenceIncorporationError()) {
trace.report(TYPE_INFERENCE_INCORPORATION_ERROR.on(reference));
}
else if (status.hasTypeParameterWithUnsatisfiedOnlyInputTypesError()) {
//todo
trace.report(TYPE_INFERENCE_ONLY_INPUT_TYPES.on(reference, data.descriptor.getTypeParameters().get(0)));
}
else {
assert status.hasUnknownParameters();
trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data));
@@ -0,0 +1,14 @@
//!DIAGNOSTICS: -UNUSED_PARAMETER
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <@kotlin.internal.OnlyInputTypes T> assertEquals1(t1: T, t2: T) {}
open class A
class B: A()
class C: A()
class D
fun test1(a: A, b: B, c: C) {
assertEquals1(a, b)
<!TYPE_INFERENCE_ONLY_INPUT_TYPES!>assertEquals1<!>(b, c)
}
@@ -0,0 +1,32 @@
package
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun </*0*/ T> assertEquals1(/*0*/ t1: T, /*1*/ t2: T): kotlin.Unit
public fun test1(/*0*/ a: A, /*1*/ b: B, /*2*/ c: C): kotlin.Unit
public open class A {
public constructor A()
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
}
public final class B : A {
public constructor B()
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
}
public final class C : A {
public constructor C()
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
}
public final class D {
public constructor D()
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
}
@@ -707,6 +707,12 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/noInferAnnotation.kt");
doTest(fileName);
}
@TestMetadata("resolveWithOnlyInputTypesAnnotation.kt")
public void testResolveWithOnlyInputTypesAnnotation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/resolveWithOnlyInputTypesAnnotation.kt");
doTest(fileName);
}
}
}
@@ -16,13 +16,18 @@
package org.jetbrains.kotlin.resolve.descriptorUtil
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.name.FqName
private val NO_INFER_ANNOTATION_FQ_NAME = FqName("kotlin.internal.NoInfer")
public fun Annotated.hasNoInferAnnotation(): Boolean = annotations.findAnnotation(NO_INFER_ANNOTATION_FQ_NAME) != null
public fun Annotated.hasNoInferAnnotation(): Boolean = annotations.hasAnnotation(NO_INFER_ANNOTATION_FQ_NAME)
private val EXACT_ANNOTATION_FQ_NAME = FqName("kotlin.internal.Exact")
public fun Annotated.hasExactAnnotation(): Boolean = annotations.findAnnotation(EXACT_ANNOTATION_FQ_NAME) != null
public fun Annotated.hasExactAnnotation(): Boolean = annotations.hasAnnotation(EXACT_ANNOTATION_FQ_NAME)
private val ONLY_INPUT_TYPES_FQ_NAME = FqName("kotlin.internal.OnlyInputTypes")
public fun TypeParameterDescriptor.hasOnlyInputTypesAnnotation(): Boolean = annotations.hasAnnotation(ONLY_INPUT_TYPES_FQ_NAME)
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
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.scopes.JetScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
@@ -82,6 +83,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
override fun hasContradiction() = hasParameterConstraintError() || hasConflictingConstraints()
|| hasCannotCaptureTypesError() || hasTypeInferenceIncorporationError()
|| hasTypeParameterWithUnsatisfiedOnlyInputTypesError()
override fun hasViolatedUpperBound() = !isSuccessful() && filterConstraintsOut(TYPE_BOUND_POSITION).getStatus().isSuccessful()
@@ -102,6 +104,9 @@ public class ConstraintSystemImpl : ConstraintSystem {
override fun hasCannotCaptureTypesError() = errors.any { it is CannotCapture }
override fun hasTypeInferenceIncorporationError() = errors.any { it is TypeInferenceError } || !satisfyInitialConstraints()
override fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError() =
localTypeParameterBounds.values.any { it.typeVariable.hasOnlyInputTypesAnnotation() && it.value == null }
}
private fun getParameterToInferredValueMap(
@@ -89,4 +89,6 @@ public interface ConstraintSystemStatus {
* Returns <tt>true</tt> if there's an error in constraint system incorporation.
*/
public fun hasTypeInferenceIncorporationError(): Boolean
public fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError(): Boolean
}
@@ -24,12 +24,11 @@ import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_B
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.JetTypeChecker
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.ArrayList
import java.util.LinkedHashSet
import java.util.*
public class TypeBoundsImpl(
override val typeVariable: TypeParameterDescriptor,
@@ -37,6 +36,10 @@ public class TypeBoundsImpl(
) : TypeBounds {
override val bounds = ArrayList<Bound>()
private val typesInBoundsSet: Set<JetType> by lazy {
bounds.filter { it.isProper }.map { it.constrainingType }.toSet()
}
private var resultValues: Collection<JetType>? = null
var isFixed: Boolean = false
@@ -144,6 +147,8 @@ public class TypeBoundsImpl(
values.addAll(filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND))
if (values.size == 1 && typeVariable.hasOnlyInputTypesAnnotation() && !tryPossibleAnswer(bounds, values.first())) return listOf()
return values
}
@@ -152,6 +157,8 @@ public class TypeBoundsImpl(
// a captured type might be an answer
if (!possibleAnswer.getConstructor().isDenotable() && !possibleAnswer.isCaptured()) return false
if (typeVariable.hasOnlyInputTypesAnnotation() && !typesInBoundsSet.contains(possibleAnswer)) return false
for (bound in bounds) {
when (bound.kind) {
LOWER_BOUND -> if (!JetTypeChecker.DEFAULT.isSubtypeOf(bound.constrainingType, possibleAnswer)) {
@@ -28,4 +28,11 @@ internal annotation class NoInfer
*/
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.SOURCE)
internal annotation class Exact
internal annotation class Exact
/**
* The value of this type parameter should be mentioned in input types (argument types, receiver type or expected type).
*/
@Target(AnnotationTarget.TYPE_PARAMETER)
@Retention(AnnotationRetention.SOURCE)
internal annotation class OnlyInputTypes