Skip to content

Inference of inaccessible types #4228

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
Blaisorblade opened this issue Apr 2, 2018 · 4 comments
Open

Inference of inaccessible types #4228

Blaisorblade opened this issue Apr 2, 2018 · 4 comments

Comments

@Blaisorblade
Copy link
Contributor

Blaisorblade commented Apr 2, 2018

Type inference sometimes produces inaccessible types, but should widen then to visible ones. An example from 2012: https://groups.google.com/d/msg/scala-internals/0j8laVNTQsI/B6fu1e4KJ2sJ

package a {
  private[a] trait Impl { def f = 5 }
  class Vis1 extends Object with Impl
  class Vis2 extends Object with Impl

  object Vis {
    def f = new Vis1
    def g = new Vis2
    def lub = List(f, g)  // this should be (and is) a List[Impl]
  }
}
package b {
  object Elsewhere {
    import a.Vis._
    def lub = List(f, g) // this should not be (but is) a List[a.Impl]
  }
}

Running the REPL with the output confirms the issue is still there:

> repl -classpath out
[...]
scala> a.Vis.lub
val res0: List[a.Impl] = List(a.Vis1@67e28be3, a.Vis2@e344ad3)
scala> b.Elsewhere.lub
val res1: List[a.Impl] = List(a.Vis1@63716833, a.Vis2@573284a5)

(BTW, the other example in that email is instead fixed, arguably better in Dotty than in Scalac):

scala> def f = { trait A ; trait B extends A ; trait C extends B ; new C { } }; lazy val g = f
def f: Object
val g: Object = <lazy>
@Blaisorblade
Copy link
Contributor Author

BTW, I suspect a related issue came up in #4133 (review), though I might be confused — this one doesn't crash Dotty, just produce questionable results.

@smarter
Copy link
Member

smarter commented Apr 2, 2018

We already disallow public classes extending private classes in some situations:

object A {
  private trait Foo
  class Bar extends Foo
}
-- Error: try/i4228b.scala:3:8 -------------------------------------------------
3 |  class Bar extends Foo
  |        ^
  |        non-private class Bar refers to private trait Foo
  |        in its type signature Object with A.Foo{...}

We could extend this to private-qualified superclasses and to classes defined directly in packages.

@smarter
Copy link
Member

smarter commented Apr 2, 2018

It might be possible to use https://github.com/olafurpg/scala-experiments to check how frequently projects have public classes extending private classes and if there are actual usecases for this.

@Blaisorblade
Copy link
Contributor Author

Here was one use of extending private classes — the goal was to reuse implementation: scala/scala@51ec62a8c3

Your comment in #4133 shows another (smaller) instance.

In both cases, widening inferred types to accessible ones seems a possible alternative in principle, though I'm not sure how hard it is to do in practice. I think this is yet-another-instance of a well-known problem with ML modules, the "avoidance problem" (@odersky mentioned it days ago), but I am not too familiar with solutions.

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

No branches or pull requests

3 participants