- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
"accidental override" error when overridden self-type member overrides
Sat, 2011-01-08, 03:53
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?
Wed, 2011-01-12, 08:07
#2
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:
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
Wed, 2011-01-12, 09:57
#3
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.
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