Fallback syntax for blanket trait implementations

First up, sorry if this has already been proposed or if this falls into the category of bikeshedding, however, recently I would have liked to be able to write the following code when doing a blanket implementation of a trait:

trait MyTrait {
   fn my_trait(&self) -> Result<bool, &'static str>;
}

impl<T> MyTrait for T where T: SomeTrait1 {
   fn my_trait(&self) -> Result<bool, &'static str> {
       Ok(true)
   }
} else where T: SomeTrait2 {
   fn my_trait(&self) -> Result<bool, &'static str> {
       Ok(false)
   }
} else {
   fn my_trait(&self) -> Result<bool, &'static str> {
       Err("Could not implement MyTrait")
   }
}

The intended logic is that the implementation of MyTrait for some type T is first attempted using whatever methods SomeTrait1 provides. If T does not satisfy SomeTrait1, we move on to the next block and see if we can use SomeTrait2's methods to implement MyTrait. Finally, there could be an else-implementation block which could be used to generate some default implementation that, for example, could just return an error.

To the best of my knowledge regarding Rust and its traits system (which admittedly is quite superficial), I do not think that this syntax would require any of the features in the specialization RFC (e.g., negative trait impls, default impl etc).

Any thoughts on this syntax? To me this syntax seems like a very intuitive and useful way to define blanket trait implementations.

This has the same problem as specialization: it's unsound if the choice of impl to apply can depend on lifetimes, and the presence of another trait implementation can depend on lifetimes.

2 Likes

Out of interest, could you give an example where a lifetime dependency would result in this unsoundness?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.