Also playing around with contracts, and I feel lik...
# eap
j
Also playing around with contracts, and I feel like I’m missing something
Copy code
@ExperimentalContracts
fun String?.trueIfNotNullOrEmpty(): Boolean {
  contract {
    returns(true) implies (this@trueIfNotNullOrEmpty != null)
  }
  return !isNullOrEmpty()
}

@ExperimentalContracts
fun foo() {
  val maybeNull : String? = "foo"
  val isNotNull = maybeNull.trueIfNotNullOrEmpty()
  if (isNotNull) {
    val definitelyNotNull : String = maybeNull
  }
}
Intellij is saying I can’t assign
maybeNull
to
definitelyNotNull
, because it’s
String
vs
String?
. My contract seems right, it’s really just the inverse of what
isNullOrEmpty
uses. Any idea where I went wrong? Sorry in advance if it’s blindingly obvious.
d
Actually that won't work irrelevant of contracts. You can change
maybeNull.trueIfNotNullOrEmpty()
into plain
maybeNull != null
, and you still won't get smartcast. Here's an issue for that: https://youtrack.jetbrains.com/issue/KT-25747
j
Ah of course, I forgot that
maybeNull != null
wouldn’t work. Interestingly I changed the contract to
Copy code
contract {
    returns(true) implies (this@trueIfNotNullOrEmpty is String)
  }
And still no good, though I would’ve expected this one to work. I suppose contracts are new so I’m not 100% sure what should work and what shouldn’t.
d
Sorry, am I right that you've changed only contract declaration? In such case, that won't work either -- the issue here is local Boolean
isNull
. Compiler has to check that this boolean is initialized to something special, and keep in mind that if
isNull == true
then
maybeNull != null
(or
maybeNull is String
, actual kind of smartcast is irrelevant). We don't do that at the moment (sorry if I got you wrong -- if you've inlined
isNull
variable and still don't get smartcast, then the issue is somewhere else. If you'll show complete code, we can continue digging here :) )
j
Ah, very cool! Inlining worked, it was able to smart cast correctly.
Interesting extracting the variable caused it to break, even though everything is a
val
Thank you for the help!