Fix unsound smartcast due to returns(null) in safecall
^KT-26382 Fixed
This commit is contained in:
@@ -19,12 +19,11 @@ package org.jetbrains.kotlin.contracts
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.contracts.interpretation.ContractInterpretationDispatcher
|
||||
import org.jetbrains.kotlin.contracts.model.Computation
|
||||
import org.jetbrains.kotlin.contracts.model.ConditionalEffect
|
||||
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||
import org.jetbrains.kotlin.contracts.model.Functor
|
||||
import org.jetbrains.kotlin.contracts.model.functors.*
|
||||
import org.jetbrains.kotlin.contracts.model.structure.CallComputation
|
||||
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
||||
import org.jetbrains.kotlin.contracts.model.structure.UNKNOWN_COMPUTATION
|
||||
import org.jetbrains.kotlin.contracts.model.structure.lift
|
||||
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||
import org.jetbrains.kotlin.contracts.parsing.isEqualsDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
@@ -114,6 +113,20 @@ class EffectsExtractingVisitor(
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitSafeQualifiedExpression(expression: KtSafeQualifiedExpression, data: Unit?): Computation {
|
||||
val computation = super.visitSafeQualifiedExpression(expression, data)
|
||||
if (computation === UNKNOWN_COMPUTATION) return computation
|
||||
|
||||
// For safecall any clauses of form 'returns(null) -> ...' are incorrect, because safecall can return
|
||||
// null bypassing function's contract, so we have to filter them out
|
||||
|
||||
fun ESEffect.containsReturnsNull(): Boolean =
|
||||
this == ESReturns(ESConstant.NULL) || this is ConditionalEffect && this.simpleEffect.containsReturnsNull()
|
||||
|
||||
val effectsWithoutReturnsNull = computation.effects.filter { !it.containsReturnsNull() }
|
||||
return CallComputation(computation.type, effectsWithoutReturnsNull)
|
||||
}
|
||||
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression, data: Unit): Computation {
|
||||
val left = extractOrGetCached(expression.left ?: return UNKNOWN_COMPUTATION)
|
||||
val right = extractOrGetCached(expression.right ?: return UNKNOWN_COMPUTATION)
|
||||
|
||||
Vendored
+1
-1
@@ -12,6 +12,6 @@ fun Any.nullWhenString(): Any? {
|
||||
|
||||
fun test(x: Int?) {
|
||||
if (x?.nullWhenString() == null) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user