Skip to content
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

qualified modifiers, private[C] and protected[C] handled incorrectly in a subclass #2568

Closed
scabug opened this issue Nov 3, 2009 · 8 comments
Labels
Milestone

Comments

@scabug
Copy link

scabug commented Nov 3, 2009

Scala compiler does allow to override private[C] or protected[C] member in a class that is defined outside of C. IMHO, according to the scala reference this should not be allowed. Please see attached source.

@scabug
Copy link
Author

scabug commented Nov 3, 2009

Imported From: https://issues.scala-lang.org/browse/SI-2568?orig=1
Reporter: jrosiek
Attachments:

  • Main.scala (created on Nov 3, 2009 8:31:10 PM UTC, 388 bytes)

@scabug
Copy link
Author

scabug commented Nov 3, 2009

jrosiek said:
Example

@scabug
Copy link
Author

scabug commented Nov 9, 2009

@adriaanm said:
This seems fine to me. Could you quote the exact passage in the reference that says this should not be allowed?

You're allowed to widen access in subclasses, just like in Java, so it's okay to do this:

  package pkg2 {
    class A {
      // Same with protected[pkg2]
      private[pkg2] def f = 0      
    }
  }
  
  class B extends pkg2.A   { // class A is visible here, so we can extend it and override its non-final members
    // f is now public
    override def f = 1
  }

@scabug
Copy link
Author

scabug commented Nov 9, 2009

jrosiek said:
I must disagree. The problem is not with extending pkg2.A but with overriding its private[pkg2] member which is invisible in class B. If you treat qualified private as a generalization of Java's private then, by analogy to overriding private member in Java (which is not allowed), I should not be allowed to override private[C] outside of C. Anyway, let me cite Scala Reference (section 5.2):

<<<<<
The modifier can be qualified with an identifier C (e.g. private[C]) that must
denote a class or package enclosing the definition. Members labeled with
such a modifier are accessible respectively only from code inside the package
C or only from code inside the class C and its companion module (�5.4).
Such members are also inherited only from templates inside C.

I'm not sure what the last sentence mean (how can I inherit private[C] member from template not inside C? Such template cannot have private[C] member.), but certainly the remaining states that B cannot access A's private[pkg2] member.

@scabug
Copy link
Author

scabug commented Nov 23, 2009

@odersky said:
I agree it would be nice if we could pretend that the pkg2-private method was not visible in B, but we can't, without seriously mangling the names (which we can't do either, to keep Java interop). So this would be desirable, but I am not sure awhether it would be also feasible. A SIP that thinks through all aspects of private/protected[X] access and inheritance would be welcome. It will be lots of work, though. As it stands, and without such a SIP, it's a won't fix.

@scabug
Copy link
Author

scabug commented Jul 27, 2013

@paulp said:
What is done at the bytecode level has no bearing on what the language should allow for. It is definitively a bug that f1() and f2() in the appended code are inherited by classes outside s1 and O respectively. That the methods can even be overridden makes access a sham. What is the point of a specification if it is to be discarded whenever it is inconvenient?

       The modifier can be qualified with an identifier C (e.g.  private[C])
       that must denote a class or package enclosing the definition. Members
       labeled with such a modifier are accessible respectively only from
       code inside the package C or only from code inside the class C and its
       companion module (§5.4). Such members are also inherited only from
       templates inside C.

That it actually works as it's supposed to if the qualifier is a class name means trial-and-error is the only way to discover the behavior.

package s1 {
  object O {
    class A {
      private[s1] def f1(): Int = 1
      private[O]  def f2(): Int = 2
      private[A]  def f3(): Int = 3
    }
  }
}
package s2 {
  class B extends s1.O.A {
    override def f1() = 11  // allowed
    override def f2() = 12  // allowed
    override def f3() = 13  // disallowed
    // ./a.scala:15: error: method f3 overrides nothing
    //     override def f3() = 12
    //                  ^
    // one error found
  }
}

@scabug scabug added the access label Apr 7, 2017
@Blaisorblade Blaisorblade changed the title qualified modifiers, private[C] and protected[C] handled incorectly in a subclass qualified modifiers, private[C] and protected[C] handled incorrectly in a subclass Apr 25, 2018
@som-snytt
Copy link

som-snytt commented Nov 23, 2019

dotc also allows the f3 override in the last example.

@som-snytt
Copy link

Clarified at #9321 in 2015 and at the linked dotty ticket.

This is certainly a case where I was misled by outdated discussion, see my pre-pandemic comment. I just noticed that odersky's more sage comment was also Nov 23 exactly ten years earlier: it needs a SIP, or at least the spec update in the linked ticket.

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