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"); 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 @Test
@TestMetadata("genericConstructorWithMultipleBounds.kt") @TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception { public void testGenericConstructorWithMultipleBounds() throws Exception {
@@ -19187,6 +19193,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/j+k/types/typeParameter.kt"); 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 @Test
@TestMetadata("varargOverride.kt") @TestMetadata("varargOverride.kt")
public void testVarargOverride() throws Exception { public void testVarargOverride() throws Exception {
@@ -23110,6 +23122,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/platformTypes/samConstructor.kt"); 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 @Test
@TestMetadata("supertypeTypeArguments.kt") @TestMetadata("supertypeTypeArguments.kt")
public void testSupertypeTypeArguments() throws Exception { 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); 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 @Test
@TestMetadata("checkEnhancedUpperBounds.kt") @TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception { public void testCheckEnhancedUpperBounds() throws Exception {
@@ -7,7 +7,7 @@ FILE: main.kt
public abstract interface PsiClass : R|kotlin/Any| { public abstract interface PsiClass : R|kotlin/Any| {
} }
public final fun test(): R|kotlin/Unit| { 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| } ^ R|<local>/method|?.{ $subj$.R|/PsiMethod.containingClass| }
} }
)) ))
@@ -1,4 +1,4 @@
FILE: main.kt 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| { 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| { 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| { public final fun test_2(): R|kotlin/Unit| {
lval set: R|util/HashSet<kotlin/Int>| = R|util/HashSet.HashSet|<R|kotlin/Int|>() lval set: R|util/HashSet<kotlin/Int>| = R|util/HashSet.HashSet|<R|kotlin/Int|>()
} }
public final fun test_3(): R|kotlin/Unit| { 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| { public final fun test_4(): R|kotlin/Unit| {
lval list: R|foo/LinkedList<kotlin/Int>| = R|foo/LinkedList.LinkedList|<R|kotlin/Int|>() 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| lval element: R|DE| = R|<local>/d|.R|/Diagnostic.element|
R|/Fix.Fix|(R|<local>/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 final val DERIVED_FACTORY: R|DiagnosticFactory0<DerivedElement>| = R|/DiagnosticFactory0.DiagnosticFactory0|<R|DerivedElement|>()
private get(): R|DiagnosticFactory0<ft<DerivedElement, DerivedElement?>>| private get(): R|DiagnosticFactory0<DerivedElement>|
public final fun createViaFactory(d: R|EmptyDiagnostic|): R|kotlin/Unit| { 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 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| lval element: R|DerivedElement| = R|<local>/casted|.R|/Diagnostic.element|
@@ -1,6 +1,6 @@
FILE: flexibleTypeBug.kt FILE: flexibleTypeBug.kt
public final fun foo(): R|kotlin/Unit| { 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)) 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|) 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 FILE: main.kt
public final fun main(): R|kotlin/Unit| { 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 FILE: main.kt
public final fun main(): R|kotlin/Unit| { 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|() ^ 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] [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] [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] [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] [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, T?>| from Java enhancement scope for /B [id: 2] [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] [Source]: private final var name: R|kotlin/String| = R|<local>/name| from Use site scope of /C [id: 0]
D: D:
@@ -1,5 +1,5 @@
FILE: main.kt FILE: main.kt
public final fun <T : R|kotlin/CharSequence?|> foo(mapper: R|Mapper|, cls: R|java/lang/Class<T>?|): R|kotlin/Unit| { 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| R|<local>/result|.R|kotlin/CharSequence.length|
} }
@@ -3,5 +3,5 @@ FILE: main.kt
public final typealias ImmutableSet<E> = R|MySet<E>| public final typealias ImmutableSet<E> = R|MySet<E>|
private final typealias ImmutableMultimap<K, V> = R|ImmutableMap<K, ImmutableSet<V>>| 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>| { 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|>() 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 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<ft<kotlin/String, kotlin/String?>, ft<kotlin/CharSequence, kotlin/CharSequence?>>| private get(): R|java/util/concurrent/ConcurrentHashMap<kotlin/String, kotlin/CharSequence>|
private final fun bar(): R|kotlin/Unit| { 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|() } 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>| public final typealias ImmutableLinkedHashSet<E> = R|imm/LinkedHashSet<E>|
private final typealias ImmutableMultimap<K, V> = R|ImmutableMap<K, ImmutableSet<V>>| 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| { 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 FILE: javaLangComparator.kt
public final fun test_2(list: R|kotlin/collections/List<kotlin/Int>|): R|kotlin/Unit| { 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) ^ Int(1)
} }
) )
@@ -1,6 +1,6 @@
FILE: kotlinComparatorAlias.kt FILE: kotlinComparatorAlias.kt
public final fun test_1(): R|kotlin/Unit| { 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) ^ Int(1)
} }
) )
@@ -1,6 +1,6 @@
FILE: weakHashMap.kt 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 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<ft<kotlin/Any, kotlin/Any?>, ft<kotlin/Any, kotlin/Any?>>| public get(): R|java/util/WeakHashMap<kotlin/Any?, kotlin/Any?>|
public final fun foo(): R|kotlin/Unit| { public final fun foo(): R|kotlin/Unit| {
R|/someMap|.R|SubstitutionOverride<java/util/WeakHashMap.get: R|kotlin/Any?|>|(String()) 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 typealias Arguments = R|kotlin/collections/Map<kotlin/String, ArgsInfo>|
public final fun R|Arguments|.deepCopy(): R|Arguments| { 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> { 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| ^deepCopy R|<local>/result|
@@ -18164,6 +18164,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt"); 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 @Test
@TestMetadata("genericConstructorWithMultipleBounds.kt") @TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception { public void testGenericConstructorWithMultipleBounds() throws Exception {
@@ -19187,6 +19193,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/j+k/types/typeParameter.kt"); 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 @Test
@TestMetadata("varargOverride.kt") @TestMetadata("varargOverride.kt")
public void testVarargOverride() throws Exception { public void testVarargOverride() throws Exception {
@@ -23110,6 +23122,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/platformTypes/samConstructor.kt"); 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 @Test
@TestMetadata("supertypeTypeArguments.kt") @TestMetadata("supertypeTypeArguments.kt")
public void testSupertypeTypeArguments() throws Exception { 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); 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 @Test
@TestMetadata("checkEnhancedUpperBounds.kt") @TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception { public void testCheckEnhancedUpperBounds() throws Exception {
@@ -18164,6 +18164,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt"); 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 @Test
@TestMetadata("genericConstructorWithMultipleBounds.kt") @TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception { public void testGenericConstructorWithMultipleBounds() throws Exception {
@@ -19187,6 +19193,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/j+k/types/typeParameter.kt"); 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 @Test
@TestMetadata("varargOverride.kt") @TestMetadata("varargOverride.kt")
public void testVarargOverride() throws Exception { public void testVarargOverride() throws Exception {
@@ -23110,6 +23122,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/platformTypes/samConstructor.kt"); 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 @Test
@TestMetadata("supertypeTypeArguments.kt") @TestMetadata("supertypeTypeArguments.kt")
public void testSupertypeTypeArguments() throws Exception { 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); 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 @Test
@TestMetadata("checkEnhancedUpperBounds.kt") @TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception { public void testCheckEnhancedUpperBounds() throws Exception {
@@ -102,7 +102,19 @@ private fun JavaType?.toConeTypeProjection(
return lowerBound return lowerBound
} }
val upperBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes, 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 -> { is JavaArrayType -> {
@@ -92,7 +92,12 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
qualifiers: IndexedJavaTypeQualifiers, qualifiers: IndexedJavaTypeQualifiers,
index: Int, index: Int,
subtreeSizes: List<Int>, subtreeSizes: List<Int>,
isFromDefinitelyNotNullType: Boolean = false,
): ConeSimpleKotlinType? { ): ConeSimpleKotlinType? {
if (this is ConeDefinitelyNotNullType) {
return original.enhanceInflexibleType(session, position, qualifiers, index, subtreeSizes, isFromDefinitelyNotNullType = true)
}
val shouldEnhance = position.shouldEnhance() val shouldEnhance = position.shouldEnhance()
if ((!shouldEnhance && typeArguments.isEmpty()) || this !is ConeLookupTagBasedType) { if ((!shouldEnhance && typeArguments.isEmpty()) || this !is ConeLookupTagBasedType) {
return null return null
@@ -104,7 +109,7 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
// TODO: implement warnings // TODO: implement warnings
val nullabilityFromQualifiers = effectiveQualifiers.nullability val nullabilityFromQualifiers = effectiveQualifiers.nullability
.takeIf { shouldEnhance && !effectiveQualifiers.isNullabilityQualifierForWarning } .takeIf { shouldEnhance && !effectiveQualifiers.isNullabilityQualifierForWarning }
val enhancedNullability = when (nullabilityFromQualifiers) { val enhancedIsNullable = when (nullabilityFromQualifiers) {
NullabilityQualifier.NULLABLE -> true NullabilityQualifier.NULLABLE -> true
NullabilityQualifier.NOT_NULL -> false NullabilityQualifier.NOT_NULL -> false
else -> isNullable else -> isNullable
@@ -124,14 +129,14 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
} }
val shouldAddAttribute = nullabilityFromQualifiers == NullabilityQualifier.NOT_NULL && !hasEnhancedNullability 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 return null // absolutely no changes
} }
val mergedArguments = Array(typeArguments.size) { enhancedArguments[it] ?: typeArguments[it] } val mergedArguments = Array(typeArguments.size) { enhancedArguments[it] ?: typeArguments[it] }
val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes
val enhancedType = enhancedTag.constructType(mergedArguments, enhancedNullability, mergedAttributes) val enhancedType = enhancedTag.constructType(mergedArguments, enhancedIsNullable, mergedAttributes)
return if (effectiveQualifiers.definitelyNotNull) return if (effectiveQualifiers.definitelyNotNull || (isFromDefinitelyNotNullType && nullabilityFromQualifiers == null))
ConeDefinitelyNotNullType.create(enhancedType, session.typeContext) ?: enhancedType ConeDefinitelyNotNullType.create(enhancedType, session.typeContext) ?: enhancedType
else else
enhancedType enhancedType
@@ -103,10 +103,12 @@ abstract class AbstractConeSubstitutor(protected val typeContext: ConeTypeContex
} }
private fun ConeDefinitelyNotNullType.substituteOriginal(): ConeKotlinType? { private fun ConeDefinitelyNotNullType.substituteOriginal(): ConeKotlinType? {
val substituted = substituteOrNull(original) val substitutedOriginal = substituteOrNull(original) ?: return null
?.withNullability(ConeNullability.NOT_NULL, typeContext) val substituted = substitutedOriginal.withNullability(
?.withAttributes(original.attributes) ConeNullability.NOT_NULL,
?: return null typeContext,
substitutedOriginal.attributes.add(original.attributes)
)
return ConeDefinitelyNotNullType.create(substituted, typeContext) ?: substituted return ConeDefinitelyNotNullType.create(substituted, typeContext) ?: substituted
} }
@@ -562,8 +562,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
return intersectionType.withAlternative(secondCandidate) return intersectionType.withAlternative(secondCandidate)
} }
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker = override fun useRefinedBoundsForTypeVariableInFlexiblePosition(): Boolean = true
createFlexibleType(this.makeSimpleTypeDefinitelyNotNullOrNotNull(), this.withNullability(true))
override fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? = override fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? =
if (baseType is ConeLookupTagBasedType) createSubstitutionForSupertype(baseType, session) else null 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.descriptors.valueClassLoweringKind
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* 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.expressions.*
import org.jetbrains.kotlin.fir.resolve.directExpansionType import org.jetbrains.kotlin.fir.resolve.directExpansionType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
@@ -289,7 +292,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
else -> listOf(session.builtinTypes.anyType.type) else -> listOf(session.builtinTypes.anyType.type)
} }
} }
is ConeCapturedTypeConstructor -> supertypes!! is ConeCapturedTypeConstructor -> supertypes.orEmpty()
is ConeIntersectionType -> intersectedTypes is ConeIntersectionType -> intersectedTypes
is ConeIntegerLiteralType -> supertypes is ConeIntegerLiteralType -> supertypes
else -> unknownConstructorError() else -> unknownConstructorError()
@@ -475,13 +478,13 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
return when (this) { return when (this) {
is ConeFlexibleType -> this.upperBound.isNullableType() is ConeFlexibleType -> this.upperBound.isNullableType()
is ConeTypeParameterType -> lookupTag.symbol.allBoundsAreNullable() is ConeTypeParameterType -> lookupTag.symbol.allBoundsAreNullableOrUnresolved()
is ConeTypeVariableType -> { is ConeTypeVariableType -> {
val symbol = lookupTag.toSymbol(session) ?: return false val symbol = lookupTag.toSymbol(session) ?: return false
when (symbol) { when (symbol) {
is FirClassSymbol -> false is FirClassSymbol -> false
is FirTypeAliasSymbol -> symbol.fir.expandedConeType?.isNullableType() ?: false is FirTypeAliasSymbol -> symbol.fir.expandedConeType?.isNullableType() ?: false
is FirTypeParameterSymbol -> symbol.allBoundsAreNullable() is FirTypeParameterSymbol -> symbol.allBoundsAreNullableOrUnresolved()
} }
} }
is ConeIntersectionType -> intersectedTypes.all { it.isNullableType() } is ConeIntersectionType -> intersectedTypes.all { it.isNullableType() }
@@ -490,8 +493,13 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
} }
} }
private fun FirTypeParameterSymbol.allBoundsAreNullable(): Boolean { private fun FirTypeParameterSymbol.allBoundsAreNullableOrUnresolved(): Boolean {
return resolvedBounds.all { it.coneType.isNullableType() } for (bound in fir.bounds) {
if (bound !is FirResolvedTypeRef) return true
if (!bound.type.isNullableType()) return false
}
return true
} }
private fun TypeConstructorMarker.toFirRegularClass(): FirRegularClass? { private fun TypeConstructorMarker.toFirRegularClass(): FirRegularClass? {
@@ -60,7 +60,7 @@ fun TypeCheckerProviderContext.equalTypes(a: ConeKotlinType, b: ConeKotlinType):
private fun ConeTypeContext.makesSenseToBeDefinitelyNotNull(originalType: ConeKotlinType): Boolean { private fun ConeTypeContext.makesSenseToBeDefinitelyNotNull(originalType: ConeKotlinType): Boolean {
return when (val type = originalType.lowerBoundIfFlexible()) { 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. // 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`. // Basically, if we have `T : X..X?`, then `T <: Any` but we still have `T` != `T & Any`.
is ConeTypeVariableType, is ConeCapturedType -> { is ConeTypeVariableType, is ConeCapturedType -> {
@@ -75,12 +75,13 @@ private fun ConeTypeContext.makesSenseToBeDefinitelyNotNull(originalType: ConeKo
fun ConeDefinitelyNotNullType.Companion.create( fun ConeDefinitelyNotNullType.Companion.create(
original: ConeKotlinType, original: ConeKotlinType,
typeContext: ConeTypeContext typeContext: ConeTypeContext,
forceWithoutCheck: Boolean = false,
): ConeDefinitelyNotNullType? { ): ConeDefinitelyNotNullType? {
return when (original) { return when (original) {
is ConeDefinitelyNotNullType -> original is ConeDefinitelyNotNullType -> original
is ConeFlexibleType -> create(original.lowerBound, typeContext) is ConeFlexibleType -> create(original.lowerBound, typeContext)
is ConeSimpleKotlinType -> runIf(typeContext.makesSenseToBeDefinitelyNotNull(original)) { is ConeSimpleKotlinType -> runIf(forceWithoutCheck || typeContext.makesSenseToBeDefinitelyNotNull(original)) {
ConeDefinitelyNotNullType(original.coneLowerBoundIfFlexible()) 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.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.impl.toConeType 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.symbols.ensureResolved
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
@@ -66,11 +65,7 @@ internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
when (val typeArgument = candidate.typeArgumentMapping[index]) { when (val typeArgument = candidate.typeArgumentMapping[index]) {
is FirTypeProjectionWithVariance -> csBuilder.addEqualityConstraint( is FirTypeProjectionWithVariance -> csBuilder.addEqualityConstraint(
freshVariable.defaultType, freshVariable.defaultType,
getTypePreservingFlexibilityWrtTypeVariable( typeArgument.typeRef.coneType.fullyExpandedType(context.session),
typeArgument.typeRef.coneType,
typeParameter,
context.session
).fullyExpandedType(context.session),
ConeExplicitTypeParameterConstraintPosition(typeArgument) ConeExplicitTypeParameterConstraintPosition(typeArgument)
) )
is FirStarProjection -> csBuilder.addEqualityConstraint( 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( private fun createToFreshVariableSubstitutorAndAddInitialConstraints(
@@ -21,7 +21,8 @@ import org.jetbrains.kotlin.types.model.TypeVariableMarker
object ConeConstraintSystemUtilContext : ConstraintSystemUtilContext { object ConeConstraintSystemUtilContext : ConstraintSystemUtilContext {
override fun TypeVariableMarker.shouldBeFlexible(): Boolean { 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 return false
} }
@@ -59,7 +59,11 @@ class ConstraintIncorporator(
typeVariable: TypeVariableMarker, typeVariable: TypeVariableMarker,
constraint: Constraint constraint: Constraint
) { ) {
val shouldBeTypeVariableFlexible = with(utilContext) { typeVariable.shouldBeFlexible() } val shouldBeTypeVariableFlexible =
if (useRefinedBoundsForTypeVariableInFlexiblePosition())
false
else
with(utilContext) { typeVariable.shouldBeFlexible() }
// \alpha <: constraint.type // \alpha <: constraint.type
if (constraint.kind != ConstraintKind.LOWER) { if (constraint.kind != ConstraintKind.LOWER) {
@@ -174,9 +174,9 @@ abstract class TypeCheckerStateForConstraintSystem(
* *
* T? * T?
* *
* Foo <: T? -- Foo & Any <: T -- Foo!! <: T * Foo <: T? -- Foo & Any <: T
* Foo? <: T? -- Foo? & Any <: T -- Foo!! <: T * Foo? <: T? -- Foo? & Any <: T -- Foo & Any <: T
* (Foo..Bar) <: T? -- (Foo..Bar) & Any <: T -- (Foo..Bar)!! <: T * (Foo..Bar) <: T? -- (Foo..Bar) & Any <: T
* *
* T! * T!
* *
@@ -248,12 +248,34 @@ abstract class TypeCheckerStateForConstraintSystem(
when (subType) { when (subType) {
is SimpleTypeMarker -> is SimpleTypeMarker ->
// Foo <: T! -- (Foo!! .. Foo) <: T when {
subType.createConstraintPartForLowerBoundAndFlexibleTypeVariable() 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 -> 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") 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 <=> T <: Foo && Nothing? <: Foo
* T <: Foo -- leave as is * T <: Foo -- leave as is
*/ */
private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean = with(extensionTypeContext) { private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean = with(extensionTypeContext) {
val typeVariableLowerBound = typeVariable.lowerBoundIfFlexible() val typeVariableLowerBound = typeVariable.lowerBoundIfFlexible()
val simplifiedSuperType = if (typeVariableLowerBound.isDefinitelyNotNullType()) {
superType.withNullability(true) val simplifiedSuperType = when {
} else if (typeVariable.isFlexible() && superType is SimpleTypeMarker) { typeVariable.isFlexible() && useRefinedBoundsForTypeVariableInFlexiblePosition() ->
createFlexibleType(superType, superType.withNullability(true)) createFlexibleType(
} else superType 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) 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 // JSPECIFY_STATE: strict
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode // !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
// FILE: J1.java // FILE: J1.java
@@ -37,7 +37,7 @@ fun <R> main(a: ReturnType<R>) {
takeNullableStringAndKNullable(x1) takeNullableStringAndKNullable(x1)
takeNotNullStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x1<!>) takeNotNullStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x1<!>)
takeNullableStringAndNotNullK(<!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()<!> val x2 = <!DEBUG_INFO_EXPRESSION_TYPE("ReturnType.A<kotlin.String?, R!!>..ReturnType.A<kotlin.String?, R!!>?!")!>a.foo2()<!>
takeNotNullStringAndKNullable(<!ARGUMENT_TYPE_MISMATCH!>x2<!>) takeNotNullStringAndKNullable(<!ARGUMENT_TYPE_MISMATCH!>x2<!>)
@@ -39,7 +39,7 @@ fun <R> main(a: ReturnTypeWithWarnings<R>) {
takeNullableStringAndKNullable(x1) takeNullableStringAndKNullable(x1)
takeNotNullStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x1<!>) takeNotNullStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x1<!>)
takeNullableStringAndNotNullK(<!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()<!> val x2 = <!DEBUG_INFO_EXPRESSION_TYPE("ReturnTypeWithWarnings.A<kotlin.String?, R!!>..ReturnTypeWithWarnings.A<kotlin.String?, R!!>?!")!>a.foo2()<!>
takeNotNullStringAndKNullable(<!ARGUMENT_TYPE_MISMATCH!>x2<!>) 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 // !LANGUAGE: +DefinitelyNonNullableTypes +ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated
// FILE: A.java // FILE: A.java
@@ -27,7 +27,7 @@ val xExplicit: X = Test().findViewById(0)
val xCast = Test().findViewById(0) as X val xCast = Test().findViewById(0) as X
val xCastExplicitType = Test().findViewById<X>(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 yExplicit: Y<String> = Test().findViewById(0)
val yCast = Test().findViewById(0) as Y<String> 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() { fun test() {
A.bar(null, "") A.bar(null, "")
A.bar<String>(null, "") A.bar<String>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
A.bar<String?>(null, "") A.bar<String?>(null, "")
A.bar(null, A.platformString()) 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 import java.util.ArrayList
fun foo() { 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() { fun foo() {
var x = ArrayList<String>() var x = ArrayList<String>()
x.add(null) x.add(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.add(bar()) x.add(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>)
x.add("") x.add("")
x[0] = null x[0] = <!NULL_FOR_NONNULL_TYPE!>null<!>
x[0] = bar() x[0] = <!ARGUMENT_TYPE_MISMATCH!>bar()<!>
x[0] = "" x[0] = ""
val b1: MutableList<String?> = x val b1: MutableList<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableList<String> = x val b2: MutableList<String> = x
val b3: List<String?> = x val b3: List<String?> = x
val b4: Collection<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] = "" x[0] = ""
val b1: MutableList<String?> = x val b1: MutableList<String?> = x
val b2: MutableList<String> = x val b2: MutableList<String> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b3: List<String?> = x val b3: List<String?> = x
val b4: Collection<String?> = x val b4: Collection<String?> = x
@@ -28,5 +28,5 @@ fun foo() {
x.add("") x.add("")
val b1: Collection<String?> = x 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] = bar()
x[0] = "" x[0] = ""
val b1: MutableList<String?> = x val b1: MutableList<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableList<String> = x val b2: MutableList<String> = x
val b3: List<String?> = x val b3: List<String?> = x
val b4: Collection<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() { fun fooHashSet() {
var x = HashSet<String>() var x = HashSet<String>()
x.add(null) x.add(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.add(bar()) x.add(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>)
x.add("") x.add("")
val b1: MutableSet<String?> = x val b1: MutableSet<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableSet<String> = x val b2: MutableSet<String> = x
val b3: Set<String?> = x val b3: Set<String?> = x
val b4: Collection<String?> = x val b4: Collection<String?> = x
val b6: MutableCollection<String?> = x val b6: MutableCollection<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
} }
fun fooTreeSet() { fun fooTreeSet() {
var x = TreeSet<String>() var x = TreeSet<String>()
x.add(null) x.add(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.add(bar()) x.add(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>)
x.add("") x.add("")
val b1: MutableSet<String?> = x val b1: MutableSet<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableSet<String> = x val b2: MutableSet<String> = x
val b3: Set<String?> = x val b3: Set<String?> = x
val b4: Collection<String?> = x val b4: Collection<String?> = x
val b6: MutableCollection<String?> = x val b6: MutableCollection<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
} }
fun fooLinkedHashSet() { fun fooLinkedHashSet() {
@@ -39,10 +39,10 @@ fun fooLinkedHashSet() {
x.add(bar()) x.add(bar())
x.add("") x.add("")
val b1: MutableSet<String?> = x val b1: MutableSet<String?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableSet<String> = x val b2: MutableSet<String> = x
val b3: Set<String?> = x val b3: Set<String?> = x
val b4: Collection<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: overridden:
public open fun clear (): kotlin.Unit [fake_override] declared in kotlin.collections.AbstractMutableMap 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> $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: 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 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> $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] 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: overridden:
public open fun remove (p0: @[FlexibleNullability] K of kotlin.collections.AbstractMutableMap?): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap 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 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> $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> 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: 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 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> $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: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?> 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] 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: overridden:
@@ -18170,6 +18170,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt"); 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 @Test
@TestMetadata("genericConstructorWithMultipleBounds.kt") @TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception { public void testGenericConstructorWithMultipleBounds() throws Exception {
@@ -19193,6 +19199,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/j+k/types/typeParameter.kt"); 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 @Test
@TestMetadata("varargOverride.kt") @TestMetadata("varargOverride.kt")
public void testVarargOverride() throws Exception { public void testVarargOverride() throws Exception {
@@ -23116,6 +23128,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/platformTypes/samConstructor.kt"); 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 @Test
@TestMetadata("supertypeTypeArguments.kt") @TestMetadata("supertypeTypeArguments.kt")
public void testSupertypeTypeArguments() throws Exception { 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); 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 @Test
@TestMetadata("checkEnhancedUpperBounds.kt") @TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception { 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 * For case Foo <: (T..T?) return LowerConstraint for new constraint LowerConstraint <: T
* In FE 1.0, in case nullable it was just Foo?, so constraint was Foo? <: 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 * 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 * 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( fun createCapturedStarProjectionForSelfType(
typeVariable: TypeVariableTypeConstructorMarker, typeVariable: TypeVariableTypeConstructorMarker,
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.substitutedUnderlyingType
import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.error.ErrorTypeKind 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.model.*
import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.types.typeUtil.*
import org.jetbrains.kotlin.utils.addIfNotNull 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.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
import org.jetbrains.kotlin.types.typeUtil.isStubType as isSimpleTypeStubType import org.jetbrains.kotlin.types.typeUtil.isStubType as isSimpleTypeStubType
import org.jetbrains.kotlin.types.typeUtil.isStubTypeForBuilderInference as isSimpleTypeStubTypeForBuilderInference 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 import org.jetbrains.kotlin.types.typeUtil.isStubTypeForVariableInSubtyping as isSimpleTypeStubTypeForVariableInSubtyping
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext { interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
@@ -876,12 +876,7 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
return (baseType.memberScope as? SubstitutingScope)?.substitutor return (baseType.memberScope as? SubstitutingScope)?.substitutor
} }
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker = override fun useRefinedBoundsForTypeVariableInFlexiblePosition(): Boolean = false
if (this.isMarkedNullable()) {
this
} else {
createFlexibleType(this, this.withNullability(true))
}
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): TypeCheckerState.SupertypesPolicy { override fun substitutionSupertypePolicy(type: SimpleTypeMarker): TypeCheckerState.SupertypesPolicy {
require(type is SimpleType, type::errorMessage) require(type is SimpleType, type::errorMessage)