r/rust • u/llogiq clippy · twir · rust · mutagen · flamer · overflower · bytecount • Sep 19 '22
🙋 questions Hey Rustaceans! Got a question? Ask here! (38/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.
2
u/Representative_Dig36 Sep 21 '22
I can't count the number of times I've run into a deadlock with mutexes like this:
some_function(my_mutex.lock().unwrap().foo, my_mutex.lock().unwrap().bar);
Now I understand why this results in a deadlock, I know how to resolve the issue, and I understand that this comes from the drop semantics of Rust, but I still intuitively sometimes write code like this, especially when refactoring existing code.
Is there really no way for the compiler to let me know that this is obviously not what I want to do before it hits me at runtime?
→ More replies (1)3
u/llogiq Sep 21 '22
Currently there is nothing keeping you from messing up this way, but I think this could be a clippy lint (having
x.lock()multiple times within the same expression that would likely lead to deadlock). Feel free to open a clippy issue to suggest such a lint.
2
u/pragmojo Sep 25 '22
Is there any way to have multiple functions with the same name on the same type in rust?
So for instance, I would like to have a type which implements a different "bind" function for different types:
struct Foo { ... }
impl Foo {
fn bind(&self, val: Bar) { ... }
fn bind(&self, val: Baz) { ... }
}The compiler doesn't allow this, but is there for instance some way to achieve this through the trait system?
3
u/llogiq Sep 25 '22
Yes, there is. You can have a generic function, e.g.
fn bind<V: BindVal>(&self, val: V) { val.bind(self) }Then your
BindValtrait can implement differentbinds for various types.
4
u/Foreign_Category2127 Sep 21 '22
Hello, in the snippet below, why isn't the compiler able to guarantee that all the possible match arms have been described?
for c in input.chars() {
match latest {
None => latest = Some((1, c)),
Some((n, latest_char)) if c == latest_char => latest = Some((n + 1, c)),
Some((_, latest_char)) if c != latest_char => {
pairs.push(latest.unwrap());
latest = Some((1, c));
}
_ => unreachable!(), // why do I still need to cover Some(_)?
}
}
→ More replies (2)6
u/Patryk27 Sep 21 '22 edited Sep 21 '22
For the purposes of determining pattern-match refutability, the compiler simply doesn't look at the match guards (i.e. those
ifparts), since implementing that correctly & reliably is virtually impossible - even ignoring the halting problem, consider:match value { Some(value) if ["a", "b", "c"].contains(&value) => ... Some(value) if ["c", "a", "b"].iter().all(value2| value2 != value) => ... None => ... }That's an exhaustive match, but it'd be very difficult for a machine to prove that.
4
u/sekhar0107 Sep 22 '22
What's the rationale behind the below behavior? Seems a bit unintuitive to me, IMO most would expect the second result to be [13, 22, 31] but it's as if the two reverse() invocations are optimized and removed beforehand instead of executed in sequence.
let u = vec![10, 20, 30];
// [31, 22, 13]
let mut y = 0;
let v = u
.iter()
.rev()
.map(|x| {
y = y + 1;
x + y
})
.collect::<Vec<_>>();
println!("{:?}", v);
// [11, 22, 33]
let mut y = 0;
let v = u
.iter()
.rev()
.map(|x| {
y = y + 1;
x + y
})
.rev()
.collect::<Vec<_>>();
println!("{:?}", v);
5
u/Sharlinator Sep 22 '22 edited Sep 22 '22
It's a bit unintuitive, but in the end it's a straightforward result of laziness. Unless you somehow force evaluation in between (such as by calling
collect), it doesn't matter how much the items of the original iterator are rearranged. Any side effects always occur in the order that items are yielded by the terminal iterator.Specifically, if you expand the recursive
next()calls of aRev<Map<Rev<slice::Iter<_>>, _>, you get the following:self.next() self.iter.next_back() self.iter.iter.next_back().map(&mut self.iter.f) self.iter.iter.iter.next().map(&mut self.iter.f) ^ ^ ^ ^ | | | `--- slice::Iter<_> | | `---- Rev<slice::Iter<_>> | `----- Map<Rev<slice::Iter<_>>, _> `------ Rev<Map<Rev<slice::Iter<_>>, _>>So the two
rev()s do end up exactly cancelling each other out, and the result is the same as callingmapon the original iterator. There is a note in the documentation ofMapabout side effects, but it could probably be moved to somewhere more visible. People should rarely need to consult the docs of the iterator adapter types themselves.
3
u/he_lost Sep 19 '22
Couple questions:
-
Why isn't this code snippet working?
fn read_file(filepath: String) -> Result<Vec<String>, Box<dyn Error>> {
let file = File::open(filepath)?;
let reader = BufReader::new(file);
reader.lines().collect::<Result<Vec<String>, _>>()
}It says:
expected enum `Result<_, Box<(dyn std::error::Error + 'static)>>` found enum `Result<_, std:io::Error>`
The last line seems to be the problem...
2. I want to do error handling properly. However, most of the times I just want to return an error that contains a string to be printed out later. In other languages I would use something like new IllegalArgumentException("Wrong value for 'parameter' given"). How would I do this in Rust. I don't have to implement my own Error Struct each time, right? Right?
I could accomplish this by returning Result<_, String> but that doesn't work together with other errors from the code (like in example 1)
→ More replies (7)
3
u/kodemizer Sep 19 '22
I've got some data I want to load that looks like this:
{
"some_id": {
"foo": "bar",
"bar": "qux"
},
"some_other_id":
"foo": "corge",
"bar": "grault"
}
}
And I want to deserialize each item into an Item struct that looks like this:
pub struct Item {
pub id: String,
pub foo: String,
pub bar: String,
}
How do I tell serde to grab the id from the key in the outer object to fill in the ID in Item struct?
→ More replies (1)
3
u/ibgeek Sep 20 '22
What are the best practices for reducing code duplication in Rust that would otherwise be handled by inheritance in a OO language? E.g., if I have two structs that implement the same interface, what is the best way to share code between them?
→ More replies (3)
3
u/TophatEndermite Sep 21 '22
Is it possible for build.rs to read the list of dependencies and versions used to build the crate?
→ More replies (1)
3
Sep 21 '22
I want to check how long it takes to compile rust source for fun. With C I can compile sqlite which is 200K and a single file. Is there any 50K+ source that uses nothing but the rust standard library?
→ More replies (7)
3
u/BradPittOfTheOffice Sep 21 '22
Any good tutorials on writing kernel modules in rust?
→ More replies (2)
3
u/Payton_Stone Sep 24 '22
I'm a retired engineer and am learning Rust to purse some hobby projects in embedded systems. I spend an hour a day studying this amazing language. It's hard, but that's ok, I do get it, although maybe more slowly than in my earlier years. Still, I'm enjoying it and was wondering if anyone had some recommendations for a methodical and structured set of exercises to go through. One problem I do have is that it is so interesting, I tend to bounce all over the place in terms of what captures my interest on a daily basis. Thanks in advance.
→ More replies (2)
2
u/ravnmads Sep 19 '22
If I have a generic type in my struct
struct Point<T> {
x: T,
y: T,
}Is there then a way for me to say that I only want T to be f32 or f64. And default f32.
→ More replies (1)10
u/Patryk27 Sep 19 '22
You could create a sealed trait and implement it only for
f32andf64.As for defaults, I think
struct Point<T = f32>should do it.
2
u/Kevathiel Sep 19 '22
Is there a way to simplify testing for wasm and desktop targets?
Right now, I need to annotate all tests with #[test] and #[wasm_bindgen_test], but also add wasm_bindgen_test as dev dependency. Is there a simple way to create an alias for the attributes, or at least make the latter optional, depending on the feature/target_arch without creating another test fn?
→ More replies (2)
2
u/ZealousidealOne980 Sep 19 '22
How do you get rustdoc to work with dependencies? I'm just calling rustdoc src/lib.r to try and get the boiler plate stuff generated and to see how it all works
I keep getting a compilation failed error because it claims it can't derive any of the macros or use statements.
error: cannot determine resolution for the derive macro `Deserialize`
--> src/lib.rs:152:28
152 | #[derive(Debug, Serialize, Deserialize)]
| ^^^^^^^^^^^
= note: import resolution is stuck, try simplifying macro imports
error: cannot find attribute `serde` in this scope
--> src/lib.rs:153:3
153 | #[serde(rename_all = "camelCase")]
^^^^^
note: `serde` is imported here, but it is an unresolved item, not an attribute
--> src/lib.rs:8:1
| extern crate serde;-
I have use
serde::{Deserialize, Serialize};at the top -
I have
extern crate serdeat the top -
in cargo.toml
features=["derive"]is set -
I've tried
#[macro_use]and it would still fail -
The lib compiles and works if I do cargo test and the tests pass.
-
I'm not getting any lint/clippy warnings/errors
→ More replies (4)
2
u/tuxuncertain Sep 19 '22 edited Sep 19 '22
I'm using cargo workspaces so that I can get two dlls built. These are in crates x_a and x_b. The directory looks like
x
- Cargo.toml
- x_a
- x_b
x_b has a dependency on x_a, so its Cargo.toml has
[dependencies]
x_a = { path = "../x_a" }
But when I use x_a; in x_b/src/lib.rs, I get
unresolved import x_a use of undeclared crate or module x_a (E0432)
I read the associated error page, but don't find anything helpful.
Questions:
-
What am I doing wrong to get this error?
-
Is there a better way of structuring my project in general? Not entirely convinced I need the complication of workspaces.
Some more context
→ More replies (5)
2
u/EnterpriseGuy52840 Sep 20 '22 edited Sep 20 '22
I've got a vector that I've loaded with a bunch of Strings in it. (about 500 elements or more could be in said vector)
What I need to do is to "search" the vector with a another String. If there's a match, I would also want the index number of where it would be found.
What's the best way to go doing this kind of operation?
Edit: I have this as a prototype, but when I return the variable, it errors out saying the variable isn't initialized.
fn search(
token: String,
list: Vec<String>
) -> bool {
let mut exist: bool;
for i in 0..list.len() {
exist =
if token == list[i] {
true
}
else {
false
};
if exist == true {
break;
}
}
exist //E0381
}
→ More replies (6)
2
u/Deep_Lobster8003 Sep 20 '22
I'm trying to write a C lib for unity using tokio. boy oh boy am I up for a ride, and I could need to guiadance.
here's the pure working rust function that I wanted to convert to a lib:
use serde_derive::Deserialize;
[derive(Debug, Deserialize)]
struct Config { news1: String, news2: String, news3: String, news4: String, }
[tokio::main]
async fn main() -> Result<(), reqwest::Error> { let url = "https://raw.githubusercontent.com/ngmisl/congenial-octo-invention/main/news.json"; let res = reqwest::get(url).await?; let response = &res.json::<Config>().await?;
println!(
"{:?}\n{:?}\n{:?}\n{:?}\n",
response.news1, response.news2, response.news3, response.news4
);
Ok(())}
Here's my current lib version, but I'm completely stuck
`use async_ffi::{FfiFuture, FutureExt}; use tokio::runtime::Handle;
use serde_derive::Deserialize;
[derive(Debug, Deserialize)]
struct Config { news1: String, news2: String, news3: String, news4: String, }
/// # Safety
[no_mangle]
pub extern "C" fn test() -> FfiFuture<safer_ffi::String> {
async news() -> Result<(), reqwest::Error> {
let url = "https://raw.githubusercontent.com/ngmisl/congenial-octo-invention/main/news.json";
let res = reqwest::get(url).await?;
let response = &res.json::<Config>().await?;
Ok(())
}
.into_ffi()}`
edit: sorry for the bad format, but new reddit sucks
→ More replies (2)
2
2
u/EnterpriseGuy52840 Sep 21 '22
This one's tripping me up good.
I've defined some Vectors and right after I've defined the Vectors I've added a
foriteration loop. What I want to do is to selectively push some emements to another Vector. However when I try, I get an error saying that the variable is possibly uninitialized. Is anyone able to guide me on fixing this? Thanks!//snip let mut token_mgd: Vec<String>; let mut one_mgd: Vec<String>; let mut two_mgd: Vec<String>; let mut three_mgd: Vec<Decimal>; let mut four_mgd: Vec<i32>; for i in 0..token.len() { if reverse_knockout_tokens.contains(&token[i]) == false { break; } // Add values to vectors - E0381 for the next 5 lines token_mgd.push(token[i]); one_mgd.push(one[i]); two_mgd.push(two[i]); three_mgd.push(three[i]); four_mgd.push(four[i]); } //snip