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