Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I omit top-level type parameter in generic / nested structs?

Tags:

rust

I want to create a database structure that I can use like this:

let c: Database<Disk<u8>> = ...

However, when I naively implement it:

trait Element {}

trait Storage<E> where E: Element {}

struct Disk<E> where E: Element {
    data: E,
}  

impl<E> Storage<E> for Disk<E> where E: Element {}

struct Database<S>
where
    S: Storage<E>, 
    E: Element,
{
    storage: S,
}

I get an error that E is unknown:

error[E0412]: cannot find type `E` in this scope
  --> src/main.rs:30:16
   |
30 |     S: Storage<E>, // <-- Error: E not found.
   |                ^ did you mean `Eq`?

Playground

I could obviously make E explicit such as:

struct DatabaseUgly<S, E>
where
    S: Storage<E>,
    E: Element 

But then I would have to repeat the element type:

let c: DatabaseUgly<Disk<u8>, u8> = ...

How can I make Database work?

like image 657
left4bread Avatar asked Mar 23 '26 07:03

left4bread


1 Answers

A simple solution is to use associated type in the trait, rather than a generic:

trait Element {}

trait Storage { // not generic
    type Element: Element;
}

struct Disk<E>
where
    E: Element,
{
    data: E,
}

impl<E> Storage for Disk<E>
where
    E: Element,
{
    type Element = E;
}

struct Database<S>
where
    S: Storage,
    S::Element: Element,
{
    storage: S,
}

(link to playground)

See also When is it appropriate to use an associated type versus a generic type?

like image 68
mcarton Avatar answered Mar 25 '26 00:03

mcarton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!