Introduce UnsafeVariance annotation
This commit is contained in:
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.typeBinding.TypeBinding
|
import org.jetbrains.kotlin.resolve.typeBinding.TypeBinding
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.resolve.typeBinding.createTypeBinding
|
import org.jetbrains.kotlin.resolve.typeBinding.createTypeBinding
|
||||||
import org.jetbrains.kotlin.resolve.typeBinding.createTypeBindingForReturnType
|
import org.jetbrains.kotlin.resolve.typeBinding.createTypeBindingForReturnType
|
||||||
import org.jetbrains.kotlin.psi.JetCallableDeclaration
|
import org.jetbrains.kotlin.psi.JetCallableDeclaration
|
||||||
@@ -161,7 +162,8 @@ class VarianceChecker(private val trace: BindingTrace) {
|
|||||||
val classifierDescriptor = jetType.getConstructor().getDeclarationDescriptor()
|
val classifierDescriptor = jetType.getConstructor().getDeclarationDescriptor()
|
||||||
if (classifierDescriptor is TypeParameterDescriptor) {
|
if (classifierDescriptor is TypeParameterDescriptor) {
|
||||||
val declarationVariance = classifierDescriptor.getVariance()
|
val declarationVariance = classifierDescriptor.getVariance()
|
||||||
if (!declarationVariance.allowsPosition(position)) {
|
if (!declarationVariance.allowsPosition(position)
|
||||||
|
&& !jetType.annotations.hasAnnotation(KotlinBuiltIns.FQ_NAMES.unsafeVariance)) {
|
||||||
diagnosticSink.report(
|
diagnosticSink.report(
|
||||||
Errors.TYPE_VARIANCE_CONFLICT.on(
|
Errors.TYPE_VARIANCE_CONFLICT.on(
|
||||||
psiElement,
|
psiElement,
|
||||||
|
|||||||
+4
@@ -1272,6 +1272,10 @@ public object Unit {
|
|||||||
/*primary*/ private constructor Unit()
|
/*primary*/ private constructor Unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.MustBeDocumented() @kotlin.annotation.annotation() public final class UnsafeVariance : kotlin.Annotation {
|
||||||
|
/*primary*/ public constructor UnsafeVariance()
|
||||||
|
}
|
||||||
|
|
||||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.VALUE_PARAMETER}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented() @kotlin.annotation.annotation() private final class crossinline : kotlin.Annotation {
|
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.VALUE_PARAMETER}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented() @kotlin.annotation.annotation() private final class crossinline : kotlin.Annotation {
|
||||||
/*primary*/ public constructor crossinline()
|
/*primary*/ public constructor crossinline()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
class A<out T, in E> {
|
||||||
|
fun foo(x: @UnsafeVariance T) {}
|
||||||
|
fun foo(x: @UnsafeVariance T, y: List<@UnsafeVariance T>): @UnsafeVariance E = null!!
|
||||||
|
|
||||||
|
fun bar(): List<@UnsafeVariance E> = null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(x: A<String, Any?>, cs: CharSequence, ls: List<CharSequence>) {
|
||||||
|
val y: A<CharSequence, String> = x
|
||||||
|
|
||||||
|
y.foo(cs)
|
||||||
|
val s: String = y.foo(cs, ls)
|
||||||
|
|
||||||
|
val ls2: List<String> = y.bar()
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ x: A<kotlin.String, kotlin.Any?>, /*1*/ cs: kotlin.CharSequence, /*2*/ ls: kotlin.List<kotlin.CharSequence>): kotlin.Unit
|
||||||
|
|
||||||
|
public final class A</*0*/ out T, /*1*/ in E> {
|
||||||
|
public constructor A</*0*/ out T, /*1*/ in E>()
|
||||||
|
public final fun bar(): kotlin.List<@kotlin.UnsafeVariance() E>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(/*0*/ x: @kotlin.UnsafeVariance() T): kotlin.Unit
|
||||||
|
public final fun foo(/*0*/ x: @kotlin.UnsafeVariance() T, /*1*/ y: kotlin.List<@kotlin.UnsafeVariance() T>): @kotlin.UnsafeVariance() E
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -6399,6 +6399,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("suppressVarianceConflict.kt")
|
||||||
|
public void testSuppressVarianceConflict() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/generics/nullability")
|
@TestMetadata("compiler/testData/diagnostics/tests/generics/nullability")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -119,6 +119,14 @@ public annotation class HiddenDeclaration
|
|||||||
@MustBeDocumented
|
@MustBeDocumented
|
||||||
private annotation class external
|
private annotation class external
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suppresses errors about variance conflict
|
||||||
|
*/
|
||||||
|
@Target(TYPE)
|
||||||
|
@Retention(SOURCE)
|
||||||
|
@MustBeDocumented
|
||||||
|
public annotation class UnsafeVariance
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies that the corresponding type should be ignored during type inference.
|
* Specifies that the corresponding type should be ignored during type inference.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ public abstract class KotlinBuiltIns {
|
|||||||
public final FqName retention = annotationName("Retention");
|
public final FqName retention = annotationName("Retention");
|
||||||
public final FqName repeatable = annotationName("Repeatable");
|
public final FqName repeatable = annotationName("Repeatable");
|
||||||
public final FqName mustBeDocumented = annotationName("MustBeDocumented");
|
public final FqName mustBeDocumented = annotationName("MustBeDocumented");
|
||||||
|
public final FqName unsafeVariance = fqName("UnsafeVariance");
|
||||||
|
|
||||||
public final FqName mutableList = fqName("MutableList");
|
public final FqName mutableList = fqName("MutableList");
|
||||||
public final FqName mutableSet = fqName("MutableSet");
|
public final FqName mutableSet = fqName("MutableSet");
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ public interface Annotations : Iterable<AnnotationDescriptor> {
|
|||||||
|
|
||||||
public fun findAnnotation(fqName: FqName): AnnotationDescriptor?
|
public fun findAnnotation(fqName: FqName): AnnotationDescriptor?
|
||||||
|
|
||||||
|
public fun hasAnnotation(fqName: FqName) = findAnnotation(fqName) != null
|
||||||
|
|
||||||
public fun findExternalAnnotation(fqName: FqName): AnnotationDescriptor?
|
public fun findExternalAnnotation(fqName: FqName): AnnotationDescriptor?
|
||||||
|
|
||||||
public fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget>
|
public fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget>
|
||||||
|
|||||||
Reference in New Issue
Block a user