I ran into a situation where I am importing a top-...
# announcements
d
I ran into a situation where I am importing a top-property with a * import, and a type with the same name explicitly. I wanted to invoke a static method from the type, which resolved to a call on the property that I imported. At first I thought this is definitely a bug, but I realized that it is probably a subjective matter. There are two rules at play: * In Kotlin, properties and local variables take precedence over types/companion objects when resolving a function-with-receiver call. * Also, explicit imports take precedence over symbols imported with a
*
import. The reality is that the first rule seems to take priority over the second. I think it should be the other way around. What do you think?
To visualize, you have a situation like this:
Copy code
import a.*
import <http://b.GL|b.GL>

fun bindBuffer() = GL.bindBuffer()
if
a
package contains a property named
GL
, it will take precedence.
r
I guess there are more than just the two rules. It makes sense that local variables take precedence over whatever else exists ("nearest" symbol in scope distance wins) Yet, I agree that b.GL should have precedence over a.GL. What if you switch the import statement, any change? Does b.GL has a
bindBuffer
function defined on the companion of b.GL ?
d
yes, I didn't mention that, it does indeed.
it doesn't help if I switch the order of the import statements.
r
fair enough, does the GL in package
a
has a bindBuffer function? If so, then I would say that's the correct behaviour as it is nearer in terms of scoping
d
no `a.GL`'s type does not have
bindBuffer()
, and I would argue that its presence should not matter. what do you mean by nearer in terms of scoping exactly?
r
Your situation is a bit like:
Copy code
class A {
    companion object {
        fun foo() {}
    }
}

class B 

fun foo() {
    val A = B()
    A.foo()
}
IMO the compiler should search for foo on the companion object of A but only after failing to find the function on the local variable A (so on type B)
d
that is correct, and that is the behaviour exactly.
However, we have a situation where the local variable is imported implicitly, whereas the companion object is imported explicitly.
the property is imported because it does not actually collide with the type that has the same name. If the property were instead a type, it would not be present at all because the type that is imported explicitly takes precedence.
It's an edge case for sure
but I would argue that the call should resolve to
b.GL.bindBuffer()
in this case
r
I agree on it's an edge case but still would argue it should behave the same way it behaves inside a function. The only thing which is not correct IMO is that the compiler gives up too early. That's the bug IMO but if this is how it is supposed to be, then I am with you, it is counter-intuitive that the explicit import is ignored
Maybe worth opening an issue on youtrack for it
d
Yeah. I don't know if the compiler shouldn't "give up", I think calls should not be resolved in an ambiguous manner.
r
What happens if you import
b.GL.Companion as GL
d
In my case,
GL
is a java class with static functions.
I assumed that is treated the same as companion objects (for the purpose of resolving functions-with-receiver expressions)
it appears that is not the case, as when I test it with a companion object, the behaviour changes.
Now it's even more of an edge case 😂 sorry for wasting your time
r
no worries, surely good if you share your insights with Jetbrains