I’ve found an unusual edge case: ``` object foo { ...
# language-proposals
n
I’ve found an unusual edge case:
Copy code
object foo {
    operator fun invoke() {
        println("an object")
    }
}

fun foo() {
    println("a function")
}


fun main(args: Array<String>) {
    foo() // prints "a function"
}
l
This is not a language proposal, but a Kotlin Puzzler. You should submit it to the Kotlin Puzzler repo used for the KotlinConf session
1
c
it could at least generate a warning.
1
l
I don't think so. It's like members vs extensions. members win because of static compilation. Here, the most specific symbol is picked. You can still call the object's one with
foo.invoke()
if needed.
n
Sorry… my next message didn’t get posted to Slack because my train went into a tunnel
I meant to continue…
I’d expect the compiler to report an error in this code
g
Not sure about error, this is valid code and also can be backward incompatible in some cases
l
Reporting an error for this would break code. I'd only expect a warning for people who dare to write ambiguous code with
foo
😜
😉 2
n
Worse… having an object (or value) and a function with the same name is allowed when compiling to the JVM platform but causes a compile error when compiling to the Javascript platform 😱
youtrack 3
1
😱 4
I guess it’s too late to make it an error now.
But a warning would be nice.
g
wow, this is definitely a bug that should be fixed
n
I’d like it to be a unique warning that can be turned into an error with a compiler option
g
Yes, this would be a nice feature to have such fine-grained warningAsError config
👍 1
l
Submit on kotl.in/issue to know what they can do about this
n
Oops correction… I mistyped “compiler error” but I meant “compile error”
It doesn’t crash the compiler.
But Kotlin having two parallel namespaces when compiled for one platform, and a single namespace when compiled to another is really confusing.
l
Probably, I'm waiting for the link of the issue to vote on 😉
s
Seems pervasive in Kotlin that the platform leaks through. Method overloads with generics, multiple private classes in same package, etc.
n
e
What if
object foo
is in another file? In another package (and imported)? Inherited from parent class? Auto-imported from kotlin stdlib? When exactly it should be a warning?
n
I’d say, if same compilation unit
Or in same file and private.
e
(Kotlin’s compilation unit is actually a module, not a file)
n
E.g. if there is a name ambiguity
Yes.
If I can create an ambiguous name at compile time that relies upon Kotlin having two parallel namespaces only on the JVM platform, I’d want a warning that I can turn into an error with a compiler option.
e
Should the warning be on use of
foo
or an declaration of foo? Or on declaration of
foo.invoke
(given that
foo()
function is present)?
n
There are two issues…
The first is that the declaration of invoke is ambiguous when Kotlin has two namespaces
The second is that the declaration of
object foo
and
fun foo
assumes two namespaces and is therefore not portable.
e
Declaration of
foo
is not ambiguous. Kotlin perfectly distinguishes between types and functions (see
List
interface and
List()
function in stdlib).
n
I’d like the compiler to warn me about both those issues
e
It only becomes “ambiguous” when the type is an object (or has a companion object) with
invoke
operator. Even then, it is unambiguously resolved to a function both by compiler and IDE (you can Ctrl+Click on
foo()
call to confirm that)
n
It’s not the type
foo
I’m concerned about, it’s the value named
foo
e
(I’d comment in an issue)
n
I know that the compiler does generate code (for the JVM) that calls the function, but it’s not obvious in the source what that behaviour is, because the call to
foo()
refers to two different things in the same namespace.
It’s arbitrary what the generated code will do, and therefore should at least be a warning.
e
It is not arbitrary. There are some rock-solid resolution rules. Function is always preferred in this case. The are literally tons of other resolution rules like that to unambiguosly resolve short names like
foo
(short name needs to be always resolved using some rules, because those names are short and would otherwise conflict in any large project)
n
Ok. I did not find this behaviour documented. And it doesn’t even compile on Javascript, which made me think it was an artifact of the JVM codegen, not a deliberate feature of Kotlin semantics.
p
one thing I’ve found missing when running into such things is a detailed and complete language spec
n
Aye
e
You don’t want it documented. You should not be writing the code like that and when you do, you should get a warning.
I mean, it is really bad style when code relies on some obscure corner-cases. That is true for any language.
n
Yes. I’m asking for a warning. That’s why I created the YouTrack issue
p
@elizarov no offense but this sounds like a ridiculous excuse for not having a language spec (which is sorely missing)
e
I know. But trust me, you really don’t want to know all the dirty details of how resolution really works in Kotlin, because if you need to know that, it means there is something seriously wrong with your code.
It takes a lot of effort to produce a thorough language spec (and we are working on that) but for me, personally, the benefits of actually having it are quite unclear. I’d invest this time into writing more tests.
n
But as an application developer, we want to know when we’re straying into that territory accidentally. Without a language spec there’s no way to know if what we’re writing is what the Kotlin language designers consider to be “wrong” or “right”
Especially if that changes depending on the codegen target!!
d
I don't think we should be asking for a wiki where we can look up how JB thinks we should behave (how we should write code) in edge cases. Slack works well for that purpose if you want to know that. Straying into that "territory" should be an occasion where you might get unexpected results. No developer wants a tool where they can look up if code they are about to write is going to behave unexpectedly. If you find a case that might be ambiguous, like you did, test it, report it, and learn if it's consistent. 🙂
e
That is what we use code inspections for. They are supposed to warn you when you stray into the gray territory, when you write a puzzler-like code whose behavior, while being perfectly deterministic, may be unclear or ambiguous for people reading the code.
If you find such a puzzler and there is no warning on the code, please file an issue to http://kotl.in/issue
b
@natpryce
KT-27490
JFTR: Compilation error when compile to JS is the right(expected) behavior, at least for current BE. The reason is that the compiler has to generate the same name for declarations object foo and fun foo but it’s impossible on JS. Note it wouldn’t be compilation error if the function had parameters since its name would be mangled (got additional prefix). In the case, you want to left such names in Kotlin code you can use JsName to resolve the issue.