FE 1.0: report TYPE_VARIANCE_CONFLICT also on qualifier type arguments
#KT-51439 Fixed
This commit is contained in:
+12
@@ -17448,6 +17448,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/inner/traits.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVarianceConflict.kt")
|
||||
public void testTypeVarianceConflict() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/typeVarianceConflict.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVarianceConflictFeatureOn.kt")
|
||||
public void testTypeVarianceConflictFeatureOn() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/typeVarianceConflictFeatureOn.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("visibility.kt")
|
||||
public void testVisibility() throws Exception {
|
||||
|
||||
+12
@@ -17448,6 +17448,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inner/traits.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVarianceConflict.kt")
|
||||
public void testTypeVarianceConflict() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/typeVarianceConflict.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVarianceConflictFeatureOn.kt")
|
||||
public void testTypeVarianceConflictFeatureOn() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/typeVarianceConflictFeatureOn.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("visibility.kt")
|
||||
public void testVisibility() throws Exception {
|
||||
|
||||
+12
@@ -17448,6 +17448,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inner/traits.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVarianceConflict.kt")
|
||||
public void testTypeVarianceConflict() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/typeVarianceConflict.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVarianceConflictFeatureOn.kt")
|
||||
public void testTypeVarianceConflictFeatureOn() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/typeVarianceConflictFeatureOn.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("visibility.kt")
|
||||
public void testVisibility() throws Exception {
|
||||
|
||||
@@ -199,6 +199,8 @@ public interface Errors {
|
||||
DiagnosticFactory1.create(WARNING, VARIANCE_IN_PROJECTION);
|
||||
DiagnosticFactory1<PsiElement, VarianceConflictDiagnosticData> TYPE_VARIANCE_CONFLICT =
|
||||
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory1<PsiElement, VarianceConflictDiagnosticData> TYPE_VARIANCE_CONFLICT_WARNING =
|
||||
DiagnosticFactory1.create(WARNING, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory1<PsiElement, VarianceConflictDiagnosticData> TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE =
|
||||
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory0<PsiElement> FINITE_BOUNDS_VIOLATION = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
+3
@@ -807,6 +807,9 @@ public class DefaultErrorMessages {
|
||||
};
|
||||
MAP.put(TYPE_VARIANCE_CONFLICT, "Type parameter {0} is declared as ''{1}'' but occurs in ''{2}'' position in type {3}",
|
||||
varianceConflictDataRenderer);
|
||||
MAP.put(TYPE_VARIANCE_CONFLICT_WARNING, "Type parameter {0} is declared as ''{1}'' but occurs in ''{2}'' position in type {3}. " +
|
||||
"This diagnostic will become an error soon. See https://youtrack.jetbrains.com/issue/KT-50947",
|
||||
varianceConflictDataRenderer);
|
||||
MAP.put(TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE, "Type parameter {0} is declared as ''{1}'' but occurs in ''{2}'' position in abbreviated type {3}",
|
||||
varianceConflictDataRenderer);
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ class LazyTopDownAnalyzer(
|
||||
|
||||
overrideResolver.check(c)
|
||||
|
||||
varianceChecker.check(c)
|
||||
varianceChecker.check(c, languageVersionSettings)
|
||||
|
||||
declarationResolver.resolveAnnotationsOnFiles(c, fileScopeProvider)
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtTypeElement
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.psi.KtUserType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
@@ -30,6 +31,7 @@ interface TypeBinding<out P : PsiElement> {
|
||||
val type: KotlinType
|
||||
val isInAbbreviation: Boolean
|
||||
val arguments: List<TypeArgumentBinding<P>?>
|
||||
val isArgumentFromQualifier: Boolean get() = false
|
||||
}
|
||||
|
||||
interface TypeArgumentBinding<out P : PsiElement> {
|
||||
@@ -44,15 +46,20 @@ fun KtTypeReference.createTypeBinding(trace: BindingContext): TypeBinding<KtType
|
||||
return if (type == null || psiElement == null)
|
||||
null
|
||||
else
|
||||
createTypeBindingFromPsi(trace, psiElement, type)
|
||||
createTypeBindingFromPsi(trace, psiElement, type, isArgumentFromQualifier = false)
|
||||
}
|
||||
|
||||
private fun createTypeBindingFromPsi(trace: BindingContext, psiElement: KtTypeElement, type: KotlinType): TypeBinding<KtTypeElement> {
|
||||
private fun createTypeBindingFromPsi(
|
||||
trace: BindingContext,
|
||||
psiElement: KtTypeElement,
|
||||
type: KotlinType,
|
||||
isArgumentFromQualifier: Boolean
|
||||
): TypeBinding<KtTypeElement> {
|
||||
val abbreviatedType = type.getAbbreviatedType()
|
||||
return if (abbreviatedType != null)
|
||||
AbbreviatedTypeBinding(type, psiElement)
|
||||
AbbreviatedTypeBinding(type, psiElement, isArgumentFromQualifier)
|
||||
else
|
||||
ExplicitTypeBinding(trace, psiElement, type)
|
||||
ExplicitTypeBinding(trace, psiElement, type, isArgumentFromQualifier)
|
||||
}
|
||||
|
||||
fun KtCallableDeclaration.createTypeBindingForReturnType(trace: BindingContext): TypeBinding<PsiElement>? {
|
||||
@@ -74,13 +81,20 @@ private class TypeArgumentBindingImpl<out P : PsiElement>(
|
||||
private class ExplicitTypeBinding(
|
||||
private val trace: BindingContext,
|
||||
override val psiElement: KtTypeElement,
|
||||
override val type: KotlinType
|
||||
override val type: KotlinType,
|
||||
override val isArgumentFromQualifier: Boolean
|
||||
) : TypeBinding<KtTypeElement> {
|
||||
override val isInAbbreviation: Boolean get() = false
|
||||
|
||||
override val arguments: List<TypeArgumentBinding<KtTypeElement>?>
|
||||
get() {
|
||||
val psiTypeArguments = psiElement.typeArgumentsAsTypes
|
||||
val psiTypeArguments = psiElement.typeArgumentsAsTypes.toMutableList()
|
||||
val qualifierArgumentStartIndex = psiTypeArguments.size
|
||||
var current = psiElement
|
||||
while (current is KtUserType) {
|
||||
current = current.qualifier ?: break
|
||||
psiTypeArguments += current.typeArgumentsAsTypes
|
||||
}
|
||||
assert(type.getAbbreviatedType() == null) { "Non-abbreviated type expected: $type" }
|
||||
val isErrorBinding = run {
|
||||
val sizeIsEqual = psiTypeArguments.size == type.arguments.size
|
||||
@@ -90,16 +104,17 @@ private class ExplicitTypeBinding(
|
||||
|
||||
return psiTypeArguments.indices.map { index: Int ->
|
||||
// todo fix for List<*>
|
||||
val jetTypeReference = psiTypeArguments[index]
|
||||
val jetTypeElement = jetTypeReference?.typeElement ?: return@map null
|
||||
val typeReference = psiTypeArguments[index]
|
||||
val typeElement = typeReference?.typeElement ?: return@map null
|
||||
val isArgumentFromQualifier = index >= qualifierArgumentStartIndex
|
||||
|
||||
if (isErrorBinding) {
|
||||
val nextJetType = trace[BindingContext.TYPE, jetTypeReference] ?: return@map null
|
||||
val nextType = trace[BindingContext.TYPE, typeReference] ?: return@map null
|
||||
|
||||
return@map TypeArgumentBindingImpl(
|
||||
TypeProjectionImpl(nextJetType),
|
||||
TypeProjectionImpl(nextType),
|
||||
null,
|
||||
createTypeBindingFromPsi(trace, jetTypeElement, nextJetType)
|
||||
createTypeBindingFromPsi(trace, typeElement, nextType, isArgumentFromQualifier)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -107,7 +122,7 @@ private class ExplicitTypeBinding(
|
||||
return@map TypeArgumentBindingImpl(
|
||||
typeProjection,
|
||||
type.constructor.parameters[index],
|
||||
createTypeBindingFromPsi(trace, jetTypeElement, typeProjection.type)
|
||||
createTypeBindingFromPsi(trace, typeElement, typeProjection.type, isArgumentFromQualifier)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -115,13 +130,14 @@ private class ExplicitTypeBinding(
|
||||
|
||||
private class AbbreviatedTypeBinding(
|
||||
override val type: KotlinType,
|
||||
override val psiElement: KtTypeElement
|
||||
override val psiElement: KtTypeElement,
|
||||
override val isArgumentFromQualifier: Boolean
|
||||
) : TypeBinding<KtTypeElement> {
|
||||
override val isInAbbreviation: Boolean get() = true
|
||||
|
||||
override val arguments: List<TypeArgumentBinding<KtTypeElement>?>
|
||||
get() = createTypeArgumentBindingsWithSinglePsiElement(type) { argumentType ->
|
||||
AbbreviatedTypeBinding(argumentType, psiElement)
|
||||
AbbreviatedTypeBinding(argumentType, psiElement, isArgumentFromQualifier)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ package org.jetbrains.kotlin.resolve
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.ReportTypeVarianceConflictOnQualifierArguments
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl
|
||||
@@ -43,7 +46,8 @@ class ManualVariance(val descriptor: TypeParameterDescriptor, val variance: Vari
|
||||
class VarianceChecker(trace: BindingTrace) {
|
||||
private val core = VarianceCheckerCore(trace.bindingContext, trace)
|
||||
|
||||
fun check(c: TopDownAnalysisContext) {
|
||||
fun check(c: TopDownAnalysisContext, languageVersionSettings: LanguageVersionSettings) {
|
||||
core.languageVersionSettings = languageVersionSettings
|
||||
core.check(c)
|
||||
}
|
||||
}
|
||||
@@ -59,6 +63,7 @@ class VarianceCheckerCore(
|
||||
private val diagnosticSink: DiagnosticSink,
|
||||
private val manualVariance: ManualVariance? = null
|
||||
) {
|
||||
internal var languageVersionSettings: LanguageVersionSettings? = null
|
||||
|
||||
fun check(c: TopDownAnalysisContext) {
|
||||
checkClasses(c)
|
||||
@@ -153,7 +158,17 @@ class VarianceCheckerCore(
|
||||
) {
|
||||
val varianceConflictDiagnosticData = VarianceConflictDiagnosticData(containingType, classifierDescriptor, position)
|
||||
val diagnostic =
|
||||
if (isInAbbreviation) Errors.TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE else Errors.TYPE_VARIANCE_CONFLICT
|
||||
when {
|
||||
isArgumentFromQualifier -> {
|
||||
if (languageVersionSettings?.supportsFeature(ReportTypeVarianceConflictOnQualifierArguments) == true) {
|
||||
Errors.TYPE_VARIANCE_CONFLICT
|
||||
} else {
|
||||
Errors.TYPE_VARIANCE_CONFLICT_WARNING
|
||||
}
|
||||
}
|
||||
isInAbbreviation -> Errors.TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE
|
||||
else -> Errors.TYPE_VARIANCE_CONFLICT
|
||||
}
|
||||
diagnosticSink.report(diagnostic.on(psiElement, varianceConflictDiagnosticData))
|
||||
}
|
||||
return declarationVariance.allowsPosition(position)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// !LANGUAGE: -ReportTypeVarianceConflictOnQualifierArguments
|
||||
|
||||
class Bar<K> {
|
||||
inner class Inner {
|
||||
inner class SuperInner
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Foo<in T> {
|
||||
abstract fun yuckyEventHandler(
|
||||
fn: Bar<<!TYPE_VARIANCE_CONFLICT!>T<!>>.Inner.() -> Unit
|
||||
): () -> Unit
|
||||
|
||||
abstract fun second(fn: Bar<<!TYPE_VARIANCE_CONFLICT!>T<!>>.Inner)
|
||||
|
||||
abstract fun third(fn: Bar<<!TYPE_VARIANCE_CONFLICT!>T<!>>.Inner.SuperInner)
|
||||
}
|
||||
|
||||
abstract class Baz<out T> {
|
||||
abstract fun yuckyEventHandler(
|
||||
fn: Bar<<!TYPE_VARIANCE_CONFLICT!>T<!>>.Inner.() -> Unit
|
||||
): () -> Unit
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// !LANGUAGE: -ReportTypeVarianceConflictOnQualifierArguments
|
||||
|
||||
class Bar<K> {
|
||||
inner class Inner {
|
||||
inner class SuperInner
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Foo<in T> {
|
||||
abstract fun yuckyEventHandler(
|
||||
fn: Bar<<!TYPE_VARIANCE_CONFLICT_WARNING!>T<!>>.Inner.() -> Unit
|
||||
): () -> Unit
|
||||
|
||||
abstract fun second(fn: Bar<<!TYPE_VARIANCE_CONFLICT_WARNING!>T<!>>.Inner)
|
||||
|
||||
abstract fun third(fn: Bar<<!TYPE_VARIANCE_CONFLICT_WARNING!>T<!>>.Inner.SuperInner)
|
||||
}
|
||||
|
||||
abstract class Baz<out T> {
|
||||
abstract fun yuckyEventHandler(
|
||||
fn: Bar<<!TYPE_VARIANCE_CONFLICT_WARNING!>T<!>>.Inner.() -> Unit
|
||||
): () -> Unit
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package
|
||||
|
||||
public final class Bar</*0*/ K> {
|
||||
public constructor Bar</*0*/ K>()
|
||||
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 inner class Inner /*captured type parameters: /*0*/ K*/ {
|
||||
public constructor Inner()
|
||||
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 inner class SuperInner /*captured type parameters: /*0*/ K*/ {
|
||||
public constructor SuperInner()
|
||||
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 abstract class Baz</*0*/ out T> {
|
||||
public constructor Baz</*0*/ out T>()
|
||||
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 abstract fun yuckyEventHandler(/*0*/ fn: Bar<T>.Inner.() -> kotlin.Unit): () -> kotlin.Unit
|
||||
}
|
||||
|
||||
public abstract class Foo</*0*/ in T> {
|
||||
public constructor Foo</*0*/ in T>()
|
||||
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 abstract fun second(/*0*/ fn: Bar<T>.Inner): kotlin.Unit
|
||||
public abstract fun third(/*0*/ fn: Bar<T>.Inner.SuperInner): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
public abstract fun yuckyEventHandler(/*0*/ fn: Bar<T>.Inner.() -> kotlin.Unit): () -> kotlin.Unit
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: +ReportTypeVarianceConflictOnQualifierArguments
|
||||
|
||||
class Bar<K> {
|
||||
inner class Inner
|
||||
}
|
||||
|
||||
abstract class Foo<in T> {
|
||||
abstract fun yuckyEventHandler(
|
||||
fn: Bar<<!TYPE_VARIANCE_CONFLICT!>T<!>>.Inner.() -> Unit
|
||||
): () -> Unit
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package
|
||||
|
||||
public final class Bar</*0*/ K> {
|
||||
public constructor Bar</*0*/ K>()
|
||||
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 inner class Inner /*captured type parameters: /*0*/ K*/ {
|
||||
public constructor Inner()
|
||||
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 abstract class Foo</*0*/ in T> {
|
||||
public constructor Foo</*0*/ in T>()
|
||||
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 abstract fun yuckyEventHandler(/*0*/ fn: Bar<T>.Inner.() -> kotlin.Unit): () -> kotlin.Unit
|
||||
}
|
||||
Generated
+12
@@ -17454,6 +17454,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/traits.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVarianceConflict.kt")
|
||||
public void testTypeVarianceConflict() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/typeVarianceConflict.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVarianceConflictFeatureOn.kt")
|
||||
public void testTypeVarianceConflictFeatureOn() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inner/typeVarianceConflictFeatureOn.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("visibility.kt")
|
||||
public void testVisibility() throws Exception {
|
||||
|
||||
@@ -269,6 +269,7 @@ enum class LanguageFeature(
|
||||
ForbidExtensionFunctionTypeOnNonFunctionTypes(KOTLIN_1_9), // related to KT-43527
|
||||
ProhibitEnumDeclaringClass(KOTLIN_1_9, kind = BUG_FIX), // KT-49653
|
||||
StopPropagatingDeprecationThroughOverrides(KOTLIN_1_9, kind = BUG_FIX), // KT-47902
|
||||
ReportTypeVarianceConflictOnQualifierArguments(KOTLIN_1_9, kind = BUG_FIX), // KT-50947
|
||||
|
||||
// Disabled for indefinite time. See KT-48535 and related discussion
|
||||
ApproximateIntegerLiteralTypesInReceiverPosition(sinceVersion = null),
|
||||
|
||||
Reference in New Issue
Block a user