[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:
-9
@@ -1,9 +0,0 @@
|
||||
interface A
|
||||
interface B: A
|
||||
interface D
|
||||
|
||||
interface BaseSuper<out T>
|
||||
interface BaseImpl: BaseSuper<D>
|
||||
interface DerivedSuper<out S>: <!INCONSISTENT_TYPE_PARAMETER_VALUES!>BaseSuper<S>, BaseImpl<!>
|
||||
|
||||
fun test(t: BaseSuper<B>) = t is <!CANNOT_CHECK_FOR_ERASED!>DerivedSuper<A><!>
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
interface A
|
||||
interface B: A
|
||||
interface D
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: Util.java
|
||||
public class Util {
|
||||
public static String getString() { return null; }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
fun testWithMap(map: ConcurrentHashMap<Int, String>): Int {
|
||||
var string = map[1]
|
||||
if (string == null) {
|
||||
string = map.computeIfAbsent(1) { "hello" }
|
||||
}
|
||||
return string.length
|
||||
}
|
||||
|
||||
fun testWithUtil(map: ConcurrentHashMap<Int, String>): Int {
|
||||
var string = map[1]
|
||||
if (string == null) {
|
||||
string = Util.getString()
|
||||
}
|
||||
return string<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test(list: java.util.ArrayList<String?>) {
|
||||
val x = list.get(0)<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: Util.java
|
||||
public class Util {
|
||||
public static String getString() { return null; }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
fun testWithMap(map: ConcurrentHashMap<Int, String>): Int {
|
||||
var string = map[1]
|
||||
if (string == null) {
|
||||
string = map.computeIfAbsent(1) { "hello" }
|
||||
}
|
||||
return <!DEBUG_INFO_SMARTCAST!>string<!>.length
|
||||
}
|
||||
|
||||
fun testWithUtil(map: ConcurrentHashMap<Int, String>): Int {
|
||||
var string = map[1]
|
||||
if (string == null) {
|
||||
string = Util.getString()
|
||||
}
|
||||
return string<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test(list: java.util.ArrayList<String?>) {
|
||||
val x = list.get(0)<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ list: java.util.ArrayList<kotlin.String?>): kotlin.Unit
|
||||
public fun testWithMap(/*0*/ map: java.util.concurrent.ConcurrentHashMap<kotlin.Int, kotlin.String>): kotlin.Int
|
||||
public fun testWithUtil(/*0*/ map: java.util.concurrent.ConcurrentHashMap<kotlin.Int, kotlin.String>): kotlin.Int
|
||||
|
||||
public open class Util {
|
||||
public constructor Util()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public open fun getString(): kotlin.String!
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
interface A {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
interface B : A {
|
||||
abstract override fun foo()
|
||||
}
|
||||
|
||||
interface C : A {
|
||||
abstract override fun foo()
|
||||
}
|
||||
|
||||
interface D : A
|
||||
|
||||
// Fake override Z#foo should be abstract
|
||||
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>class Z<!> : B, C, D
|
||||
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
interface A {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
// FILE: A.java
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
public interface A<T> {
|
||||
void foo(@NotNull T x);
|
||||
}
|
||||
|
||||
// FILE: B.java
|
||||
public class B<E> {
|
||||
public void foo(E x) {}
|
||||
}
|
||||
|
||||
// FILE: C.java
|
||||
public class C<F> extends B<F> implements A<F> {
|
||||
public static C<String> create() { return null; }
|
||||
public void foo(F x) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun test() {
|
||||
C.create().foo(null)
|
||||
C.create().foo("")
|
||||
|
||||
C<String>().foo(null)
|
||||
C<String?>().foo(null)
|
||||
C<String?>().foo("")
|
||||
}
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: A.java
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
interface X<T>
|
||||
interface A: X<String>
|
||||
interface B : <!INCONSISTENT_TYPE_PARAMETER_VALUES!>A, X<Int><!>
|
||||
|
||||
fun foo(x: B) {
|
||||
// Checks that when checking subtypes we search closes corresponding constructor (e.g. with BFS)
|
||||
val y: X<Int> = <!INITIALIZER_TYPE_MISMATCH!>x<!>
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
interface X<T>
|
||||
|
||||
+3
-3
@@ -20,11 +20,11 @@ fun test(b: B, c: C, d: D, e: E) {
|
||||
eatAString(b)
|
||||
eatAString(c)
|
||||
eatAString(d)
|
||||
eatAString(e)
|
||||
eatAString(<!ARGUMENT_TYPE_MISMATCH!>e<!>)
|
||||
|
||||
eatAStringN(b)
|
||||
eatAStringN(c)
|
||||
eatAStringN(d)
|
||||
eatAStringN(<!ARGUMENT_TYPE_MISMATCH!>d<!>)
|
||||
eatAStringN(e)
|
||||
}
|
||||
|
||||
@@ -39,4 +39,4 @@ class W: B(), Z
|
||||
fun test2(w: W) {
|
||||
eatAString(w)
|
||||
eatAStringN(<!ARGUMENT_TYPE_MISMATCH!>w<!>)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,4 @@ class W: B(), Z
|
||||
fun test2(w: W) {
|
||||
eatAString(w)
|
||||
eatAStringN(<!TYPE_MISMATCH!>w<!>)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,6 +16,6 @@ fun foo() {
|
||||
concurrent.remove(null, null)
|
||||
|
||||
// @PurelyImplements
|
||||
concurrentHash.remove(null, 1)
|
||||
concurrentHash.remove(null, null)
|
||||
concurrentHash.remove(<!NULL_FOR_NONNULL_TYPE!>null<!>, 1)
|
||||
concurrentHash.remove(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ fun foo(x: MutableMap<String, Int>, y: java.util.HashMap<String, Int>, z: java.u
|
||||
|
||||
y.remove("", 1)
|
||||
y.remove("", <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
y.remove("", null)
|
||||
y.remove("", <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
|
||||
z.remove("", 1)
|
||||
z.remove("", <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
|
||||
+27
-27
@@ -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[""]<!>
|
||||
|
||||
compiler/testData/diagnostics/testsWithStdLib/purelyImplementedCollection/mapsWithNullableKey.fir.kt
Vendored
+9
-8
@@ -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
|
||||
|
||||
Vendored
+1
@@ -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
|
||||
|
||||
+10
-10
@@ -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("")<!>
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user