Using extensions shadowing as lint check

I wanted to use extensions shadowing as lint check, similar to how Flow do with SharedFlow (github source). I couldn’t find anywhere where this behavior is used, documented or explained so I fiddled with it myself.

For people unaware this is what I’m talking about:
image

I’ve found that it works if both extensions have the same signature and are in the same package and that extension for lowest subclass takes precedence (this seems also to be the case for classes with generic arguments.

However there are some weird behaviors:

1: When generics come into play resolution is inconsistent and all extensions appear:

fun Any.bounce() = this

@Deprecated("Bouncing Result is not allowed", level = DeprecationLevel.ERROR)
@JvmName("bounceResult")
fun <T>Result<T>.bounce() : T = getOrThrow()

image

Regardless of which options is selected it does end up resolving “correctly”.
image
It also happend with other classes that are not inline so that’s not the culprit.

2: if signatures match but argument names are different you can forcefully name argument to get to higher extension. This is odd but can be avoided by using same argument names.

fun Any.foo(bar: String) { }

@Deprecated( "Fooing the Int is not allowed", level = DeprecationLevel.ERROR)
fun Int.foo(baz: String) { }

image
IntelliJ even suggest all overload names:
image


I’d like to use this in my project but I’m a little confused. Am I doing something wrong with generic declaration that it’s hinted twice? I can’t call it a bug since its not documented so it’s not clear if it’s even supposed to work.

It would be nice if this behavior got supported, at least to the point where generic resolution was cleared up so overloads don’t appear twice (or more) in autocomplete, right now that’s the reason keeping me away from using it.

For reference im using Android Studio Electric Eel and Kotlin 1.8.