Marko Novakovic
03/10/2022, 1:13 PMprivate fun UserContact?.isValid(): Boolean {
contract {
returns(true) implies (this@isValid != null)
}
return this != null &&
userId.isNotBlank() &&
!email.isNullOrBlank() &&
!phoneNumber.isNullOrBlank()
}
suspend operator fun invoke(): UserData {
val userData = getUserData()
val contact = getUserContact()
return when {
contact.isValid() -> userData.fillInWithUserContact(contact)
else -> userData
}
}
compiler is complaining contact
inside invoke
fillWithUserContact
is nullable. shouldn’t contract
ensure it’s not treated as nullable?hfhbd
03/10/2022, 5:10 PMcontact.isValid() == true
. if contact
is null, isValid
is not called, and returns null
.Joffrey
03/10/2022, 5:12 PMisValid()
extension is defined on the nullable type, so I don't think what you wrote is correcthfhbd
03/10/2022, 5:45 PMBoolean
not a Boolean?
. So you need to call == true
anyway, and the smart cast works as expected.
@ExperimentalContracts
fun main() {
val a: String? = ""
val length = when {
a.a() -> a.length
else -> -1
}
println(length)
}
@ExperimentalContracts
fun String?.a(): Boolean? {
contract {
returns(null) implies (this@a == null)
returns(true) implies (this@a != null)
}
return this != null
}
Klitos Kyriacou
03/10/2022, 5:51 PMcontact.isValid()
returns a Boolean
, not a Boolean?
.
In the same way as null.toString()
returns a String
(with the value "null") and not a String?
So when contact
is null , contact.isValid()
returns false
. It never returns null.hfhbd
03/10/2022, 6:05 PM?
...
fun main() {
val a: String? = ""
val length = when {
a.a() -> a.length
else -> -1
}
println(length)
}
@ExperimentalContracts
fun String?.a(): Boolean {
contract {
returns(true) implies (this@a != null)
}
return this != null
}
But why does it work for this sample? 🤔Joffrey
03/10/2022, 6:44 PMsuspend
fun, so that might break inference somewhere