I have been developping a game in Rust on my free time for almost a year now, and I have written several libraries. During this time, I have encountered lots of problems with Rust and its ecosystem.

Usually when I have a problem I try to fix it myself (or at least open an issue), but after this post I thought that I’d share everything I encountered. Some things are more related to the needs of my own projects while some others apply to gamedev as a whole, but I didn’t include anything really specific to my game.

Two things to note:

None of these are critical. They are all only missed optimisations, things that are annoying to use, things that can be bypass by hacks or with C libraries, etc.

I didn’t mention obvious things such as HKTs, plugins or cargo install. I think that these features would be awesome to have (especially plugins, I don’t think people realize how plugins are a total game-changer), but I don’t want to overload the list.

So here we go.

No way to store a borrower and a borrowed in the same struct. See this link for more infos.

There is no easy way to cast between (f32, f32, f32) and [f32; 3] (for vectors, matrices, etc.). This causes problems of interoperability between functions/libraries that use the former and functions/libraries that use the latter.

Fixed-size arrays are missing traits. For example you can’t call .clone() on a [u8; 50] . Fixed-size arrays are just too annoying to use right now because of the traits that aren’t implemented on them. This means that I have to use a Vec and lose some data locality.

Unsized types do not implement Copy . I want to create my own Box -like type but that stores the data in video memory. Since this is video memory, I need to restrict the content to Copy types. But if I write struct Buffer<T: ?Sized + Copy> , then I can’t use Buffer<[u8]> because [u8] isn’t Copy .

There’s no way to build unsized structs. If you take for example struct Foo { val1: f32, rest: [u8] } , there’s just no way to build it. Not even with mem::uninitialized .

Even if you want to allocate space for an unsized struct, it is too hard to build a pointer to it. Even if you manually allocate some memory to store an unsized struct (like Foo in the previous point), the only way to build a *mut Foo or a &Foo is to transmute from a (usize, usize) . Oh and if you do it with an unsized enum or a trait object, you will get a segfault. Right now there’s no way to combine unsized structs and safety.

No write-only references. Some low-level APIs forbid you from reading from pointers they give to you, and if you do your program can get killed by the O/S. This can happen for example when mapping video memory. Currently the only way to provide a safe wrapper around such a pointer is to provide only setters and no getters. But this is a crappy solution in terms of usability and it comes with a performance cost.

Loading symbols at runtime from a non-Rust shared library is too hard. Some time ago glutin switched from linking to xlib at compile-time to using dlopen to load it (in order to handle systems that don’t have xlib). The current solution works using some hacky macros.

There’s no min! and max! macro. You need to write max(max(max(max(max(max, a), b), c), d), e) for example. I have a code with 15 max like this.

No way to detect at compile-time whether we are in the main thread. This one is a bit weird, but on OS/X some GUI operations can only be done in the main thread. It would be nicer if this was detectable at compile-time.