RFC 0546: Self-not-sized-by-default

lang (traits | typesystem)

Summary

  1. Remove the Sized default for the implicitly declared Self parameter on traits.
  2. Make it "object unsafe" for a trait to inherit from Sized.

Motivation

The primary motivation is to enable a trait object SomeTrait to implement the trait SomeTrait. This was the design goal of enforcing object safety, but there was a detail that was overlooked, which this RFC aims to correct.

Secondary motivations include:

This change has been implemented. Fallout within the standard library was quite minimal, since the default only affects default method implementations.

Detailed design

Currently, all type parameters are Sized by default, including the implicit Self parameter that is part of a trait definition. To avoid the default Sized bound on Self, one declares a trait as follows (this example uses the syntax accepted in RFC 490 but not yet implemented):

trait Foo for ?Sized { ... }

This syntax doesn't have any other precendent in the language. One might expect to write:

trait Foo : ?Sized { ... }

However, placing ?Sized in the supertrait listing raises awkward questions regarding inheritance. Certainly, when experimenting with this syntax early on, we found it very surprising that the ?Sized bound was "inherited" by subtraits. At the same time, it makes no sense to inherit, since all that the ?Sized notation is saying is "do not add Sized", and you can't inherit the absence of a thing. Having traits simply not inherit from Sized by default sidesteps this problem altogether and avoids the need for a special syntax to suppress the (now absent) default.

Removing the default also has the benefit of making traits applicable to more types by default. One particularly useful case is trait objects. We are working towards a goal where the trait object for a trait Foo always implements the trait Foo. Because the type Foo is an unsized type, this is naturally not possible if Foo inherits from Sized (since in that case every type that implements Foo must also be Sized).

The impact of this change is minimal under the current rules. This is because it only affects default method implementations. In any actual impl, the Self type is bound to a specific type, and hence it known whether or not that type is Sized. This change has been implemented and hence the fallout can be seen on this branch (specifically, this commit contains the fallout from the standard library). That same branch also implements the changes needed so that every trait object Foo implements the trait Foo.

Drawbacks

The Self parameter is inconsistent with other type parameters if we adopt this RFC. We believe this is acceptable since it is syntactically distinguished in other ways (for example, it is not declared), and the benefits are substantial.

Alternatives

Unresolved questions