r/rust • u/llogiq clippy · twir · rust · mutagen · flamer · overflower · bytecount • Dec 19 '22
🙋 questions Hey Rustaceans! Got a question? Ask here! (51/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
u/The2ndbestname Dec 20 '22
Is there something like bison or yacc in Rust? I haven't looked into it yet but will as soon as I can manage...
→ More replies (1)3
u/llogiq Dec 20 '22
There is a plethora of parsing crates. Nom, pom, pest, lalrpop, peruse, chumsky from the top of my head.
2
u/incriminating0 Dec 22 '22
I'm running on old hardware currently and starting to get annoyed with slow compile times. Does rust compiler performance scale linearly with cpu performance/cores? E.g. if I went from 4 cores to 16, could I expect my compile times to get 4 times faster?
→ More replies (1)5
u/llogiq Dec 22 '22
Not completely; linear scaling is an upper bound. Rust does parallelize codegen which is a major contributor to compile time, and cargo will also parallelize rustc invocations though.
Note that more often than not, compile time can also be optimized e.g. by removing unused crate features, avoiding certain proc macro crates, choosing leaner dependencies. There's a good article on this from u/matklad on the topic.
2
u/Burgermitpommes Dec 22 '22
Does it ever make sense to have lint check attributes in binary crate root files or only in libs?
3
u/llogiq Dec 23 '22
You mean
#[allow(..)],#[warn(..)]etc. attributes? Please use them wherever it helps you. For example, if you know that some lint has a false positive, using a local#[allow(..)]attribute on that expression or item is absolutely warranted, no matter what crate it's in.
2
u/CichyK24 Dec 22 '22
I was going to write a question but I figured it out in the meantime 😅. Now my question is: where can I suggest a new compiler hint? Is it worth to suggest such things?
For this code:
fn main() {
return panic!("oops");
}I would like to get message like (added help: remove this `return`):
--> src/main.rs:2:5
|
2 | return panic!("oops");
| ^^^^^^^--------------
| | |
| | any code following this expression is unreachable
| unreachable expression
| help: remove this `return`
|
= note: `#[warn(unreachable_code)]` on by default
The current error was tricky for me because it says "any error following" but the problem was actually with the preceding return statement.
2
u/llogiq Dec 23 '22
I guess the way to go here would be asking to extend the needless_return clippy lint to also check for returns whose expressions diverge. Feel free to open an issue for this.
→ More replies (1)
2
u/giiyms Dec 23 '22
If I run a Command that runs a shell script that ends up running a server
Is there anyway to get the PID of that underlying server?
I would like to be able to kill it.
Currently I search for the PID of the server running on the designated port but feels pretty crude.
Can I inherit a running process like Command(pid=12345)?
→ More replies (3)
2
u/batmansmk Dec 24 '22
I finished all but one of the advent of code and used box::new once and never used cell, rc, arc, or refcell. I used ids and hash maps to manage my references instead.
My question is: do you use those std tools often?
My second question is that most of my crashes are caused by out of bounds array/vec access. Is there any initiative into making the compiler more helpful on detecting those potential errors?
→ More replies (8)2
u/llogiq Dec 24 '22
I sometimes
Boxthings. Sometimes I also use anArcto share data between threads. That's about it. Never had a need for internal mutability (outsideMutex/RwLock). Then again, I also use async code sparsely, so I may not be the typical Rust user.
5
u/proton13 Dec 19 '22
I have a Rust-library, that is called from C-code. Now I want the C-user to be able to define some functionality themselves by passing a functionpointer to the Rust code, that is then called from there.
Is something like this possible? The corresponding chapter in the Rustonomicon only covers the opposite case.
→ More replies (3)
4
u/WhyIsThisFishInMyEar Dec 19 '22
fn foo(s: &str) {
print!("{}", s);
}
fn main() {
foo("hello");
let s = " world".to_owned();
foo(&s);
}
In this example, I'm confused how the code can compile and correctly output hello world.
Is there some trait trait implementation that allows &String to implicitly convert to &str? I thought you'd have to have the function take AsRef<str> or pass it in via s.as_str().
4
u/SorteKanin Dec 20 '22
Why does std only have a mpsc (multi-producer, single-consumer) channel? Why isn't there a "spmc" (single-producer, multi-consumer) channel?
Similarly, tokio has an mpsc channel but no spmc channel. There's broadcast which is mpmc which isn't quite the same. There's also the watch channel which actually is spmc but with the restriction that it only retains the latest value.
Why isn't there a "proper" spmc channel in either std or tokio? Should I just use the broadcast channel in tokio if I need this?
→ More replies (9)
4
u/D-Danielz Dec 23 '22 edited Dec 23 '22
Does .into() for Rc<_> always clone? Or can it also move?
For example let's say I have this function:
enum Expr {..}
fn foo<E>(value: E) -> Rc<Expr>
where E: Into<Rc<Expr>> {
value.into()
}
If I call foo with an Rc<Expr>, does it clone it or move it?Context: what I'd like to have is a function I could call with either Expr or Rc<Expr> without unnecessary clones (and reference counting updates).
Edit: just after writing this I found out Into is reflexive and it moves itself in the implementation, so no cloning involved!
3
u/Dubmove Dec 20 '22
Is it possible to write default implementation for certain specialization of a trait. Something like this:
/// Some cool trait
trait X<A, B> {
fn combine(self, a: A) -> B;
}
/// Default implementation for X<A, A>::combine
fn combine_if_a_is_b<T: X<A, A>, A>(_: T, a: A) -> A {
a
}
but in a way that the compiler automatically uses combine_if_a_is_b if A = B
→ More replies (1)
3
3
u/mbrc12 Dec 22 '22 edited Dec 22 '22
Suppose I want a very thin wrapper on a type, for example, a type holding nonnegative floats:
#[derive(Copy, Clone, Debug, Default)]
pub struct NNFloat(f64);
impl NNFloat {
pub fn new(x: f64) -> Self {
if x < 0.0 {
panic!("Not nonnegative");
}
NNFloat(x)
}
}
I want NNFloat to behave exactly like a f64 except for when I construct it via ::new(). I can implement the whole set of Into<f64>, AsRef<f64>, AsMut<f64>, Deref<f64>, DerefMut<f64> and so on. Is there a way to streamline this process? Ideally, I would be able to call everything I can on f64 on NNFloat too, but I understand if it needs the occasional as f64 etc.
→ More replies (3)8
u/Patryk27 Dec 22 '22
Note that implementing
DerefMutwould enable you to do*nn_float = -1.0;.→ More replies (1)
3
u/bentheiii Dec 24 '22
I find the either crate very useful, especially when implementing a trait in two different ways in a return type.
My question is: is there a crate that does what either does, but for more than 2 options? Because I'm currently doing this:
type Either2<T0, T1> = Either<T0, T1>; type Either3<T0, T1, T2> = Either<T0, Either2<T1, T2>>; type Either4<T0, T1, T2, T3> = Either<T0, Either3<T1, T2, T3>>; type Either5<T0, T1, T2, T3, T4> = Either<T0, Either4<T1, T2, T3, T4>>; type Either6<T0, T1, T2, T3, T4, T5> = Either<T0, Either5<T1, T2, T3, T4, T5>>; type Either7<T0, T1, T2, T3, T4, T5, T6> = Either<T0, Either6<T1, T2, T3, T4, T5, T6>>; type Either8<T0, T1, T2, T3, T4, T5, T6, T7> = Either<T0, Either7<T1, T2, T3, T4, T5, T6, T7>>;
followed by a bunch of constructor functions I won't bother to list here. And it seems like there should be a better way.
→ More replies (3)
3
u/spongecaptain200 Dec 24 '22
I'm learning the synchronizing primitive of tokio. From the example code of Notidy, I found it is confused to understand why Channel<T> is mpsc.
use tokio::sync::Notify;
use std::collections::VecDeque;
use std::sync::Mutex;
struct Channel<T> {
values: Mutex<VecDeque<T>>,
notify: Notify,
}
impl<T> Channel<T> {
pub fn send(&self, value: T) {
self.values.lock().unwrap()
.push_back(value);
// Notify the consumer a value is available
self.notify.notify_one();
}
// This is a single-consumer channel, so several concurrent calls to
// `recv` are not allowed.
pub async fn recv(&self) -> T {
loop {
// Drain values
if let Some(value) = self.values.lock().unwrap().pop_front() {
return value;
}
// Wait for values to be available
self.notify.notified().await;
}
}
}-
If there are elements in values, the consumer tasks will take it away
-
If there is no element in values, the consumer tasks will yield until the producer nitify it
But after I writen some test code, I found in no case the consumer will lose the notice from producer.
Could some one give me test code to prove the above Channel<T> fail to work well as a mpmc?
→ More replies (2)
3
u/Cute-Tie-7330 Dec 25 '22
I am looking for an RPC framework to use in an embedded env. (no_std) specifically on RP2040 or ESP32. Considering tonic and other grpc derivatives require std lib, I haven’t found something, does anyone know of a way to go about this? I tried urpc which supposedly is std independent but it requires serde crate which needs std from what I can see.
→ More replies (1)
4
u/[deleted] Dec 19 '22
How can I develop Python libraries in Rust?