[FIR] Preserve enhanced mutability when nullability was enhanced for warning

#KT-56989
This commit is contained in:
Kirill Rakhman
2023-10-23 11:57:32 +02:00
committed by Space Team
parent a63ec9efdc
commit 2005446296
10 changed files with 118 additions and 12 deletions
@@ -1189,6 +1189,12 @@ public class FirPsiOldFrontendForeignAnnotationsCompiledJavaTestGenerated extend
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/methodWithTypeParameter.kt");
}
@Test
@TestMetadata("mutabilityAndNullabilityForWarning.kt")
public void testMutabilityAndNullabilityForWarning() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/mutabilityAndNullabilityForWarning.kt");
}
@Test
@TestMetadata("notNullVarargsOverrides.kt")
public void testNotNullVarargsOverrides() throws Exception {
@@ -1247,6 +1247,12 @@ public class FirPsiOldFrontendForeignAnnotationsCompiledJavaWithPsiClassReadingT
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/methodWithTypeParameter.kt");
}
@Test
@TestMetadata("mutabilityAndNullabilityForWarning.kt")
public void testMutabilityAndNullabilityForWarning() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/mutabilityAndNullabilityForWarning.kt");
}
@Test
@TestMetadata("notNullVarargsOverrides.kt")
public void testNotNullVarargsOverrides() throws Exception {
@@ -1247,6 +1247,12 @@ public class FirPsiOldFrontendForeignAnnotationsSourceJavaTestGenerated extends
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/methodWithTypeParameter.kt");
}
@Test
@TestMetadata("mutabilityAndNullabilityForWarning.kt")
public void testMutabilityAndNullabilityForWarning() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/mutabilityAndNullabilityForWarning.kt");
}
@Test
@TestMetadata("notNullVarargsOverrides.kt")
public void testNotNullVarargsOverrides() throws Exception {
@@ -151,7 +151,10 @@ internal fun FirExpression.checkExpressionForEnhancedTypeMismatch(
val (actualTypeForComparison, expectedTypeForComparison) = getEnhancedTypesForComparison(actualType, expectedType, context)
?: return
if (!actualTypeForComparison.isSubtypeOf(context.session.typeContext, expectedTypeForComparison)) {
if (!actualTypeForComparison.isSubtypeOf(context.session.typeContext, expectedTypeForComparison) &&
// Don't report anything if the original types didn't match.
actualType.isSubtypeOf(context.session.typeContext, expectedType.asExpectedFunctionTypeIfSam(actualType, context))
) {
reporter.reportOn(source, factory, actualTypeForComparison, expectedTypeForComparison, context)
}
}
@@ -175,16 +178,22 @@ private fun getEnhancedTypesForComparison(
val actualTypeForComparison = enhancedActualType ?: actualType
val expectedTypeForComparison = enhancedExpectedType ?: expectedType
val expectedTypeAsFunctionTypeIfSam = if (
actualTypeForComparison.isSomeFunctionType(context.session) &&
!expectedTypeForComparison.isSomeFunctionType(context.session)
) {
// TODO remove after KT-62847
val samResolver = FirSamResolver(context.session, context.scopeSession)
samResolver.getFunctionTypeForPossibleSamType(expectedTypeForComparison) ?: expectedTypeForComparison
} else {
expectedTypeForComparison
}
val expectedTypeAsFunctionTypeIfSam = expectedTypeForComparison.asExpectedFunctionTypeIfSam(actualTypeForComparison, context)
return actualTypeForComparison to expectedTypeAsFunctionTypeIfSam
}
/**
* If the receiver is a SAM type and the [actualType] is a function type, converts the receiver to the corresponding function type.
* Otherwise, returns receiver.
*
* TODO remove after KT-62847
* */
private fun ConeKotlinType.asExpectedFunctionTypeIfSam(actualType: ConeKotlinType, context: CheckerContext): ConeKotlinType {
if (!actualType.isSomeFunctionType(context.session) || isSomeFunctionType(context.session)) {
return this
}
val samResolver = FirSamResolver(context.session, context.scopeSession)
return samResolver.getFunctionTypeForPossibleSamType(this) ?: this
}
@@ -106,7 +106,14 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
)
return if (effectiveQualifiers.isNullabilityQualifierForWarning && enhanced != null) {
this.withAttributes(attributes.plus(EnhancedTypeForWarningAttribute(enhanced)))
val newAttributes = attributes.plus(EnhancedTypeForWarningAttribute(enhanced))
if (enhancedTag != lookupTag) {
// Handle case when mutability was enhanced and nullability was enhanced for warning.
enhancedTag.constructType(typeArguments, isNullable, newAttributes)
} else {
this.withAttributes(newAttributes)
}
} else {
enhanced
}
@@ -0,0 +1,27 @@
// NULLABILITY_ANNOTATIONS: @org.jetbrains.annotations:warn
// DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: ReadOnly.java
package org.jetbrains.annotations;
public @interface ReadOnly {}
// FILE: J.java
import java.util.List;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
public class J {
@ReadOnly
@Nullable
public static List<String> foo() {
return null;
}
}
// FILE: main.kt
fun main() {
takeMutable(<!ARGUMENT_TYPE_MISMATCH!>J.foo()<!>)
}
fun takeMutable(l: MutableList<String>) {}
@@ -0,0 +1,27 @@
// NULLABILITY_ANNOTATIONS: @org.jetbrains.annotations:warn
// DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: ReadOnly.java
package org.jetbrains.annotations;
public @interface ReadOnly {}
// FILE: J.java
import java.util.List;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
public class J {
@ReadOnly
@Nullable
public static List<String> foo() {
return null;
}
}
// FILE: main.kt
fun main() {
takeMutable(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>J.foo()<!>)
}
fun takeMutable(l: MutableList<String>) {}
@@ -1189,6 +1189,12 @@ public class ForeignAnnotationsCompiledJavaTestGenerated extends AbstractForeign
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/methodWithTypeParameter.kt");
}
@Test
@TestMetadata("mutabilityAndNullabilityForWarning.kt")
public void testMutabilityAndNullabilityForWarning() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/mutabilityAndNullabilityForWarning.kt");
}
@Test
@TestMetadata("notNullVarargsOverrides.kt")
public void testNotNullVarargsOverrides() throws Exception {
@@ -1247,6 +1247,12 @@ public class ForeignAnnotationsCompiledJavaWithPsiClassReadingTestGenerated exte
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/methodWithTypeParameter.kt");
}
@Test
@TestMetadata("mutabilityAndNullabilityForWarning.kt")
public void testMutabilityAndNullabilityForWarning() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/mutabilityAndNullabilityForWarning.kt");
}
@Test
@TestMetadata("notNullVarargsOverrides.kt")
public void testNotNullVarargsOverrides() throws Exception {
@@ -1247,6 +1247,12 @@ public class ForeignAnnotationsSourceJavaTestGenerated extends AbstractForeignAn
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/methodWithTypeParameter.kt");
}
@Test
@TestMetadata("mutabilityAndNullabilityForWarning.kt")
public void testMutabilityAndNullabilityForWarning() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/misc/mutabilityAndNullabilityForWarning.kt");
}
@Test
@TestMetadata("notNullVarargsOverrides.kt")
public void testNotNullVarargsOverrides() throws Exception {