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

repeated chain of "(in X)(in X)..." in type error #8777

Closed
scabug opened this issue Aug 3, 2014 · 5 comments
Closed

repeated chain of "(in X)(in X)..." in type error #8777

scabug opened this issue Aug 3, 2014 · 5 comments
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Aug 3, 2014

trait Foo extends scala.tools.nsc.Global {
  override def newCodePrinter(out: java.io.PrintWriter, tree: Tree, printRootPkg: Boolean): TreePrinter =
    super.newCodePrinter(out, tree, printRootPkg)
}
// ./a.scala:3: error: type mismatch;
//  found   : Foo.this.TreePrinter(in trait Printers)(in trait Printers)(in trait Printers)(in trait Printers)
//  required: Foo.this.TreePrinter(in trait Printers)(in trait Printers)(in trait Printers)(in trait Printers)
//     super.newCodePrinter(out, tree, printRootPkg)
//                         ^
// one error found

It compiles if I don't declare the return type. If this is "expected behavior" somehow, then the bug is the design.

@scabug
Copy link
Author

scabug commented Aug 3, 2014

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

@scabug
Copy link
Author

scabug commented Aug 3, 2014

@retronym said:
I see two problems here. Let's look at them with this minimization:

trait ApiUniverse {
  protected trait TreePrinter
  protected def newCodePrinter: TreePrinter
}

trait InternalSymbolTable extends ApiUniverse {
  class TreePrinter extends super.TreePrinter
  def newCodePrinter: TreePrinter = null
}

abstract class Global extends InternalSymbolTable {
  class TreePrinter extends super.TreePrinter
}

trait Broke extends Global {
  override def newCodePrinter: TreePrinter = super.newCodePrinter
}

trait Okay extends Global {
  override def newCodePrinter /*: super[InternalSymbolTable].TreePrinter !!! */
    = super.newCodePrinter
}

Firstly, CodePrinter is not designed for reuse in a virtual-class-like setup. It's a class, rather than a trait, and as such can never conform to Global.this.TreePrinter, which is a subclass of SymbolTable.this.TreePrinter.

Secondly, return type inference based on inheritance lets you express a type that isn't expressible directly.

qscalac -Xprint:typer -uniqid sandbox/t8777.scala 2>&1 | egrep 'Printer|trait|class' | grep -v init
 found   : Broke#7652.this.TreePrinter#14744
 required: Broke#7652.this.TreePrinter#15802
  override def newCodePrinter: TreePrinter = super.newCodePrinter
  abstract trait ApiUniverse#7646 extends scala#20.AnyRef#2681 {
    abstract protected trait TreePrinter#7997 extends scala#20.AnyRef#2681;
    protected def newCodePrinter#7998: ApiUniverse#7646.this.TreePrinter#7997
  abstract trait InternalSymbolTable#7712 extends AnyRef#2681 with ApiUniverse#7646 {
    class TreePrinter#14744 extends AnyRef#2681 with InternalSymbolTable#7712.this.TreePrinter#7997 {
    def newCodePrinter#14745: InternalSymbolTable#7712.this.TreePrinter#14744 = null
  abstract class Global#7682 extends AnyRef#2681 with InternalSymbolTable#7712 {
    class TreePrinter#15802 extends Global#7682.super.TreePrinter#14744 {
  abstract trait Broke#7652 extends Global#7682 {
    override def newCodePrinter#15809: Broke#7652.this.TreePrinter#15802 = Broke#7652.super.<newCodePrinter: error>
  abstract trait Okay#7757 extends Global#7682 {
    override def newCodePrinter#25163: Okay#7757.this.TreePrinter#14744 = Okay#7757.super.newCodePrinter#14745

Note the reference to Okay#7757.this.TreePrinter#14744 in the last line above.

@scabug
Copy link
Author

scabug commented Aug 3, 2014

@retronym said:
Oh, I forgot the third problem in disambiguation of error messages.

I fixed that over on another WIP branch recently: retronym/scala@scala:2.11.x...topic/existential-in-compound

@scabug
Copy link
Author

scabug commented Aug 4, 2014

@paulp said:
The inability to refer to the enclosures of superclasses also figures in the access debacle. Here are both fails at once. You are forced to make the method completely public if you wish to override it, plus this bug.

class A1 {
  trait C
  protected[A1] def make(): C = new C { }
}
class A2 extends A1 {
  class C extends super.C
}
class A3 extends A2 {
  class C extends super.C
}
class A4 extends A3 {
  override protected[A4] def make(): C = super.make()
  // ./a.scala:12: error: type mismatch;
  //  found   : A4.this.C(in class A1)
  //  required: A4.this.C(in class A3)
  //   override protected[A4] def make(): C = super.make()
  //                                                    ^
  // ./a.scala:12: error: overriding method make in class A1 of type ()A4.this.C;
  //  method make has weaker access privileges; it should be at least protected[A1]
  //   override protected[A4] def make()  = super.make()
  //                              ^
  // one error found
}

@scabug
Copy link
Author

scabug commented Jun 20, 2015

@retronym said:
scala/scala#4569

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

2 participants