FIR: Refine inference constraints when type variable in flexible position

That issue might be fixed via changing
TypeVariableMarker.shouldBeFlexible at ConeConstraintSystemUtilContext
but this and some other tricks have been added because of incorrect
handling of constraints where type variable has a flexible bound

^KT-51168 Fixed
This commit is contained in:
Denis.Zharkov
2022-04-12 16:30:55 +03:00
committed by teamcity
parent 853b7ec078
commit f70ae2df3a
54 changed files with 411 additions and 154 deletions
@@ -18164,6 +18164,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt");
}
@Test
@TestMetadata("flexibleTypeVariablePosition.kt")
public void testFlexibleTypeVariablePosition() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/flexibleTypeVariablePosition.kt");
}
@Test
@TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception {
@@ -19187,6 +19193,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/j+k/types/typeParameter.kt");
}
@Test
@TestMetadata("upperBoundsCheckAgainstSelfTypeInJava.kt")
public void testUpperBoundsCheckAgainstSelfTypeInJava() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/types/upperBoundsCheckAgainstSelfTypeInJava.kt");
}
@Test
@TestMetadata("varargOverride.kt")
public void testVarargOverride() throws Exception {
@@ -23110,6 +23122,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/platformTypes/samConstructor.kt");
}
@Test
@TestMetadata("starProjectionToFlexibleVariable.kt")
public void testStarProjectionToFlexibleVariable() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/starProjectionToFlexibleVariable.kt");
}
@Test
@TestMetadata("supertypeTypeArguments.kt")
public void testSupertypeTypeArguments() throws Exception {
@@ -37928,6 +37946,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/java"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("assertThatOnMap.kt")
public void testAssertThatOnMap() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/java/assertThatOnMap.kt");
}
@Test
@TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception {
@@ -7,7 +7,7 @@ FILE: main.kt
public abstract interface PsiClass : R|kotlin/Any| {
}
public final fun test(): R|kotlin/Unit| {
lval processor: R|AdapterProcessor<ft<PsiMethod, PsiMethod?>, ft<PsiClass, PsiClass?>>| = R|/AdapterProcessor.AdapterProcessor|<R|ft<PsiMethod, PsiMethod?>|, R|ft<PsiClass, PsiClass?>|>(R|/Function|<R|ft<PsiMethod, PsiMethod?>|, R|ft<PsiClass, PsiClass?>|>(<L> = Function@fun <anonymous>(method: R|PsiMethod?|): R|ft<PsiClass, PsiClass?>| <inline=NoInline> {
lval processor: R|AdapterProcessor<PsiMethod, PsiClass>| = R|/AdapterProcessor.AdapterProcessor|<R|PsiMethod|, R|PsiClass|>(R|/Function|<R|ft<PsiMethod, PsiMethod?>|, R|ft<PsiClass, PsiClass?>|>(<L> = Function@fun <anonymous>(method: R|PsiMethod?|): R|ft<PsiClass, PsiClass?>| <inline=NoInline> {
^ R|<local>/method|?.{ $subj$.R|/PsiMethod.containingClass| }
}
))
@@ -1,4 +1,4 @@
FILE: main.kt
public final fun <T> test(executor: R|BuildActionExecuter<T>|, modelType: R|java/lang/Class<T>|, env: R|kotlin/collections/Map<kotlin/String, kotlin/String>|): R|kotlin/Unit| {
lval model: R|ft<BuildActionExecuter<ft<T, T?>>, BuildActionExecuter<ft<T, T?>>?>| = R|<local>/executor|.R|SubstitutionOverride</BuildActionExecuter.setEnvironmentVariables: R|ft<BuildActionExecuter<ft<T, T?>>, BuildActionExecuter<ft<T, T?>>?>|>|(R|<local>/env|)
lval model: R|ft<BuildActionExecuter<ft<T & Any, T?>>, BuildActionExecuter<ft<T & Any, T?>>?>| = R|<local>/executor|.R|SubstitutionOverride</BuildActionExecuter.setEnvironmentVariables: R|ft<BuildActionExecuter<ft<T & Any, T?>>, BuildActionExecuter<ft<T & Any, T?>>?>|>|(R|<local>/env|)
}
@@ -26,13 +26,13 @@ FILE: main.kt
}
public final fun test_1(): R|kotlin/Unit| {
lval map: R|util/HashMap<ft<kotlin/Int, kotlin/Int?>, ft<kotlin/Int, kotlin/Int?>>| = R|util/HashMap.HashMap|<R|ft<kotlin/Int, kotlin/Int?>|, R|ft<kotlin/Int, kotlin/Int?>|>()
lval map: R|util/HashMap<kotlin/Int, kotlin/Int>| = R|util/HashMap.HashMap|<R|kotlin/Int|, R|kotlin/Int|>()
}
public final fun test_2(): R|kotlin/Unit| {
lval set: R|util/HashSet<kotlin/Int>| = R|util/HashSet.HashSet|<R|kotlin/Int|>()
}
public final fun test_3(): R|kotlin/Unit| {
lval list: R|foo/ArrayList<ft<kotlin/Int, kotlin/Int?>>| = R|foo/ArrayList.ArrayList|<R|ft<kotlin/Int, kotlin/Int?>|>()
lval list: R|foo/ArrayList<kotlin/Int>| = R|foo/ArrayList.ArrayList|<R|kotlin/Int|>()
}
public final fun test_4(): R|kotlin/Unit| {
lval list: R|foo/LinkedList<kotlin/Int>| = R|foo/LinkedList.LinkedList|<R|kotlin/Int|>()
@@ -13,8 +13,8 @@ FILE: test.kt
lval element: R|DE| = R|<local>/d|.R|/Diagnostic.element|
R|/Fix.Fix|(R|<local>/element|)
}
private final val DERIVED_FACTORY: R|DiagnosticFactory0<ft<DerivedElement, DerivedElement?>>| = R|/DiagnosticFactory0.DiagnosticFactory0|<R|ft<DerivedElement, DerivedElement?>|>()
private get(): R|DiagnosticFactory0<ft<DerivedElement, DerivedElement?>>|
private final val DERIVED_FACTORY: R|DiagnosticFactory0<DerivedElement>| = R|/DiagnosticFactory0.DiagnosticFactory0|<R|DerivedElement|>()
private get(): R|DiagnosticFactory0<DerivedElement>|
public final fun createViaFactory(d: R|EmptyDiagnostic|): R|kotlin/Unit| {
lval casted: R|Diagnostic<ft<DerivedElement, DerivedElement?>>| = R|/DERIVED_FACTORY|.R|SubstitutionOverride</DiagnosticFactory0.cast: R|@EnhancedNullability Diagnostic<ft<DerivedElement, DerivedElement?>>|>|(R|<local>/d|)
lval element: R|DerivedElement| = R|<local>/casted|.R|/Diagnostic.element|
@@ -1,6 +1,6 @@
FILE: flexibleTypeBug.kt
public final fun foo(): R|kotlin/Unit| {
lvar list1: R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>| = Q|java/util/Collections|.R|java/util/Collections.emptyList|<R|ft<kotlin/String, kotlin/String?>|>()
lvar list1: R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>| = Q|java/util/Collections|.R|java/util/Collections.emptyList|<R|kotlin/String|>()
lval list2: R|kotlin/collections/List<kotlin/String>| = R|kotlin/collections/listOf|<R|kotlin/String|>(String(b))
R|<local>/list1| = R|<local>/list1|.R|kotlin/collections/plus|<R|ft<kotlin/String, kotlin/String?>|>(R|<local>/list2|)
}
@@ -1,4 +1,4 @@
FILE: main.kt
public final fun main(): R|kotlin/Unit| {
R|/JavaClass.JavaClass|<R|ft<kotlin/String, kotlin/String?>|>(Null(null)).R|SubstitutionOverride</JavaClass.foo: R|ft<kotlin/String, kotlin/String?>|>|().R|kotlin/String.length|
R|/JavaClass.JavaClass|<R|kotlin/String|>(Null(null)).R|SubstitutionOverride</JavaClass.foo: R|ft<kotlin/String, kotlin/String?>|>|().R|kotlin/String.length|
}
@@ -1,6 +1,6 @@
FILE: main.kt
public final fun main(): R|kotlin/Unit| {
R|/MyFunction|<R|ft<kotlin/Int, kotlin/Int?>|, R|ft<kotlin/String, kotlin/String?>|>(<L> = MyFunction@fun <anonymous>(x: R|ft<kotlin/Int, kotlin/Int?>|): R|ft<kotlin/String, kotlin/String?>| <inline=NoInline> {
R|/MyFunction|<R|kotlin/Int|, R|kotlin/String|>(<L> = MyFunction@fun <anonymous>(x: R|ft<kotlin/Int, kotlin/Int?>|): R|ft<kotlin/String, kotlin/String?>| <inline=NoInline> {
^ R|<local>/x|.R|kotlin/Int.toInt|().R|kotlin/Int.toString|()
}
)
@@ -2,8 +2,8 @@ C:
[Source]: public open override fun getName(): R|kotlin/String| from Use site scope of /C [id: 0]
[Enhancement]: public abstract fun getName(): R|ft<kotlin/String, kotlin/String?>| from Substitution scope for [Java enhancement scope for /B] for type C [id: 1]
[Source]: public open override fun setName(newName: R|kotlin/String|): R|kotlin/Any?| from Use site scope of /C [id: 0]
[SubstitutionOverride]: public abstract fun setName(newName: R|ft<kotlin/String, kotlin/String?>|): R|kotlin/Any?| from Substitution scope for [Java enhancement scope for /B] for type C [id: 1]
[Enhancement]: public abstract fun setName(newName: R|ft<kotlin/String, kotlin/String?>|): R|ft<T, T?>| from Java enhancement scope for /B [id: 2]
[SubstitutionOverride]: public abstract fun setName(newName: R|ft<kotlin/String, kotlin/String?>|): R|ft<kotlin/Any, kotlin/Any?>| from Substitution scope for [Java enhancement scope for /B] for type C [id: 1]
[Enhancement]: public abstract fun setName(newName: R|ft<kotlin/String, kotlin/String?>|): R|ft<T & Any, T?>| from Java enhancement scope for /B [id: 2]
[Source]: private final var name: R|kotlin/String| = R|<local>/name| from Use site scope of /C [id: 0]
D:
@@ -1,5 +1,5 @@
FILE: main.kt
public final fun <T : R|kotlin/CharSequence?|> foo(mapper: R|Mapper|, cls: R|java/lang/Class<T>?|): R|kotlin/Unit| {
lval result: R|T & Any| = R|<local>/mapper|.R|/Mapper.readValue|<R|ft<T, T?>|>(R|<local>/cls|)!!
lval result: R|T & Any| = R|<local>/mapper|.R|/Mapper.readValue|<R|T|>(R|<local>/cls|)!!
R|<local>/result|.R|kotlin/CharSequence.length|
}
@@ -3,5 +3,5 @@ FILE: main.kt
public final typealias ImmutableSet<E> = R|MySet<E>|
private final typealias ImmutableMultimap<K, V> = R|ImmutableMap<K, ImmutableSet<V>>|
private final fun <K, V> R|ImmutableMultimap<K, V>|.put(key: R|K|, value: R|V|, oldSet: R|ImmutableSet<V>|): R|ImmutableMultimap<K, V>| {
^put this@R|/put|.R|SubstitutionOverride</MyMap.put: R|ft<MyMap<ft<K, K?>, ft<ImmutableSet<V>, ImmutableSet<V>?>>, MyMap<ft<K, K?>, ft<ImmutableSet<V>, ImmutableSet<V>?>>?>|>|(R|<local>/key|, R|<local>/oldSet|.R|SubstitutionOverride</MySet.add: R|ft<MySet<ft<V, V?>>, MySet<ft<V, V?>>?>|>|(R|<local>/value|))
^put this@R|/put|.R|SubstitutionOverride</MyMap.put: R|ft<MyMap<ft<K & Any, K?>, ft<ImmutableSet<V>, ImmutableSet<V>?>>, MyMap<ft<K & Any, K?>, ft<ImmutableSet<V>, ImmutableSet<V>?>>?>|>|(R|<local>/key|, R|<local>/oldSet|.R|SubstitutionOverride</MySet.add: R|ft<MySet<ft<V & Any, V?>>, MySet<ft<V & Any, V?>>?>|>|(R|<local>/value|))
}
@@ -5,8 +5,8 @@ FILE: concurrentMapOfAliases.kt
super<R|kotlin/Any|>()
}
private final val foo: R|java/util/concurrent/ConcurrentHashMap<ft<kotlin/String, kotlin/String?>, ft<kotlin/CharSequence, kotlin/CharSequence?>>| = Q|java/util/concurrent|.R|java/util/concurrent/ConcurrentHashMap.ConcurrentHashMap|<R|ft<kotlin/String, kotlin/String?>|, R|ft<kotlin/CharSequence, kotlin/CharSequence?>|>()
private get(): R|java/util/concurrent/ConcurrentHashMap<ft<kotlin/String, kotlin/String?>, ft<kotlin/CharSequence, kotlin/CharSequence?>>|
private final val foo: R|java/util/concurrent/ConcurrentHashMap<kotlin/String, kotlin/CharSequence>| = Q|java/util/concurrent|.R|java/util/concurrent/ConcurrentHashMap.ConcurrentHashMap|<R|kotlin/String|, R|kotlin/CharSequence|>()
private get(): R|java/util/concurrent/ConcurrentHashMap<kotlin/String, kotlin/CharSequence>|
private final fun bar(): R|kotlin/Unit| {
this@R|/A|.R|/A.foo|.R|SubstitutionOverride<java/util/concurrent/ConcurrentHashMap.get: R|kotlin/CharSequence?|>|(String(dd))?.{ (this@R|/A|, $subj$).R|/A.baz|() }
@@ -4,5 +4,5 @@ FILE: main.kt
public final typealias ImmutableLinkedHashSet<E> = R|imm/LinkedHashSet<E>|
private final typealias ImmutableMultimap<K, V> = R|ImmutableMap<K, ImmutableSet<V>>|
private final fun <K, V> R|ImmutableMultimap<K, V>|.put(key: R|K|, value: R|V|): R|kotlin/Unit| {
this@R|/put|.R|SubstitutionOverride<imm/Map.get: R|ft<imm/Option<ft<ImmutableSet<V>, ImmutableSet<V>?>>, imm/Option<ft<ImmutableSet<V>, ImmutableSet<V>?>>?>|>|(R|<local>/key|).R|SubstitutionOverride<imm/Option.getOrElse: R|ft<ImmutableSet<V>, ImmutableSet<V>?>|>|(Q|ImmutableLinkedHashSet|.R|imm/LinkedHashSet.empty|<R|ft<V, V?>|>())
this@R|/put|.R|SubstitutionOverride<imm/Map.get: R|ft<imm/Option<ft<ImmutableSet<V>, ImmutableSet<V>?>>, imm/Option<ft<ImmutableSet<V>, ImmutableSet<V>?>>?>|>|(R|<local>/key|).R|SubstitutionOverride<imm/Option.getOrElse: R|ft<ImmutableSet<V>, ImmutableSet<V>?>|>|(Q|ImmutableLinkedHashSet|.R|imm/LinkedHashSet.empty|<R|V|>())
}
@@ -1,6 +1,6 @@
FILE: javaLangComparator.kt
public final fun test_2(list: R|kotlin/collections/List<kotlin/Int>|): R|kotlin/Unit| {
lval comp: R|java/util/Comparator<ft<kotlin/Int, kotlin/Int?>>| = Q|java/util|.R|java/util/Comparator|<R|ft<kotlin/Int, kotlin/Int?>|>(<L> = Comparator@fun <anonymous>(x: R|ft<kotlin/Int, kotlin/Int?>|, y: R|ft<kotlin/Int, kotlin/Int?>|): R|kotlin/Int| <inline=NoInline> {
lval comp: R|java/util/Comparator<kotlin/Int>| = Q|java/util|.R|java/util/Comparator|<R|kotlin/Int|>(<L> = Comparator@fun <anonymous>(x: R|ft<kotlin/Int, kotlin/Int?>|, y: R|ft<kotlin/Int, kotlin/Int?>|): R|kotlin/Int| <inline=NoInline> {
^ Int(1)
}
)
@@ -1,6 +1,6 @@
FILE: kotlinComparatorAlias.kt
public final fun test_1(): R|kotlin/Unit| {
lval comp: R|java/util/Comparator<ft<kotlin/Int, kotlin/Int?>>| = R|java/util/Comparator|<R|ft<kotlin/Int, kotlin/Int?>|>(<L> = Comparator@fun <anonymous>(x: R|ft<kotlin/Int, kotlin/Int?>|, y: R|ft<kotlin/Int, kotlin/Int?>|): R|kotlin/Int| <inline=NoInline> {
lval comp: R|java/util/Comparator<kotlin/Int>| = R|java/util/Comparator|<R|kotlin/Int|>(<L> = Comparator@fun <anonymous>(x: R|ft<kotlin/Int, kotlin/Int?>|, y: R|ft<kotlin/Int, kotlin/Int?>|): R|kotlin/Int| <inline=NoInline> {
^ Int(1)
}
)
@@ -1,6 +1,6 @@
FILE: weakHashMap.kt
public final val someMap: R|java/util/WeakHashMap<ft<kotlin/Any, kotlin/Any?>, ft<kotlin/Any, kotlin/Any?>>| = R|java/util/WeakHashMap.WeakHashMap|<R|ft<kotlin/Any, kotlin/Any?>|, R|ft<kotlin/Any, kotlin/Any?>|>()
public get(): R|java/util/WeakHashMap<ft<kotlin/Any, kotlin/Any?>, ft<kotlin/Any, kotlin/Any?>>|
public final val someMap: R|java/util/WeakHashMap<kotlin/Any?, kotlin/Any?>| = R|java/util/WeakHashMap.WeakHashMap|<R|kotlin/Any?|, R|kotlin/Any?|>()
public get(): R|java/util/WeakHashMap<kotlin/Any?, kotlin/Any?>|
public final fun foo(): R|kotlin/Unit| {
R|/someMap|.R|SubstitutionOverride<java/util/WeakHashMap.get: R|kotlin/Any?|>|(String())
}
@@ -9,9 +9,9 @@ FILE: typeAliasWithForEach.kt
}
public final typealias Arguments = R|kotlin/collections/Map<kotlin/String, ArgsInfo>|
public final fun R|Arguments|.deepCopy(): R|Arguments| {
lval result: R|java/util/HashMap<ft<kotlin/String, kotlin/String?>, ft<ArgsInfo, ArgsInfo?>>| = R|java/util/HashMap.HashMap|<R|ft<kotlin/String, kotlin/String?>|, R|ft<ArgsInfo, ArgsInfo?>|>()
lval result: R|java/util/HashMap<kotlin/String, ArgsInfo>| = R|java/util/HashMap.HashMap|<R|kotlin/String|, R|ArgsInfo|>()
this@R|/deepCopy|.R|SubstitutionOverride<kotlin/collections/Map.forEach: R|kotlin/Unit|>|(<L> = forEach@fun <anonymous>(key: R|@EnhancedNullability kotlin/String|, value: R|@EnhancedNullability ArgsInfo|): R|kotlin/Unit| <inline=NoInline> {
R|<local>/result|.R|kotlin/collections/set|<R|ft<kotlin/String, kotlin/String?>|, R|ft<ArgsInfo, ArgsInfo?>|>(R|<local>/key|, R|/ArgsInfoImpl.ArgsInfoImpl|(R|<local>/value|))
R|<local>/result|.R|kotlin/collections/set|<R|kotlin/String|, R|ArgsInfo|>(R|<local>/key|, R|/ArgsInfoImpl.ArgsInfoImpl|(R|<local>/value|))
}
)
^deepCopy R|<local>/result|
@@ -18164,6 +18164,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt");
}
@Test
@TestMetadata("flexibleTypeVariablePosition.kt")
public void testFlexibleTypeVariablePosition() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/flexibleTypeVariablePosition.kt");
}
@Test
@TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception {
@@ -19187,6 +19193,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/j+k/types/typeParameter.kt");
}
@Test
@TestMetadata("upperBoundsCheckAgainstSelfTypeInJava.kt")
public void testUpperBoundsCheckAgainstSelfTypeInJava() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/types/upperBoundsCheckAgainstSelfTypeInJava.kt");
}
@Test
@TestMetadata("varargOverride.kt")
public void testVarargOverride() throws Exception {
@@ -23110,6 +23122,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/platformTypes/samConstructor.kt");
}
@Test
@TestMetadata("starProjectionToFlexibleVariable.kt")
public void testStarProjectionToFlexibleVariable() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/starProjectionToFlexibleVariable.kt");
}
@Test
@TestMetadata("supertypeTypeArguments.kt")
public void testSupertypeTypeArguments() throws Exception {
@@ -37928,6 +37946,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/java"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("assertThatOnMap.kt")
public void testAssertThatOnMap() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/java/assertThatOnMap.kt");
}
@Test
@TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception {
@@ -18164,6 +18164,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt");
}
@Test
@TestMetadata("flexibleTypeVariablePosition.kt")
public void testFlexibleTypeVariablePosition() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/flexibleTypeVariablePosition.kt");
}
@Test
@TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception {
@@ -19187,6 +19193,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/j+k/types/typeParameter.kt");
}
@Test
@TestMetadata("upperBoundsCheckAgainstSelfTypeInJava.kt")
public void testUpperBoundsCheckAgainstSelfTypeInJava() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/types/upperBoundsCheckAgainstSelfTypeInJava.kt");
}
@Test
@TestMetadata("varargOverride.kt")
public void testVarargOverride() throws Exception {
@@ -23110,6 +23122,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/platformTypes/samConstructor.kt");
}
@Test
@TestMetadata("starProjectionToFlexibleVariable.kt")
public void testStarProjectionToFlexibleVariable() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/starProjectionToFlexibleVariable.kt");
}
@Test
@TestMetadata("supertypeTypeArguments.kt")
public void testSupertypeTypeArguments() throws Exception {
@@ -37928,6 +37946,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/java"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("assertThatOnMap.kt")
public void testAssertThatOnMap() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/java/assertThatOnMap.kt");
}
@Test
@TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception {
@@ -102,7 +102,19 @@ private fun JavaType?.toConeTypeProjection(
return lowerBound
}
val upperBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes, lowerBound)
if (isRaw) ConeRawType(lowerBound, upperBound) else ConeFlexibleType(lowerBound, upperBound)
val finalLowerBound = when (lowerBound) {
is ConeTypeParameterType ->
ConeDefinitelyNotNullType.create(
lowerBound, session.typeContext,
// Upper bounds might be not initialized properly yet, so we force creating DefinitelyNotNullType
// It should not affect semantics, since it would be still a valid type anyway
forceWithoutCheck = true,
) ?: lowerBound
else -> lowerBound
}
if (isRaw) ConeRawType(finalLowerBound, upperBound) else ConeFlexibleType(finalLowerBound, upperBound)
}
is JavaArrayType -> {
@@ -92,7 +92,12 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
qualifiers: IndexedJavaTypeQualifiers,
index: Int,
subtreeSizes: List<Int>,
isFromDefinitelyNotNullType: Boolean = false,
): ConeSimpleKotlinType? {
if (this is ConeDefinitelyNotNullType) {
return original.enhanceInflexibleType(session, position, qualifiers, index, subtreeSizes, isFromDefinitelyNotNullType = true)
}
val shouldEnhance = position.shouldEnhance()
if ((!shouldEnhance && typeArguments.isEmpty()) || this !is ConeLookupTagBasedType) {
return null
@@ -104,7 +109,7 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
// TODO: implement warnings
val nullabilityFromQualifiers = effectiveQualifiers.nullability
.takeIf { shouldEnhance && !effectiveQualifiers.isNullabilityQualifierForWarning }
val enhancedNullability = when (nullabilityFromQualifiers) {
val enhancedIsNullable = when (nullabilityFromQualifiers) {
NullabilityQualifier.NULLABLE -> true
NullabilityQualifier.NOT_NULL -> false
else -> isNullable
@@ -124,14 +129,14 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
}
val shouldAddAttribute = nullabilityFromQualifiers == NullabilityQualifier.NOT_NULL && !hasEnhancedNullability
if (lookupTag == enhancedTag && enhancedNullability == isNullable && !shouldAddAttribute && enhancedArguments.all { it == null }) {
if (lookupTag == enhancedTag && enhancedIsNullable == isNullable && !shouldAddAttribute && enhancedArguments.all { it == null }) {
return null // absolutely no changes
}
val mergedArguments = Array(typeArguments.size) { enhancedArguments[it] ?: typeArguments[it] }
val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes
val enhancedType = enhancedTag.constructType(mergedArguments, enhancedNullability, mergedAttributes)
return if (effectiveQualifiers.definitelyNotNull)
val enhancedType = enhancedTag.constructType(mergedArguments, enhancedIsNullable, mergedAttributes)
return if (effectiveQualifiers.definitelyNotNull || (isFromDefinitelyNotNullType && nullabilityFromQualifiers == null))
ConeDefinitelyNotNullType.create(enhancedType, session.typeContext) ?: enhancedType
else
enhancedType
@@ -103,10 +103,12 @@ abstract class AbstractConeSubstitutor(protected val typeContext: ConeTypeContex
}
private fun ConeDefinitelyNotNullType.substituteOriginal(): ConeKotlinType? {
val substituted = substituteOrNull(original)
?.withNullability(ConeNullability.NOT_NULL, typeContext)
?.withAttributes(original.attributes)
?: return null
val substitutedOriginal = substituteOrNull(original) ?: return null
val substituted = substitutedOriginal.withNullability(
ConeNullability.NOT_NULL,
typeContext,
substitutedOriginal.attributes.add(original.attributes)
)
return ConeDefinitelyNotNullType.create(substituted, typeContext) ?: substituted
}
@@ -562,8 +562,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
return intersectionType.withAlternative(secondCandidate)
}
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker =
createFlexibleType(this.makeSimpleTypeDefinitelyNotNullOrNotNull(), this.withNullability(true))
override fun useRefinedBoundsForTypeVariableInFlexiblePosition(): Boolean = true
override fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? =
if (baseType is ConeLookupTagBasedType) createSubstitutionForSupertype(baseType, session) else null
@@ -13,7 +13,10 @@ import org.jetbrains.kotlin.descriptors.ValueClassKind
import org.jetbrains.kotlin.descriptors.valueClassLoweringKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.resolve.directExpansionType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
@@ -289,7 +292,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
else -> listOf(session.builtinTypes.anyType.type)
}
}
is ConeCapturedTypeConstructor -> supertypes!!
is ConeCapturedTypeConstructor -> supertypes.orEmpty()
is ConeIntersectionType -> intersectedTypes
is ConeIntegerLiteralType -> supertypes
else -> unknownConstructorError()
@@ -475,13 +478,13 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
return when (this) {
is ConeFlexibleType -> this.upperBound.isNullableType()
is ConeTypeParameterType -> lookupTag.symbol.allBoundsAreNullable()
is ConeTypeParameterType -> lookupTag.symbol.allBoundsAreNullableOrUnresolved()
is ConeTypeVariableType -> {
val symbol = lookupTag.toSymbol(session) ?: return false
when (symbol) {
is FirClassSymbol -> false
is FirTypeAliasSymbol -> symbol.fir.expandedConeType?.isNullableType() ?: false
is FirTypeParameterSymbol -> symbol.allBoundsAreNullable()
is FirTypeParameterSymbol -> symbol.allBoundsAreNullableOrUnresolved()
}
}
is ConeIntersectionType -> intersectedTypes.all { it.isNullableType() }
@@ -490,8 +493,13 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
}
private fun FirTypeParameterSymbol.allBoundsAreNullable(): Boolean {
return resolvedBounds.all { it.coneType.isNullableType() }
private fun FirTypeParameterSymbol.allBoundsAreNullableOrUnresolved(): Boolean {
for (bound in fir.bounds) {
if (bound !is FirResolvedTypeRef) return true
if (!bound.type.isNullableType()) return false
}
return true
}
private fun TypeConstructorMarker.toFirRegularClass(): FirRegularClass? {
@@ -60,7 +60,7 @@ fun TypeCheckerProviderContext.equalTypes(a: ConeKotlinType, b: ConeKotlinType):
private fun ConeTypeContext.makesSenseToBeDefinitelyNotNull(originalType: ConeKotlinType): Boolean {
return when (val type = originalType.lowerBoundIfFlexible()) {
is ConeTypeParameterType -> type.isNullableType()
is ConeTypeParameterType -> !type.lookupTag.symbol.isInitializedFir || type.isNullableType()
// Actually, this branch should work for type parameters as well, but it breaks some cases. See KT-40114.
// Basically, if we have `T : X..X?`, then `T <: Any` but we still have `T` != `T & Any`.
is ConeTypeVariableType, is ConeCapturedType -> {
@@ -75,12 +75,13 @@ private fun ConeTypeContext.makesSenseToBeDefinitelyNotNull(originalType: ConeKo
fun ConeDefinitelyNotNullType.Companion.create(
original: ConeKotlinType,
typeContext: ConeTypeContext
typeContext: ConeTypeContext,
forceWithoutCheck: Boolean = false,
): ConeDefinitelyNotNullType? {
return when (original) {
is ConeDefinitelyNotNullType -> original
is ConeFlexibleType -> create(original.lowerBound, typeContext)
is ConeSimpleKotlinType -> runIf(typeContext.makesSenseToBeDefinitelyNotNull(original)) {
is ConeSimpleKotlinType -> runIf(forceWithoutCheck || typeContext.makesSenseToBeDefinitelyNotNull(original)) {
ConeDefinitelyNotNullType(original.coneLowerBoundIfFlexible())
}
}
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExplicitTypeParamete
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.StandardClassIds
@@ -66,11 +65,7 @@ internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
when (val typeArgument = candidate.typeArgumentMapping[index]) {
is FirTypeProjectionWithVariance -> csBuilder.addEqualityConstraint(
freshVariable.defaultType,
getTypePreservingFlexibilityWrtTypeVariable(
typeArgument.typeRef.coneType,
typeParameter,
context.session
).fullyExpandedType(context.session),
typeArgument.typeRef.coneType.fullyExpandedType(context.session),
ConeExplicitTypeParameterConstraintPosition(typeArgument)
)
is FirStarProjection -> csBuilder.addEqualityConstraint(
@@ -85,29 +80,6 @@ internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
}
}
}
private fun getTypePreservingFlexibilityWrtTypeVariable(
type: ConeKotlinType,
typeParameter: FirTypeParameterRef,
session: FirSession,
): ConeKotlinType {
return if (typeParameter.shouldBeFlexible(session.typeContext)) {
val notNullType = type.withNullability(ConeNullability.NOT_NULL, session.typeContext) as ConeSimpleKotlinType
ConeFlexibleType(notNullType, notNullType.withNullability(ConeNullability.NULLABLE, session.typeContext))
} else {
type
}
}
private fun FirTypeParameterRef.shouldBeFlexible(context: ConeTypeContext): Boolean {
return symbol.resolvedBounds.any {
val type = it.coneType
type is ConeFlexibleType || with(context) {
(type.typeConstructor() as? ConeTypeParameterLookupTag)?.symbol?.fir?.shouldBeFlexible(context) ?: false
}
}
}
}
private fun createToFreshVariableSubstitutorAndAddInitialConstraints(
@@ -21,7 +21,8 @@ import org.jetbrains.kotlin.types.model.TypeVariableMarker
object ConeConstraintSystemUtilContext : ConstraintSystemUtilContext {
override fun TypeVariableMarker.shouldBeFlexible(): Boolean {
// TODO
// In FIR, there's no need in hack with shouldTryUseDifferentFlexibilityForUpperType
// See org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext.useRefinedBoundsForTypeVariableInFlexiblePosition
return false
}
@@ -59,7 +59,11 @@ class ConstraintIncorporator(
typeVariable: TypeVariableMarker,
constraint: Constraint
) {
val shouldBeTypeVariableFlexible = with(utilContext) { typeVariable.shouldBeFlexible() }
val shouldBeTypeVariableFlexible =
if (useRefinedBoundsForTypeVariableInFlexiblePosition())
false
else
with(utilContext) { typeVariable.shouldBeFlexible() }
// \alpha <: constraint.type
if (constraint.kind != ConstraintKind.LOWER) {
@@ -174,9 +174,9 @@ abstract class TypeCheckerStateForConstraintSystem(
*
* T?
*
* Foo <: T? -- Foo & Any <: T -- Foo!! <: T
* Foo? <: T? -- Foo? & Any <: T -- Foo!! <: T
* (Foo..Bar) <: T? -- (Foo..Bar) & Any <: T -- (Foo..Bar)!! <: T
* Foo <: T? -- Foo & Any <: T
* Foo? <: T? -- Foo? & Any <: T -- Foo & Any <: T
* (Foo..Bar) <: T? -- (Foo..Bar) & Any <: T
*
* T!
*
@@ -248,12 +248,34 @@ abstract class TypeCheckerStateForConstraintSystem(
when (subType) {
is SimpleTypeMarker ->
// Foo <: T! -- (Foo!! .. Foo) <: T
subType.createConstraintPartForLowerBoundAndFlexibleTypeVariable()
when {
useRefinedBoundsForTypeVariableInFlexiblePosition() ->
// Foo <: T! -- (Foo!! .. Foo) <: T
createFlexibleType(
subType.makeSimpleTypeDefinitelyNotNullOrNotNull(),
subType.withNullability(true)
)
// In K1 (FE1.0), there is an obsolete behavior
subType.isMarkedNullable() -> subType
else -> createFlexibleType(subType, subType.withNullability(true))
}
is FlexibleTypeMarker ->
// (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
createFlexibleType(subType.lowerBound().makeSimpleTypeDefinitelyNotNullOrNotNull(), subType.upperBound())
when {
useRefinedBoundsForTypeVariableInFlexiblePosition() ->
// (Foo..Bar) <: T! -- (Foo!! .. Bar?) <: T
createFlexibleType(
subType.lowerBound().makeSimpleTypeDefinitelyNotNullOrNotNull(),
subType.upperBound().withNullability(true)
)
else ->
// (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
createFlexibleType(
subType.lowerBound().makeSimpleTypeDefinitelyNotNullOrNotNull(),
subType.upperBound()
)
}
else -> error("sealed")
}
@@ -273,17 +295,29 @@ abstract class TypeCheckerStateForConstraintSystem(
}
/**
* T! <: Foo <=> T <: Foo..Foo?
* T! <: Foo <=> T <: Foo & Any..Foo?
* T? <: Foo <=> T <: Foo && Nothing? <: Foo
* T <: Foo -- leave as is
*/
private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean = with(extensionTypeContext) {
val typeVariableLowerBound = typeVariable.lowerBoundIfFlexible()
val simplifiedSuperType = if (typeVariableLowerBound.isDefinitelyNotNullType()) {
superType.withNullability(true)
} else if (typeVariable.isFlexible() && superType is SimpleTypeMarker) {
createFlexibleType(superType, superType.withNullability(true))
} else superType
val simplifiedSuperType = when {
typeVariable.isFlexible() && useRefinedBoundsForTypeVariableInFlexiblePosition() ->
createFlexibleType(
superType.lowerBoundIfFlexible().makeSimpleTypeDefinitelyNotNullOrNotNull(),
superType.upperBoundIfFlexible().withNullability(true)
)
typeVariableLowerBound.isDefinitelyNotNullType() -> {
superType.withNullability(true)
}
typeVariable.isFlexible() && superType is SimpleTypeMarker ->
createFlexibleType(superType, superType.withNullability(true))
else -> superType
}
addUpperConstraint(typeVariableLowerBound.typeConstructor(), simplifiedSuperType)
@@ -1,17 +0,0 @@
// JSPECIFY_STATE: strict
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
// FILE: J1.java
import org.jetbrains.annotations.Nullable;
public interface J1<T> {
@Nullable
public static <T> T foo(J1<T> x) { return null; }
}
// FILE: J2.java
import org.jspecify.nullness.Nullable;
public interface J2<V extends @Nullable Object> extends J1<V> { }
// FILE: kotlin.kt
private fun J2<*>.bar() = <!NEW_INFERENCE_ERROR!>J1.foo(this)<!>
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// JSPECIFY_STATE: strict
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
// FILE: J1.java
@@ -37,7 +37,7 @@ fun <R> main(a: ReturnType<R>) {
takeNullableStringAndKNullable(x1)
takeNotNullStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x1<!>)
takeNullableStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x1<!>)
takeNotNullString(<!ARGUMENT_TYPE_MISMATCH!>a.foo41.foo411<!>)
takeNotNullString(a.foo41.foo411)
val x2 = <!DEBUG_INFO_EXPRESSION_TYPE("ReturnType.A<kotlin.String?, R!!>..ReturnType.A<kotlin.String?, R!!>?!")!>a.foo2()<!>
takeNotNullStringAndKNullable(<!ARGUMENT_TYPE_MISMATCH!>x2<!>)
@@ -39,7 +39,7 @@ fun <R> main(a: ReturnTypeWithWarnings<R>) {
takeNullableStringAndKNullable(x1)
takeNotNullStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x1<!>)
takeNullableStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x1<!>)
takeNotNullString(<!ARGUMENT_TYPE_MISMATCH!>a.foo41.foo411<!>)
takeNotNullString(a.foo41.foo411)
val x2 = <!DEBUG_INFO_EXPRESSION_TYPE("ReturnTypeWithWarnings.A<kotlin.String?, R!!>..ReturnTypeWithWarnings.A<kotlin.String?, R!!>?!")!>a.foo2()<!>
takeNotNullStringAndKNullable(<!ARGUMENT_TYPE_MISMATCH!>x2<!>)
@@ -0,0 +1,42 @@
// !LANGUAGE: +DefinitelyNonNullableTypes +ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated
// FILE: A.java
import org.jetbrains.annotations.*;
public interface A<T> {
public T foo(T x) { return x; }
@NotNull
public T bar(@NotNull T x) {}
}
// FILE: main.kt
interface B<T1> : A<T1> {
override fun foo(x: T1): T1
override fun bar(x: T1 & Any): T1 & Any
}
interface C<T2> : A<T2> {
override fun foo(x: T2 & Any): T2 & Any
<!NOTHING_TO_OVERRIDE!>override<!> fun bar(x: T2): T2
}
interface D : A<String?> {
override fun foo(x: String?): String?
override fun bar(x: String): String
}
interface E : A<String> {
override fun foo(x: String): String
override fun bar(x: String): String
}
interface F : A<String?> {
override fun foo(x: String): String
<!NOTHING_TO_OVERRIDE!>override<!> fun bar(x: String?): String?
}
interface G<T3 : Any> : A<T3> {
override fun foo(x: T3): T3
override fun bar(x: T3): T3
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !LANGUAGE: +DefinitelyNonNullableTypes +ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated
// FILE: A.java
@@ -27,7 +27,7 @@ val xExplicit: X = Test().findViewById(0)
val xCast = Test().findViewById(0) as X
val xCastExplicitType = Test().findViewById<X>(0) as X
val xSafeCastExplicitType = Test().findViewById<X>(0) as? X
val xSafeCastExplicitType = Test().findViewById<X>(0) <!USELESS_CAST!>as? X<!>
val yExplicit: Y<String> = Test().findViewById(0)
val yCast = Test().findViewById(0) as Y<String>
@@ -0,0 +1,20 @@
// SKIP_TXT
// FILE: JavaClass.java
public class JavaClass {
public static <K> K simpleId(K k) { // fun <K> simpleId(k: K & Any..K?): K & Any..K? =
return k;
}
}
// FILE: main.kt
fun takeN(n: Number?): Int = 1
fun bar(n: Number?) {
fun takeN(n: Number): String = ""
// in K1, it was resolved to nullable takeN
// in K2, it would be resolved to not-nullable and may fail with NPE
takeN(JavaClass.simpleId(n)).<!UNRESOLVED_REFERENCE!>div<!>(1)
takeN(JavaClass.simpleId(n)).length
}
@@ -0,0 +1,20 @@
// SKIP_TXT
// FILE: JavaClass.java
public class JavaClass {
public static <K> K simpleId(K k) { // fun <K> simpleId(k: K & Any..K?): K & Any..K? =
return k;
}
}
// FILE: main.kt
fun takeN(n: Number?): Int = 1
fun bar(n: Number?) {
fun takeN(n: Number): String = ""
// in K1, it was resolved to nullable takeN
// in K2, it would be resolved to not-nullable and may fail with NPE
takeN(JavaClass.simpleId(n)).div(1)
takeN(JavaClass.simpleId(n)).<!UNRESOLVED_REFERENCE!>length<!>
}
@@ -0,0 +1,11 @@
// FIR_IDENTICAL
// SKIP_TXT
// FILE: XBreakpointProperties.java
public abstract class XBreakpointProperties<T> {}
// FILE: XBreakpoint.java
public interface XBreakpoint<P extends XBreakpointProperties> {}
// FILE: XBreakpointType.java
public abstract class XBreakpointType<B extends XBreakpoint<P>, P extends XBreakpointProperties> {}
// FILE: main.kt
fun foo(x: XBreakpointType<XBreakpoint<*>, *>) {}
@@ -12,7 +12,7 @@ public class A {
fun test() {
A.bar(null, "")
A.bar<String>(null, "")
A.bar<String>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
A.bar<String?>(null, "")
A.bar(null, A.platformString())
}
@@ -1,9 +0,0 @@
import java.util.ArrayList
fun foo() {
val list = ArrayList<String?>()
for (s in list) {
s.length
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
import java.util.ArrayList
fun foo() {
@@ -0,0 +1,20 @@
// FIR_IDENTICAL
// SKIP_TXT
// FILE: ExtensionPointName.java
public final class ExtensionPointName<T> {}
// FILE: ExtensionPoint.java
import org.jetbrains.annotations.NotNull;
public interface ExtensionPoint<@NotNull T> {
T foo();
}
// FILE: Area.java
public class Area {
@NotNull
public static <T> ExtensionPoint<T> getExtensionPoint(@NotNull ExtensionPointName<T> extensionPointName) { return null; }
}
// FILE: main.kt
private fun unregisterEverything(extensionPoint: ExtensionPointName<*>) {
Area.getExtensionPoint(extensionPoint).foo().hashCode()
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,36 @@
// FIR_IDENTICAL
// SKIP_TXT
// FILE: AbstractMapAssert.java
import java.util.Map;
public abstract class AbstractMapAssert<SELF extends AbstractMapAssert<SELF, ACTUAL, K, V>, ACTUAL extends Map<K, V>, K, V> {
public SELF isNotNull() {
return (SELF) this;
}
}
// FILE: MapAssert.java
import java.util.Map;
public class MapAssert<KEY, VALUE> extends AbstractMapAssert<MapAssert<KEY, VALUE>, Map<KEY, VALUE>, KEY, VALUE> {
public MapAssert(Map<KEY, VALUE> actual) {}
}
// FILE: Assertions.java
import java.util.Map;
public class Assertions {
public static <K, V> MapAssert<K, V> assertThat(Map<K, V> actual) {
return new MapAssert<>(actual);
}
}
// FILE: test.kt
fun <S : Map<*,*>> S?.must() {
Assertions.assertThat(this).isNotNull
}
@@ -5,18 +5,18 @@ fun bar(): String? = null
fun foo() {
var x = ArrayList<String>()
x.add(null)
x.add(bar())
x.add(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.add(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>)
x.add("")
x[0] = null
x[0] = bar()
x[0] = <!NULL_FOR_NONNULL_TYPE!>null<!>
x[0] = <!ARGUMENT_TYPE_MISMATCH!>bar()<!>
x[0] = ""
val b1: MutableList<String?> = x
val b1: MutableList<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableList<String> = x
val b3: List<String?> = x
val b4: Collection<String?> = x
val b6: MutableCollection<String?> = x
}
val b6: MutableCollection<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
}
@@ -14,7 +14,7 @@ fun foo() {
x[0] = ""
val b1: MutableList<String?> = x
val b2: MutableList<String> = x
val b2: MutableList<String> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b3: List<String?> = x
val b4: Collection<String?> = x
@@ -28,5 +28,5 @@ fun foo() {
x.add("")
val b1: Collection<String?> = x
val b2: MutableCollection<String?> = x
val b2: MutableCollection<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
}
@@ -31,10 +31,10 @@ fun foo() {
x[0] = bar()
x[0] = ""
val b1: MutableList<String?> = x
val b1: MutableList<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableList<String> = x
val b3: List<String?> = x
val b4: Collection<String?> = x
val b6: MutableCollection<String?> = x
val b6: MutableCollection<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
}
@@ -7,30 +7,30 @@ fun bar(): String? = null
fun fooHashSet() {
var x = HashSet<String>()
x.add(null)
x.add(bar())
x.add(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.add(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>)
x.add("")
val b1: MutableSet<String?> = x
val b1: MutableSet<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableSet<String> = x
val b3: Set<String?> = x
val b4: Collection<String?> = x
val b6: MutableCollection<String?> = x
val b6: MutableCollection<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
}
fun fooTreeSet() {
var x = TreeSet<String>()
x.add(null)
x.add(bar())
x.add(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.add(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>)
x.add("")
val b1: MutableSet<String?> = x
val b1: MutableSet<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableSet<String> = x
val b3: Set<String?> = x
val b4: Collection<String?> = x
val b6: MutableCollection<String?> = x
val b6: MutableCollection<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
}
fun fooLinkedHashSet() {
@@ -39,10 +39,10 @@ fun fooLinkedHashSet() {
x.add(bar())
x.add("")
val b1: MutableSet<String?> = x
val b1: MutableSet<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableSet<String> = x
val b3: Set<String?> = x
val b4: Collection<String?> = x
val b6: MutableCollection<String?> = x
val b6: MutableCollection<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
}
@@ -34,11 +34,11 @@ FILE fqName:<root> fileName:/AbstractMutableMap.kt
overridden:
public open fun clear (): kotlin.Unit [fake_override] declared in kotlin.collections.AbstractMutableMap
$this: VALUE_PARAMETER name:<this> type:java.util.AbstractMap<K of java.util.AbstractMap, V of java.util.AbstractMap>
FUN FAKE_OVERRIDE name:putAll visibility:public modality:OPEN <> ($this:java.util.AbstractMap<K of java.util.AbstractMap, V of java.util.AbstractMap>, p0:@[EnhancedNullability] kotlin.collections.Map<out @[FlexibleNullability] K of <root>.MyMap?, out @[FlexibleNullability] V of <root>.MyMap?>) returnType:kotlin.Unit [fake_override]
FUN FAKE_OVERRIDE name:putAll visibility:public modality:OPEN <> ($this:java.util.AbstractMap<K of java.util.AbstractMap, V of java.util.AbstractMap>, p0:@[EnhancedNullability] kotlin.collections.Map<out @[FlexibleNullability] K of <root>.MyMap?, @[FlexibleNullability] V of <root>.MyMap?>) returnType:kotlin.Unit [fake_override]
overridden:
public open fun putAll (p0: @[EnhancedNullability] kotlin.collections.Map<out @[FlexibleNullability] K of kotlin.collections.AbstractMutableMap?, out @[FlexibleNullability] V of kotlin.collections.AbstractMutableMap?>): kotlin.Unit [fake_override] declared in kotlin.collections.AbstractMutableMap
$this: VALUE_PARAMETER name:<this> type:java.util.AbstractMap<K of java.util.AbstractMap, V of java.util.AbstractMap>
VALUE_PARAMETER name:p0 index:0 type:@[EnhancedNullability] kotlin.collections.Map<out @[FlexibleNullability] K of <root>.MyMap?, out @[FlexibleNullability] V of <root>.MyMap?>
VALUE_PARAMETER name:p0 index:0 type:@[EnhancedNullability] kotlin.collections.Map<out @[FlexibleNullability] K of <root>.MyMap?, @[FlexibleNullability] V of <root>.MyMap?>
FUN FAKE_OVERRIDE name:remove visibility:public modality:OPEN <> ($this:java.util.AbstractMap<K of java.util.AbstractMap, V of java.util.AbstractMap>, p0:@[FlexibleNullability] K of <root>.MyMap?) returnType:V of <root>.MyMap? [fake_override]
overridden:
public open fun remove (p0: @[FlexibleNullability] K of kotlin.collections.AbstractMutableMap?): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap
@@ -74,12 +74,12 @@ FILE fqName:<root> fileName:/AbstractMutableMap.kt
public open fun replaceAll (p0: @[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] K of kotlin.collections.AbstractMutableMap, in @[EnhancedNullability] V of kotlin.collections.AbstractMutableMap, out @[EnhancedNullability] V of kotlin.collections.AbstractMutableMap>): kotlin.Unit [fake_override] declared in kotlin.collections.AbstractMutableMap
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>
VALUE_PARAMETER name:p0 index:0 type:@[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] K of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out @[EnhancedNullability] V of <root>.MyMap>
FUN FAKE_OVERRIDE name:merge visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:@[EnhancedNullability] K of <root>.MyMap, p1:@[EnhancedNullability] V of <root>.MyMap, p2:@[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] V of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>) returnType:V of <root>.MyMap? [fake_override]
FUN FAKE_OVERRIDE name:merge visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:@[EnhancedNullability] K of <root>.MyMap, p1:@[EnhancedNullability] {V of <root>.MyMap & Any}, p2:@[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] V of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>) returnType:V of <root>.MyMap? [fake_override]
overridden:
public open fun merge (p0: @[EnhancedNullability] K of kotlin.collections.AbstractMutableMap, p1: @[EnhancedNullability] {V of kotlin.collections.AbstractMutableMap & Any}, p2: @[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] {V of kotlin.collections.AbstractMutableMap & Any}, in @[EnhancedNullability] {V of kotlin.collections.AbstractMutableMap & Any}, out V of kotlin.collections.AbstractMutableMap?>): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>
VALUE_PARAMETER name:p0 index:0 type:@[EnhancedNullability] K of <root>.MyMap
VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] V of <root>.MyMap
VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] {V of <root>.MyMap & Any}
VALUE_PARAMETER name:p2 index:2 type:@[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] V of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>
FUN FAKE_OVERRIDE name:computeIfPresent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:@[EnhancedNullability] K of <root>.MyMap, p1:@[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] K of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>) returnType:V of <root>.MyMap? [fake_override]
overridden:
@@ -18170,6 +18170,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt");
}
@Test
@TestMetadata("flexibleTypeVariablePosition.kt")
public void testFlexibleTypeVariablePosition() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/flexibleTypeVariablePosition.kt");
}
@Test
@TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception {
@@ -19193,6 +19199,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/j+k/types/typeParameter.kt");
}
@Test
@TestMetadata("upperBoundsCheckAgainstSelfTypeInJava.kt")
public void testUpperBoundsCheckAgainstSelfTypeInJava() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/types/upperBoundsCheckAgainstSelfTypeInJava.kt");
}
@Test
@TestMetadata("varargOverride.kt")
public void testVarargOverride() throws Exception {
@@ -23116,6 +23128,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/platformTypes/samConstructor.kt");
}
@Test
@TestMetadata("starProjectionToFlexibleVariable.kt")
public void testStarProjectionToFlexibleVariable() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/starProjectionToFlexibleVariable.kt");
}
@Test
@TestMetadata("supertypeTypeArguments.kt")
public void testSupertypeTypeArguments() throws Exception {
@@ -38018,6 +38036,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/java"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("assertThatOnMap.kt")
public void testAssertThatOnMap() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/java/assertThatOnMap.kt");
}
@Test
@TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception {
@@ -289,15 +289,19 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
}
/**
* For case Foo <: (T..T?) return LowerBound for new constraint LowerBound <: T
* In FE 1.0, in case nullable it was just Foo?, so constraint was Foo? <: T
* For case Foo <: (T..T?) return LowerConstraint for new constraint LowerConstraint <: T
* In K1, in case nullable it was just Foo?, so constraint was Foo? <: T
* But it's not 100% correct because prevent having not-nullable upper constraint on T while initial (Foo? <: (T..T?)) is not violated
*
* In FIR, we try to have a correct one: (Foo!!..Foo?) <: T
* In FIR, we try to have a correct one: (Foo & Any..Foo?) <: T
*
* The same logic applies for T! <: UpperConstraint, as well
* In K1, it was reduced to T <: UpperConstraint..UpperConstraint?
* In FIR, we use UpperConstraint & Any..UpperConstraint?
*
* In future once we have only FIR (or FE 1.0 behavior is fixed) this method should be inlined to the use-site
*/
fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker
fun useRefinedBoundsForTypeVariableInFlexiblePosition(): Boolean
fun createCapturedStarProjectionForSelfType(
typeVariable: TypeVariableTypeConstructorMarker,
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.substitutedUnderlyingType
import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.error.ErrorTypeKind
import org.jetbrains.kotlin.types.error.ErrorUtils
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.typeUtil.*
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
import org.jetbrains.kotlin.types.typeUtil.isStubType as isSimpleTypeStubType
import org.jetbrains.kotlin.types.typeUtil.isStubTypeForBuilderInference as isSimpleTypeStubTypeForBuilderInference
import org.jetbrains.kotlin.types.error.ErrorUtils
import org.jetbrains.kotlin.types.typeUtil.isStubTypeForVariableInSubtyping as isSimpleTypeStubTypeForVariableInSubtyping
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
@@ -876,12 +876,7 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
return (baseType.memberScope as? SubstitutingScope)?.substitutor
}
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker =
if (this.isMarkedNullable()) {
this
} else {
createFlexibleType(this, this.withNullability(true))
}
override fun useRefinedBoundsForTypeVariableInFlexiblePosition(): Boolean = false
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): TypeCheckerState.SupertypesPolicy {
require(type is SimpleType, type::errorMessage)