https://kotlinlang.org logo
Title
d

Dico

01/26/2019, 9:39 PM
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:
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

robstoll

01/26/2019, 9:45 PM
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

Dico

01/26/2019, 9:46 PM
yes, I didn't mention that, it does indeed.
it doesn't help if I switch the order of the import statements.
r

robstoll

01/26/2019, 9:47 PM
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

Dico

01/26/2019, 9:47 PM
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

robstoll

01/26/2019, 9:50 PM
Your situation is a bit like:
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

Dico

01/26/2019, 9:51 PM
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

robstoll

01/26/2019, 9:56 PM
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

Dico

01/26/2019, 9:57 PM
Yeah. I don't know if the compiler shouldn't "give up", I think calls should not be resolved in an ambiguous manner.
r

robstoll

01/26/2019, 10:01 PM
What happens if you import
b.GL.Companion as GL
d

Dico

01/26/2019, 10:14 PM
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

robstoll

01/26/2019, 10:17 PM
no worries, surely good if you share your insights with Jetbrains