3

In Swift, I can add method to a generic type with parameter equality constraint.

extension Optional where Wrapped == String {
    // Available only for `Optional<String>` type.
    func sample1() { ... }
}

How to do this in Rust?


Update

This feature is called Extensions with a Generic Where Clause.

I think this is basically same feature with Rust's impl with where clause without explicit trait.

trait OptionUtil {
    fn sample1(&self);
}

impl<T> OptionUtil for Option<T> where T:std::fmt::Debug {
    fn sample1(&self) {
        println!("{:#?}", self);
    }
}

Is equivalent (without explicit trait) to

extension Optional where Wrapped: DebugDescription {
    func sample1() {
        print("\(self)")
    }
}

Therefore, I thought this Rust code would work, but it doesn't work with an error. (equality constraints are not yet supported in where clauses (see #20041))

impl<T> OptionUtil for Option<T> where T == String {
    fn sample1(&self) {
        println!("{:#?}", self);
    }
}
eonil
  • 83,476
  • 81
  • 317
  • 516
  • https://doc.rust-lang.org/std/cmp/trait.PartialEq.html and https://doc.rust-lang.org/book/ch10-02-traits.html – Stargateur Nov 09 '19 at 09:08
  • @Stargateur I think `PartialEq`/`Eq` trait is equivalent to `Equatable` protocol in Swift. Which is not what I am asking here. – eonil Nov 09 '19 at 09:38
  • oh so you want https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md ? – Stargateur Nov 09 '19 at 10:18
  • 1
    Does he? Is figured he just wanted `impl Foo for Option` for some extension trait `Foo`. @Eonil, since not all of us are familiar with Swift, can you describe what this feature does? – mcarton Nov 09 '19 at 10:29
  • @mcarton I think what you talked is what I was looking for. It works as I expected. Thanks. Can you convert your comment into an answer? I updated my question BTW. – eonil Nov 09 '19 at 11:12
  • @Stargateur I think it's something else though it looks like something highly related. – eonil Nov 09 '19 at 11:19

1 Answers1

3

You can just implement the trait for the concrete type Option<String>:

impl OptionUtil for Option<String> {
    fn sample1(self: &Self) {
        println!("{:#?}", self);
    }
}

I wrote crate, type_eq, which would let you write something that looks more like your Swift example. But it is identical to implementing the trait for Option<String>:

use type_eq::{Constrain, TypeEq};
use std::fmt::Debug;

trait OptionUtil {
    fn sample1(&self);
}

impl<T> OptionUtil for Option<T>
where
    Constrain: TypeEq<T, String>,
    T: Debug,
{
    fn sample1(&self) {
        println!("{:#?}", self);
    }
}

fn main() {
    let s = Some(String::from("hello"));
    println!("{:?}", s);
}

There are actually very few cases where this crate is useful. Most of the time the simpler code above will work, and is preferred.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204