Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method type confused when using self type

Following code does not compile with Scala 2 (tested 2.13.7 and Scala 2.12.15):

trait AttributeBase

trait Attribute extends AttributeBase {
  def name: String
}

trait Base {
  def attribute: AttributeBase
}

trait Derived { self: Base =>
  
  def attribute: Attribute
  
  def name = attribute.name
}

The code compiles fine with Scala 3. With Scala 2 the error is:

value name is not a member of AttributeBase

It compiles fine when extends is used instead of a self type:

trait Derived extends Base {

Another possible workaround is:

  def name = (this:Derived).attribute.name

Why is the type of Derived.attributed assumed to be AttributeBase and not Attribute? Is this a Scala compiler bug, or some Scala 2 limitation?

like image 684
Suma Avatar asked Oct 15 '22 19:10

Suma


1 Answers

I'd say it would be a bug or at least a difference between 2 and 3 in interpreting self-types. Here:

trait Derived { self: Base =>
  
  def attribute: Attribute
}

you are doing 2 things

  • telling compiler that this should be treated as Base (which defines attribute as AttributeBase
  • specialising attribute as Attribute

So which takes the precedence?

In Scala 2.13 specification I wasn't able to to pinpoint the definition of a self-type, AFAIK it only exists in syntax summary as SelfType or in changelogs. It seems it just an informal way of calling a type-ascription on (possibly aliased) this (following all the normal rules about type ascription and type definitions, so no special treatment, so no need to address it explicitly). If so, it might follow what we read in Tour of Scala about self-types - self: Tpe => does a sort of casting (narrowing) of this into Tpe from the POV of all the definitions inside, but at the same time allows adding new and specializing existing definitions (so 2.13 is kind of inconsistent as you noticed).

It seems that Scala 3 has it better sorted out as it seemingly treat it as a type-bound instead of a (selective) type-cast (which makes sense considering that Scala 3 implements DOT calculus and tries to remove inconsistencies and ambiguities). However, I wasn't able to find an exact statement on self-types in specification either so I would say that this improvement might be "just" a side effect of following the better formalism.

like image 120
Mateusz Kubuszok Avatar answered Oct 25 '22 04:10

Mateusz Kubuszok