Proposal : Abstract `This` type inside every class/trait


I find myself many times wanting to refer to the current class/trait type, but not the type of the instance (not this.type). For example:

trait Foo[T] {
  type This <: Foo[T]
trait Bar[T1, T2] extends Foo[T1] {
  type This <: Bar[T1, T2]

I propose that a This abstract type will be added to Any and its upper bound automatically set by the compiler for every new trait/class definition which is not anonymous.


It’s worth thinking about it.

I fear if This is always an abstract type it would not be very useful. You could not use it as a type of a parameter, for instance.

Also, quite a few class hierarchies already define This. What should happen in this case?


I wanted to give an example, and then realized my proposal was incomplete.
Say I want to create a generic print method that should have an implicit Printer at scope.

trait PrinterOf[T] {
  def apply(that : T) : Unit
trait MyGeneric {
  type This <: MyGeneric
  def print()(implicit print : PrinterOf[this.type]) : Unit = print(this)
  def printThis()(implicit print : PrinterOf[This]) : Unit = print(this.asInstanceOf[This])
class Foo[T] extends MyGeneric {
  type This <: Foo[T]

object Test {
  implicit def printerOfFoo[T] : PrinterOf[Foo[T]] =  foo => println("I pity the Foo")
  val myFoo = new Foo[Int] {
    type This = Foo[Int]
  myFoo.printThis() //works
  myFoo.print() //fails

There may be issues with variance annotations, I realize that. Any other ideas?


So my proposal is that This remains abstract until when its parent is instantiated, where This will be completed as the most constrained upper-bound, which is not this.type.


I’m not exactly sure what you’re referring to. Here is an example with inheritance from two traits with This defined:

trait PrinterOf[T] {
  def apply(that : T) : Unit
trait MyGeneric {
  type This <: MyGeneric
  def print()(implicit print : PrinterOf[this.type]) : Unit = print(this)
  def printThis()(implicit print : PrinterOf[This]) : Unit = print(this.asInstanceOf[This])
trait Foo1[T] extends MyGeneric {
  type This <: Foo1[T]
trait Foo2[T] extends MyGeneric {
  type This <: Foo2[T]
trait CombinedFoo[T] extends Foo1[T] with Foo2[T] {
  type This <: CombinedFoo[T]

object Lab1 extends App {
  implicit def printerOfFoo[T] : PrinterOf[CombinedFoo[T]] =  foo => println("I pity the Foo")
  new CombinedFoo[Int]{
    type This = CombinedFoo[Int]


In your example it is enough to make PrinterOf contravariant, i.e. to have it being declared as

trait PrinterOf[-T] {
  def apply(that: T) : Unit

Are you sure, your printer must be invariant and at the same time you need to have instances of anonymous classes that use this printer?


This could also be the name of inheritable constructors.
For java collections this feature would be useful,

since it would express&implement this requirement:

All general-purpose Collection implementation classes
(which typically implement Collection indirectly through one of its subinterfaces)
should provide two “standard” constructors: a void (no arguments) constructor,
which creates an empty collection,
and a constructor with a single argument of type Collection,
which creates a new collection with the same elements as its argument.

I am not sure how useful&feasible inheritable constructors would be for Scala.


In the example above, the idea is to have unique (invariant) printers and not a general one.


If you already have to provide an implicit instance for a particular parameter type, then you might as well figure out which methods will receive it and manually set the argument type for these methods.


Thanks, good question.
Currently I write somethink like this:

  trait Nullable[V  <: AnyRef , T<:Nullable[V,T] ] extends Any{
    def === (that: T): Boolean

    def newInstance(v:V): T
    def clone(): T
    //Some others method

But It is not very convenient.


Interesting, few months ago I was trying to discuss something very similar in my post about clone-like methods
Effectively it was a call for something very similar to proposed here This-type

Actually that post was quite verbose, but in general it was suggested 2 approaches to solve this problem:

  • make This type concrete only in final classes (as it was actually done in Rust as far as I know/understand)
  • make some possibility to somehow declare factory method which calls constructor indirectly - but this approach should also introduce some new form of constraint - non abstract sub class of that constraint class should always have that constructor, with signature matching to intended factory method


I forgot about this. Indeed, very annoying and always bothered me.


There two rules, one simple and one complex, together allow a my-type This to work.

Simple: In argument position, subclasses must overload the method to provide a child-class-specific variant.

Complex: This-typed returns are marked with their actual return type from the implementation. A subclass for which the actual return type is no longer consistent with the subtype must override the method to provide a consistent return type.


class Parent[+A](val a: A, val aa: A) {
  def arg(me: This[A]): Unit = { println(a) }
  def change: This[A] = new Parent[A](aa, a)
  def twice: This[A] = change.change

class Child[+A <: Seq[Int]](val value: A) extends Parent(value, value)[Seq[A]] {}
// Compile error: method arg not overloaded with subclass Child
// Compile error: method change has incompatible return type in superclass implementation
//   Found return type:    Parent[A]
//   Required return type: Child[A] (as This[A])

class Child(val value: Seq[Int]) extends Parent(value, value)[Seq[Int]] {
  def arg(me: Child): Unit = arg(me: Parent[Seq[Int]])
  def change: Child = new Child(value.reverse)
  // method twice has true This[A] return type, so is okay

class Grandchild extends Child(Seq(1, 2, 3)) {}
// Compile error: method arg not overloaded with subclass Grandchild as required by inheritance from Parent
// Compile error: method change has incompatible return type from inheritance from Parent
//   Found return type:    Child
//   Required return type: Grandchild
//     Requirement for This return type from definition in Parent

This would let the compiler verify and help with a huge amount of the work of keeping self-types straight.


Did you mean to have This have a type arguments ([A])? Not all inheritors have the same type-argument signature as their parents.