Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin .let {} null safety presumably false error

When using the .let { } function I noticed that when doing the following:

bucket?.assignedVariantName.let {
        bucket?.determineVariant()  <-- guarantee safety for bucket
}

You have to guarantee safety for bucket in this case i.e. bucket?. or bucket!! while null safety is already guaranteed by using ?.let then I noticed when doing the following:

bucket?.assignedVariantName?.let { <-- added safety check for property 
        bucket.determineVariant()  <-- doesn't need to guarantee safety for bucket
}

Whilst using let on the property of the bucket and not directly on bucket I'm wondering if this is intentionally or a bug in Kotlin plugin (in this case I encountered this in Android Studio)

Additional info is that bucket is in this case a local val while assignedVariantName is a nullable var.

val bucket: T? = ...
like image 278
Dion Segijn Avatar asked Dec 02 '22 13:12

Dion Segijn


1 Answers

This is the expected behavior. The .let { ... } function is defined as

inline fun <T, R> T.let(block: (T) -> R): R = block(this)

T can be a nullable type, and let can be called on a null receiver, null.let { } is valid code.

Now take a look at the two calls:

  • bucket?.assignedVariantName.let { ... }.

    Here, let is always called regardless of whether the receiver bucket?.assignedVariantName is null or not.

    There is a possible case when bucket?.assignedVariantName is null because bucket is null -- then null is just passed into let, and it is definitely not safe to use bucket inside the let block.

    (runnable example of the case)

  • bucket?.assignedVariantName?.let { ... }

    In this case, let is called only if the receiver bucket?.assignedVariantName is not null, requiring that bucket is not null and its assignedVariantName is not null. This requirement makes it safe to use bucket inside the let block.

like image 93
hotkey Avatar answered Dec 08 '22 16:12

hotkey