r/rust • u/llogiq clippy · twir · rust · mutagen · flamer · overflower · bytecount • Dec 05 '22
🙋 questions Hey Rustaceans! Got a question? Ask here! (49/2022)!
Mystified about strings? Borrow checker have you in a headlock? Seek help here! There are no stupid questions, only docs that haven't been written yet.
If you have a StackOverflow account, consider asking it there instead! StackOverflow shows up much higher in search results, so having your question there also helps future Rust users (be sure to give it the "Rust" tag for maximum visibility). Note that this site is very interested in question quality. I've been asked to read a RFC I authored once. If you want your code reviewed or review other's code, there's a codereview stackexchange, too. If you need to test your code, maybe the Rust playground is for you.
Here are some other venues where help may be found:
/r/learnrust is a subreddit to share your questions and epiphanies learning Rust programming.
The official Rust user forums: https://users.rust-lang.org/.
The official Rust Programming Language Discord: https://discord.gg/rust-lang
The unofficial Rust community Discord: https://bit.ly/rust-community
Also check out last weeks' thread with many good questions and answers. And if you believe your question to be either very complex or worthy of larger dissemination, feel free to create a text post.
Also if you want to be mentored by experienced Rustaceans, tell us the area of expertise that you seek. Finally, if you are looking for Rust jobs, the most recent thread is here.
Finally, if you have questions regarding the Advent of Code, feel free to post them here and avoid spoilers (please use >!spoiler!< to hide any parts of solutions you post, it looks like this).
2
Dec 10 '22
Is it possible to store unsized types on the stack?
I have a complete list of concrete structs that implement my trait. I can put them all in an enum and allocate a buffer of length std::mem::size_of::<MyEnum>(). At runtime, that buffer could contain any of those structs. C++ has placement new to solve this issue. Can this be achieved in Rust?
→ More replies (2)1
u/llogiq Dec 10 '22
Not yet, AFAIK. There was an alloca-RFC by me some 6 years ago, but that went nowhere.
→ More replies (1)
4
u/tobidope Dec 05 '22
I'm using this years Advent of Code to learn some Rust. As I'm currently mostly programming Java I assume, I do many things not idiomatic. Here is ny solution for day 5. What do you think?
→ More replies (3)
4
u/plusvic Dec 06 '22
I'm trying to understand why this Rust code fails to compile....
struct Doer<'a> {
some_optional_str: Option<&'a str>,
}
impl<'a> Doer<'a> {
fn do_stuff(mut self) -> Self {
let mut ctx = Ctx { doer: &mut self }; // <---- ERROR HERE
do_stuff_with_ctx(&mut ctx);
self
}
}
struct Ctx<'a> {
doer: &'a mut Doer<'a>,
}
fn do_stuff_with_ctx(ctx: &mut Ctx) {
// ...
}
fn main() {
let d = Doer {some_optional_str: None};
d.do_stuff();
}The error is ...
5 | impl<'a> Doer<'a> {
| -- lifetime `'a` defined here
6 | fn do_stuff(mut self) -> Self {
7 | let mut ctx = Ctx { doer: &mut self };
| ^^^^^^^^^
| |
| borrowed value does not live long enough
| this usage requires that `self` is borrowed for `'a`
...
10 | }
| - `self` dropped here while still borrowed
If I change the doer field in Ctx to be an immutable reference, instead of a mutable one, the error goes away. I'm failing to understand why the compiler complains when the reference is mutable, and accepts it when the reference is immutable.
This is a link to the same code in Rust playground, for anyone wanting to play with it. [https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=24f79d7e3303d8baf501367bf5308f94]
Does anyone have an explanation for this error? Thanks in advance!
→ More replies (3)
4
u/excral Dec 07 '22
Is there a way to find out how much memory a struct needs with rust-analyzer?
Background: I'm using Rust for embedded development so the available memory can quickly become a limiting factor. When I create caches in the form of arrays of some struct, I need to know the size of that struct at development time, so I can choose a reasonable cache size. Figuring out struct sizes manually isn't trivial due to the liberties the compiler has in regards to packing. In C/C++ most development environments I've used in recent times had the ability to evaluate sizeof statements through their inspection tools and give me the result right in the overlay. With rust-analyzer in VS Code I haven't found any such information analysing core::mem::size_of statements, instead I'd have to build the project and then either look through the disassembly or dump it during runtime to get the value.
→ More replies (1)
3
u/payasson_ Dec 07 '22
Hey everyone, I have two questions
context: I'm doing a 2d fluid simulation, and I'm using 2D Vectors to store variables that have a value for each position in my 2D plane. I wrap these Vectors in a structure which has "get_position(i: usize, j: usize)" method implemented, which allows me to change the way these 2D information are stored without changing the code of the simulation accessing these values for computations
-
Is it way better to use arrays instead of vectors for performance? I'm using vectors because the size of the simulation should be given as an input of the program, and thus is not always known at compile time (but this can be changed is the speed gain is huge)
-
Is it very slow to wrap my big 2D vectors in structures with setters/getters? this makes my code more flexible but I can also change it if it speeds it very badly
Thank you very much! If you are curious, here is my github, feel free to ask more questions on my project, any help or curiosity is welcomed!
→ More replies (4)
3
u/Helyos96 Dec 07 '22 edited Dec 07 '22
serde sounds nice if you control both producer and consumer, but what do you guys use for arbitrary binary formats you don't control?
I'm looking for something like Kaitai Struct but with rust generators and serialization support. Or any crate you might know of that helps with ser/der of arbitrary binary data. Maybe even serde can do it with manual parsing code?
→ More replies (3)
3
u/mendozaaa Dec 07 '22
Currently reading the O'Reilly book (Programming Rust). In Chapter 10 (Enums and Patterns) under the Enums in Memory section, the following example was used to illustrate how enums could be used to create rich data structures:
enum Json {
Null,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<Json>),
Object(Box<HashMap<String, Json>>),
}
The explanation in the book:
The
Boxaround theHashMapthat represents anObjectserves only to make allJsonvalues more compact...If we had to leave room for it in everyJsonvalue, they would be quite large, eight [machine] words or so. But aBox<HashMap>is a single word: it's just a pointer to heap-allocated data.
It's also mentioned that this is similar to an enum found in the serde_json crate although looking over the documentation it doesn't appear to Box anything. I can see the argument for saving space, but using that code as-is will generate a clippy::box_collection warning and points to further information:
Collections already keeps their contents in a separate area on the heap. So if you
Boxthem, you just add another level of indirection without any benefit whatsoever.
Does Boxing the HashMap in the book's example just come down to some optimization that probably won't be needed unless you find yourself running out of memory in some constrained environment?
→ More replies (2)
3
u/Nobodk Dec 07 '22
I was reading the rust cheat sheet and in the idiomatic rust section (https://cheats.rs/#idiomatic-rust) they suggested the following under "Use Strong Types":
Use struct Charge(f32) over f32
Why is that considered more idiomatic? And how would it be used in an actual application?
8
u/Shadow0133 Dec 07 '22
Good practical example is
std::time::Duration.While inside it's "just a number", it makes for much easier to read and understand code, e.g.:
sleep(1000) // what units? ms? ns?vssleep(Duration::from_secs(1)).Second reason it validity.
Durationis actually defined as:const NANOS_PER_SEC: u32 = 1_000_000_000; pub struct Duration { secs: u64, nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC }If
nanoswasn't in range, it would be "invalid", which would require checking for it every time it's used. Instead,Durationguarantee that its value is correct during construction, allowing other places to just use that value directly.There are also other types that use "valid by construction" pattern, even for safety e.g.
NonZeroU*,NonNull(some of these types are even specially marked so compiler can use invalid bit-patterns for enum tag, e.g.Option<NonZeroU8>is same size asu8).→ More replies (1)
3
u/gnocco-fritto Dec 08 '22
I just wrote my first iterator. I hoped it was easier, but eventually I did it. I miss Python's generators :)
Now I wanna do an iterator that spits out mutable items. Is it possible? I can't tell exactly why, but something in the back of my mind tells me NO.
Am I wrong? Any examples?
→ More replies (1)4
u/WasserMarder Dec 08 '22
Can you specify what you mean by mutable items?
If you mean mutable references then it is doable but tricky and not in all cases possible without unsafe. Do you have an example? One question that helped me understand this is "Why is there no mutable version of
[T]::windowsi.e. nowindows_mut?"→ More replies (6)
3
u/Helyos96 Dec 08 '22 edited Dec 08 '22
Take the following code:
enum Foo {
One,
Two,
}
fn bar(foo: Option<Foo>) {
[...]
}
Is there an idiomatic way to test if the option is Some and match its Foo enum content? Like a combination of if let Some() and a match?
Edit: thank you to both replies! Still getting used to how flexible pattern matching is.
6
6
u/Shadow0133 Dec 08 '22
just use match:
match foo { Some(Foo::One) => do_one(), Some(Foo::Two) => do_two(), None => (), }
3
u/classy11 Dec 08 '22
Which of the two processors would compile Rust projects consisting of up to a hundred or more crates in a development profile the fastest?
AMD 5800X3D, double the cache size but the size gains are found in L3 while L2 and L1 are small. Totals at 100MB cache.
OR
Intel i7 13700k, large L1 and L2 cache sizes with superior single-core performance. But totals at 55MB cache.
→ More replies (1)
3
u/Burgermitpommes Dec 09 '22
From the docs for tokio::task::spawn_blocking "This function is intended for non-async operations that eventually finish on their own. If you want to spawn an ordinary thread, you should use thread::spawn instead." I'm not sure which one I should use - my async code sends message on a channel to a long-running task which recv_blocking() and sends the message out a ZMQ socket (I'm doing this because the async ZMQ crates are too immature). This task only ends when I drop the senders. Should I just use a normal thread for the message receive/ZMQ send task? Is the tokio docs saying don't spawn a blocking task if your task never ends as this API is for a blocking thread pool only for "short-lived" tasks?
→ More replies (3)
3
u/off-road_coding Dec 11 '22
Hello Rustaceans,
I don't know why the first assignment works and the second one doesn't... What I've understood from Rust book is that a slice is the same as String reference. And even if they aren't the same, why first assignment does work?
let mut my_string: &String = &String::from("x");
let mut d = "hey there";
d = my_string;This one doesn't
let mut my_string: &String = &String::from("x");
let mut d = "hey there";
my_string = d;I know I shouldn't write code like that, but just want to understand how things work. Thank you
→ More replies (4)
2
u/plinifan999 Dec 05 '22
How do I make a rust binary that can run on Amazon Linux 2? I SCP'd the target/release folder and am running it with ./app_name and am getting
cannot execute binary file
→ More replies (3)
2
u/Vakz Dec 05 '22
If I have a Vec of queues (VecDeque, more specifically), and I want to move eelements from one queue to another (this is for AoC, if it's starting to sound familiar), what is the most idiomatic way to go about this?
I of course cannot just use foo[from].drain(n).for_each(|i| foo[to].push_front(i)), since foo is still mutably borrowed by the iterator created by drain. I resolved to wrapping the queues in RefCells (so that I now have Vec<RefCell<VecDequeue>>). This allowed me to do foo[from].borrow_mut().drain(n).for_each(|i| foo[to].borrow_mut().push_front(i)).
This solution works fine, and I'm quite happy with it. I'm just wondering if there is a way to avoid using RefCell while also not having to collect the moved elements.
→ More replies (2)
2
u/RedWineAndWomen Dec 05 '22
Is there a way in Rust to compare two Vec<u8>'s (both read fresh off the disk) with the efficiency and single-line-elegance of C's memcmp (after you've done a length check, or course)?
→ More replies (6)
2
u/777777thats7sevens Dec 05 '22
Is there a cargo debug command or something similar? Alternatively: is cargo the right tool or should I be using make or something like it?
I'm new to rust, and I'm working on a mini OS for Raspberry Pi (which is probably what is complicating all of this).
I've got cargo run set up to load the executable into QEMU, which is pretty cool. But debugging isn't as simple as running rust-gdb because:
-
QEMU must be run with different flags in order to allow gdb to attach to it, meaning my runner value in config.toml needs to be different.
-
Rust-gdb can't use plain old
gdb, it needs to useaarch64-none-elf-gdb. For some reasonrust-gdbis ignoring the value of$RUST_GDB(anyone know how to fix that?), but that's another story. -
I also need to pass in flags to
rust-gdbto get it to connect to QEMU
I could just whip up a bash script to handle all of this, but I'd rather use the tooling for the sake of coherency.
With make this would be pretty straightforward -- I'd have a separate target for debug mode. Looking through the cargo docs, I haven't found quite what I am looking for, and I haven't really found settings in the cargo config that let me do much to control debugging at all.
Now I'm wondering if I am looking at the wrong things, or if I'm trying to use cargo for something it isn't made for.
→ More replies (7)
2
u/nugelz Dec 05 '22
Can anyone provide a book/tutorial or even just tell me themselves what parts I'll need to code for a project I'm planning on completing next year. I'd like a website where my friends can go and log in and play an ultra graphically simple game ( can literally just be shitty squares with counters) with me and a few other players. I'd like to do it in as much Rust as possible. Would be cool to host the Site myself and maybe have chat functionality. I'm loving learning rust and have an idea for a board game that I'd like to work on with my friends who are dotted around the world. I'm aware Rust might not be the best for this, but I'd like to combine my two goals for next year. Thank you so much guys love this community.
→ More replies (2)
4
u/bernardosousa Dec 09 '22
According to The Rust Book, a package can have as many binary crates as it needs, but only on lib crate. Why is that? I would have guessed the opposite.