https://kotlinlang.org logo
Title
x

xii

08/24/2021, 7:34 PM
and also, i've upgraded for kotlin 1.3 to 1.4 and noticed some smart casts to string have broken; is doing toString in the original object sufficient, or does smart cast do something I'm not taking into account?
c

corneil

08/24/2021, 8:42 PM
How about an example of the failing code?
x

xii

08/25/2021, 8:12 AM
of course:
data class Test(
  val otherValue: Instant
  val nullableMap: Map<String,String>? = null
)

class TestClass(){
  fun previouslyFineFunction(foo: Test){
    val body = mutableMapOf(
      "otherValue" to foo.otherValue
    )
    if (foo.nullableMap != null){
       body["baz"] = foo.nullableMap
    }
  }
}
previously the
body["baz"] = foo.nullableMap
worked straight up
k

Klitos Kyriacou

08/25/2021, 8:18 AM
Isn't the right-hand side of that assignment supposed to be an Instant?
x

xii

08/25/2021, 8:21 AM
no, it's a mutable map of <String, Any>
previously, my IDE would say
Smart cast to kotlin.collections.Map<kotlin.String, kotlin.String>
on the body["baz"] line
but now it doesnt do it by itself
k

Klitos Kyriacou

08/25/2021, 8:36 AM
Yes, it still smart-casts
foo.nullableMap
to
Map<kotlin.String, kotlin.String>
since it knows it's not null. But that's not where the problem is. You can't put a Map as a value into a Map that was initialized with an Instant as a value. If you really want to do that, you have to be explicit about its type when you create it:
val body : Map<String, Any> = mutableMapOf(...)
x

xii

08/25/2021, 8:45 AM
hmmm
the error i get from 1.4 forwards is
Type mismatch.
Required:
Comparable<{Instant & String}>
Found:
Map<String, String>
Type mismatch.
Required:
Serializable
Found:
Map<String, String>
Type mismatch.
Required:
{Comparable{Instant & String}> & java.io.Serializable}
Found:
Map<String, String>
but you are right in that if I specify <String, Any> it behaves as it used to
k

Klitos Kyriacou

08/25/2021, 9:08 AM
The inferred type of
body
depends on the contents of the
MutableMap
that you initialize it with. For the compiler to give the above error message, you must have initialized it with:
val body = mutableMapOf(
            "otherValue" to foo.otherValue,
            "xyz" to "abc",
        )
and not just with
"otherValue" to foo.otherValue
. The inferred type it chooses is the most restrictive type that matches all of the arguments to
mutableMapOf
. If you gave it another type, which was totally different from these two, then it would have to infer the map type as
Map<String, Any>
. For example, if you did this:
val body = mutableMapOf(
            "otherValue" to foo.otherValue,
            "xyz" to listOf(123)
        )
then your code would work.
👍 1
x

xii

08/25/2021, 9:11 AM
yep, very interesting! thank you! 🙂