3
votes

I have this custom type:

pub type Address = [u8; 32];

I tried implementing fmt::Display for this type:

impl fmt::Display for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let public_key = sr25519::Public::from_raw(self);
        let address = public_key.to_ss58check();
        write!(f,"{}",address)
    }
}

But I get this compile error:

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> core/linix-primitives/src/lib.rs:122:1
    |
122 | impl fmt::Display for Address {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate

I understand that to implement a trait I need to have one of two: either the definition of a type locally or a definition of a trait locally.

Well, I already defined the type locally:

pub type Address = [u8; 32];

So why am I getting a compile error?

1

1 Answers

5
votes

The problem here is that the following does not declare a new type:

pub type Address = [u8; 32];

But instead a type alias, which is closer to a c-style typedef. This means that your code gets turned into the following:

impl fmt::Display for [u8; 32] {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let public_key = sr25519::Public::from_raw(self);
        let address = public_key.to_ss58check();
        write!(f,"{}",address)
    }
}

And here, [u8; 32] isn't a local type. What you probably want to do is use what is called the newtype pattern. You will probably want to add a #[repr] attribute to that if your type might have some padding.