FIR DFA: correct exit node retrieval when a safe call is the last expression
^KT-44699 Fixed
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
266432a482
commit
83e3201677
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
FILE: safeCallOnTypeAlias.kt
|
FILE: safeCallOnTypeAlias.kt
|
||||||
public final typealias MyTypeAlias = R|() -> kotlin/String?|
|
public final typealias MyTypeAlias = R|() -> kotlin/String?|
|
||||||
public final fun foo(x: R|MyTypeAlias|): R|kotlin/Unit| {
|
public final fun foo(x: R|MyTypeAlias|): R|kotlin/Unit| {
|
||||||
R|<local>/x|?.{ $subj$.R|kotlin/let|<R|() -> kotlin/String?|, R|kotlin/String|>(<L> = let@fun <anonymous>(y: R|() -> kotlin/String?|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
R|<local>/x|?.{ $subj$.R|kotlin/let|<R|() -> kotlin/String?|, R|kotlin/String?|>(<L> = let@fun <anonymous>(y: R|() -> kotlin/String?|): R|kotlin/String?| <kind=EXACTLY_ONCE> {
|
||||||
^ R|<local>/y|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/String?|>|()?.{ $subj$.R|kotlin/let|<R|kotlin/String|, R|kotlin/String|>(<L> = let@fun <anonymous>(result: R|kotlin/String|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
^ R|<local>/y|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/String?|>|()?.{ $subj$.R|kotlin/let|<R|kotlin/String|, R|kotlin/String|>(<L> = let@fun <anonymous>(result: R|kotlin/String|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||||
^ R|/bar|(R|<local>/result|)
|
^ R|/bar|(R|<local>/result|)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -11,7 +11,7 @@ FILE: coercionToUnitWithEarlyReturn.kt
|
|||||||
public final fun foo(x: R|() -> kotlin/Unit|): R|kotlin/Unit| {
|
public final fun foo(x: R|() -> kotlin/Unit|): R|kotlin/Unit| {
|
||||||
}
|
}
|
||||||
public final fun main(x: R|A?|): R|kotlin/Unit| {
|
public final fun main(x: R|A?|): R|kotlin/Unit| {
|
||||||
lval lambda: R|() -> kotlin/Unit| = l@fun <anonymous>(): R|kotlin/Unit| {
|
lval lambda: R|() -> kotlin/Unit?| = l@fun <anonymous>(): R|kotlin/Unit?| {
|
||||||
when () {
|
when () {
|
||||||
==(R|<local>/x|?.{ $subj$.R|kotlin/Any.hashCode|() }, Int(0)) -> {
|
==(R|<local>/x|?.{ $subj$.R|kotlin/Any.hashCode|() }, Int(0)) -> {
|
||||||
^@l Unit
|
^@l Unit
|
||||||
@@ -21,5 +21,5 @@ FILE: coercionToUnitWithEarlyReturn.kt
|
|||||||
^ R|<local>/x|?.{ $subj$.R|/A.unit|() }
|
^ R|<local>/x|?.{ $subj$.R|/A.unit|() }
|
||||||
}
|
}
|
||||||
|
|
||||||
R|/foo|(R|<local>/lambda|)
|
<Inapplicable(INAPPLICABLE): /foo>#(R|<local>/lambda|)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -15,5 +15,5 @@ fun main(x: A?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lambda has a type (() -> Unit?)
|
// lambda has a type (() -> Unit?)
|
||||||
foo(lambda)
|
<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>(lambda)<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -133,7 +133,6 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
fun CFGNode<*>.extractArgument(): FirElement? = when (this) {
|
fun CFGNode<*>.extractArgument(): FirElement? = when (this) {
|
||||||
is FunctionEnterNode, is TryMainBlockEnterNode, is CatchClauseEnterNode -> null
|
is FunctionEnterNode, is TryMainBlockEnterNode, is CatchClauseEnterNode -> null
|
||||||
is ExitSafeCallNode -> lastPreviousNode.extractArgument()
|
|
||||||
is StubNode, is BlockExitNode -> firstPreviousNode.extractArgument()
|
is StubNode, is BlockExitNode -> firstPreviousNode.extractArgument()
|
||||||
else -> fir.extractArgument()
|
else -> fir.extractArgument()
|
||||||
}
|
}
|
||||||
@@ -1090,8 +1089,9 @@ class ControlFlowGraphBuilder {
|
|||||||
* lastNode -> exitNode
|
* lastNode -> exitNode
|
||||||
* instead of
|
* instead of
|
||||||
* lastNode -> enterNode -> exitNode
|
* lastNode -> enterNode -> exitNode
|
||||||
* because of we need to fork flow on `enterNode`, so `exitNode`
|
* because we need to fork flow before `enterNode`, so `exitNode`
|
||||||
* will have unchanged flow from `lastNode`
|
* will have unchanged flow from `lastNode`
|
||||||
|
* which corresponds to a path with nullable receiver.
|
||||||
*/
|
*/
|
||||||
val lastNode = lastNodes.pop()
|
val lastNode = lastNodes.pop()
|
||||||
val enterNode = createEnterSafeCallNode(safeCall)
|
val enterNode = createEnterSafeCallNode(safeCall)
|
||||||
@@ -1104,6 +1104,12 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitSafeCall(): ExitSafeCallNode {
|
fun exitSafeCall(): ExitSafeCallNode {
|
||||||
|
// There will be two paths towards this exit safe call node:
|
||||||
|
// one from the node prior to the enclosing safe call, and
|
||||||
|
// the other from the selector part in the enclosing safe call.
|
||||||
|
// Note that *neither* points to the safe call directly.
|
||||||
|
// So, when it comes to the real exit of the enclosing block/function,
|
||||||
|
// the safe call bound to this exit safe call node should be retrieved.
|
||||||
return exitSafeCallNodes.pop().also {
|
return exitSafeCallNodes.pop().also {
|
||||||
addNewSimpleNode(it)
|
addNewSimpleNode(it)
|
||||||
it.updateDeadStatus()
|
it.updateDeadStatus()
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
// !WITH_NEW_INFERENCE
|
|
||||||
|
|
||||||
interface ClassId
|
|
||||||
|
|
||||||
interface JavaAnnotation {
|
|
||||||
val classId: ClassId?
|
|
||||||
}
|
|
||||||
|
|
||||||
interface JavaAnnotationOwner {
|
|
||||||
val annotations: Collection<JavaAnnotation>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MapBasedJavaAnnotationOwner : JavaAnnotationOwner {
|
|
||||||
val annotationsByFqNameHash: Map<Int?, JavaAnnotation>
|
|
||||||
}
|
|
||||||
|
|
||||||
fun JavaAnnotationOwner.buildLazyValueForMap() = lazy {
|
|
||||||
annotations.associateBy { it.classId?.hashCode() }
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class BinaryJavaMethodBase(): MapBasedJavaAnnotationOwner {
|
|
||||||
override val <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>annotationsByFqNameHash<!> by buildLazyValueForMap()
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
|
||||||
interface ClassId
|
interface ClassId
|
||||||
|
|
||||||
interface JavaAnnotation {
|
interface JavaAnnotation {
|
||||||
|
|||||||
Reference in New Issue
Block a user