Pre-RFC: Sealed traits

I should note, that sealed traits are also a good solution to the problem of private trait bounds in public interfaces.

Consider this public function:

pub fn function<T: PrivateBound>(arg: T) { /* do something */ }

Such functions are prohibited currently, because PrivateBound is a “private trait in a public interface”. However, desire to write such functions was expressed by various people (here and here).
Private bounds can be used to emulate function overloading: instead of

pub fn function(arg: f32) {}
pub fn function(arg: f64) {}
pub fn function(arg: my_f16) {}

the author provides one generic function

pub fn function<T: MyFloat>(arg: T) {}

where MyFloat denotes the closed set of types {f32, f64, my_f16} and the author doesn’t want users to extend this set.

However, look at this function from user’s perspective - function is a function that can accept what, MyFloat? What is MyFloat? Something private and undocumented. Do I have to read the source code to understand what arguments can function accept? Should the author write some informal documentation next to function about what MyFloat represent?

This situation is suboptimal. The trait MyFloat should be public and documented. The user should be able to write wrapper functions around function and use MyFloat as a bound. I’m not sure if the user should be able to use MyFloat's methods. Finally, the user shouldn’t be able to implement MyFloat because the function's author wants the overload set to be closed and controlled by him. The whole setup reminds sealed traits a lot.

10 Likes