[FIR] Extract non-null info from x?.y!! ^KT-44513 Fixed
This commit is contained in:
+21
-9
@@ -654,16 +654,28 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
// Add `Any` to the set of possible types; the intersection type `T? & Any` will be reduced to `T` after smartcast.
|
// Add `Any` to the set of possible types; the intersection type `T? & Any` will be reduced to `T` after smartcast.
|
||||||
val (node, unionNode) = graphBuilder.exitCheckNotNullCall(checkNotNullCall, callCompleted)
|
val (node, unionNode) = graphBuilder.exitCheckNotNullCall(checkNotNullCall, callCompleted)
|
||||||
node.mergeIncomingFlow()
|
node.mergeIncomingFlow()
|
||||||
val argument = checkNotNullCall.argument
|
|
||||||
variableStorage.getOrCreateRealVariable(node.previousFlow, argument.symbol, argument)?.let { operandVariable ->
|
fun FirExpression.propagateNotNullInfo() {
|
||||||
node.flow.addTypeStatement(operandVariable typeEq any)
|
val symbol = this.symbol
|
||||||
logicSystem.approveStatementsInsideFlow(
|
if (symbol != null) {
|
||||||
node.flow,
|
variableStorage.getOrCreateRealVariable(node.previousFlow, symbol, this)?.let { operandVariable ->
|
||||||
operandVariable notEq null,
|
node.flow.addTypeStatement(operandVariable typeEq any)
|
||||||
shouldRemoveSynthetics = true,
|
logicSystem.approveStatementsInsideFlow(
|
||||||
shouldForkFlow = false
|
node.flow,
|
||||||
)
|
operandVariable notEq null,
|
||||||
|
shouldRemoveSynthetics = true,
|
||||||
|
shouldForkFlow = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when (this) {
|
||||||
|
is FirSafeCallExpression -> this.receiver.propagateNotNullInfo()
|
||||||
|
is FirTypeOperatorCall -> this.argument.propagateNotNullInfo()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkNotNullCall.argument.propagateNotNullInfo()
|
||||||
|
|
||||||
unionNode?.let { unionFlowFromArguments(it) }
|
unionNode?.let { unionFlowFromArguments(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-41
@@ -1,41 +0,0 @@
|
|||||||
package a
|
|
||||||
|
|
||||||
interface A {
|
|
||||||
val b: B
|
|
||||||
val nb: B?
|
|
||||||
}
|
|
||||||
|
|
||||||
interface B {
|
|
||||||
fun foo(): Int
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test(u: A?, x: A?, y: A?, z: A?, w: A, v: A?) {
|
|
||||||
u?.b?.foo()!! // was UNNECESSARY_SAFE_CALL everywhere, because result type (of 'foo()') wasn't made nullable
|
|
||||||
u!!.b<!UNNECESSARY_SAFE_CALL!>?.<!>foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
x?.b!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
// x?.b is not null
|
|
||||||
x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
|
|
||||||
y?.nb?.foo()!!
|
|
||||||
y!!.nb?.foo()!!
|
|
||||||
z?.nb!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
// z?.nb is not null
|
|
||||||
z<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.nb!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
|
|
||||||
w.b<!UNNECESSARY_SAFE_CALL!>?.<!>foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
w.b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
w.nb?.foo()!!
|
|
||||||
w.nb!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
|
|
||||||
v!!.b.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
|
||||||
}
|
|
||||||
|
|
||||||
fun B?.bar(): Int = 1
|
|
||||||
fun B?.baz(): Int? = 1
|
|
||||||
|
|
||||||
fun doInt(i: Int) = i
|
|
||||||
|
|
||||||
fun test(a: A?) {
|
|
||||||
doInt(a?.b.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
|
|
||||||
doInt(a?.b.baz()!!)
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
package a
|
package a
|
||||||
|
|
||||||
interface A {
|
interface A {
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
//KT-702 Type inference failed
|
|
||||||
package a
|
|
||||||
//+JDK
|
|
||||||
|
|
||||||
fun <T> getJavaClass() : java.lang.Class<T> { <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
|
|
||||||
|
|
||||||
public class Throwables() {
|
|
||||||
companion object {
|
|
||||||
public fun <X : Throwable?> propagateIfInstanceOf(throwable : Throwable?, declaredType : Class<X?>?) : Unit {
|
|
||||||
if (((throwable != null) && declaredType?.isInstance(throwable)!!))
|
|
||||||
{
|
|
||||||
throw declaredType?.cast(throwable)!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public fun propagateIfPossible(throwable : Throwable?) : Unit {
|
|
||||||
propagateIfInstanceOf(throwable, getJavaClass<Error?>()) // Type inference failed: Mismatch while expanding constraints
|
|
||||||
propagateIfInstanceOf(throwable, getJavaClass<RuntimeException?>()) // Type inference failed: Mismatch while expanding constraints
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
//KT-702 Type inference failed
|
//KT-702 Type inference failed
|
||||||
package a
|
package a
|
||||||
//+JDK
|
//+JDK
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public class Throwables() {
|
|||||||
public fun <X : Throwable?> propagateIfInstanceOf(throwable : Throwable?, declaredType : Class<X?>?) {
|
public fun <X : Throwable?> propagateIfInstanceOf(throwable : Throwable?, declaredType : Class<X?>?) {
|
||||||
if (((throwable != null) && declaredType?.isInstance(throwable)!!))
|
if (((throwable != null) && declaredType?.isInstance(throwable)!!))
|
||||||
{
|
{
|
||||||
throw declaredType?.cast(throwable)!!
|
throw declaredType<!UNNECESSARY_SAFE_CALL!>?.<!>cast(throwable)!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public fun propagateIfPossible(throwable : Throwable?) {
|
public fun propagateIfPossible(throwable : Throwable?) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ fun kt6840_2(s: String?) {
|
|||||||
|
|
||||||
fun kt1635(s: String?) {
|
fun kt1635(s: String?) {
|
||||||
s?.hashCode()!!
|
s?.hashCode()!!
|
||||||
s<!UNSAFE_CALL!>.<!>hashCode()
|
s.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun kt2127() {
|
fun kt2127() {
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ fun kt6840_2(s: String?) {
|
|||||||
|
|
||||||
fun kt1635(s: String?) {
|
fun kt1635(s: String?) {
|
||||||
s?.hashCode()!!
|
s?.hashCode()!!
|
||||||
s<!UNSAFE_CALL!>.<!>hashCode()
|
s.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun kt2127() {
|
fun kt2127() {
|
||||||
|
|||||||
Reference in New Issue
Block a user