Open treemcgee42 opened 11 months ago
trait_c
is considered equal totrait_d
if and only if implementingtrait_c
is necessary and sufficient to implementtrait_d
. For example, taking the traits as defined above,trait trait_c = trait_b; trait trait_d = trait_a + trait_b;
The reason
trait_c == trait_d
is becausetrait_a < trait_b
, sotrait_a + trait_b <= trait_b + trait_b == trait_b
. But alsotrait_b <= trait_a + trait_b
(trait addition has the same semantics as adding positive integers).
Should these compare as equal? Like how type
defines a new type while const
defines an alias, shouldn't trait
define a new trait (that needs to be chosen to be implemented), while const
simply aliases a collection?
Marker traits
A trait with no functions can be used as a marker, and is auto-implemented in the following way:
Trait arithmetic
A few operations can be performed on traits to compare them and create new ones.
Addition
The result of adding two traits is a trait which requires its summand traits to be implemented for a type before it itself can be implemented.
Less than
We say that
trait_a < trait_b
if implementingtrait_b
would be sufficient but not necessary to implementtrait_a
.Note that simply implementing
trait_b
on a type does not automatically implementtrait_a
on that type. However, after implementingtrait_b
, one can automatically implementtrait_a
:Equality
trait_c
is considered equal totrait_d
if and only if implementingtrait_c
is necessary and sufficient to implementtrait_d
. For example, taking the traits as defined above,The reason
trait_c == trait_d
is becausetrait_a < trait_b
, sotrait_a + trait_b <= trait_b + trait_b == trait_b
. But alsotrait_b <= trait_a + trait_b
(trait addition has the same semantics as adding positive integers).Automatic implementation
Scoping
Dynamic dispatch
There are situations where calling trait functions will result in dynamic dispatch, but this is not always the case. If the only thing known about an object is that it implements a trait, then calling a trait function on that object will result in dynamic dispatch. However, if the type of the object is known at compile time when calling a trait function, the compiler can directly include a call to the specific implementation of the trait function.
In the following few examples, we will use the following trait, and type which implements that trait:
This is an example of where dynamic dispatch occurs.
This is an example of where dynamic dispatch does not occur.
Compile-time enforcement
It's useful to ensure at compile-time that dynamic dispatch does not occur. For instance, dynamic dispatch on hot paths can have a significant impact on performance.
To that end, we propose the following syntax: