Skip to content

[SUPERSEDED] Inherited members have same binding level as package level [ci: last-only] #8839

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

som-snytt
Copy link
Contributor

As with names introduced by package statements, base classes
can introduce definitions that shadow local definitions and
import statements.

Let inherited members have the same name-binding precedence
as package-level definitions: highest when defined in the current
compilation unit, and lowest otherwise. This means that a base
class defined elsewhere cannot introduce a name that shadows a
local definition.

The inherited name can be referred to unambiguously using this;
a conflicting local variable or parameter must be renamed or
aliased; a conflicting member using a C.this prefix.

Fixes scala/bug#11921

@scala-jenkins scala-jenkins added this to the 2.13.3 milestone Mar 28, 2020
As with names introduced by package statements, base classes
can introduce definitions that shadow local definitions and
import statements.

Let inherited members have the same name-binding precedence
as package-level definitions: highest when defined in the current
compilation unit, and lowest otherwise. This means that a base
class defined elsewhere cannot introduce a name that shadows a
local definition.

The inherited name can be referred to unambiguously using `this`;
a conflicting local variable or parameter must be renamed or
aliased; a conflicting member using a `C.this` prefix.
@som-snytt som-snytt changed the title Inherited members have same binding level as package level Inherited members have same binding level as package level [ci: last-only] Mar 29, 2020
@dwijnand
Copy link
Member

(Can't [ci: last-only] post-creation, sadly. Might actually change that, it's so annoying.)

@odersky
Copy link
Contributor

odersky commented Mar 29, 2020

The problem is that this way inherited members also cause ambiguities local imports which is too strict, IMO.

@som-snytt
Copy link
Contributor Author

@dwijnand I have syntax fixes to come, I thought it had worked previously? I'll find out.

@odersky I liked the simplicity of the rule, but it wreaks havoc in the cake.

@som-snytt som-snytt added the WIP label Mar 29, 2020
@som-snytt
Copy link
Contributor Author

Sample confusing thing:

trait Aliases { _: Context => def TypeTag[T](tpe: Type) = universe.TypeTag[T](...) }
trait ExprUtils { _: Context => import universe._ ; def f = TypeTag[String](...) }

which TypeTag is intended? I have no way of seeing if it's provided by the self-type or the import, and in fact I would assume the import.

Here Aliases is a misnomer, because the signatures differ. Its TypeTag method adapts universe.TypeTag. Context is also a misnomer, because it means here Everything, or everything supplemental to universe: Global.

For purposes of naming, it's not obvious that a conflicting definition somewhere in Context is different from a conflicting definition somewhere in an enclosing package. The package-scoped definition is at least scoped: it suggests that all clients in this package use this definition. But the mixed-in definition could come from anywhere. (Arguably, "In Scala 3 we don't compose like that any more.")

The proposed precedence rule makes it harder to write a "grab-bag" import; Java calls it "on-demand".

@SethTisue SethTisue added the release-notes worth highlighting in next release notes label Mar 29, 2020
@som-snytt
Copy link
Contributor Author

@dwijnand it seems to respect last-only, whew. I wasn't prepared to squash yet.

Some people sit at home sewing surgical masks during quarantine.

The experience here was similar to updating the implementation previously to spec: the troublesome code was hard to read (scaladoc packagings).

I thought the cross-talk with Any members and wildcard import would doom this approach, but now I'm not sure. Today's scaladoc example is inherited def toString(link: LinkTo) subverted by wildcard import of toString().

"Root" imports don't import Any members; possibly importing without rename could be disallowed, but that seems draconian, like locking down entire nations in a pandemic.

➜  scala git:(issue/11921) skala
Welcome to Scala 2.13.2-20200329-011423-83a8963 (OpenJDK 64-Bit Server VM, Java 11.0.3).
Type in expressions for evaluation. Or try :help.

scala> object X ; locally { import X._ ; toString() }
object X
val res0: String = X$@7e7e962d

scala>
:quit
➜  scala git:(issue/11921) scala
Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 11.0.3).
Type in expressions for evaluation. Or try :help.

scala> object X ; locally { import X._ ; toString() }
                                         ^
       error: reference to toString is ambiguous;
       it is both defined in class Object and imported subsequently by
       import X._

scala> :quit

Anyway, this implementation isn't quite correct; I'll take a second look to see if it's worth a third look.

@dwijnand
Copy link
Member

@dwijnand it seems to respect last-only, whew. I wasn't prepared to squash yet.

Yeah. I guess it's per-push. I think this is right: if you open a PR with 10 commits and then edit the title, then it will still consider all 10 commits combined; but if you push again then it switches to last only.

@som-snytt som-snytt marked this pull request as draft April 17, 2020 00:52
@som-snytt som-snytt closed this Apr 20, 2020
@som-snytt som-snytt reopened this May 9, 2020
@SethTisue SethTisue modified the milestones: 2.13.3, 2.13.4 May 12, 2020
@som-snytt
Copy link
Contributor Author

I'll resubmit this for the next pandemic.

@som-snytt som-snytt closed this Jul 27, 2020
@SethTisue SethTisue removed this from the 2.13.4 milestone Jul 29, 2020
@som-snytt
Copy link
Contributor Author

It's still lockdown.

@som-snytt som-snytt reopened this Sep 26, 2020
@scala-jenkins scala-jenkins added this to the 2.13.4 milestone Sep 26, 2020
@dwijnand dwijnand modified the milestones: 2.13.4, 2.13.5 Oct 16, 2020
@som-snytt
Copy link
Contributor Author

Closing for pandemic.

@som-snytt
Copy link
Contributor Author

The superseding linked PR attempts to follow Scala 3 semantics.

@som-snytt som-snytt changed the title Inherited members have same binding level as package level [ci: last-only] [SUPERSEDED] Inherited members have same binding level as package level [ci: last-only] Nov 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Type error when outer scope name is shadowed by inheritance
5 participants