[FIR] Add diagnostic CONFLICTING_PROJECTION

This commit is contained in:
Nick
2020-08-14 15:22:09 +03:00
parent d40bca4143
commit 091e12c093
21 changed files with 419 additions and 12 deletions
@@ -0,0 +1,95 @@
class None<T>
class In<in T>
class Out<out T>
fun a1(value: None<Int>) {}
fun a2(value: None<in Int>) {}
fun a3(value: None<out Int>) {}
fun a4(value: In<Int>) {}
fun a5(value: In<in Int>) {}
fun a6(value: <!CONFLICTING_PROJECTION!>In<out Int><!>) {}
fun a7(value: Out<Int>) {}
fun a8(value: <!CONFLICTING_PROJECTION!>Out<in Int><!>) {}
fun a9(value: Out<out Int>) {}
typealias A1<K> = None<K>
typealias A2<K> = None<in K>
typealias A3<K> = None<out K>
typealias A4<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = None<K>
typealias A5<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = None<in K>
typealias A6<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = None<out K>
typealias A7<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = None<K>
typealias A8<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = None<in K>
typealias A9<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = None<out K>
typealias A10<K> = In<K>
typealias A11<K> = In<in K>
typealias A12<K> = <!CONFLICTING_PROJECTION!>In<out K><!>
typealias A13<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = In<K>
typealias A14<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = In<in K>
typealias A15<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = <!CONFLICTING_PROJECTION!>In<out K><!>
typealias A16<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = In<K>
typealias A17<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = In<in K>
typealias A18<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = <!CONFLICTING_PROJECTION!>In<out K><!>
typealias A19<K> = Out<K>
typealias A20<K> = <!CONFLICTING_PROJECTION!>Out<in K><!>
typealias A21<K> = Out<out K>
typealias A22<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = Out<K>
typealias A23<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = <!CONFLICTING_PROJECTION!>Out<in K><!>
typealias A24<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in K<!>> = Out<out K>
typealias A25<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = Out<K>
typealias A26<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = <!CONFLICTING_PROJECTION!>Out<in K><!>
typealias A27<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out K<!>> = Out<out K>
class Outer<T> {
inner class Intermediate<K> {
inner class Inner<G> {
}
}
}
fun test1(): Outer<Int>.Intermediate<String>.Inner<Char> = Outer<Int>().Intermediate<String>().Inner()
fun test2(): Outer<in Int>.Intermediate<String>.Inner<Char> = Outer<Int>().Intermediate<String>().Inner()
fun test3(): Outer<out Int>.Intermediate<String>.Inner<Char> = Outer<Int>().Intermediate<String>().Inner()
fun test4(): Outer<Int>.Intermediate<in String>.Inner<Char> = Outer<Int>().Intermediate<String>().Inner()
fun test5(): Outer<Int>.Intermediate<out String>.Inner<Char> = Outer<Int>().Intermediate<String>().Inner()
fun test6(): Outer<Int>.Intermediate<String>.Inner<in Char> = Outer<Int>().Intermediate<String>().Inner()
fun test7(): Outer<Int>.Intermediate<String>.Inner<out Char> = Outer<Int>().Intermediate<String>().Inner()
fun test8(): Outer<in Int>.Intermediate<out String>.Inner<Char> = Outer<Int>().Intermediate<String>().Inner()
fun test9(): Outer<Int>.Intermediate<in String>.Inner<out Char> = Outer<Int>().Intermediate<String>().Inner()
class InOuter<in T> {
inner class OutIntermediate<out K> {
inner class InInner<in G> {
}
}
}
fun test10(): InOuter<Int>.OutIntermediate<String>.InInner<Char> = InOuter<Int>().OutIntermediate<String>().InInner()
fun test11(): InOuter<in Int>.OutIntermediate<String>.InInner<Char> = InOuter<Int>().OutIntermediate<String>().InInner()
fun test12(): <!CONFLICTING_PROJECTION!>InOuter<out Int>.OutIntermediate<String>.InInner<Char><!> = InOuter<Int>().OutIntermediate<String>().InInner()
fun test13(): <!CONFLICTING_PROJECTION!>InOuter<Int>.OutIntermediate<in String>.InInner<Char><!> = InOuter<Int>().OutIntermediate<String>().InInner()
fun test14(): InOuter<Int>.OutIntermediate<out String>.InInner<Char> = InOuter<Int>().OutIntermediate<String>().InInner()
fun test15(): InOuter<Int>.OutIntermediate<String>.InInner<in Char> = InOuter<Int>().OutIntermediate<String>().InInner()
fun test16(): <!CONFLICTING_PROJECTION!>InOuter<Int>.OutIntermediate<String>.InInner<out Char><!> = InOuter<Int>().OutIntermediate<String>().InInner()
fun test17(): InOuter<in Int>.OutIntermediate<out String>.InInner<Char> = InOuter<Int>().OutIntermediate<String>().InInner()
fun test18(): <!CONFLICTING_PROJECTION!>InOuter<Int>.OutIntermediate<in String>.InInner<out Char><!> = InOuter<Int>().OutIntermediate<String>().InInner()
@@ -0,0 +1,158 @@
FILE: conflictingProjection.kt
public final class None<T> : R|kotlin/Any| {
public constructor<T>(): R|None<T>| {
super<R|kotlin/Any|>()
}
}
public final class In<in T> : R|kotlin/Any| {
public constructor<in T>(): R|In<T>| {
super<R|kotlin/Any|>()
}
}
public final class Out<out T> : R|kotlin/Any| {
public constructor<out T>(): R|Out<T>| {
super<R|kotlin/Any|>()
}
}
public final fun a1(value: R|None<kotlin/Int>|): R|kotlin/Unit| {
}
public final fun a2(value: R|None<in kotlin/Int>|): R|kotlin/Unit| {
}
public final fun a3(value: R|None<out kotlin/Int>|): R|kotlin/Unit| {
}
public final fun a4(value: R|In<kotlin/Int>|): R|kotlin/Unit| {
}
public final fun a5(value: R|In<in kotlin/Int>|): R|kotlin/Unit| {
}
public final fun a6(value: R|In<out kotlin/Int>|): R|kotlin/Unit| {
}
public final fun a7(value: R|Out<kotlin/Int>|): R|kotlin/Unit| {
}
public final fun a8(value: R|Out<in kotlin/Int>|): R|kotlin/Unit| {
}
public final fun a9(value: R|Out<out kotlin/Int>|): R|kotlin/Unit| {
}
public final typealias A1<K> = R|None<K>|
public final typealias A2<K> = R|None<in K>|
public final typealias A3<K> = R|None<out K>|
public final typealias A4<in K> = R|None<K>|
public final typealias A5<in K> = R|None<in K>|
public final typealias A6<in K> = R|None<out K>|
public final typealias A7<out K> = R|None<K>|
public final typealias A8<out K> = R|None<in K>|
public final typealias A9<out K> = R|None<out K>|
public final typealias A10<K> = R|In<K>|
public final typealias A11<K> = R|In<in K>|
public final typealias A12<K> = R|In<out K>|
public final typealias A13<in K> = R|In<K>|
public final typealias A14<in K> = R|In<in K>|
public final typealias A15<in K> = R|In<out K>|
public final typealias A16<out K> = R|In<K>|
public final typealias A17<out K> = R|In<in K>|
public final typealias A18<out K> = R|In<out K>|
public final typealias A19<K> = R|Out<K>|
public final typealias A20<K> = R|Out<in K>|
public final typealias A21<K> = R|Out<out K>|
public final typealias A22<in K> = R|Out<K>|
public final typealias A23<in K> = R|Out<in K>|
public final typealias A24<in K> = R|Out<out K>|
public final typealias A25<out K> = R|Out<K>|
public final typealias A26<out K> = R|Out<in K>|
public final typealias A27<out K> = R|Out<out K>|
public final class Outer<T> : R|kotlin/Any| {
public constructor<T>(): R|Outer<T>| {
super<R|kotlin/Any|>()
}
public final inner class Intermediate<K, T> : R|kotlin/Any| {
public constructor<K>(): R|Outer.Intermediate<K, T>| {
super<R|kotlin/Any|>()
}
public final inner class Inner<G, K, T> : R|kotlin/Any| {
public constructor<G>(): R|Outer.Intermediate.Inner<G, K, T>| {
super<R|kotlin/Any|>()
}
}
}
}
public final fun test1(): R|Outer.Intermediate.Inner<kotlin/Char, kotlin/String, kotlin/Int>| {
^test1 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final fun test2(): R|Outer.Intermediate.Inner<kotlin/Char, kotlin/String, in kotlin/Int>| {
^test2 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final fun test3(): R|Outer.Intermediate.Inner<kotlin/Char, kotlin/String, out kotlin/Int>| {
^test3 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final fun test4(): R|Outer.Intermediate.Inner<kotlin/Char, in kotlin/String, kotlin/Int>| {
^test4 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final fun test5(): R|Outer.Intermediate.Inner<kotlin/Char, out kotlin/String, kotlin/Int>| {
^test5 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final fun test6(): R|Outer.Intermediate.Inner<in kotlin/Char, kotlin/String, kotlin/Int>| {
^test6 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final fun test7(): R|Outer.Intermediate.Inner<out kotlin/Char, kotlin/String, kotlin/Int>| {
^test7 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final fun test8(): R|Outer.Intermediate.Inner<kotlin/Char, out kotlin/String, in kotlin/Int>| {
^test8 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final fun test9(): R|Outer.Intermediate.Inner<out kotlin/Char, in kotlin/String, kotlin/Int>| {
^test9 R|/Outer.Outer|<R|kotlin/Int|>().R|/Outer.Intermediate.Intermediate|<R|kotlin/String|>().R|/Outer.Intermediate.Inner.Inner|<R|kotlin/Char|>()
}
public final class InOuter<in T> : R|kotlin/Any| {
public constructor<in T>(): R|InOuter<T>| {
super<R|kotlin/Any|>()
}
public final inner class OutIntermediate<out K, in T> : R|kotlin/Any| {
public constructor<out K>(): R|InOuter.OutIntermediate<K, T>| {
super<R|kotlin/Any|>()
}
public final inner class InInner<in G, out K, in T> : R|kotlin/Any| {
public constructor<in G>(): R|InOuter.OutIntermediate.InInner<G, K, T>| {
super<R|kotlin/Any|>()
}
}
}
}
public final fun test10(): R|InOuter.OutIntermediate.InInner<kotlin/Char, kotlin/String, kotlin/Int>| {
^test10 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Char|>()
}
public final fun test11(): R|InOuter.OutIntermediate.InInner<kotlin/Char, kotlin/String, in kotlin/Int>| {
^test11 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Char|>()
}
public final fun test12(): R|InOuter.OutIntermediate.InInner<kotlin/Char, kotlin/String, out kotlin/Int>| {
^test12 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Char|>()
}
public final fun test13(): R|InOuter.OutIntermediate.InInner<kotlin/Char, in kotlin/String, kotlin/Int>| {
^test13 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Char|>()
}
public final fun test14(): R|InOuter.OutIntermediate.InInner<kotlin/Char, out kotlin/String, kotlin/Int>| {
^test14 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Char|>()
}
public final fun test15(): R|InOuter.OutIntermediate.InInner<in kotlin/Char, kotlin/String, kotlin/Int>| {
^test15 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Char|>()
}
public final fun test16(): R|InOuter.OutIntermediate.InInner<out kotlin/Char, kotlin/String, kotlin/Int>| {
^test16 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Any?|>()
}
public final fun test17(): R|InOuter.OutIntermediate.InInner<kotlin/Char, out kotlin/String, in kotlin/Int>| {
^test17 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Char|>()
}
public final fun test18(): R|InOuter.OutIntermediate.InInner<out kotlin/Char, in kotlin/String, kotlin/Int>| {
^test18 R|/InOuter.InOuter|<R|kotlin/Int|>().R|/InOuter.OutIntermediate.OutIntermediate|<R|kotlin/String|>().R|/InOuter.OutIntermediate.InInner.InInner|<R|kotlin/Any?|>()
}
@@ -931,6 +931,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingOverloads.kt");
}
@TestMetadata("conflictingProjection.kt")
public void testConflictingProjection() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingProjection.kt");
}
@TestMetadata("constructorInInterface.kt")
public void testConstructorInInterface() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/constructorInInterface.kt");
@@ -931,6 +931,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingOverloads.kt");
}
@TestMetadata("conflictingProjection.kt")
public void testConflictingProjection() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingProjection.kt");
}
@TestMetadata("constructorInInterface.kt")
public void testConstructorInInterface() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/constructorInInterface.kt");
@@ -23,6 +23,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirTypeParametersInObjectChecker,
FirConflictsChecker,
FirConstructorInInterfaceChecker,
FirConflictingProjectionChecker,
)
override val memberDeclarationCheckers: List<FirMemberDeclarationChecker> = listOf(
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
// we can't just check for FirTypedDeclaration
// because it leads to duplicate reports for
// some cases. Maybe we should fix this via not
// visiting the same firs twice instead.
when (declaration) {
is FirPropertyAccessor -> {}
is FirProperty -> {
checkTypeRef(declaration.returnTypeRef, context, reporter)
}
is FirFunction<*> -> {
for (it in declaration.valueParameters) {
checkTypeRef(it.returnTypeRef, context, reporter)
}
checkTypeRef(declaration.returnTypeRef, context, reporter)
}
is FirClass<*> -> {
for (it in declaration.superTypeRefs) {
checkTypeRef(it, context, reporter)
}
}
is FirTypeAlias -> {
for (it in declaration.typeParameters) {
if (it.variance != Variance.INVARIANT) {
reporter.reportVarianceNotAllowed(it.source)
}
}
checkTypeRef(declaration.expandedTypeRef, context, reporter)
}
}
}
private fun checkTypeRef(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
val declaration = typeRef.safeAs<FirResolvedTypeRef>()
?.coneTypeSafe<ConeClassLikeType>()
?.lookupTag
?.toSymbol(context.session)
?.fir.safeAs<FirRegularClass>()
?: return
declaration.typeParameters.zip(typeRef.coneType.typeArguments).forEach { (proto, actual) ->
val protoVariance = proto.safeAs<FirTypeParameterRef>()
?.symbol?.fir
?.variance
?: return@forEach
if (protoVariance == Variance.INVARIANT) {
return@forEach
}
if (
actual is ConeKotlinTypeProjectionIn && protoVariance == Variance.OUT_VARIANCE ||
actual is ConeKotlinTypeProjectionOut && protoVariance == Variance.IN_VARIANCE
) {
reporter.reportConflictingProjections(typeRef.source, typeRef.coneType.toString())
return
}
}
}
private fun DiagnosticReporter.reportConflictingProjections(source: FirSourceElement?, desiredProjection: String) {
source?.let { report(FirErrors.CONFLICTING_PROJECTION.on(it, desiredProjection)) }
}
private fun DiagnosticReporter.reportVarianceNotAllowed(source: FirSourceElement?) {
source?.let { report(FirErrors.VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED.on(it)) }
}
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_IN_SUPERTYP
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_OVERLOADS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_VAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_OBJECT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL
@@ -104,6 +105,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_LABEL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_EXPECTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_INVOCATION_KIND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS
@@ -254,6 +256,15 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(TYPE_PARAMETERS_IN_OBJECT, "Type parameters are not allowed for objects")
// map.put(ILLEGAL_PROJECTION_USAGE, ...) // &
map.put(TYPE_PARAMETERS_IN_ENUM, "Enum class cannot have type parameters")
map.put(
CONFLICTING_PROJECTION,
"Projection is conflicting with variance of the corresponding type parameter of {0}. Remove the projection or replace it with ''*''",
TO_STRING
)
map.put(
VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED,
"Variance annotations are only allowed for type parameters of classes and interfaces"
)
// Redeclarations
map.put(MANY_COMPANION_OBJECTS, "Only one companion object is allowed per class")
@@ -125,6 +125,8 @@ object FirErrors {
val TYPE_PARAMETERS_IN_OBJECT by error0<FirSourceElement, PsiElement>()
val ILLEGAL_PROJECTION_USAGE by error0<FirSourceElement, PsiElement>()
val TYPE_PARAMETERS_IN_ENUM by error0<FirSourceElement, PsiElement>()
val CONFLICTING_PROJECTION by error1<FirSourceElement, PsiElement, String>()
val VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED by error0<FirSourceElement, PsiElement>()
// Redeclarations
val MANY_COMPANION_OBJECTS by error0<FirSourceElement, PsiElement>()
+4
View File
@@ -0,0 +1,4 @@
$TESTDATA_DIR$/conflictingProjection.kt
-Xuse-fir
-d
$TEMP_DIR$
+19
View File
@@ -0,0 +1,19 @@
class None<T>
class In<in T>
class Out<out T>
fun a1(value: None<Int>) {}
fun a2(value: None<in Int>) {}
fun a3(value: None<out Int>) {}
fun a7(value: Out<Int>) {}
fun a8(value: Out<in Int>) {}
fun a9(value: Out<out Int>) {}
typealias A1<K> = None<K>
typealias A2<K> = None<in K>
typealias A3<K> = None<out K>
typealias A13<in K> = In<K>
typealias A14<in K> = In<in K>
typealias A15<in K> = In<out K>
+16
View File
@@ -0,0 +1,16 @@
compiler/testData/cli/jvm/conflictingProjection.kt:10:15: error: projection is conflicting with variance of the corresponding type parameter of Out<in kotlin/Int>. Remove the projection or replace it with '*'
fun a8(value: Out<in Int>) {}
^
compiler/testData/cli/jvm/conflictingProjection.kt:17:15: error: variance annotations are only allowed for type parameters of classes and interfaces
typealias A13<in K> = In<K>
^
compiler/testData/cli/jvm/conflictingProjection.kt:18:15: error: variance annotations are only allowed for type parameters of classes and interfaces
typealias A14<in K> = In<in K>
^
compiler/testData/cli/jvm/conflictingProjection.kt:19:15: error: variance annotations are only allowed for type parameters of classes and interfaces
typealias A15<in K> = In<out K>
^
compiler/testData/cli/jvm/conflictingProjection.kt:19:23: error: projection is conflicting with variance of the corresponding type parameter of In<out K>. Remove the projection or replace it with '*'
typealias A15<in K> = In<out K>
^
COMPILATION_ERROR
@@ -4,11 +4,11 @@ class Inv<T>
class X
fun f1(p: In<in X>) {}
fun f2(p: In<out X>) {}
fun f2(p: <!CONFLICTING_PROJECTION!>In<out X><!>) {}
fun f3(p: In<X>) {}
fun f4(p: Out<out X>) {}
fun f5(p: Out<in X>) {}
fun f5(p: <!CONFLICTING_PROJECTION!>Out<in X><!>) {}
fun f6(p: Out<X>) {}
fun f6(p: Inv<X>) {}
@@ -51,7 +51,7 @@ val String.x1 get() = ""
fun <K> bar1(f: KFunction2<K, String, String>) {}
fun <K> bar2(f: KFunction2<out K, String, String>) {}
fun <K> bar2(f: <!CONFLICTING_PROJECTION!>KFunction2<out K, String, String><!>) {}
fun <K> bar3(f: Any?) {}
@@ -7,5 +7,5 @@ class In<in T>() {
fun test1(x: In<String>): Unit = x.f("1")
fun test2(x: In<in String>): Unit = x.f("1")
fun test3(x: In<out String>): Unit = x.f("1")
fun test3(x: <!CONFLICTING_PROJECTION!>In<out String><!>): Unit = x.f("1")
fun test4(x: In<*>): Unit = x.f("1")
@@ -6,8 +6,8 @@ interface Out<out T>
typealias InAlias<T> = In<T>
typealias OutAlias<T> = Out<T>
typealias TestOutForIn<T> = In<out T>
typealias TestInForOut<T> = Out<in T>
typealias TestOutForIn<T> = <!CONFLICTING_PROJECTION!>In<out T><!>
typealias TestInForOut<T> = <!CONFLICTING_PROJECTION!>Out<in T><!>
typealias TestOutForInWithinAlias<T> = InAlias<out T>
typealias TestInForOutWithinAlias<T> = OutAlias<in T>
@@ -1,6 +1,6 @@
// !DIAGNOSTICS: -UNUSED_TYPEALIAS_PARAMETER
typealias WithVariance<in X, out Y> = Int
typealias WithVariance<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in X<!>, <!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out Y<!>> = Int
typealias WithBounds1<T : T> = Int
typealias WithBounds2<X : Y, Y : X> = Int
@@ -6,11 +6,11 @@ class Inv<T>
typealias In1<T> = In<T>
typealias In2<T> = In<in T>
typealias In3<T> = In<out T>
typealias In3<T> = <!CONFLICTING_PROJECTION!>In<out T><!>
typealias In4<T> = In<*>
typealias Out1<T> = Out<T>
typealias Out2<T> = Out<in T>
typealias Out2<T> = <!CONFLICTING_PROJECTION!>Out<in T><!>
typealias Out3<T> = Out<out T>
typealias Out4<T> = Out<*>
@@ -35,7 +35,7 @@ interface Test<in I, out O, P> {
fun neOk6(i: In<In<O>>)
fun neOk7(i: Pair<In<I>, O>)
fun neOk8(i: Inv<out O>)
fun neOk9(i: In<out P>)
fun neOk9(i: <!CONFLICTING_PROJECTION!>In<out P><!>)
fun neOk10(i: Out<O>)
fun neOk11(i: Inv<in I>)
@@ -23,7 +23,7 @@ interface Test<in I, out O, P> {
var neOk7: Pair<In<I>, O>
var neOk8: Inv<in O>
var neOk9: Inv<in I>
var neOk10: In<out I>
var neOk10: <!CONFLICTING_PROJECTION!>In<out I><!>
var neOk11: I
var neOk12: In<O>
@@ -28,7 +28,7 @@ interface Test<in I, out O, P> {
fun neOk5(): Inv<O>
fun neOk6(): Pair<In<O>, I>
fun neOk7(): Inv<in O>
fun neOk8(): Out<in I>
fun neOk8(): <!CONFLICTING_PROJECTION!>Out<in I><!>
fun neOk10(): Inv<in O>
fun neOk11(): Inv<out I>
@@ -140,6 +140,11 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/jvm/conflictingOverloads.args");
}
@TestMetadata("conflictingProjection.args")
public void testConflictingProjection() throws Exception {
runTest("compiler/testData/cli/jvm/conflictingProjection.args");
}
@TestMetadata("coroutinesEnable.args")
public void testCoroutinesEnable() throws Exception {
runTest("compiler/testData/cli/jvm/coroutinesEnable.args");