possibly lazyweb but are there IR APIs for calling...
# compiler
z
possibly lazyweb but are there IR APIs for calling expected defaults functions/constructors? This is specifically for cases where the calling generated code is computing the mask values itself at runtime. Currently I'm simulating the existence of the constructor by creating a synthetic one to link against during code gen, but I'm sure there's better ways. With functions I imagine this gets a bit more complex with defaults being static
b
Call site default argument transformation happens as a lowering in IR which is performed after
IrGenerationExtension
. If you set the arguments at the call site to be
null
, the compiler should automatically convert that to a call to the synthetic function/constructor and calculate all the mask/marker information needed. Call-site lowering for JVM: https://github.com/JetBrains/kotlin/blob/266fcba624f8e93102ee8aa3ee5f6a4942fc7510/[…]tbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt Declaration-site lowering for JVM: https://github.com/JetBrains/kotlin/blob/266fcba624f8e93102ee8aa3ee5f6a4942fc7510/[…]ins/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt
z
Yep I knew about the null args too, unfortunately this is a case where I’m generating a class that doesn’t know the absent args at compile time but also doesn’t want to do reflection heh
b
Okay, let me know if I'm understanding this correctly. You have the following class you are trying to generate a JsonAdapter for:
Copy code
@JsonClass(generateAdapter = true)
value class ValueClass(val i: Int = 0)
And the issues is the adapter should use the default value from the constructor if it is not found when parsing JSON?
Copy code
class ValueClassJsonAdapter : JsonAdapter<ValueClass>() {
    override fun fromJson(reader: JsonReader): ValueClass? {
        val i = if (reader.hasNext()) reader.nextInt() else /* use default from constructor */
        return ValueClass(i)
    }

    override fun toJson(writer: JsonWriter, value: ValueClass?) {
        if (value != null) writer.value(value.i)
    }
}
z
right yeah, though not just for value classes but rather a class with any number of properties
and since their present values are computed at runtime, this relies on being able to compute the mask at runtime and call the defaults constructor directly
b
So kotlinx-serialization achieves this by coping the default
IrExpression
from the constructor: https://github.com/JetBrains/kotlin/blob/master/plugins/kotlinx-serialization/kotl[…]kotlinx/serialization/compiler/backend/ir/DefaultValuesUtils.kt. In your case, are you generating the JsonAdaptor as a nested class or a top-level class?
z
it's a top-level class currently. Could move it but it would def break where moshi expects the class to be and thus a breaking change 😓
maybe something for moshi 2 in the future
👍 1