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

private class escapes defining scope #2441

Closed
scabug opened this issue Oct 5, 2009 · 4 comments
Closed

private class escapes defining scope #2441

scabug opened this issue Oct 5, 2009 · 4 comments
Assignees

Comments

@scabug
Copy link

scabug commented Oct 5, 2009

The following code should not compile, but does:

trait X
trait A { def f: Option[X] }
object B {
    private class Y extends X { val y = 42 }
}
class B extends A {
    override def f = Some(new B.Y)
}

This piece of code contains a programming mistake which should be detected by the compile: the line

override def f = Some(new B.Y)

should instead read

override def f: Option[X] = Some(new B.Y)

because otherwise the result type will be inferred as Option[B.Y], revealing the private class Y through the public method f, so that any other module can access Y.y:

println((new B).f.get.y)  // prints 42

The error is correctly detected if object B is private or Y is a member of class B.
[[BR]][[BR]]
Tested with versions 2.7.7.RC1 and 2.7.3final.

@scabug
Copy link
Author

scabug commented Oct 5, 2009

Imported From: https://issues.scala-lang.org/browse/SI-2441?orig=1
Reporter: Ivo Kasiuk (ikasiuk)

@scabug
Copy link
Author

scabug commented Jan 18, 2010

@paulp said:
I was coming to report this and see it's already open. I would add that it's not clear to me it's a programming mistake: if an abstract class declares a method signatures and an implementing class has exactly one which matches but with an undeclared return type, should it not easily infer the return type?

Either way, the error message is incredibly unhelpful in terms of indicating what has to happen for it to compile. If you don't already know what's up, you will be head scratching.

Here is my example, which I enclose because it is somewhat different: the "private class" in question is private not by virtue of an access modifier but because it's a member of a constructor parameter. In trunk as of r20562 if you make these changes:

// add these two lines to MarkupParserCommon
  type ElementType
  def mkProcInstr(position: PositionType): ElementType  

// add these two to MarkupParsers after line 71
    type ElementType = Tree
    def mkProcInstr(position: Position) = handle.procInstr(position, "", "")

And we get:

[scalacfork] /scratch/trunk2/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala:74: error: private value parser escapes its defining scope as part of type MarkupParser.this.parser.symbXMLBuilder.global.Tree
[scalacfork]     def mkProcInstr(position: Position) = handle.procInstr(position, "", "")
[scalacfork]         ^

Define mkProcInstr with return type Tree, and all is well.

@scabug
Copy link
Author

scabug commented Jan 8, 2011

@paulp said:
Although I admit this one had a 1700 ticket head start, I'm closing it as a duplicate of #4114 because recency is a motivator. I added a pointer here.

@scabug
Copy link
Author

scabug commented Jan 10, 2011

@paulp said:
(In r23958) A test case for recently fixed #4114. Plus!

I had closed #2441 as a duplicate of that, but unfortunately #4114 did
not bring #2441 along with it. Then I realized I'm a programmer, not a
helpless trac watcher. As is often the case with thes things, fixing that
revealed a bug in the library. Closes #2441 for real, review by odersky.

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

No branches or pull requests

2 participants