[unstable] Unsized locals feature not working as shown on docs

https://doc.rust-lang.org/beta/unstable-book/language-features/unsized-locals.html

If you scroll down to the section on variable length arrays, we see:

#![feature(unsized_locals)]

fn mergesort<T: Ord>(a: &mut [T]) {
    let mut tmp = [T; dyn a.len()];
    // ...
}

fn main() {
    let mut a = [3, 1, 5, 6];
    mergesort(&mut a);
    assert_eq!(a, [1, 3, 5, 6]);
}

Okay, so I try that in my project:

/// Removes multiple list fields from a subsection
    #[allow(unused_results)]
    pub fn remove_list_fields<T: AsRef<str>, V: AsRef<str>, K: AsRef<str>, J: AsRef<[K]>>(&mut self, section: T, subsection: V, fields: J) -> Result<usize, FsError<String>> {
        let ss = self.get_subsection_mut(section.as_ref(), subsection.as_ref())?;

        let fields = fields.as_ref();

        let mut found_indexes = &mut [false; dyn fields.len()];
        let mut count = 0;

        ss.fields.retain(|line| unsafe {
            for (idx, entry) in fields.iter().enumerate() {
                //let found_index = (&mut found_indexes).get_unchecked_mut(idx);
                if !*found_indexes[idx] {
                    if line.field == entry.as_ref() {
                        *found_indexes[idx] = true;
                        count += 1;
                        return false;
                    }
                }
            }

            true
        });

        Ok(count)
    }

And I get a compile time error:

error: expected expression, found keyword `dyn`
   --> hyxe_config\src\config_handler.rs:418:46
    |
418 |         let mut found_indexes = &mut [false; dyn fields.len()];
    |                                              ^^^ expected expression

Why might this not be working as explained in the docs?

The paragraph just bellow the example:

VLAs are not implemented yet. The syntax isn't final, either.

So it's just an example of what it could look like when implemented.

Why not use a Box or a Vec? It's on the heap but it's very likely you won't notice any difference.

I am already using a vec for it and it works, but I just wanted to see if I could allocate VLA's :slight_smile:

On a side note, I want to remove a list of items from a larger list of items. Once one of the items to remove is found, it adds the index that way it doesn't have to search again for it (hence saving computation time, especially for large searches). Do you think the algorithm i have is optimal?

This is the one that I have and works:

    /// Removes multiple list fields from a subsection
    #[allow(unused_results)]
    pub fn remove_list_fields<T: AsRef<str>, V: AsRef<str>, K: AsRef<str>, J: AsRef<[K]>>(&mut self, section: T, subsection: V, fields: J) -> Result<usize, FsError<String>> {
        let ss = self.get_subsection_mut(section.as_ref(), subsection.as_ref())?;

        let fields = fields.as_ref();

        let mut found_indexes = Vec::with_capacity(fields.len());
        let mut count = 0;

        for _ in 0..found_indexes.capacity() {
            (&mut found_indexes).push(false);
        }

        ss.fields.retain(|line| unsafe {
            for (idx, entry) in fields.iter().enumerate() {
                let found_index = (&mut found_indexes).get_unchecked_mut(idx);
                if !*found_index {
                    if line.field == entry.as_ref() {
                        *found_index = true;
                        count += 1;
                        return false;
                    }
                }
            }

            true
        });

        Ok(count)
    }

I'm definitely not the right person to answer. But I'll try anyway =) Based on the number of values in fields, you might gain some time by sorting it. If you want (need) to go even faster I'd try to use hashes.
A BitVec (or similar) might be faster than a Vec<bool>, you'd have to test but it'll be smaller at least.

But regardless I'd change:

let mut found_indexes = Vec::with_capacity(fields.len());
for _ in 0..found_indexes.capacity() {
    (&mut found_indexes).push(false);
}

to:

let mut found_indexes = vec![false; fields.len()];

You should be able to use Iterator::zip instead of get_unchecked_mut.
And also do:

if !*found_index || line.field == entry.as_ref() {

This one is almost just formatting.

And if you copy/pasted all your code and only use fields once, you can remove:

let fields = fields.as_ref();

Just a note, you can use methods on found_indexes without taking a mutable reference to it.

In the end, most of my reply isn't really what you asked for (sorry) but it could be useful.

1 Like

Thank you!! :slight_smile:

Now that I think about it, since fields is a AsRef<[K]>, you'll have to make a new collection to sort it, so maybe a HashMap would be a better idea.