# this.type

## Definition

*ThisType* is also referred to as *SelfType*, in Eiffel it is
written *like Current*.

The purpose of *ThisType* is to allow co-variant argument and result
type changes for operations such as `numeric.infix +(a numeric)`

in heir
features such as `i32`

, where this should be `i32.infix +(a i32)`

.

## Motivation

Often, features need to work with instances of the same type as the current
instance, even if we are in an heir feature. An example is `infix +`

defined in an abstract feature `numeric`

whose argument must match
the type of `numeric.this`

. For heir `i32`

, the
argument must be of type `i32`

, while for `complex f64`

,
the argument must also be of type `complex f64`

.

`like this`

in Eiffel

Eiffel provides a type `like anchor`

that is essentially syntax
sugar for redefinitions of features with changes in their result types, the
redefinition of the `anchor`

automatically redefines the type of all
features using type `like anchor`

.

A special case in Eiffel is the anchor `Current`

that corresponds
to `this`

in Java or `A.B.C.this`

in Fuzion. An anchored
type `like Current`

in an Eiffel feature `F`

the type of
the current instance, which is just `F`

unless the current instance
is of an heir `G`

of `F`

, where it is `G`

.

The example given by Bertrand Meyer in *Object-Oriented Software
Construction, 2nd edition* is as follows:

class POINT feature x, y: REAL conjugate: like Current is do Result := clone (Current) Result.move(0, -2*y) end end

In a descendant of `POINT`

, `conjugate`

will
automatically be changed to result in an instance of the descendant type. E.g.,

class PARTICLE inherit POINT feature ... end

will automatically redefine `conjugate`

to result in an instance
of `PARTICLE`

.

## Workaround using parametric types

As a first solution, Fuzion uses constrained type parameters to
mimic *ThisType*. As an example. feature `numeric`

is declared
generically as `numeric(T type: numeric T)`

, and the type argument `T`

is
carried through heirs `integer(T type: integer T) : numeric T`

,
`wrapping_integer(T type : wrapping_integer T) : integer T`

and `i32(val i32) : wrapping_integer i32`

. This works, but is
cumbersome, in particular when the inheritance graph becomes more complex
(e.g. `i32`

also inherits from `has_interval`

, which uses the same
mechanism to mimic *ThisType*).

## Type parameters as anchors in Fuzion

Imagine we want to declare an abstract feature `numeric`

that
provides operations such as `infix +`

to add numeric values. Concrete
instances of `numeric`

could be 32-bit unsigned integers, 64-bit
floats, complex numbers, or user defined features that provide the required
operations.

What should the argument type of `infix +`

be in this case? It
does not make much sense in an expression `a + b`

where `a`

is of type `i32`

to permit arbitrary numeric
values, it makes most sense to accept only values of the same heir
of `numeric`

, which is `i32`

in this case.

One way to achieve this is to give numeric a type
parameter `T`

that is set to the actual type by heirs of numeric and
then declare operations as follows

numeric(T type : numeric T) is ... infix +(b T) T => abstract

and give a concrete type for `T`

in a concrete heir
for `numeric`

:

i32(val i32) : numeric i32 is ... infix +(b i32) i32 => addi32_intrinsic i32.this b

This works, but is a little ugly.

`this.type`

in Fuzion

A Fuzion variant of Eiffel's `like Current`

could be the
expression `A.B.C.this.type`

. Since there might be several outer
features, we need to qualify which outer instance we refer to. Applied to the
numeric example above, the code could then become:

numeric is ... infix +(b numeric.this.type) numeric.this.type => abstract

with heirs able to provide concrete types:

i32(val i32) : numeric is ... infix +(b i32) i32 => addi32_intrinsic i32.this b

### Rules for assignments `this.type`

that must be respected

- values of type
`A.B.C.this.type`

can be assigned to one another, they are of the same type - the value
`A.B.C.this`

is of type`A.B.C.this.type`

, so it can be assigned to a field of type`A.B.C.this.type`

- values of type
`A.B.C.this.type`

may have an actual type that is a sub-type of`A.B.C`

, so they cannot be assigned to a field of type`A.B.C`

unless`A.B.C`

is a`ref`

type. - consequently, value
`A.B.C.this`

cannot be assigned to a field of type`A.B.C`

unless`A.B.C`

is a`ref`

type.

### Rules for redefinitions using `this.type`

that must be respected

A redefinition using `A.B.C.this.type`

in
feature `A.B.C1`

must replace the type accordingly
by `A.B.C1.this.type`

. E.g., an heir to `numeric`

might
be `integer`

as follows:

integer : numeric is ... redef infix +(b integer.this.type) integer.this.type => abstract

Alternatively, an heir might provide a concrete implementations such
as `i32`

that replaces `numeric.this.type`

by `i32`

:

infix +(b i32) i32 => addi32_intrinsic i32.this b

However, this redefinition no longer provides a valid implementation
of `infix +`

in any heir of `i32`

. Here is an
outline of a possible heir `mod5`

that provides module-5 arithmetic
based on `i32`

:

mod5(redef val i32) : i32 val pre 0 <= val < 5 is ... infix +(b mod5) mod5 => mod5 (val + b.val) % 5

## Literature

- Sukyoung Ryo: ThisType for Object-Oriented Languages: From Theory to Practice.
- Saito and Igarashi presented a paper Matching ThisType to Subtyping.