# Struct Alias

**URL:** <https://internals.rust-lang.org/t/struct-alias/16960>\
**Category:** language design\
**Created:** [July 7, 2022, 3:13am UTC](https://internals.rust-lang.org/t/struct-alias/16960 "2022-07-07T03:13:54Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![tvallotton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tvallotton/32/8153_2.png) [@tvallotton](https://internals.rust-lang.org/u/tvallotton)\
**Post date:** [July 7, 2022, 3:13am UTC](https://internals.rust-lang.org/t/struct-alias/16960/1 "2022-07-07T03:13:54Z")

</div>

A struct alias would be a way to construct a new type from a previous one. Unlike type aliases, a struct alias is an owned type, so foreign traits can be implemented on it.

```rust
struct NewStruct = ForeignStruct; 

```

# Rationale

Their main purpose is to make the new type pattern more ergonomic and involve less boilerplate. The new type pattern serves as a good solution to sidestepping orphan rules, but it is usually avoided for the amount of boilerplate that it involves.

This is not meant to cover every single possible use case that there is to the new type pattern, because that may not be at all possible. But rather cover the most frequent and often most painful use cases.

## Inheritance and shadowing

The new type will inherit the entire public API of the old type, which includes fields, methods, associated constants, and trait implementations. Additionally, the new type has the possibility of shadowing methods and associated constants when new ones are defined.

## Shadow vs override

To be clear, struct aliases cannot override methods or trait implementations in a way that can influence the original type. They can only expose a different API shadowing the inherited one. This conforms with the traditional new type pattern where the new type can expose a different API to the old one, but cannot tinker with the old's type traits and method implementations.

For example:

```rust
struct Parent { pub field: bool }; 
impl Parent {
    pub const NUM: i32 = 10; 
    pub fn get_num() -> i32 {
        Self::NUM
    }
}

struct Child = Parent; 
impl Child {
    // shadows Parent::NUM
    // Parent::NUM still exists, but it cannot be accessed
    // through Child::NUM. It can still be accessed through `get_num()`
    pub const NUM: i32 = 99; 
}

let _ = Child { field: bool }; // you can construct a Child just like a Parent. 
assert_eq!(Child::NUM, 99); // Child::NUM shadows Parent::NUM
assert_eq!(Child::get_num(), 10); // note that this still returns Parent::NUM

```

Inherited traits can also be shadowed by implementing them over the type.

```rust
#[derive(Debug)]
struct Parent;
impl Parent {
    fn print() {
        println!("{Parent}"); 
    }
}

struct Child = Parent; 
impl Debug for Child {
    fn fmt(&self, f: Formatter<'_>) -> fmt::Result<()> {
        write!(f, "Child"); 
    }
}

Child.print() // still prints "Parent"
println!("{}", Child); // prints "Child"

```

## Casts

All struct aliases are types in their own right, so they do not support implicit coercion. In order to cast one to another users must manually implement `From` or use a derive macro.

Struct aliases are guaranteed to have the same layout, so it is always safe to transmute one type into the other. They work as if the New type was defined with `repr(transparent)`. This guarantee is important, because if the foreign type has private fields, users will not be able to cast one type into the other.

```rust
// a From derive macro would expand to this.
let new = unsafe { transmute::<ForeignType, New>(foreign) }; 

```

## Privacy

The privacy for all fields of a struct alias is set to be at most `pub(crate)`. This ensures that refactoring a struct alias into a proper struct is never a breaking change.

```rust
// its ok to change this: 
pub struct New = Old; 
// into this, because library users weren't able to access the fields of `New`
pub struct New(Old); 

```

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [July 7, 2022, 4:48am UTC](https://internals.rust-lang.org/t/struct-alias/16960/2 "2022-07-07T04:48:01Z")

</div>

> [@tvallotton](#):
>
> ## Privacy
> 
> The privacy for all fields of a struct alias is set to be at most `pub(crate)`. This ensures that refactoring a struct alias into a proper struct is never a breaking change.

So this means there's no\[1\] difference between struct aliases and [delegation](https://lib.rs/crates/ambassador)\[2\], right?

> [@tvallotton](#):
>
> This ensures that refactoring a struct alias into a proper struct is never a breaking change.

But it's terribly impractical to _actually_ have it be nonbreaking, though, as you'd have to delegate all of the lost inherent items and trait implementations.

> [@tvallotton](#):
>
> ```rust
> // into this, because library users weren't able to access the fields of `New`
> pub struct New(Old); 
> 
> ```

You forgot the `#[repr(transparent)]` you're providing 🙂

* * *

While this is indeed _useful_, the resulting behavior is almost the same as `#[derive(Deref, DerefMut)]` and should be justified how it is meaningfully better than that.

I suspect the answer is having the struct alias prevent using `&[mut] NewStruct` where `&[mut] ForeignStruct` is expected is desired and thus the answer (especially since coercing to `&[mut] ForeignStruct` would use the foreign impls rather than the shadowed ones), but this should be spelled out.

Additionally, I'd say the fields should be publicly accessible (as with `Deref[Mut]`, but maybe hopefully still allowing mut splitting?) and if field hiding is desired to use a tuple struct and delegation from the beginning.

* * *

1. well, rather the difference is just a. automatic delegation of every trait and inherent item and b. removal (shadowing) of delegation when directly provided 

2. obviously a built-in has the difference to ambassador's library implementation of working for any type (and inherent impls) and not just annotated traits in addition to the above difference to built-in delegation

---

<div class="post-metadata">

**Author:** ![tvallotton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tvallotton/32/8153_2.png) [@tvallotton](https://internals.rust-lang.org/u/tvallotton)\
**Post date:** [July 7, 2022, 5:07am UTC](https://internals.rust-lang.org/t/struct-alias/16960/3 "2022-07-07T05:07:38Z")

</div>

> [@CAD97](#):
>
> * * *
> 
> While this is indeed _useful_, the resulting behavior is almost the same as `#[derive(Deref, DerefMut)]` and should be justified how it is meaningfully better than that.

This differs from delegation in that here the new type does actually implement all traits the old type implements, as opposed to using autoderef to behave as if it implements them. In addition, it would inherit all the previous types constructors and associated functions/constants. In contrast, delegation can only inherit methods.

> [@CAD97](#):
>
> But it's terribly impractical to _actually_ have it be nonbreaking, though, as you'd have to delegate all of the lost inherent items and trait implementations.

Now that you mention it, changing from one to the other may be non breaking if you implement `Deref` and `DerefMut`.

---

<div class="post-metadata">

**Author:** ![Neutron3529](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/neutron3529/32/6976_2.png) [@Neutron3529](https://internals.rust-lang.org/u/Neutron3529)\
**Post date:** [July 7, 2022, 6:07am UTC](https://internals.rust-lang.org/t/struct-alias/16960/4 "2022-07-07T06:07:33Z")

</div>

> [@tvallotton](#):
>
> To be clear, struct aliases cannot override methods or trait implementations in a way that can influence the original type. They can only expose a different API shadowing the inherited one

why not use const generics instead?

```rust
struct ParentAndChild<const N:i32> {pub field:bool}
impl<const N:i32> ParentAndChild<N>{
    pub const NUM:i32 = N;
    pub fn get_num()->i32{
        N
    }
    fn show(&self)->i32{
        N
    }
}
type Parent=ParentAndChild<10>;
type Child=ParentAndChild<99>;
fn main(){
    let a=ParentAndChild::<12>{field:true};
    println!("{}",a.show());
    println!("{}",Parent::get_num());
    println!("{}",Child::get_num())
}

```

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [July 7, 2022, 6:12am UTC](https://internals.rust-lang.org/t/struct-alias/16960/5 "2022-07-07T06:12:34Z")

</div>

> [@tvallotton](#):
>
> This differs from delegation in that here the new type does actually implement all traits the old type implements, as opposed to using autoderef to behave as if it implements them. In addition, it would inherit all the previous types constructors and associated functions/constants. In contrast, delegation can only inherit methods.

Note that by delegation I _do not_ mean `#[derive(Deref[Mut])]`. I mean the theoretical Rust feature that would let you write something like

```rust
struct Child(Parent);
impl Child {
    pub use {self.0}::get_num;
}
impl Debug for Child {
    pub use {self.0}::fmt;
}

```

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [July 7, 2022, 6:56am UTC](https://internals.rust-lang.org/t/struct-alias/16960/6 "2022-07-07T06:56:36Z")

</div>

Consider

```rust
struct NewU32 = u32;

let a: NewU32;
let b: NewU32;

```

Are these expressions valid, and if so, what is their type?

- `a + b`
- `a.checked_add(b)`
- `a.overflowing_add(b)`
- `NewU32::MIN`
- `a.trailing_ones()`
- `a << b`

---

<div class="post-metadata">

**Author:** ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)\
**Post date:** [July 7, 2022, 10:19am UTC](https://internals.rust-lang.org/t/struct-alias/16960/7 "2022-07-07T10:19:01Z")

</div>

`u32` is not a struct, so I guess this would not be allowed.

However, you make a good point that automatically deriving traits can be problematic. In the case of `Add<Rhs>`, `Rhs` defaults to `Self`. So in this example:

```rust
struct Foo(u32);

impl Add for Foo {
    type Output = Foo;
    ...
}

struct Bar = Foo;

```

`Bar` would implement `Add<Bar, Output = Foo>`, but neither `Add<Foo, Output = Foo>`, nor `Add<Bar, Output = Bar>`.

This breaks the assumption that `Self` in an `impl` block can be replaced with the type, and vice versa.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [July 7, 2022, 11:00am UTC](https://internals.rust-lang.org/t/struct-alias/16960/8 "2022-07-07T11:00:55Z")

</div>

> [@Aloso](#):
>
> `u32` is not a struct, so I guess this would not be allowed.

Where is it said that the wrapped type needs to be a struct? From what I understand the `struct` keyword is there to say that the wrapper is a `struct` (e.g. `struct NewU32 = u32;` becomes `struct NewU32(u32);` plus all the implementations)

> [@Aloso](#):
>
> However, you make a good point that automatically deriving traits can be problematic. In the case of `Add<Rhs>`, `Rhs` defaults to `Self`. So in this example:
> 
> ```rust
> struct Foo(u32);
> 
> impl Add for Foo {
> type Output = Foo;
> ...
> }
> 
> struct Bar = Foo;
> 
> ```
> 
> `Bar` would implement `Add<Bar, Output = Foo>`, but neither `Add<Foo, Output = Foo>`, nor `Add<Bar, Output = Bar>`.
> 
> This breaks the assumption that `Self` in an `impl` block can be replaced with the type, and vice versa.

All of this is correct if you assume that `Self` will remain `Self` when extending traits, meaning `impl Add for Foo` actually implements `Add<Self>` for `Foo`. There's also another way to see it, that is `Self` gets resolved in the implementation, so `impl Add for Foo` implements `Add<Foo>` for `Foo`, and any subsequent use of that implementation won't know of the `Self`.

This is still problematic though, as now the wrapped type gets leaked everywhere a `Self` was implied.

---

<div class="post-metadata">

**Author:** ![tvallotton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tvallotton/32/8153_2.png) [@tvallotton](https://internals.rust-lang.org/u/tvallotton)\
**Post date:** [July 7, 2022, 3:33pm UTC](https://internals.rust-lang.org/t/struct-alias/16960/9 "2022-07-07T15:33:33Z")

</div>

> [@CAD97](#):
>
> Note that by delegation I _do not_ mean `#[derive(Deref[Mut])]`

Oh, I wasn't familiarized with that feature. In that case, it may not be that much different.

> [@SkiFire13](#):
>
> Are these expressions valid, and if so, what is their type?

All appearances of `Self` are automatically changed to `NewU32`, so all previous constructors, operators and functions return `NewU32`, and all methods take `NewU32`.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [July 7, 2022, 4:04pm UTC](https://internals.rust-lang.org/t/struct-alias/16960/10 "2022-07-07T16:04:53Z")

</div>

> [@tvallotton](#):
>
> > [@SkiFire13](#):
> >
> > Are these expressions valid, and if so, what is their type?
> 
> All appearances of `Self` are automatically changed to `NewU32`, so all previous constructors, operators and functions return `NewU32`, and all methods take `NewU32`.

I think @SkiFire13 chose an interesting set of examples, and this answer that says little more than “everything works” doesn’t really address these examples properly at all.

For example `u3::checked_add` does _not_ return `Self = u32`, but instead `Option<u32>`. How would this be handled and would that way of handling it make sense? Operators like `+` operate via traits. So `u32: Add<u32>` is a trait implementation. Transferring all trait implementations could mean `NewU32: Add<u32>`, whereas replacing all instances of `Self` could mean `NewU32: Add<NewU32>`. Or would we want both?

`u32::trailing_ones` returns `u32`, but the same operation on other types (e.g. `u8::trailing_ones` or `i64::trailing_ones` returns `u32`, too!) Always blindly replacing matching output types would mean that a `NewU32::trailing_ones` returns `NewU32` while a `NewU8::trailing_ones` would still return `u32`?

`<<` is implemented for very many combinations of types, e.g. `x: u8, y: isize` support `x << y` and `y << x`, etc… Can `NewU32` interact with all those types and `NewU32` itself but not `u32`? Or something else? What exactly, and why, and is that a good idea for a general rule?

---

<div class="post-metadata">

**Author:** ![ckaran](https://avatars.discourse-cdn.com/v4/letter/c/f475e1/32.png) [@ckaran](https://internals.rust-lang.org/u/ckaran)\
**Post date:** [July 7, 2022, 4:08pm UTC](https://internals.rust-lang.org/t/struct-alias/16960/11 "2022-07-07T16:08:07Z")

</div>

I'm trying to wrap my mind around this, so I'm thinking out loud here... please correct me if I make any mistakes.

This feels like syntactic sugar for creating a newtype, and I mean that in the most literal sense. Basically, the following happens:

1. When the compiler hits `struct NewStruct = ForeignStruct`, it copies the source code for `ForeignStruct` into the current file (kind of like macro expansion). This could be a recursive copy if there are sealed traits or other bits that have to be copied over.
2. The compiler does something almost like `sed s/ForeignStruct/NewStruct/g` across the newly copied source code.
3. The compiler continues processing code that was in the `NewStruct` file, using new implementations to replace the code for old implementations.

Is this essentially what you're proposing?

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [July 7, 2022, 4:19pm UTC](https://internals.rust-lang.org/t/struct-alias/16960/12 "2022-07-07T16:19:12Z")

</div>

Oh, here's a couple of other interesting examples:

* * *

```rust
struct NewString = String;
let s: NewString;

```

What's the type of `s.replace("foo", "bar")`? Note that `String`, and thus `NewString`, doesn't have a `replace` method, it actually comes from dereferencing to `str`! Thus it would use the normal `str` method and return `String`.

* * *

You might also want to have a `struct NewStr = str;`, but how do you change all `NewString`'s methods that use `&str` to use `NewStr`?

* * *

```rust
trait A {}
trait B {}
trait C {}

struct Foo<T>;
impl<T: B> A for Foo<T> {}

struct Bar<T> = Foo<T>;
impl<T: C> A for Bar<T> {}

```

Is `A` implemented for `Bar<T>` where `T: B + !C`?

- if yes, isn't this specialization, with all its soundness problems?
- if no, this is kinda surprising, it means you can lose traits implementations (well, technically you already do with the ones where `Self` is replaced by the wrapper struct).

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [July 7, 2022, 5:11pm UTC](https://internals.rust-lang.org/t/struct-alias/16960/13 "2022-07-07T17:11:44Z")

</div>

> [@tvallotton](#):
>
> All appearances of `Self` are automatically changed to `NewU32`, so all previous constructors, operators and functions return `NewU32`, and all methods take `NewU32`.

This adds a semantic difference to an impl using the `Self` alias or just saying `T` which currently doesn't exist. For the reasons @steffahn mentioned just swapping all mentions of the self type which _don't_ use `Self` is also problematic. And as SkiFire points out you can have indirect mentions of the self type as well.

Additionally, this is an implementation concern, as `Self` (and other name aliases) are eagerly normalized in the compiler, so it's currently impossible to (reliably) tell if a transparent alias was used.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [October 5, 2022, 5:12pm UTC](https://internals.rust-lang.org/t/struct-alias/16960/14 "2022-10-05T17:12:23Z")

</div>

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