Added 'OnlyInputTypes' annotation
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
+2
@@ -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);
|
||||
|
||||
|
||||
+4
@@ -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));
|
||||
|
||||
+14
@@ -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)
|
||||
}
|
||||
+32
@@ -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
|
||||
}
|
||||
+6
@@ -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)
|
||||
+5
@@ -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(
|
||||
|
||||
+2
@@ -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
|
||||
}
|
||||
|
||||
+10
-3
@@ -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
|
||||
Reference in New Issue
Block a user