https://kotlinlang.org logo
Title
d

david-wg2

08/13/2019, 8:30 AM
could anyone explain why smart-cast doesn’t work for range checks?
if (pin?.length != 36) throw UnauthorizedResponse()
// pin is smart cast here
if (pin?.length !in (8..36)) throw UnauthorizedResponse()
// pin is not smart cast here
g

gildor

08/13/2019, 8:33 AM
Yes, it doesn’t work
d

david-wg2

08/13/2019, 8:34 AM
but shouldn’t it? 🤔
g

gildor

08/13/2019, 8:34 AM
nope
d

david-wg2

08/13/2019, 8:34 AM
it’s smart cast because you know it’s 36 in the first example in the second example you know it’s in the range 8 to 36
which is just as non-nullable
g

gildor

08/13/2019, 8:35 AM
In theory it’s possible to implement in compiler, but it just doesn’t work now
d

david-wg2

08/13/2019, 8:35 AM
that i understand
g

gildor

08/13/2019, 8:35 AM
also in second case compiler should understand range implementation detail which doesn’t look feasible (only by coupling stdlib implementation details to compiler)
also in general such code looks a bit messy for me. Better to make pin non nullable and handle it properly than combine null and range check, but it’s just my opinion
d

david-wg2

08/13/2019, 8:38 AM
that’s what i ended up doing, i was just curious why it didn’t work
g

gildor

08/13/2019, 8:48 AM
it’s just matter of compiler’s complexity imo
so example with 36 may be handled, probably make sense to create an issue. But I don’t think that it make sense for range (or even possible for generic implementation)
c

christophsturm

08/13/2019, 8:53 AM
it can’t hurt to file a ticket
k

Kroppeb

08/13/2019, 1:07 PM
Can't a contract help here?
private fun Int?.notInRange(range: IntRange): Boolean {
	contract {
		returns(false) implies (this@notInRange != null)
	}
	return this !in range
}
I tried this before but it seems contracts don't work on infix operators?