This page is no longer maintained — Please continue to the home page at www.scala-lang.org

"accidental override" error when overridden self-type member overrides

3 replies
Daniel Dekany
Joined: 2011-01-06,
User offline. Last seen 42 years 45 weeks ago.

A Scala bug maybe? For example:

trait TCommon {
def f: String
}

class C1 extends TCommon {
def f = "in C1"
}

trait TOverrider { this: TCommon =>
override def f = "in TOverrider" // The overridden self-type member...
}

class C2 extends C1 with TOverrider // ... fails to override, here.

The error message is:

error: overriding method f in class C1 of type => java.lang.String;
method f in trait TOverrider of type => java.lang.String cannot
override a concrete member without a third member that's overridden by
both (this rule is designed to prevent ``accidental overrides'')
class C2 extends C1 with TOverrider // Fails

But there is a third member that's overridden by both: f in TCommon.
So it's definitely not an accidental clash.

Note that the above example works if I replace

trait TOverrider { this: TCommon =>

with

trait TOverrider extends TCommon {

I know they are not the same, but regarding this error why are they
different?

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: "accidental override" error when overridden self-type membe

On Sat, Jan 08, 2011 at 03:53:29AM +0100, Daniel Dekany wrote:
> A Scala bug maybe? For example:

My assessment is:

- this is a bug.
- fixing this bug revealed interesting new bugs.
- fixing those still left me with a crasher.

The genesis of bugs like this can be understood by seeing what happens
when you try to compile it with 2.7:

0107.scala:12: error: method f overrides nothing
override def f = "in TOverrider" // The overridden self-type member...
^

That is, overriding self type members was not possible until 2.8.0. So
it is not too surprising there remain some checks which fail to take
take it into account. I see this already came up:

https://lampsvn.epfl.ch/trac/scala/ticket/2808
"Accidental override error when using self-types"

But the fix was insufficient.

More interesting was that post-fix the library would no longer compile
because people have been getting away with some sketchy behavior which
should have been prohibited all along. For instance:

override type Future[+P] = scala.actors.Future[P]

I didn't think there was any legitimate use for "override type" and I'm
not sure why it's allowed. (Anyone?)

And then there's this, which was revealed by a similar type alias arity
bait-and-switch uncovered by fixing the self type overriding issue.

// crash2.scala
trait C[T]

trait A[T] {
type EPC[X1] = C[X1]
}
trait B[T] extends A[T] {
override type EPC = C[T]
}

// % scalac29 crash2.scala
// Exception in thread "main" java.lang.AssertionError: assertion failed: Unsound substitution from List() to List(type X1)
// at scala.Predef$.assert(Predef.scala:99)
// at scala.tools.nsc.symtab.Types$SubstMap.(Types.scala:3368)
// at scala.tools.nsc.symtab.Types$SubstSymMap.(Types.scala:3426)
// at scala.tools.nsc.symtab.Types$Type.substSym(Types.scala:590)
// at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkOverrideTypes$1(RefChecks.scala:379)
// at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkOverride$1(RefChecks.scala:367)
// at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkAllOverrides(RefChecks.scala:445)
// at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1347)
// at scala.tools.nsc.ast.Trees$Transformer.transformTemplate(Trees.scala:859)
// at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:751)
// at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform

Donna Malayeri
Joined: 2009-10-21,
User offline. Last seen 42 years 45 weeks ago.
Re: "accidental override" error when overridden self-type membe
I'm now seriously thinking that it was a mistake for me to suggest (and implement) the "feature" that one should be able to override self-type members. (I did see your SCL-543 review request, Paul, but haven't gotten to it yet.)  At the time that I suggested this, I had not realized that it we cannot (in general) allow "super" calls to the overridden member, as it would be impossible (with the current design of self-types) to ensure that this call would not simply be an infinite recursion. Moreover, Ingo has been of the opinion that self-type member overriding makes code harder to understand (but he was unfortunately away at an internship when we made this apparently-ill-fated decision).
Assuming that this reasoning is valid, the question is, should the "feature" be deprecated/removed?

Donna

On Sat, Jan 8, 2011 at 7:58 AM, Paul Phillips <paulp@improving.org> wrote:
On Sat, Jan 08, 2011 at 03:53:29AM +0100, Daniel Dekany wrote:
> A Scala bug maybe? For example:

My assessment is:

- this is a bug.
- fixing this bug revealed interesting new bugs.
- fixing those still left me with a crasher.

The genesis of bugs like this can be understood by seeing what happens
when you try to compile it with 2.7:

0107.scala:12: error: method f overrides nothing
 override def f = "in TOverrider"   // The overridden self-type member...
              ^

That is, overriding self type members was not possible until 2.8.0.  So
it is not too surprising there remain some checks which fail to take
take it into account.  I see this already came up:

 https://lampsvn.epfl.ch/trac/scala/ticket/2808
 "Accidental override error when using self-types"

But the fix was insufficient.

More interesting was that post-fix the library would no longer compile
because people have been getting away with some sketchy behavior which
should have been prohibited all along.  For instance:

 override type Future[+P] = scala.actors.Future[P]

I didn't think there was any legitimate use for "override type" and I'm
not sure why it's allowed.  (Anyone?)

And then there's this, which was revealed by a similar type alias arity
bait-and-switch uncovered by fixing the self type overriding issue.

// crash2.scala
trait C[T]

trait A[T] {
 type EPC[X1] = C[X1]
}
trait B[T] extends A[T] {
 override type EPC = C[T]
}

// % scalac29 crash2.scala
// Exception in thread "main" java.lang.AssertionError: assertion failed: Unsound substitution from List() to List(type X1)
//  at scala.Predef$.assert(Predef.scala:99)
//  at scala.tools.nsc.symtab.Types$SubstMap.<init>(Types.scala:3368)
//  at scala.tools.nsc.symtab.Types$SubstSymMap.<init>(Types.scala:3426)
//  at scala.tools.nsc.symtab.Types$Type.substSym(Types.scala:590)
//  at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkOverrideTypes$1(RefChecks.scala:379)
//  at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkOverride$1(RefChecks.scala:367)
//  at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkAllOverrides(RefChecks.scala:445)
//  at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1347)
//  at scala.tools.nsc.ast.Trees$Transformer.transformTemplate(Trees.scala:859)
//  at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:751)
//  at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform

--
Paul Phillips      | The important thing here is that the music is not in
In Theory          | the piano.  And knowledge and edification is not in the
Empiricist         | computer.  The computer is simply an instrument whose
slap pi uphill!    | music is ideas.  -- Alan Kay

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: "accidental override" error when overridden self-type membe

On Wed, Jan 12, 2011 at 08:03:15AM +0100, Donna Malayeri wrote:
> Assuming that this reasoning is valid, the question is, should the
> "feature" be deprecated/removed?

Ingo's email way back when convinced me it was trouble. We gave up a
sharp boundary and didn't get enough in return.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland