Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to create a type alias for multiple traits?

Tags:

rust

I have a generic function that prints the minimum of two items:

use std::fmt::Display;

fn print_min<T: PartialOrd + Display>(a: &T, b: &T) {
    println!("min = {}", if a < b { a } else { b });
}

This works pretty well with anything that implements both the PartialOrd and Display traits:

print_min(&45, &46);
// min = 45
print_min(&"a", &"b");
// min = a

Having to put the PartialOrd + Display in the function definition is kind of ugly, especially if I want to have a whole bunch of functions that operate on this (implementing a binary search tree, for example), or if my bounds get more complex. My first inclination was to attempt to write a type alias:

type PartialDisplay = PartialOrd + Display;

but this gives me some fairly bizarre compiler errors:

error[E0393]: the type parameter `Rhs` must be explicitly specified
 --> src/main.rs:7:23
  |
7 | type PartialDisplay = PartialOrd + Display;
  |                       ^^^^^^^^^^ missing reference to `Rhs`
  |
  = note: because of the default `Self` reference, type parameters must be specified on object types

error[E0225]: only auto traits can be used as additional traits in a trait object
 --> src/main.rs:7:36
  |
7 | type PartialDisplay = PartialOrd + Display;
  |                                    ^^^^^^^ non-auto additional trait

I'm guessing either my syntax is wrong or this just isn't possible yet. I'd like something like

type PartialDisplay = ???
fn print_min<T: PartialDisplay> { /* ... */ }
like image 762
Dan Simon Avatar asked Sep 27 '14 01:09

Dan Simon


3 Answers

PartialOrd and Display are traits. It has been discussed how to implement an alias but it was decided that it wasn't needed.

Instead, you can create a new trait with the traits you want as super traits and provide a blanket implementation:

use std::fmt::Display;

trait PartialDisplay: PartialOrd + Display {}
impl<T: PartialOrd + Display> PartialDisplay for T {}

fn print_min<T: PartialDisplay>(a: &T, b: &T) {
    println!("min = {}", if a < b { a } else { b });
}

fn main() {
    print_min(&45, &46);
    print_min(&"aa", &"bb");
}
like image 85
snf Avatar answered Nov 05 '22 23:11

snf


RFC 1733 introduced the concept of a trait alias. When it is stabilized, you will be able to say:

#![feature(trait_alias)]

use std::fmt::Display;

trait PartialDisplay<Rhs = Self> = PartialOrd<Rhs> + Display;

fn print_min<T: PartialDisplay>(a: &T, b: &T) {
    println!("min = {}", if a < b { a } else { b });
}

fn main() {
    print_min(&45, &46);
    print_min(&"a", &"b");
}
like image 27
Shepmaster Avatar answered Nov 05 '22 22:11

Shepmaster


While awaiting the stabilization of trait aliasing, you can use the trait-set crate. Here is an example of its use:

trait-set! {
    pub trait HashKey = Hash + Eq + Clone
}
like image 3
Gabriel Ferrer Avatar answered Nov 05 '22 22:11

Gabriel Ferrer