[FIR] Properly collect overriddens for method enhancement

If some java class has multiple supertypes then we need to collect
  overriddens from all those types directly, even if superTypeScope
  (which is FirTypeIntersectionScope in this case) returns only
  one symbol from one of this types (not intersection one)

This is needed to proper enhancement in cases when some type occurs
  multiple times in supertypes graph with different nullability
  of arguments:

class ConcurrentHashMap<K, V> : AbstractMap<K!, V!>, MutableMap<K, V>

If we try to find method `get(key: K): V` supertype scope returns
  `AbstractMap.get(key: K!): V!` (because it actually overrides
  `MutableMap(key: K): V?`), but we need to get both symbols to
  properly enhance types for `ConcurrentHashMap.remove`
This commit is contained in:
Dmitriy Novozhilov
2021-11-19 18:16:07 +03:00
parent 01c0cf80d0
commit 9807c67ae4
42 changed files with 393 additions and 301 deletions
@@ -9,20 +9,20 @@ val nullableInt: Int? = null
fun hashMapTest() {
var x: HashMap<String, Int> = HashMap<String, Int>()
x.put(null, null)
x.put("", null)
x.put(bar(), 1)
x.put(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put("", <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>, 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
x[<!NULL_FOR_NONNULL_TYPE!>null<!>] = 1
x[<!ARGUMENT_TYPE_MISMATCH!>bar()<!>] = 1
x[""] = <!ARGUMENT_TYPE_MISMATCH!>nullableInt<!>
x[""] = 1
val b1: MutableMap<String, Int?> = x
val b1: MutableMap<String, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableMap<String, Int> = x
val b3: Map<String?, Int> = x
val b4: Map<String?, Int?> = x
val b3: Map<String?, Int> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b4: Map<String?, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b5: Map<String, Int?> = x
val b6: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x[""]<!>
@@ -33,20 +33,20 @@ fun hashMapTest() {
fun treeMapTest() {
var x: TreeMap<String, Int> = TreeMap<String, Int>()
x.put(null, null)
x.put("", null)
x.put(bar(), 1)
x.put(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put("", <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>, 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
x[<!NULL_FOR_NONNULL_TYPE!>null<!>] = 1
x[<!ARGUMENT_TYPE_MISMATCH!>bar()<!>] = 1
x[""] = <!ARGUMENT_TYPE_MISMATCH!>nullableInt<!>
x[""] = 1
val b1: MutableMap<String, Int?> = x
val b1: MutableMap<String, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableMap<String, Int> = x
val b3: Map<String?, Int> = x
val b4: Map<String?, Int?> = x
val b3: Map<String?, Int> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b4: Map<String?, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b5: Map<String, Int?> = x
val b6: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x[""]<!>
@@ -57,20 +57,20 @@ fun treeMapTest() {
fun concurrentHashMapTest() {
var x: ConcurrentHashMap<String, Int> = ConcurrentHashMap<String, Int>()
x.put(null, null)
x.put("", null)
x.put(bar(), 1)
x.put(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put("", <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>, 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
x[<!NULL_FOR_NONNULL_TYPE!>null<!>] = 1
x[<!ARGUMENT_TYPE_MISMATCH!>bar()<!>] = 1
x[""] = <!ARGUMENT_TYPE_MISMATCH!>nullableInt<!>
x[""] = 1
val b1: MutableMap<String, Int?> = x
val b1: MutableMap<String, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableMap<String, Int> = x
val b3: Map<String?, Int> = x
val b4: Map<String?, Int?> = x
val b3: Map<String?, Int> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b4: Map<String?, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b5: Map<String, Int?> = x
val b6: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x[""]<!>
@@ -8,17 +8,18 @@ val nullableInt: Int? = null
fun hashMapTest() {
var x: HashMap<String?, Int> = HashMap<String?, Int>()
x.put(null, null)
x.put("", null)
x.put(null, <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put("", <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
x[""] = <!ARGUMENT_TYPE_MISMATCH!>nullableInt<!>
x[""] = 1
x[""] = <!NULL_FOR_NONNULL_TYPE!>null<!>
val b1: MutableMap<String?, Int?> = x
val b1: MutableMap<String?, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableMap<String?, Int> = x
val b3: Map<String?, Int> = x
val b4: Map<String?, Int?> = x
@@ -33,17 +34,17 @@ fun hashMapTest() {
fun treeMapTest() {
var x: TreeMap<String?, Int> = TreeMap<String?, Int>()
x.put(null, null)
x.put("", null)
x.put(null, <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put("", <!NULL_FOR_NONNULL_TYPE!>null<!>)
x.put(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
x[""] = <!ARGUMENT_TYPE_MISMATCH!>nullableInt<!>
x[""] = 1
val b1: MutableMap<String?, Int?> = x
val b1: MutableMap<String?, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b2: MutableMap<String?, Int> = x
val b3: Map<String?, Int> = x
val b4: Map<String?, Int?> = x
@@ -17,6 +17,7 @@ fun hashMapTest() {
x[bar()] = 1
x[""] = <!TYPE_MISMATCH!>nullableInt<!>
x[""] = 1
x[""] = <!NULL_FOR_NONNULL_TYPE!>null<!>
val b1: MutableMap<String?, Int?> = <!TYPE_MISMATCH!>x<!>
val b2: MutableMap<String?, Int> = x
@@ -8,13 +8,13 @@ val nullableInt: Int? = null
fun hashMapTest() {
var x: HashMap<String, Int?> = HashMap<String, Int?>()
x.put(null, null)
x.put(<!NULL_FOR_NONNULL_TYPE!>null<!>, null)
x.put("", null)
x.put(bar(), 1)
x.put(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>, 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[<!NULL_FOR_NONNULL_TYPE!>null<!>] = 1
x[<!ARGUMENT_TYPE_MISMATCH!>bar()<!>] = 1
x[""] = nullableInt
x[""] = 1
@@ -22,7 +22,7 @@ fun hashMapTest() {
val b2: MutableMap<String, Int?> = x
val b3: Map<String, Int> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b4: Map<String, Int?> = x
val b5: Map<String?, Int?> = x
val b5: Map<String?, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b6: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x[""]<!>
val b7: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x.get("")<!>
@@ -32,13 +32,13 @@ fun hashMapTest() {
fun treeMapTest() {
var x: TreeMap<String, Int?> = TreeMap<String, Int?>()
x.put(null, null)
x.put(<!NULL_FOR_NONNULL_TYPE!>null<!>, null)
x.put("", null)
x.put(bar(), 1)
x.put(<!ARGUMENT_TYPE_MISMATCH!>bar()<!>, 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[<!NULL_FOR_NONNULL_TYPE!>null<!>] = 1
x[<!ARGUMENT_TYPE_MISMATCH!>bar()<!>] = 1
x[""] = nullableInt
x[""] = 1
@@ -46,7 +46,7 @@ fun treeMapTest() {
val b2: MutableMap<String, Int?> = x
val b3: Map<String, Int> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b4: Map<String, Int?> = x
val b5: Map<String?, Int?> = x
val b5: Map<String?, Int?> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
val b6: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x[""]<!>
val b7: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x.get("")<!>
@@ -45,7 +45,7 @@ fun foo(x: List<String>, y: Throwable, z: A3) {
y.fillInStackTrace() checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Int>() }
HashMap<String, Int>().getOrDefault(<!ARGUMENT_TYPE_MISMATCH!>Any()<!>, null)
HashMap<String, Int>().getOrDefault(<!ARGUMENT_TYPE_MISMATCH!>Any()<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
// Falls back to extension in stdlib
y.printStackTrace()