I’m curious about the rationale behind <this chang...
# ktor
s
I’m curious about the rationale behind this change where
AttributeKey<T>
went from being compared by identity to being compared by name. On the face of it this seems like a backwards step, because it makes it easy to have two keys that compare equal but have different
T
value types. I would have thought that preventing that possibility is one of the key reasons to use a type-safe container pattern in the first place. The PR mentions a ticket https://youtrack.jetbrains.com/issue/KTOR-3538, but I get a 404 on that link so I can’t learn the history behind the change.
a
I've changed the visibility of the issue so you could see it. So in your opinion we should also check that the types are equal?
thank you color 1
s
Thanks! The problem is that the value type
T
is erased at runtime, so there’s no way to check if two attribute keys have equal value types. Using identity comparisons for the keys solves that problem, because they only way for two keys to compare equal is if they are the same key, in which case they must have the same
T
type. Today I was reviewing a PR that introduced a new plugin something like this:
Copy code
class MetricsPlugin {
    // ...
    companion object: HttpClientPlugin<Config, MetricsPlugin> {
        override val key: AttributeKey<MetricsPlugin> = AttributeKey("metrics")
    }
}
In the past, this would have been safe, because the key is a global singleton that uniquely refers to that plugin. But now there are two issues: • I can make an
AttributeKey
with the same name but a different
T
type, and get a class cast exception when trying to retrieve the plugin instance • I can make a second plugin with the same name, and get an error when trying to install both plugins together My solution for now is to use the fully qualified class name as the plugin name, which at least avoids naming conflicts. But I preferred the old solution where the name was not important.
a
Can you please file an issue about your concerns?
s
Sure, will do!