Skip to content

non public type members allowed in public signatures #4400

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

Open
scabug opened this issue Mar 27, 2011 · 6 comments
Open

non public type members allowed in public signatures #4400

scabug opened this issue Mar 27, 2011 · 6 comments
Labels
Milestone

Comments

@scabug
Copy link

scabug commented Mar 27, 2011

=== What steps will reproduce the problem? ===

Given this trait, with a private type member:

 scala> trait X { private[this] type A = Int; def a: A = 1 }
 defined trait X

The access restrictions correctly prevent me from accessing the type
member from outside of x.

 scala> type xA = x.A
 <console>:10: error: type A is not a member of java.lang.Object with X
        type xA = x.A
                  ^
 scala> val x = new X {}
 x: java.lang.Object with X = $$anon$$1@58bf7b3e

 scala> x.a
 res6: Int = 1

But I can see the type in the eta-expanded signature here:

 scala> x.a _
 res7: () => x.A = <function0>

Not sure if this is a problem, it just strikes me as a bit odd to
allow private type members to appear in public signatures, by contrast
with the way private template definitions are handled.

 scala> trait X { private[this] trait A; def a: A = null }
 <console>:8: error: private trait A escapes its defining scope as
part of type X.this.A
        trait X { private[this] trait A; def a: A = null }

Similar problems exists with other access modifiers.

=== What is the expected behavior? ===

Whatever Adriaan deems sound upon his return from the Antipodes.

=== What do you see instead? ===

=== Additional information ===

https://groups.google.com/d/topic/scala-language/_txHz6q3Rw4/discussion

=== What versions of the following are you using? ===

  • Scala: 2.8.1 / 2.9.0.RC1
@scabug
Copy link
Author

scabug commented Mar 27, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4400?orig=1
Reporter: @retronym

@scabug
Copy link
Author

scabug commented Dec 11, 2015

@SethTisue said:
this is changing in Dotty: scala/scala3#997

@som-snytt
Copy link

The example from 2011 is i1130.scala. I'll see how close I can get i997.scala.

@scala scala deleted a comment from scabug Jul 20, 2021
@SethTisue
Copy link
Member

SethTisue commented Dec 10, 2024

in both Scala 2 and 3, it matters whether private is qualified or unqualified:

scala 2.13.15> trait Foo { private[Foo] trait A; def a: A = null }
trait Foo

scala 2.13.15> trait Foo { private trait A; def a: A = null }
                                                   ^
               error: private trait A escapes its defining scope as part of type Foo.this.A
Welcome to Scala 3.6.2 (17.0.13, Java OpenJDK 64-Bit Server VM).
                                                                                                    
scala> trait Foo { private[Foo] trait A; def a: A = null }
// defined trait Foo
                                                                                                    
scala> trait Foo { private trait A; def a: A = null }
-- Error: ----------------------------------------------------------------------
1 |trait Foo { private trait A; def a: A = null }
  |                                 ^
  |               non-private method a in trait Foo refers to private trait A
  |               in its type signature => Foo.this.A
1 error found

I don't know why that would be.

@SethTisue
Copy link
Member

SethTisue commented Dec 10, 2024

https://scala-lang.org/files/archive/spec/2.13/05-classes-and-objects.html#private is relevant:

Members marked private without a qualifier are called class-private, whereas members labeled with private[this] are called object-private. A member is private if it is either class-private or object-private, but not if it is marked private[C] where C is an identifier; in the latter case the member is called qualified private.

so in spec-ese, "qualified private" is in fact a separate concept, it seems. But I'm not currently finding spec language that gives further insight into the difference

https://www.scala-lang.org/old/node/10488 gives some insight and pointers — but it concludes with Heiko asking my exact question:

Why doesn't the compile-time check prevent a trait/class defined qualified private (private[foo]) to escape its defining scope? Is this intentional?

and Martin never answered

@som-snytt
Copy link

@SethTisue private means doesn't participate in overriding 5.1.4. I don't know about leakability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants