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_CANNOT_CAPTURE_TYPES = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> TYPE_INFERENCE_INCORPORATION_ERROR = DiagnosticFactory0.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);
|
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory2<JetExpression, JetType, JetType> TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.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_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_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_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_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);
|
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()) {
|
else if (status.hasTypeInferenceIncorporationError()) {
|
||||||
trace.report(TYPE_INFERENCE_INCORPORATION_ERROR.on(reference));
|
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 {
|
else {
|
||||||
assert status.hasUnknownParameters();
|
assert status.hasUnknownParameters();
|
||||||
trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data));
|
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");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/noInferAnnotation.kt");
|
||||||
doTest(fileName);
|
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
|
package org.jetbrains.kotlin.resolve.descriptorUtil
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
private val NO_INFER_ANNOTATION_FQ_NAME = FqName("kotlin.internal.NoInfer")
|
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")
|
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.calls.inference.constraintPosition.derivedFrom
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
|
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.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||||
@@ -82,6 +83,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
|
|
||||||
override fun hasContradiction() = hasParameterConstraintError() || hasConflictingConstraints()
|
override fun hasContradiction() = hasParameterConstraintError() || hasConflictingConstraints()
|
||||||
|| hasCannotCaptureTypesError() || hasTypeInferenceIncorporationError()
|
|| hasCannotCaptureTypesError() || hasTypeInferenceIncorporationError()
|
||||||
|
|| hasTypeParameterWithUnsatisfiedOnlyInputTypesError()
|
||||||
|
|
||||||
override fun hasViolatedUpperBound() = !isSuccessful() && filterConstraintsOut(TYPE_BOUND_POSITION).getStatus().isSuccessful()
|
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 hasCannotCaptureTypesError() = errors.any { it is CannotCapture }
|
||||||
|
|
||||||
override fun hasTypeInferenceIncorporationError() = errors.any { it is TypeInferenceError } || !satisfyInitialConstraints()
|
override fun hasTypeInferenceIncorporationError() = errors.any { it is TypeInferenceError } || !satisfyInitialConstraints()
|
||||||
|
|
||||||
|
override fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError() =
|
||||||
|
localTypeParameterBounds.values.any { it.typeVariable.hasOnlyInputTypesAnnotation() && it.value == null }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getParameterToInferredValueMap(
|
private fun getParameterToInferredValueMap(
|
||||||
|
|||||||
+2
@@ -89,4 +89,6 @@ public interface ConstraintSystemStatus {
|
|||||||
* Returns <tt>true</tt> if there's an error in constraint system incorporation.
|
* Returns <tt>true</tt> if there's an error in constraint system incorporation.
|
||||||
*/
|
*/
|
||||||
public fun hasTypeInferenceIncorporationError(): Boolean
|
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.TypeBounds.BoundKind.UPPER_BOUND
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
|
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.*
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
import java.util.LinkedHashSet
|
|
||||||
|
|
||||||
public class TypeBoundsImpl(
|
public class TypeBoundsImpl(
|
||||||
override val typeVariable: TypeParameterDescriptor,
|
override val typeVariable: TypeParameterDescriptor,
|
||||||
@@ -37,6 +36,10 @@ public class TypeBoundsImpl(
|
|||||||
) : TypeBounds {
|
) : TypeBounds {
|
||||||
override val bounds = ArrayList<Bound>()
|
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
|
private var resultValues: Collection<JetType>? = null
|
||||||
|
|
||||||
var isFixed: Boolean = false
|
var isFixed: Boolean = false
|
||||||
@@ -144,6 +147,8 @@ public class TypeBoundsImpl(
|
|||||||
|
|
||||||
values.addAll(filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND))
|
values.addAll(filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND))
|
||||||
|
|
||||||
|
if (values.size == 1 && typeVariable.hasOnlyInputTypesAnnotation() && !tryPossibleAnswer(bounds, values.first())) return listOf()
|
||||||
|
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +157,8 @@ public class TypeBoundsImpl(
|
|||||||
// a captured type might be an answer
|
// a captured type might be an answer
|
||||||
if (!possibleAnswer.getConstructor().isDenotable() && !possibleAnswer.isCaptured()) return false
|
if (!possibleAnswer.getConstructor().isDenotable() && !possibleAnswer.isCaptured()) return false
|
||||||
|
|
||||||
|
if (typeVariable.hasOnlyInputTypesAnnotation() && !typesInBoundsSet.contains(possibleAnswer)) return false
|
||||||
|
|
||||||
for (bound in bounds) {
|
for (bound in bounds) {
|
||||||
when (bound.kind) {
|
when (bound.kind) {
|
||||||
LOWER_BOUND -> if (!JetTypeChecker.DEFAULT.isSubtypeOf(bound.constrainingType, possibleAnswer)) {
|
LOWER_BOUND -> if (!JetTypeChecker.DEFAULT.isSubtypeOf(bound.constrainingType, possibleAnswer)) {
|
||||||
|
|||||||
@@ -28,4 +28,11 @@ internal annotation class NoInfer
|
|||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
@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