# Various suggestions - empty impls, empty traits, struct field traits,

**URL:** <https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131>\
**Category:** language design\
**Created:** [August 4, 2022, 4:04pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131 "2022-08-04T16:04:40Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![yoav-lavi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yoav-lavi/32/9684_2.png) [@yoav-lavi](https://internals.rust-lang.org/u/yoav-lavi)\
**Post date:** [August 4, 2022, 4:04pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/1 "2022-08-04T16:04:40Z")

</div>

Hi!

I wanted to make a few suggestions / understand if there's already an RFC for any of these:

1. Empty `impl`s / Empty traits

When working with marker traits, I personally think it would be nice to be able to not supply the trailing block, as Rust currently allows for structs. e.g.:

```rust
trait MarkerTrait;
impl MarkerTrait for Entity;

```

vs

```rust
trait MarkerTrait {}
impl MarkerTrait for Entity {}

```

I personally find the former more readable (and subjectively, think it looks nicer)

1. Struct field traits

I've seen a few questions around this in the past and a mention of a proposal, but wanted to give my two cents on why this would be useful.

Since Rust traits only allow for functions rather than fields, grouping functionality can become a bit more difficult in the case where you want a struct to have a certain shape, e.g. for serialization, to later be able to use it for a specific purpose.

For instance if I wanted to set an invariant for records that can be stored in a DB where they must have an ID field and a few other fields that must exist to be able to later query said records, I could theoretically define a trait with functions that supply those fields, but that doesn't actually guarantee anything in terms of the record shape.

1. Allow referring to associated `const`s in traits

This one is similar to the previous point, I think it could be useful to be able to blanket `impl` a trait which rather than a function, requires the implementing type to define an associated `const` of a certain type, to be able to implement functionality once (e.g. in a function on the same trait which uses said `const`) rather than implementing the same function for each struct.

Thanks!

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [August 4, 2022, 7:35pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/2 "2022-08-04T19:35:27Z")

</div>

> [@yoav-lavi](#):
>
> as Rust currently allows for structs

Note that `struct Foo;` and `struct Foo {}` do different things! The former adds `const Foo: Foo = Foo {};`, but the latter doesn't.

Since there isn't a similar thing for `impl`s and `trait`s, I don't think it's worth having another way to write the same thing.

(I do think `;` looks a bit nicer than `{}`, but not enough to need to support both nor to force everyone to transition over an edition.)

---

<div class="post-metadata">

**Author:** ![yoav-lavi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yoav-lavi/32/9684_2.png) [@yoav-lavi](https://internals.rust-lang.org/u/yoav-lavi)\
**Post date:** [August 4, 2022, 7:59pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/3 "2022-08-04T19:59:53Z")

</div>

Thanks @scottmcm! I wasn't aware of the difference.

Regarding the point on an edition - not sure I understand why one would be needed, would this not be backwards compatible with existing code?

Are new editions not normally created in cases where for example a new keyword could break existing variables with the same name?

Thanks!

---

<div class="post-metadata">

**Author:** ![yoav-lavi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yoav-lavi/32/9684_2.png) [@yoav-lavi](https://internals.rust-lang.org/u/yoav-lavi)\
**Post date:** [August 4, 2022, 8:03pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/4 "2022-08-04T20:03:08Z")

</div>

Regarding the `const` creation, was the decision to allow the short form for convenience or for another reason?

(Perhaps "unit" enum variants (with no data) use the same machinery, since enum variants behave like structs syntactically?)

Thanks!

Edit: removed part of the question since it wasn't relevant / correct

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [August 4, 2022, 8:32pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/5 "2022-08-04T20:32:29Z")

</div>

> [@yoav-lavi](#):
>
> I wasn't aware of the difference.

If you're curious, see [https://rust-lang.github.io/rfcs/1506-adt-kinds.html#unit-structs](https://rust-lang.github.io/rfcs/1506-adt-kinds.html#unit-structs)

> [@yoav-lavi](#):
>
> Regarding the point on an edition - not sure I understand why one would be needed, would this not be backwards compatible with existing code?

It would absolutely be backward compatible to support _both_. What I was referring to there is that I'm not a fan of both, so if we wanted to remove `{}` support (to no longer have two ways of writing it) then that would take an edition.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [August 4, 2022, 8:52pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/6 "2022-08-04T20:52:35Z")

</div>

I think it'd be nice to have. It's not super important, but I remember being slightly annoyed that `unsafe impl Send for Type {}` requires useless brackets, and that my editor and rustfmt have different opinion on their placement.

---

<div class="post-metadata">

**Author:** ![yoav-lavi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yoav-lavi/32/9684_2.png) [@yoav-lavi](https://internals.rust-lang.org/u/yoav-lavi)\
**Post date:** [August 4, 2022, 9:12pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/7 "2022-08-04T21:12:42Z")

</div>

I see, although I'm not sure (maybe missed it in the link) whether `struct Foo;` has a `const` to make usage easier (in which case it's a change for convenience on top of a change for convenience, which theoretically means two different ways to do the same thing has "precedent"), or if it has another reason for the difference in which case it's not actually two ways to do the same thing.

Mainly asking out of curiosity, although personally I'm not sure I'd be against having both, there's other examples (like `where`) where there's multiple simultaneous options

---

<div class="post-metadata">

**Author:** ![yoav-lavi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yoav-lavi/32/9684_2.png) [@yoav-lavi](https://internals.rust-lang.org/u/yoav-lavi)\
**Post date:** [August 4, 2022, 9:14pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/8 "2022-08-04T21:14:38Z")

</div>

The post itself has three (unrelated) points by the way, in case it's unclear that the latter two are not a continuation of the first

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [August 5, 2022, 1:12am UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/9 "2022-08-05T01:12:23Z")

</div>

> [@yoav-lavi](#):
>
> 1. Allow referring to associated `const`s in traits

[This is already possible,](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2b6ce384aef9054286d87b4920d857a2) unless I misunderstood you.

---

<div class="post-metadata">

**Author:** ![yoav-lavi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yoav-lavi/32/9684_2.png) [@yoav-lavi](https://internals.rust-lang.org/u/yoav-lavi)\
**Post date:** [August 5, 2022, 6:03am UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/10 "2022-08-05T06:03:54Z")

</div>

You're right!

The post originally stated a blanket `impl` for a struct with a const which I don't think is possible but perhaps I didn't find it, but I edited the description and dropped the word `impl` so you're entirely correct that it exists (I also wasn't aware of this existing and it solves my original issue, but perhaps `impl` for a struct with `const` x still makes sense)

Edited the original

---

<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:** [August 8, 2022, 1:08pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/11 "2022-08-08T13:08:31Z")

</div>

> [@scottmcm](#):
>
> Note that `struct Foo;` and `struct Foo {}` do different things! The former adds `const Foo: Foo = Foo {};`, but the latter doesn't.

I would consider this an implementation detail. The `const` item is just added to also allow omitting the `{}` at the usage site. Other than that, it doesn't affect behavior in any way; when importing a unit struct, the `const` item is implicitly imported as well.

Note that enum variants also allow omitting the `{}`, which is equivalent to declaring an associated `const` with the same name, except that this [doesn't actually work](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1cd49ce43e638613d9af2edb47241822).

Personally I'm not opposed to allowing `;` in addition to `{}` after traits and impls. The main question is where we draw the line.

- Do we also want to allow `;` after functions with an empty body? **No** , because that means something very different in a trait.
- Do we want to allow it after empty enums and unions? Maybe for consistency.
- expressions such as `if`, `while`, `loop` and `for`? Probably not, although there is precedent in other programming languages.
- macro calls? Maybe.

---

<div class="post-metadata">

**Author:** ![simonbuchan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simonbuchan/32/9390_2.png) [@simonbuchan](https://internals.rust-lang.org/u/simonbuchan)\
**Post date:** [August 17, 2022, 9:38am UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/12 "2022-08-17T09:38:45Z")

</div>

I'm surprised about the const item detail, I thought it was a literal `'static` expression of the sort `&0` is. Is there an observable difference? Is it affected by type aliases?

Empty traits/impls should certainly be identical regardless of being spelled with a `;` or `{}` - if nothing else anything else would break all the derived code out there AFAICT.

For some reason, `enum Foo;` (and union) makes my skin crawl - I have no idea why? Maybe because empty enums are definitely not a "default" thing?

Absolutely not for control flow: otherwise `if some long confusing condition; { always runs }` is possible. This has burned people in other languages.

I think it makes sense in macros, (only in item position, of course), for cases where you just need to paste the same items a bunch of places (presumably using the deliberate lack of item name hygiene, iirc?)

Regarding the OP second point, I've always wondered why this hasn't been a thing, in C++ or Rust or whatever. It seems reasonable to me that

```rust
trait Record {
  fn save(&self);

  id: u32;
}

```

Would define a vtable layout with two entries, the address of an `fn save()`, and the object-relative offset to a `u32`. I guess the impl looks like:

```rust
struct User(u32);

impl Record for User {
  fn save(&self) ...

  id = 0; // as in, member 0, not the value 0 - though the offset in this case would be.
}

```

So that's a bit weird.

---

<div class="post-metadata">

**Author:** ![anon32976453](https://avatars.discourse-cdn.com/v4/letter/a/49beb7/32.png) [@anon32976453](https://internals.rust-lang.org/u/anon32976453)\
**Post date:** [August 17, 2022, 12:26pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/13 "2022-08-17T12:26:57Z")

</div>

> [@simonbuchan](#):
>
> Regarding the OP second point, I've always wondered why this hasn't been a thing, in C++ or Rust or whatever. It seems reasonable to me that
> 
> ```rust
> trait Record {
> fn save(&self);
> 
> id: u32;
> }
> 
> ```
> 
> Would define a vtable layout with two entries, the address of an `fn save()`, and the object-relative offset to a `u32`. I guess the impl looks like:
> 
> ```rust
> struct User(u32);
> 
> impl Record for User {
> fn save(&self) ...
> 
> id = 0; // as in, member 0, not the value 0 - though the offset in this case would be.
> }
> 
> ```
> 
> So that's a bit weird.

That's not how traits work in Rust. Traits are compile time constructs. Only if you use a `dyn Record` **type** (which is type erased at run time) would there be a v-table.

e.g.

```rust
fn foo (record: impl Record) {
    record.save() // there is no v-table lookup here, it's a static call
    //...
}

```

---

<div class="post-metadata">

**Author:** ![simonbuchan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simonbuchan/32/9390_2.png) [@simonbuchan](https://internals.rust-lang.org/u/simonbuchan)\
**Post date:** [August 17, 2022, 12:52pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/14 "2022-08-17T12:52:02Z")

</div>

Yeah, I was talking about the `dyn` case, because the `impl` case is obvious.

---

<div class="post-metadata">

**Author:** ![anon32976453](https://avatars.discourse-cdn.com/v4/letter/a/49beb7/32.png) [@anon32976453](https://internals.rust-lang.org/u/anon32976453)\
**Post date:** [August 17, 2022, 1:29pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/15 "2022-08-17T13:29:49Z")

</div>

Well, the example provided is incorrect/incomplete and the phrasing confusing.

Let me try to address your point though:

1. The trait definition syntax is shared between the two cases, `dyn trait` is the syntax at the usage site. It isn't obvious at all that it is the dynamic case as you claimed.
2. A type can implement multiple traits in an open world design - this posses multiple issues: If I do `impl Foo for Bar {}` and `Bar` is defined by another crate which was compiled separately - how do we define the field mapping and how would the compiler know how to resolve this? If I combine multiple traits by e.g. defining `dyn (X + Y)` how would that work?

---

<div class="post-metadata">

**Author:** ![simonbuchan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simonbuchan/32/9390_2.png) [@simonbuchan](https://internals.rust-lang.org/u/simonbuchan)\
**Post date:** [August 17, 2022, 8:58pm UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/16 "2022-08-17T20:58:44Z")

</div>

You're being needlessly pedantic. I was talking about a vtable it would define, so yes, I feel it's pretty obvious that I'm talking about the vtable it would define for when vtables are used.

You can define a field mapping for a foreign type only if the field is public. Perhaps there's some ecosystem impact here given that public fields are pretty uncommon, but you always either control the type or trait, so I don't really see what it would be.

You can only "combine" empty traits like that in current Rust, so it wouldn't be legal. If it is supported at some point, then the field offset is just another vtable entry defined by the `impl`, I don't see the additional problem it would cause. It would probably just be defining a new vtable concatenating the entries, for example, so what's in the entries doesn't matter at all.

---

<div class="post-metadata">

**Author:** ![anon32976453](https://avatars.discourse-cdn.com/v4/letter/a/49beb7/32.png) [@anon32976453](https://internals.rust-lang.org/u/anon32976453)\
**Post date:** [August 18, 2022, 3:24am UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/17 "2022-08-18T03:24:08Z")

</div>

> [@simonbuchan](#):
>
> You're being needlessly pedantic. I was talking about a vtable it would define, so yes, I feel it's pretty obvious that I'm talking about the vtable it would define for when vtables are used.

That's a bit rude. I'm simply pointing out that you're changing the trait **definition** for the purposes of a specific usage pattern without addressing what would be the semantics of said extended definition for other usage patterns.

On the other points, combining multiple non-empty traits is a limitation today due to implementation concerns. Afaik it is definitely planned to loosen that restriction eventually. There has been some work towards that as part of working towards supporting up casting.

And lastly, the open world design means this needs to accommodate separate compilation as each crate is compiled separately.

I did not say it is impossible to achieve your goals. Merely asking to clarify how these points would be accommodated in your suggested design. Your design is simply incomplete without addressing these prerequisites.

---

<div class="post-metadata">

**Author:** ![simonbuchan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simonbuchan/32/9390_2.png) [@simonbuchan](https://internals.rust-lang.org/u/simonbuchan)\
**Post date:** [August 18, 2022, 4:05am UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/18 "2022-08-18T04:05:26Z")

</div>

Do you have any specific issues I haven't addressed yet? Is there any reason you feel so strongly about the change, even if it's not technical? It's not like I'm even saying it would necessarily be a good idea, just that I don't see why it couldn't or shouldn't be done.

---

<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:** [November 16, 2022, 4:05am UTC](https://internals.rust-lang.org/t/various-suggestions-empty-impls-empty-traits-struct-field-traits/17131/19 "2022-11-16T04:05:30Z")

</div>

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