---
title: "Design meeting 2025-06-25: Bevy"
tags: ["T-lang", "design-meeting", "minutes"]
date: 2025-06-25
discussion: https://rust-lang.zulipchat.com/#narrow/channel/410673-t-lang.2Fmeetings/topic/Design.20meeting.202025-06-25/
url: https://hackmd.io/pViLv1J4TuemPMuX4ohMbQ
---
# Bevy, Briefly
Bevy is a data-driven game engine that is implemented primarily as a Rust library crate. It uses the pattern of having a "façade" crate and many component crates.
It is based on the Entity-Component-System model, which simplifies a lot of game engine concerns because many basic optimization problems are already partially solved by the use of an optimized query system. The query system is implemented in Rust as a kind of type-driven DSL. A System, implementing game logic, might be added like this.
https://github.com/bevyengine/bevy/blob/e9418b3845c1ffc9624a3a4003bde66a2ad6566a/examples/games/breakout.rs#L68-L78
```rust
.add_systems(
FixedUpdate,
(
apply_velocity,
move_paddle,
check_for_collisions,
play_collision_sound,
)
// `chain`ing systems together runs them in order
.chain(),
)
```
The identifiers `apply_velocity` and `move_paddle` are functions. What a query will access is described by writing the function signature as a normal Rust function. Excerpt from the `alien_cake_addict.rs` example: https://github.com/bevyengine/bevy/blob/e9418b3845c1ffc9624a3a4003bde66a2ad6566a/examples/games/alien_cake_addict.rs#L199-L206
```rust=199
// control the game character
fn move_player(
mut commands: Commands,
keyboard_input: Res<ButtonInput<KeyCode>>,
mut game: ResMut<Game>,
mut transforms: Query<&mut Transform>,
time: Res<Time>,
) {
```
This is enabled by Bevy having **many** implementations on tuples.
**Many.**
## No, seriously, it's a lot of tuples
A key crate for Bevy is the [`variadics_please` ](https://github.com/bevyengine/variadics_please) proc-macro. It is a proc-macro which drives **other** macros, using the macro to implement something for every tuple that starts and stops within an arity range, such as e.g. `0..=15`.
Limitations on the arity range are worked around by implementing e.g. `Bundle` for tuple collections of `Bundle` types, allowing arbitrary recursive nesting.
This is partially a consequence of the fact Rust has
- not stabilized anything like the Tuple trait: https://github.com/rust-lang/rust/blob/a17780db7b8eebbf42a1cbe6bc9cc83013820ba5/library/core/src/marker.rs#L1064
- not exposed anything that would allow attempts to project the types and fields at certain indices of a tuple
- not explored reflection, neither CTFE or runtime, or "compile-time iteration" over a heterogenous list
- not stabilized implementing the `fn_traits`: https://github.com/rust-lang/rust/blob/a17780db7b8eebbf42a1cbe6bc9cc83013820ba5/src/doc/unstable-book/src/library-features/fn-traits.md
- nor, of course, allowed variadic generics
# New User Complaints
Bevy makes do with what it currently has, but that causes other problems. Because these implementations are sort of a rude hack, it creates unique documentation and diagnostic problems. The following is an attempt to deduplicate the new user complaints. The complete log, with some extra formatting to make it more readable, is available here: https://hackmd.io/KJdI6tyQTrm_sSreCghMpA
## Bad tuple errors
- it looks like a C++ template error just from sheer amount of text. That would definitely be cleaner with variadic generics (since there should just be one impl, instead of like 16), but there's no way to know which part of the resulting tuple is wrong anyway.
- **Note**: This sort of thing is actually mostly fixable in the compiler: https://github.com/rust-lang/rust/pull/142034
- no variadic generics, and the horrible error messages and limitations that produces. can be fixed in more ways than variadic traits. (e.g. having custom error messages for trait errors as a starting point)...
- **Note**: sometimes these tools, like `diagnostic::do_not_recommend`, can *inhibit* getting the best error messages for tuples: https://github.com/rust-lang/rust/issues/142961
- Variadic generics are the "I want to have tuples of arbitrary length in the type system" thing that Bevy fakes for queries and system parameters
**Note**: Yes, people really did keep on repeatedly mentioning variadic generics.
## struct update syntax and defaults
These directly interact with each other
- People get tripped up on field init shorthand when building bundles.
- `..default()` syntax is confusing and recursive.
- finding out a default value that is not documented in a comment is a pain.
- **Note**: `default_field_values`?
- public types could have a manual default impl instead of deriving, and it's hard to find the source if there are reexports
- lack of `const Default` is especially painful
- `..Default::default` was judged too long, leading to a shorter `..default()` custom function in Bevy's prelude
- this is still not much better
- leads to footgun with terrible error messages when recusive implementations are defined and the compiler does not detect the problem
- some large structs (`wgpu`) cannot be fully default-ed, but good default values exist for *most* fields
- default field values should fix this
- trailing commas after struct update syntax result in a frustrating compile error, and are commonly introduced via `rustfmt` while working
- can this be valid, but formatted out instead?
Note that Bevy has taken fairly drastic steps to reduce the usage of struct update syntax because of these limitations:
- required components, which implicit glob on other components via macro magic
- bsn!: an ambitious, macro/file syntax for scene building that diverges from the design choices around explicit default values
## orphan rules
- Orphan rules come up a lot with Component/Resource/Event/Reflect derives on third-party types.
- As the ecosystem has matured, Reflect is by far the most painful, because external components are rare and wrapper types work fine for them
- There is a desire to possibly have a "remote Derive" of some kind.
- hacky version with transmutes has been implemented for reflection, copying serde
## dyn compatibility
- dyn compatibility rules can be annoying when you've already made your trait and now you need it to be dyn.
- Especially when users learn about trait objects and want to use it with Component and stuff.
- doesn't come up directly, but when users start playing with trait objects there's a very harsh and confusing wall
- [Refactors for dyn-compatibility](https://github.com/bevyengine/bevy/pull/19491) can be both complex and controversial
**Note**: This seems self-inflicted? We haven't spent the time on trying to figure out how to make more traits with newer features be dyn compatible, when they could be, because we've spent that time pushing further on other things. So it gets harder to use `dyn` as we add more things to traits without deliberately making them compatible with `dyn`.
## Newtypes (OR: PhantomData is annoyingly unergonomic)
- Lack of perfect derive runs into the standard problem: If you derive Clone on a type that contains a PhantomData, but the generic `T` doesn't implement Clone, then you get an overconstrained Clone.
- Tuple structs work, but spamming .0 everywhere is not new-user friendly.
- there ought to be a Deref trait (or some other solution) with the right semantics for newtyping.
- **Note**: Bevy currently has a `#[derive(Deref)]`, but the implementation is deliberately limited to one element structs/tuple structs.
- Rust doesn't allow you to have a generic type parameter on a struct that is unused. which means that if you want to have, say, marker components or system sets that are parameterized by a type, you cant do that easily. for example, in my game, i have two types that i use to represent coordinates: Hex and Sq, and a trait that lets me make game logic that is agnostic to the map topology. I want to write systems like:
```rust
fn my_game_mechanic<C: Coord>(
q_tile: Query<(&TileCoord<C>, &Stuff)>,
)
```
and then add two instances of that system, for each coord type. Ideally with run conditions, so that only the correct variant runs, depending on the map type:
```rust
app.add_systems(Update,
my_game_mechanic::<Hex>.run_if(map_topology::<Hex>),
my_game_mechanic::<Sq>.run_if(map_topology::<Sq>),
);
```
But if I want to create a system set, I can't do that easily:
```rust
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct MapTopologySet<C: Coord>;
```
doesn't work, because the `C` type parameter is unused. I have to add a phantom data into the struct, which makes it very annoying/ugly/boilerplatey to use. Same if I want to create a component type that I want to parameterize, so it can behave differently (by using associated functions in the Coord trait) in systems depending on the map topology. I want to be able to just write this:
```rust
#[derive(Component)]
struct TileExplosionAnimation<C: Coord>;
```
**Note**: This runs up against variance: the way the `PhantomData` describes the `T`... is it actually `&U` or `*mut U`, for instance... would determine the variance.
The `phantom_variance_markers` feature would significantly improve this.
## lifetimes
Bevy is *very* light on user-facing lifetimes (well, ones they need to think about) for a framework of its size. This is a mixed blessing for user comprehension: fewer hurdles, less practice.
lifetimes: passing system param to functions can be confusing.
- system params in generic and associated types make it hard to know where to put your lifetimes. and aside from being worse performance, cloning is not always possible, so lifetimes can't always be avoided.
- trying to use lifetimes introduces constraints that I end up spending more time trying to work around when my requirements change at all. and the inference can be wrong; when it's wrong it will be stricter than it has to be / pessimistic about the lifetime of the return value.
## closures
- learning closure rules when things are captured by reference vs moving/copying. It feels very opaque what is a reference vs what is owned.
- reborrowing, and all the general papercuts around referencing/dereferencing stuff esp around "smart pointer" types like Mut and Res/ResMut
## build woes
Most of these are more a matter for the compiler team, but can be hard to pursue in tandem with other lang asks.
- target folder bloat is an unfortunate and unfortunately-well-known problem.
- rust-analyzer doesn't by-default use a different build directory, but doing that would bloat the target folder more.
- sufficiently problematic that "use a ramdisk and redo everything every time" can be preferable to cleanup.
- using dynamic linking with bevy is common for speeding up iterations, but leads to weird errors when updating libs/rust.
## docs can be difficult to read
- cargo features aren't clearly listed in rustdoc
- are there any resources on how to *use* docs.rs and rust analyzer to discover APIs that might solve your current problem? just knowing how to "read the docs" is tricky for new users.
- the Rust Book itself isn't very approachable for new programmers.
- It's a good intro for intermediate-to-advanced coders, but there's some indication that it isn't really structured in a way that lets new coders get up to minimum proficiency.
- As an example, people sometimes seem to get stuck on the stack and heap in the ownership section, and fail to progress to data structures.
- Bevy would fix this, but the Rust Book is effectively closed to community contributions.
- finding implementers of a Trait across multiple crates can be hard.things like "what's all the Components in my project, across all dependencies". even with just Bevy itself, while docs.rs does show all implementors, it can be hard to read things like repeating "impl Plugin for" over and over, making it difficult to skim.
- ideally i think this could be a R-A feature: a easily accessible table of all implementors which allows for searching and filtering them
- most people dont know that they can build offline docs that are exactly like docs.rs but better because they include their whole deps tree and everything in the docs is perfectly connected. they tend to be very surprised/impressed when they learn from a more experienced dev.
- people get very confused around Traits and how they are rendered in API docs. it is often very difficult to figure out, say, what methods are available on a type, when you have things coming from many different traits. this is a big problem with bevy, because the bevy_ecs and bevy_app apis are very trait-heavy.
- One report: "i know how to navigate the api docs' trait listings to try to build a mental image of what types provide what apis via what traits, but i admit this is a very specific skill i have gained with a lot of rust experience, and to new rust users the experience seems very very arcane. and due to the lack of variadic generics, many of our docs are polluted with bogus impls of a trait for every possible tuple up to some arbitrary length, so you have to mentally filter out all that noise."
**Note:** Yes, that really was another mention of variadic generics.
**Already addressed**:
- lack of docs.rs support for examples
- Being able to view source on re-exported items in docs.rs would be so useful
---
# Discussion
## Attendance
- People: TC, Tomas, Jubilee, Alice Cecile, eholk, Miles (@nth), Urgau, Chris B, Josh, Tyler Mandry
## Meeting roles
- Driver: TC
- Minutes: Tomas
## initial remarks
Alice: The two biggest things we care about are variadic generics and reflection.
TC: What do you see the outcomes of the meeting and how you'd like to focus the meeting?
Alice: I'd like to focus on the small issues. The lang team knows we want variadic generics and reflection. But the potentially more approchable smaller changes might be something with impact and possibly having flown under radar.
Josh: Variadic generics and reflection are two big issues that mean different things for different people. It would be good to narrow the scope and make sure you understand what *you* want. What small subsets might help 90% of your case?
Alice: Regarding variable generics, the main thing is being able to implement a trait over a tuple where all its elements implement this trait. For that we'll need variadic generics and variadic tuples as arguments. Fundamentally, the same thing you see in the standard library for Default.
Jubilee: `std::marker::Tuple`. We use it as the argument bound for Fn, FnMut and FnOnce. It's a bound that can be used by the compiler. Hypothetically could be by anyone, but you can't use it to figure out what's inside.
https://doc.rust-lang.org/std/marker/trait.Tuple.html
Tyler: Getting a `Tuple` trait seems easier to me than getting variadic generics throughout the compiler. If that's the MVP you need to express these patterns, I'd be interested to explore that direction.
Josh: Does Bevy have much use of `dyn Trait` to solve some of these problems? E.g. you have a tuple that every element implements a trait. You can't turn that into an array. But in theory you could take the tuple, iterate over that and get a `&dyn Trait`. Would that help?
Alice: Bevy would definitely find a way to abuse this, but it won't immediately unblock us.
Alice: We're commonly making our own vtables.
Josh: Would having some stable concept of "assemble this `dyn` out of a vtable help you"?
Alice: Probably not to solve any of the core issues, but we could use it.
Josh: We have talked about being able to create a dyn trait out of function pointers, for which there's no non-dyn version of the trait.
Alice: Regarding reflection: Bevy doesn't use reflection for the core ECS. But what it does use reflection for: other features a game engine might: Serialization and Deserialization in a fairly generic way. For networking and scenes we want the concept of "what's the shape of this thing?". And the other is for developer tools (live inspection of values, automatically generating UI, animation of arbitrary values). We're using Rust's current stable reflection capabilities (type ID etc.) -- we use that inside ECS for type-based memory storage. The ability to implement dynamic types in Rust. We're storing types as bytes in an unstructured data store and then extract them.
Josh: Are you familiar with the field projection and the `Field` trait that proposes?
Alice: I've not been following that.
Josh: May be worth looking at the field projection RFC. If you know that every field of the data structure implements a particular type, in theory you could walk over every field and get its dyn implementation for every trait.
Alice: There's a lot of "life before main" stuff that we could do. Better ability to introspect the program would be nice.
Josh: And that's not something you could do with `[bevy::main]` stuff?
Alice: We could, but we'd rather not due to ergonomics etc.
Scott: What about the distributed-slice library? I was curious what sort of reasonable restrictions you'd be able to live with in things like this? e.g. "in this crate" without supporting cross-crate?
Alice: We need to have a life before main solution that works for every Bevy implementing crate that you pull into your project. We use it for type registration. If it doesn't work reliably, authors will stop registering their stuff, because it doesn't work reliably.
Scott: Running code before main has a lot of complications. Would it be okay if you were to register the crates you were using?
Alice: Those sorts of compromises seem fine but I don't think I'm the best person to make the decision on this. We just want a list of types we can access without having to go and manually registering all the times that everyone defines.
Tyler: Back to reflection, the Facet crate. Sounds like it's doing something similar. Would that help? Also, what are all the kinds of information you need?
https://crates.io/crates/facet
Alice: So far we've looked at it a bit. It seems very promising as a reflection solution. We have a functional solution, this is very new so we're holding off for now. One of our main issues is the orphan rules and how this makes seismic ecosystem changes. People say "I wish reflect would be implemented on this random crate". And we have to petition author, add another junk trait implementation in our code or do a remote reflection.
Alice: Not sure it meets our needs -- we haven't made a full evaluation yet.
Tyler: The remote Derive makes sense. It's hard to actually implement (we'd have to save the AST of every type). Haven't figured out how to surface it best, hard to scope out an implementation.
Josh: Re reflection & distributed-slice. These things potentially interact. A lot of the distributed slices we won't have to scope them to a specific crate. We could scope the crates that use this together as long as the crates are cooperating and working with the slice mechanism (and if we can ignore dynamic loading).
Josh: The orphan rule has been a limitation on remote Derives. If what you're doing is filling in information in a distributed slice somehow, you could fill it ?? and then deduplicate the distributed slice. It's not completely ridiculous to save off an AST and use it later.
Josh: Right now we're spending a lot of things on reflection and variadic generics. Let's go through a bunch of the little ones next?
Tyler: If the main things are variadic generics and reflection, I'd love to know exactly what they need -- maybe not in this meeting. What exactly does reflection mean?
Miles: There are some reflection subject matter experts that aren't here. So yes to a follow-up discussion.
Josh: Proposed next steps: 2 follow-up meetings: for variadic generics and reflection. And pull specific folks (e.g. oli for variadic generics ). Get a couple side meeting started (hint hint Tomas).
Jubilee: const Default -- why that in particular?
Alice: In gamedev you often define const stuff (here's my text style, how much life an enemy has). You can't use struct update syntax to define those, const default really bites us there.
Josh: That we should hopefully have a solution for soon: field defaults and we're actively working on const Traits.
Alice: Both of those would end up helpful here.
Jubilee: Did we add the ability for default values to add Default on random things?
Tyler: That requires const traits.
## field init shorthand
> - People get tripped up on field init shorthand when building bundles.
Josh: Tripped up how?
## Struct update syntax
> - trailing commas after struct update syntax result in a frustrating compile error, and are commonly introduced via `rustfmt` while working
> - can this be valid, but formatted out instead?
Josh: This seems like something we should fix in `rustfmt`, to not introduce the trailing comma?
Jubilee: Well, the problem is that the syntax doesn't parse, right? Oh, I see.
scottmcm: Agreed that this sounds like a rustfmt problem. We should have a nice structured suggestion for it so it's trivial to fix, but it shouldn't be legal. (There's a ton of stuff like "oh I put a `;` in my struct instead of a `,`" that we *could* make legal and format out, but I continue to think it's far better to have those things be error-with-structured-suggestion instead of allowing more things in the parser.)
Alice: The way it works is you end up with partially invalid code, you run rustfmt on it and it footguns you. I'll reproduce it, create an issue, cc the lang team.
Jubilee: Not entirely sure why we don't accept the comma in this situation. A big issue with gamedev is the iteration speed and how quickly you can change things. Rust is great in that you can have static modification of things and you know it'll work.
Scott: This is a parser problem so this should be detected instantaneously.
Alice: You don't even get a suggestion in the editor.
Jubilee: Why do we nitpick over this comma?
Scott: That's because the `..` is not part of a list (which is where we do trailing commas).
Josh: Yes, and in this case the `..` must be the last thing and nothing can come after it. But it seems somehow this is getting introduce and once that happens, all the tools break and they can't rustfmt on save and a ton of errors happen.
Alice: Yes and then from this one typo you have 30 errors emanating from it.
Josh: I've ran into something like that too where there's one error that's helpful and then a ton of other errors that all cascade from that. Wonder if we can mark some errors that are likely to blow up (and in reverse would fix all the other errors).
Josh: Actually could we just do fallback parsing here? So this won't cause all the other errors?
Alice: This is something I see pretty regularly and it trips up the newcommers a lot.
Tyler: Filing an issue for this is the way to go. I also think rustfmt should just fix it for you. Even if it's not valid Rust it's pretty obvious what you've meant.
## Why fight the language?
TC: In a number of these cases, it seems that Bevy has chosen to not use the solutions that other projects tend to use for these problems, e.g. leaning on builder patterns. It's OK to do things differently of course, but I'm curious about why Bevy has chosen to go this direction.
Jubilee: The problem is that these involve user-defined types, often. It's not necessarily easy to prescribe "hey, every Rust gamedev ever, go use builder patterns!" These are problems people encounter with the language *because they use Bevy*, but they don't always derive from Bevy.
...granted, anything that's soluble by variadic generics in particular is almost definitely a quirk of Bevy's design choices.
---
TC: What is the motivation for not using the common solutions for this?
Miles: Hard to give a generic answer. For the builder pattern: two key reasons. First, we have this scene format that involves reflecting and parsing very rust-like structs. And we don't want to have a turring-complete scene language. We just want data. A lot of Bevy is designed around imputting data as Rust struct. And second, it's a design pattern we'd be imposing on our users. And it's a pattern taht in many ways is more strict.
Miles: Games are really different than most apps.
Alice: The reason is about codegen and API bloat -- especially around documentation. We might have 20 fields and if we have 20 builder methods, it's much harded to see this in the docs.
Josh: I love that Bevy is pushing the boundary of what's possible with Rust. We have an incredibly hard time getting people to try out unstable features, unstable convenience features. It's hard to get people to try what's possible. It's great what Bevy is doing this. This is a healthy pattern of seeing how things can be done better.
Jubilee: I do think Bevy pushes the language a lot. But to a certain degree, the way in which Bevy uses things like struct default, that's more how the language wants you to do it. But then everyone looks at that, realises it might have problems and then does something else. Starting with the struct update syntax is something we've worked hard on supporting.
Jubilee: Especially in games in particular, you don't need values to agree with each other.
TC: One of the things that comes up in language design all the time is that you never see the programs that aren't written because you didn't add a certain feature. You never see the missed opportunities. What Bevy does is helpful in that respect, and what I'd like to see is to take pieces of it and turn those into experience reports. Here's why we do it this way, here's how Rust would typically do it, here are the pros and cons. That'll be what is needed in any case to make a compelling RFC.
Tyler: +1 to the experience reports idea. Bevy has been through a lot of breaking API changes, tried a lot of things a lot of different ways. Bevy is really well positioned to do this.
## The Rust Book
Alice: The Rust book assumes you're a C or Ruby programmer. A lot of our users are either coming from like C# or new to programming at all. The book's linked very prominently, it's in a permanent place where it's not accepting any external contributions.
TC: They publish this in paperback, so they have certain understandable constraints, e.g. on containing authorship. But the concerns you raised are also a challenge.
Josh: We've had some conversations in other circles of what it would be like to teach Rust as the first programming language. And it makes total sense that Bevy would see this. I'd love to see a "complete beginners" thing. That's not going to be the Rust book. Maybe we need a new book. The content of the book is freely licensed and could be fully copied.
Tyler: Thanks for raising this. Really helpful to be aware of this.
Alice: People who are new to programming and want to use Bevy for games. They're not beginners in the traditional things. A lot are professional in other areas: level design etc. This is a very pressing need to onboarding professionals for us.
Josh: I do think it's a problem that the book is so prominent and closed to community contributions. But the book has had new authors added. It seems at least worth asking whether for the next edition of the books they'd bring on another author that's open to beginners.
Alice: Given the history, I'm not sure this is going to be time well spent for me.
Josh: Maybe then it's worth building a fork.
Chris: I do a bunch of beginner Rust content. I do think a truly beginner document needs to be a separate project from the Rust Book. The Book is focused on one audience and the people we talk about are a completely different audience.
Miles: I want to second that. There should be more beginner resources and they should be separate. Projects like Gleam and Python have a lot of beginner resources that are tailored to specific backgrounds (here's how you pick Gleam if you're a Rust dev).
TC: We also have Rustlings and Rust by Example.
Miles: those are fantastic.
Alice: Those are very popular and we'll be exploring Rustlings for learning Bevy.
Tyler: There a role for two things: start an external team outside of Rust startting building resources. But I think eventually it makes sense to converge and have an official resources maintained by the Rust project. Long tearm, I'd love to do some experimentation but then have some resources maintained by the Rust project (or endorsed by the Rust project).
TC: I propose considering a project goal.
Josh: Yes and: things that shouldn't get lost: follow-up on reflection, follow-up on variadic generics. Make sure the little details (rustfmt/rust handling the comma). Tomas to follow-up.
Tyler: Agreed on goals
Josh: We ended up a bi-weekly meeting with Rust for Linux. Largely beneficial for the language but also for the RfL project. Having a meeting (say monthly) would be very beneficial to Rust -- things new users run into, any changes that might happen.
Alice: I'm down for that. Also it should be broader than just Bevy + Lang.
*Tomas to set this up.*
---
TC: Who are you working with on the Rust Foundation on this?
Alice: Joel Marcey. I have a meeting with him in a week and a half.
Josh: Hit me up for target platform etc.
TC: What kind of support are you looking for from the Foundation?
Alice: Neutral ground to host all the code. Neutral outside of Bevy -- shared across the Rust Gamedev ecosystem.
Alice: The other thing: access to legal acces arounds NDAs, what can be shared etc. Hard for the indie and open source to navigate.
Alice: Funding.
Josh: Bevy has a lot of great interaction with new users. I wouldn't object to having more peolpe but I don't want to hold it up on getting more folks involved.
Alice: Agreed. In Rust gamedev more broadly. The folks not using Bevy are experienced programmers who want to work on more things. They're experienced enough who know what they want. People who are new to Rust / new to programming it's overwhelmingly bevy.
Alice: From the Bevy side -- we'd like to avoid the perception of the special treatment to the most degree possible. The Rust Foundation working closely with Bevy would only cause harm.
Josh: Which Rust game engine projects out there are still alive, actively maintained?
Alice: Bevy, Fyrox (feature complete, struggling to find momentum), Void.dev (well-funded, closed so far), Marcoquad exists but on life support, Veloren (game project with their own engine, large healthy open source project), Godot with Rust bindings.
Jubilee: We should talk to whoever's maintaining the latest SDL bindings.
Alice: A thing that overwhelmingly holds commercial use of Rust for games (and companies' adoption), it's the perception you can't ship Rust games on consoles.
(The meeting ended here.)
---
## Orphan rules and remote derive
Josh: Very interested in this, particularly in adding some kind of standalone derive statement (e.g. `derive(X) for Type;`).
## `dyn` compatibility
Josh: Some of the work we have in progress would allow "universal" `dyn` compatibility. What do Bevy folks think of the `Init` trait proposal, and its use for being able to make more traits `dyn`-compatible?
Jubilee: Can you link the particular `Init` trait proposal you are thinking of? I saw a few revisions fly around lately.
Miles: It might be nice to be able to enforce that a trait should be dyn compat. I'd propose something like `trait MyTrait: MustBeDyn` but obviously sub-traits don't work that way. A lint would also be useful here.
eholk: I saw `#[repr(dyn)]` proposed recently as a way of saying "this trait must be dyn-safe." I think some version of this makes sense.
Miles: That would be perfect.
## `derive(Deref)`
> - **Note**: Bevy currently has a `#[derive(Deref)]`, but the implementation is deliberately limited to one element structs/tuple structs.
Josh: This seems worth adding, with that limitation.
scottmcm: I wonder if we should change `repr(transparent)` (over an edition, I guess?) to be stricter and say that it's always, maybe, the last field that's the non-1ZST? Then deriving it can always go to that field that's the interesting one, and we could plausibly give better errors about 1ZST-ness too.
Jubilee: :thinking_face: Why the last and not the first?
## Reborrowing
> - reborrowing, and all the general papercuts around referencing/dereferencing stuff esp around "smart pointer" types like Mut and Res/ResMut
Josh: Does the current in-progress smart-pointer stuff help with this? And, does the proposal for a trait for reborrowing help with the first part?
Jubilee: The main question is whether we can get to not requiring `mut arg: MutRefType` when `arg: &mut Type` is required. Because whenever you refactor between those two, it can be soul-crushing. Arguably it would even be better to have to use `mut arg: &mut Type`, from the perspective of "using Bevy", even though that would make the language less ergonomic overall, because then you would not encounter that soul-crushing refactor from converting to/from the "privileged" reborrowing type. **As far as I'm aware, the current "smart pointer" stuff does not fix this, but I haven't followed it that closely.** We'd need additional work for reborrowing.
## New-programmer documentation
> - the Rust Book itself isn't very approachable for new programmers.
> - It's a good intro for intermediate-to-advanced coders, but there's some indication that it isn't really structured in a way that lets new coders get up to minimum proficiency.
> - As an example, people sometimes seem to get stuck on the stack and heap in the ownership section, and fail to progress to data structures.
> - Bevy would fix this, but the Rust Book is effectively closed to community contributions.
Josh: Not speaking for anyone else, but I'd love to see documentation targeted at brand new developers, which was written by the Bevy folks. (Possibly with substantial material taken from other documentation.) The quality of Bevy's community-facing work is extraordinary, and we do have a gap here. Would be great to talk further about this, though possibly not in this meeting.
Miles: Personally I think there's a lot of interest in our community for writing this sort of thing.
## How to tame the tuples
tmandry: Which of these would individually make things much better, if any? Something like the `Tuple` trait sounds easier to do than supporting variadics throughout the compiler.
> This is partially a consequence of the fact Rust has
> - not stabilized anything like the Tuple trait: https://github.com/rust-lang/rust/blob/a17780db7b8eebbf42a1cbe6bc9cc83013820ba5/library/core/src/marker.rs#L1064
> - not exposed anything that would allow attempts to project the types and fields at certain indices of a tuple
> - not explored reflection, neither CTFE or runtime, or "compile-time iteration" over a heterogenous list
> - not stabilized implementing the `fn_traits`: https://github.com/rust-lang/rust/blob/a17780db7b8eebbf42a1cbe6bc9cc83013820ba5/src/doc/unstable-book/src/library-features/fn-traits.md
> - nor, of course, allowed variadic generics
Josh: I also think some of the work Oli has proposed might address this.
Jubilee: I think to make this maximally useful, we'd need to also have some way, for a `T: Tuple` bound, to express the bound that applies to `T.0`, `T.1`, etc.
Jubilee: I know for projecting the *value*, "const reflection" is a thing that oli is looking at.
## Prioritizing the new user issues
tmandry: I think we would benefit from a stack ranking of the new user issues, or really just the top 1 or 2. Many of these are known, and it's useful to know when and where they come up, but we can't address all of them at once.
## Project goals
tmandry: I think we can turn this discussion into some project goals – but those would need individual people to drive them. Is anyone in the Bevy community interested in driving Rust features upstream?