Mini-SIP: companions must be co-defined in the same tree


#1

I would propose a small tweak to the language of the spec, forbidding sources like this:

package x { class A }
package x { object A }

The context is this PR, in which this kind of structure causes multiple problems (such as that PR’s linked bug, and #5877).

The precise proposed change is in SLS 5.5:

Generally, a companion module of a class is an object which has the same name as the class and is defined in the same scope and compilation unit. Conversely, the class is called the companion class of the module.

which would be changed to

Generally, a companion module of a class is an object which has the same name as the class and is defined in the same code block, or at top level in the same file. Conversely, the class is called the companion class of the module.

(or similar, but legally-binding verbiage).

I expect the fallout from making this change to be minimal, especially as changing any non-conforming code to be conforming does not break backwards source-compatibility.

To the contributors.scala-lang hivemind: WDYT?

EDIT: The idea isn’t mine, but retronym’s.


#2

It sounds more like an implementation limitation, so instead of a SIP, maybe file a SILLY instead. (Scala Implementation, like, Limitation, y’all.)

But it doesn’t sound like a likely limitation.

It may require a bit of extra work, but the search for a companion has been a burden throughout history. Yet some people still manage it.


#3

In the context of language syntax I would interpret “scope” as “lexical scope”, so “defined in the same scope” already means what you want and a class and object with the same name in the same package but defined in different lexical scopes are indeed not companions.


#4

“defined in the same scope” already means what you want

If that’s the case, and this is an implementation bug, then I’d be glad to change the implementation.

With the proliferation of "Mini-SIP"s these days, I thought a spec change like this would be expected to go through the Mini-SIP process, wherein the SIP committee’s Mini-Mes consider the proposal.


#5

Isn’t a mini-SIP just a SIP that’s rather small?

If it isn’t, what is it?


#6

I tend to agree. I would also classify this as an implementation bug, and not a spec change, so no SIP needed. We could change the spec wording to be more precise here.


#7

In the context of Scala, I understand “lexical scope” in contrast to “implicit scope”. I see the class and its companion as merely written down differently (albeit necessarily in the same compilation unit). This is how Namers copes with anything: what can be named in advance of typing. If scope just means the names you can see, then clearly both the class and the companion are in the same scope. It doesn’t matter where the braces are placed.

But Martin’s reply suggests that there is a more conservative reading.

Edit: I see my previous pun about the search for a companion didn’t make clear: a life companion.