and also, i've upgraded for kotlin 1.3 to 1.4 and ...
# getting-started
x
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
How about an example of the failing code?
x
of course:
Copy code
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
Copy code
body["baz"] = foo.nullableMap
worked straight up
k
Isn't the right-hand side of that assignment supposed to be an Instant?
x
no, it's a mutable map of <String, Any>
previously, my IDE would say
Copy code
Smart cast to kotlin.collections.Map<kotlin.String, kotlin.String>
on the body["baz"] line
but now it doesnt do it by itself
k
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:
Copy code
val body : Map<String, Any> = mutableMapOf(...)
x
hmmm
the error i get from 1.4 forwards is
Copy code
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
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:
Copy code
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:
Copy code
val body = mutableMapOf(
            "otherValue" to foo.otherValue,
            "xyz" to listOf(123)
        )
then your code would work.
👍 1
x
yep, very interesting! thank you! 🙂