I have this line of code ``` val foo = gitl...
# announcements
p
I have this line of code
Copy code
val foo = gitlabEvent.webhookEvent.objectAttributes != null && gitlabEvent.webhookEvent.objectAttributes.action == Action.OPEN
gitlabEvent
and
webhookEvent
are non-nullable.
objectAttributes
is nullable. The compiler is telling me
Smart cast to 'ObjectAttributes' is impossible, because 'gitlabEvent.webhookEvent.objectAttributes' is a complex expression
. I thought smart casting was smarter than that 😞
d
is
webhookEvent
provided by a separate module or some dependency? if so, that’d explain the error
p
no, they are in the same compilation unit
webhookEvent
is a data Class. So are
objectAttributes
Copy code
interface GitlabEvent {
    val webhookEvent: WebhookEvent
    val filter: String

    fun buildSlackMessage(): SlackMessage
}
Copy code
@JsonIgnoreProperties(ignoreUnknown = true)
data class WebhookEvent(
    @JsonProperty("object_kind") val objectKind: WebhookEventType,
    val project: Project,
    val user: User,
    @JsonProperty("object_attributes") val objectAttributes: ObjectAttributes? = null,
    @JsonProperty("merge_request") val mergeRequest: MergeRequest? = null,
    val commit: Commit? = null,
    val issue: Issue? = null,
    val snippet: Snippet? = null
)
Copy code
@JsonIgnoreProperties(ignoreUnknown = true)
data class ObjectAttributes(
    val id: Int,
    val action: Action = Action.UNKNOWN,
    val title: String = "",
    val url: String,
    val iid: Int,
    val note: String = "",
    @JsonProperty("noteable_type") val noteableType: NoteableType = NoteableType.UNKNOWN
)
d
dunno. i’m on 1.3.10, can’t reproduce it with this code:
Copy code
val x = Fred(Bar(Foo("xyz")))

	data class Foo(val label: String)
	data class Bar(val foo: Foo? = null)
	data class Fred(val bar: Bar)

    fun doTheFoo() { val y = x.bar.foo != null && x.bar.foo.label == "xyz" }
i do get exactly that error if i declare
x
with
var
, but it looks like that’s not the case here. stumped.
p
That project is still on 1.2. I upgraded to 1.3.10 and I am still getting that, but maybe I missed something…
interestingly enough, this
Copy code
val webhookEvent = gitlabEvent.webhookEvent
val foo = webhookEvent.objectAttributes != null && webhookEvent.objectAttributes.action == Action.OPEN
compiles
d
ahh, of course, the interface:
Copy code
val x: Fred = FredImpl(Bar(Foo("xyz")))

	data class Foo(val label: String)
	data class Bar(val foo: Foo? = null)
	interface Fred { val bar: Bar }
	data class FredImpl(override val bar: Bar) : Fred
    fun doTheFoo() { val y = x.bar.foo != null && x.bar.foo.label == "xyz" }
demonstrates the problem. i ain’t smart enough to know the cause, but there ya go, i see the same thing now.
p
👍
maybe it’s because the interface could have an implementation in a different language in an external module and do bad things?
k
Or just in the same module, what if someone changes the implementation? Other classes' smartcasts shouldn't suddenly stop working.
👍 1
p
well, it’s a
val
. It can’t magically become a
var
if overriden
k
Copy code
val myNonVar: String?
    get() = if (Random().nextBoolean()) "test" else null
p
that’s just evil 😞
maybe I can rewrite that as sealed class. Then it should work
🤔
k
This is a dumb example of course, but this also happens in other situations. `val`s that offer an immutable view on another mutable property for example.
p
Yeah, makes sense.
s
This is actually a good question that could help people understand
val
further.
a
Just curious, would the
?.
still work? As in
val foo = gitlabEvent.webhookEvent.objectAttributes?.action == Action.OPEN
p
it would.
gitlabEvent.webhookEvent.objectAttributes?.action
might return
null
, and it’s perfectly valid to compare
null
with other stuff