Skip to content

Conversation

tomassedovic
Copy link
Contributor

@tomassedovic tomassedovic commented Sep 1, 2025


I am the [facilitator of the selection process](https://github.com/rust-lang/leadership-council/blob/main/policies/project-directorship/election-process.md#setup) this time around. That means I've authored the blog post above, proposed the timeline, and I'll seek out consent and statements from the nominees. I've also announced the election on zulip as well as an email that should reach all Project members and I'll see it all through, including facilitating the actual election process.

## Bevy/gamedev followup
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alice-i-cecile & @PROMETHIA-27: I've tried to add more context to the reflection & variadic generics fatures for folks who aren't as familiar with them.

Will you have time for a quick check to make sure this actually makes sense from Bevy perspective?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variadic generics section looks accurate; but I noticed the reflection section doesn't mention bevy_reflect which is the crate where most of bevy's reflection-like capabilities are implemented. #[derive(Reflect)] generates a lot of code related to reflection, #[derive(Component)] tends to generate very little.

Other than that, these sections make sense to me.


This happened with little intervention on my part, but I made sure that the Bevy folks were aware (they were!) and I'll be keeping an eye on this to help move it forward and be on the lookout for other projects that may find this useful.

### Variadic Generics
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PoignardAzur this talks about variadic generics. If you have a bit of time, would you mind checking whether it's accurate and/or suggest improvements please?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The technical side is accurate.

I do want to note that I haven't actually committed to writing an RFC, and while I'd like to and probably will, I haven't even started setting time aside for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry for misunderstanding. I'll update that part out not to put you on the spot.


This is now ready for feedback from the Lang team so I've opened a [design issue](https://github.com/rust-lang/lang-team/issues/347) and got it scheduled for review and discussion.

### Field projections
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BennoLossin I'm trying to add some context around field projections for readers who aren't familiar or don't know why it would be useful. Would you please double-check this makes sense and/or suggest improvements please?

Copy link

@BennoLossin BennoLossin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good! Thanks for taking the time to add this & letting me know.

I left some suggestions, if you need more specific ones or more information, let me know.


[field-projections]: https://rust-lang.github.io/rust-project-goals/2025h2/field-projections.html

We also had a design meeting on [Field Projections][field-projections]. When you have a type behind e.g. `Box` or `Rc`, you can access its field "directly" as if the wrapper/pointer type wasn't there:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say it's better to have an example using references &/&mut, since that's the more fundamental type. They also already have field projections built into the language, where Box and Rc do not.


This is so common that we take it for granted, but when you write `boxed.x`, we first need to dereference `boxed` (follow the pointer to the `Position` struct in the memory) and then get its `x` field.

And while this works for references and some pointer types, there's a long list of wrapper types where field access makes sense but it's not implemented because the semantics or limitations are different from the regular `Deref/DerefMut` traits. For example: `MaybeUninit<T>`, `Pin<T>`, `Cell<T>`, or the raw pointers `*const T`/`*mut T`. And of course custom types.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend using Pin<P> to differentiate it from the others that use T (since you always wrap a pointer type in Pin and never a T directly).

}
```

This is so common that we take it for granted, but when you write `boxed.x`, we first need to dereference `boxed` (follow the pointer to the `Position` struct in the memory) and then get its `x` field.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use the reference example, so for example:

struct Position {
    x: f32,
    y: f32,
}

impl Position {
    fn get_x(&self) -> &f32 {
        &self.x
    }
}

Then you don't get a dereference operation, instead it's only a pointer offset.


And while this works for references and some pointer types, there's a long list of wrapper types where field access makes sense but it's not implemented because the semantics or limitations are different from the regular `Deref/DerefMut` traits. For example: `MaybeUninit<T>`, `Pin<T>`, `Cell<T>`, or the raw pointers `*const T`/`*mut T`. And of course custom types.

Linux uses pinned values (`Pin<T>`, values that can't move around in memory) all over the place and there are several crates that provide access to the underlying fields of a pinned struct (e.g. [pin-project](https://crates.io/crates/pin-project)).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While Pin<P> is a primary part of the motivation behind field projections, it's mostly being handled by the pin_ergonomics effort by @traviscross. (we still should support it of course, since custom types also might want to have the same behavior as Pin<&mut T>) But IIUC, TC wants to make Pin<&mut T> special in the language and so it would provide its own field projections (like & and &mut already have today). This doesn't make it any less important though. But for this part you could just change it to "Linux uses lot's of pinned values, raw pointers and MaybeUninit in addition to many custom types that could benefit a lot from field projections.".


Reflection is a mechanism that lets your program look at any type and understand it: getting its name, fields and *their names and types* while your program is running. This is in contrast to the `derive` macro or trait bounds that are processed at compile time.

Projects like Bevy currently rely on the `derive` macros. For example, any component in its [ECS (Entity Component System)](https://bevy.org/learn/quick-start/getting-started/ecs/) must be annotated with `#[derive(Component)]`. While the usage is simple, these macros are difficult to write and debug. And the language has limitations on where they can be applied.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seconding Promethia's critique of this section. Component impls are extremely simple, and we could comfortably move to a macro-free design (either via blanket or manual impls) if we had to. Instead, the code generation occurs inside of the Reflect derive, from bevy_reflect. This derive is optional, but allows people to do interesting things for tooling and serialization, so it's present on virtually all of our data types.

bevy_reflect is also fully decoupled from the rest of Bevy as an ECS or game engine. We even have a few users just using it :)

The sections below on the pain of the orphan rule all still basically ring true if you replace Component with Reflect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'll get that sorted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants