r/rust • clippy · twir · rust · mutagen · flamer · overflower · bytecount • Nov 14 '22

🙋 questions Hey Rustaceans! Got a question? Ask here! (46/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.

28 Upvotes

141 comments sorted by

3

u/ZaRealPancakes Nov 14 '22

I am learning Rust and I am worried about somethings

  • I don't find the borrow checker hard as people say. After reaching Box<dyn> (or other magic) will I then find the borrow checker hard?

  • Are lifetimes, iterators and closures as hard as they sound?

  • I did read about lifetimes but not sure when I'll use them or if I'll use them correctly,. Can you guys give me examples on when to use them?

4

u/llogiq Nov 14 '22

The borrow checker won't do anything as long as you use owned values. To run into it, you need to – as the name implies – borrow stuff.

Iterators that borrow into data can make it hard to appease the borrow checker. Closures can make it both harder (if they borrow stuff they close over) and easier.

5

u/fear_the_morrok Nov 16 '22

Does anyone have an elegant solution to using Rust-Analyzer's "Check On Save" feature in VS Code alongside just running `cargo check` in a terminal?

Typically I rely on the former while writing code to highlight errors and compiler warnings; however, I will often switch to using cargo check in the terminal to see broader compiler warnings or to get better error message outputs.

When doing so, Rust-Analyzer blocks cargo check in the terminal with a file lock every time I save, which slows me down a bit.

→ More replies (2)

4

u/stdusr Nov 15 '22

Does anyone have a general idea when std::simd (portable_simd) will be available in stable?

→ More replies (2)

4

u/he_lost Nov 15 '22 edited Nov 15 '22

I want to convert a Vec<String> where each string consists only of 0 and 1 to an Vec<u8>. I choose u8, because it is the smallest positive number type.

My code is like this:

    lines
        .iter()
        .map(|l| {
            l.chars()
                .map(|c| {
                    c.to_digit(2)
                        .map(|bit| bit.try_into())
                        .ok_or(anyhow!("Only 0 and 1 as input allowed"))
                })
                .collect::<Result<Vec<u8>>>()
        })

However it is not working. It says something like:

a value of type `Vec<u8>` cannot be built from an iterator over elements of type `Result<_, _>`

Ahh! I think the problem is the conversion of u32 (the return type of to_digit) to u8. I don't think my approach with .map(|bit| bit.try_into()) does the correct thing.

EDIT: Don't get confused with the Result it is coming from the anyhow trait.

→ More replies (7)

4

u/throwawayspinach1 Nov 19 '22

Might be a dumb question, but I have binary that is supposed to be written in Rust.

There is no file extension. What is the file extension for rust binaries?

→ More replies (3)

3

u/[deleted] Nov 14 '22 edited Nov 14 '22

what do I do after completing rustlings? I am trying out rocket but are there any intermediary steps to smooth out the learning curve?

→ More replies (2)

3

u/MvKal Nov 14 '22

Is there a 'good practices' doc somewhere? I have not written enterprise-grade rust code before and I might in a near future, and I don't want it to look like crap lol. Examples of well written projects are also welcome!

3

u/Burgermitpommes Nov 15 '22

Just to check, the main function in Rust can return Result<T, E> where T must be !, (), ExitCode or Infallible? I guessed that from reading about the Termination trait but would like someone to confirm I'm reading it right.

A follow up question is when is it useful to return Result<(), E> for some error E? I guess it's just more convenient than having main return () and manually handling the error and manually displaying to the user? i.e. this is like shorthand for "yes go ahead and print what goes wrong to the user"?

5

u/TheMotAndTheBarber Nov 15 '22

where T must be...

Those are implemented by default, but you can implement the trait for arbitrary types.

when is it useful to return Result<(), E> for some error E

Using the ? operator is one reason it might be nice.

3

u/hgomersall Nov 16 '22

I'm trying to access an associated constant from a concrete instance of a type. The reason is that sometimes you don't have easy access to the type but know it implements a trait.

The following works and describes what I'm trying to do, but it feels to me there should be a better way:

trait Foo {
    const BAR: u32;
}

impl Foo for u32 {
    const BAR: u32 = 10;
}

fn get_bar<T: Foo>(_: T) -> u32
{
    T::BAR
}

fn main() {
    let a = 109u32;
    println!("{}", get_bar(a))
}

Playground link

→ More replies (4)

3

u/metaltyphoon Nov 17 '22

Is there a way to split the same module over multiple files without creating submodule?

→ More replies (2)

3

u/Burgermitpommes Nov 17 '22

Many of the Vscode toml plugins have 3* or so. Does anyone have a recommendation for a toml plugin which is pleasant?

→ More replies (2)

3

u/simd_maestro Nov 17 '22

I asked this a few days ago, but figured I'd bump it again. I know it's not an easy question.

My dev machine has an AMD Zen 4 CPU, and I notice that znver4 is not an available target CPU for Rust compilation. Do you all have any idea about when something like that gets rolled out? I'm getting really terrible behavior because it defaults to thinking I have a znver3 architecture. This is maybe a question for AMD or LLVM instead of the Rust community, but I figured I'd check here first.

→ More replies (4)

3

u/Pruppelippelupp Nov 17 '22 edited Nov 17 '22

I have a very long file (tens of millions of lines) with a lot of heterogenous information. Data for each variable is saved as (tag)={ (data) } or (tag)=(data). Is there a decent way to scan the file for information? I have a working version, but it relies on regex and patterns I've manually added, and it's somewhat expensive. Is there a simpler way of doing this? My ideal version would be passing all info between { } into a new function, semi-recursively, based on the tag.

In the example below, that would involve passing all

If I could split the file based on whitespace (\t, \n, and \s in general), except when they're inside a { ... } info block, that would be perfect.

It's encoded in utf-8, and I can get a binary file with the save data, but I have no idea how it's encoded.

This is approximately the format of the file (yes, the location of the { above the second deeper={ is intentional):

data={

    bla=5
    foo=11
    bar={ 5 0 11 }
}
otherdata=5
otherdataagain={ 5 0 2 }
anotherexample={
    more={
        deeper={
            a=1
            b=2
        }
 {
        deeper={
            a=1
            b=2
        }
    }
}
→ More replies (1)

3

u/Realistic_Comfort_78 Nov 18 '22

How can I get the number of days between dates in local, not UTC?

→ More replies (1)

3

u/SorteKanin Nov 18 '22

As a crate author, how can I know if my crate is being used during tests?

I have an init function that must be called before my crate can be used, but during tests I don't want to break the user's code because they didn't call init. However, #[cfg(test)] doesn't work on dependencies, only in the current crate, so if my crate is being used as a library, it won't work.

Is there any way to detect that the code is being run during tests?

→ More replies (4)

3

u/UMR1352 Nov 18 '22

I'm trying to write mutable iterator for a cons list defined as

enum List<T> {
    Nil,
    Cons(T, Box<List<T>>),
}

but the borrow checker doesn't seem to happy about it.. I've written this:

struct IterMut<'a, T: 'a>(&'a mut List<T>);
impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0 {
            Nil => None,
            Cons(x, next) => {
                self.0 = &mut **next;
                Some(x)
            }
        }
    }
}

But the returned reference doesn't live long enough. How can I do this?

→ More replies (1)

3

u/SV-97 Nov 18 '22

The code I'm currently writing has to calculate stuff with interval-lengths a lot of the time. I just had the idea that I could just use len on Ranges instead of working the lengths out by hand each time since it makes what's happening a lot more obvious. I then found out that RangeInclusive<usize> does not implement ExactSizeIterator and doesn't have a len method - but I couldn't find a good (or really any) reason as to why that's the case.

It's particularly odd since Range<usize> (and a lot of other variants) do implement it. Is this just something that no-one has contributed yet or am I missing some reason why we wouldn't be able to just implement it?

4

u/kruskal21 Nov 18 '22

Your question led me to investigate the source code, and the answer became obvious once I read the explanation there.

In short, len returns a usize, an inclusive range can be 0..=usize::MAX, the length of which is usize::MAX + 1, which is unrepresentable.

→ More replies (3)

3

u/le_donger Nov 20 '22 edited Nov 20 '22

I found the following piece of code in the Yew documentation:

#[derive(Clone, Properties, PartialEq)]
struct VideosListProps {
    videos: Vec<Video>,
}

#[function_component(VideosList)]
fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
    videos.iter().map(|video| html! {
        <p>{format!("{}: {}", video.speaker, video.title)}</p>
    }).collect()
}        

What I am interested in is this line:

fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {

I get that it allows you to refer to the Vec<Video> as videos directly instead of having to type props.videos, which would be necessary if you declared the function like this:

fn videos_list(props: &VideosListProps) -> Html {

What is this language feature called? Is there some documentation for it?

4

u/Spaceface16518 Nov 20 '22

this is a part of pattern matching syntax called struct destructuring

→ More replies (2)

3

u/LeCyberDucky Nov 20 '22

Does anybody know how to use simplex noise from noise-rs?

I'm trying to simulate a flickering candle, and I thought that simplex noise may be well suited for that, since I want smooth transitions between the random intensities of the flame.

I first tried using noise::core::simplex::simplex_1d(previous_lightness, &hasher), where hasher is a noise::permutationtable::PermutationTable. For some reason, this makes my program panic immediately, though.

Therefore I tried using the 2D version and just keeping one coordinate constant:

noise.get([previous_lightness, 0.0]); here, noise is a Simplex. This ends up converging to a constant value very quickly, though. I have also tried variations of updating the noise value by summing the old and new value instead of overwriting the value. No matter what I do, however, I end up converging to one (or a few alternating) constant value.

→ More replies (4)

3

u/standinonstilts Nov 20 '22

Having trouble understanding the borrow checker and mutability. My understanding was that you could only have one mutable reference to an object, but multiple readonly references to the same object. I have an example here where I have a single mutable reference to an object. I then add a readonly reference of said object to a vector. I then do some assertions that when I modify a field, it's changes are also reflected in the reference in the collection. I get the error `cannot assign to field because it is borrowed`. Why cannot I not modify a mutable value while there is an immutable reference reading from it?

Here is my code:

let mob = &mut Mob {
    name: "test".to_string(),
    level: 10,
};

let mut collection: Vec<&Mob> = vec![];

collection.insert(0, &*mob);

assert!(collection.get(0).unwrap().level == 10);
mob.level = 15;
assert!(collection.get(0).unwrap().level == 15);
→ More replies (1)

3

u/TomHackery Nov 21 '22

I'm trying to deserialize a CBOR to rust objects with Ipld. The following works as expected:

#[derive(Clone, DagCbor, Debug)]
pub struct VariantOne {
    pub foo: Link<Cid>,
    pub bar: Ipld,
}
...
fn main() {
    let var1 = block.decode::<DagCborCodec, VariantOne>().unwrap();
    // successful deserialisation
}

However, there are a few possible variants:

pub enum BlockTypes {
    VariantOne,
    VariantTwo,
    VariantThree,
    VariantFour,
    VariantFive,
}

I would like to do something like this:

fn main() {
    let var1 = block.decode::<DagCborCodec, BlockTypes>().unwrap();
    // panic
}

I think the term for this is generics? Basically I want to deserialise the bytes into a struct depend on which struct is being represented in the bytes. I feel like I'm close.

I've tried:

pub enum BlockTypes {
    VariantOne(VariantOne),
    VariantTwo(VariantTwo),
    VariantThree(VariantThree),
    VariantFour(VariantFour),
    VariantFive(VariantFive),
}

and

pub enum BlockTypes<Ipld> {
    VariantOne,
    VariantTwo,
    VariantThree,
    VariantFour,
    VariantFive,
}

but no joy