Variable not found in scope OR doesn't have a size known at compile-time

I have a function where I could get a string which contains either a word or a number. So could be:
[R1 R2] or it could be [R1 #32]
I have accounted for these possibilities, but the variable life doesn't go outside the match. If I put let matched_offset = &rxoffset.captures(&elem).unwrap()[1]; higher up it panics if there is a number.
I have tried to let mut matched_offset at the start of the fucntion but it will not compile because string size isn't known. I can't find any way of doing a C style "sizeof" just to make it as large as the input string (e.g. larger than it would ever need).

So my question is how can I make the life of the matched_offset variable valid throughout the life of the entire function?

    match instr {
        0 => { // Load Variable
            let rx = Regex::new(r"[[:space:]]+ldr[[:space:]]+([[:word:]]+)[[:space:]]+\$*-?[[:word:]]+").unwrap();
            let rxvariable = Regex::new(r".*[[:space:]]+(\$*-?[[:word:]]+)").unwrap();
            let matched_register = &rx.captures(&elem).unwrap()[1];
            let matched_variable = &rxvariable.captures(&elem).unwrap()[1];
            println!("matched_register={:?} \t matched_variable={:?}\n",matched_register, matched_variable );
        }
        1 => { // Load Memory location + Offest
            let rx = Regex::new(r"[[:space:]]+ldr[[:space:]]+([[:word:]]+)[[:space:]]+[\[]+.*").unwrap();
            let rxlocation = Regex::new(r".*[\[]+[[:space:]]*?([[:word:]]+).*").unwrap();
            let rxoffset = Regex::new(r".*[\[]+[[:space:]]*?[[:word:]]+[[:space:]]*?([[:word:]]+)[\]]+").unwrap();
            // offset can be a register or an immedaite value. Check if immedaite first.
            let rxdigit = Regex::new(r".*[[:space:]]#(-?[[:digit:]]+)").unwrap();
            let immediate_count = &rxdigit.captures_iter(&elem).count();
            let mut use_immediate_value: bool = false;
            let mut rxdigitvalue: i32 = 0;

            match immediate_count {
                1 => {
                    rxdigitvalue = rxdigit.captures(&elem).unwrap()[1]
                        .parse::<i32>()
                        .unwrap_or_default();
                    if rxdigitvalue > 255 {
                        panic!("Immediate value greater than 255 at: {:?}", elem);
                    }
                    use_immediate_value = true;
                }
                _ => {
                    let matched_offset = &rxoffset.captures(&elem).unwrap()[1];
                }
            }

            let matched_register = &rx.captures(&elem).unwrap()[1];
            let matched_variable = &rxlocation.captures(&elem).unwrap()[1];
            if use_immediate_value
            {
                println!("matched_register={:?} \t matched_variable={:?} \t matched_offset={:?}\n",matched_register, matched_variable, rxdigitvalue );
            }
            else {
                println!("matched_register={:?} \t matched_variable={:?} \t matched_offset={:?}\n",matched_register, matched_variable, matched_offset );
            }

        }
        _ => {
            // panic!("Problem with \"{:?}\" in function def_load_memory", elem);
        }
    }

Well, try to see it logically. The problem with the code you posted is less that the scope isn’t right (well, it is, but that can be fixed as I’m explaining below) and more that it isn’t clear what the value of matched_offset is supposed to be in the 1 => branch for immediate_count. Or maybe that isn’t even a problem since you know what it is supposed to be, but at least the code that you provide doesn’t explain what’s supposed to happen if immediate_count is 1.

Okay, onto fixing the scoping issue: Moving the variable further out

let matched_offset: &str;
match immediate_count {
    1 => {
        rxdigitvalue = rxdigit.captures(&elem).unwrap()[1]
            .parse::<i32>()
            .unwrap_or_default();
        if rxdigitvalue > 255 {
            panic!("Immediate value greater than 255 at: {:?}", elem);
        }
        use_immediate_value = true;
    }
    _ => {
        matched_offset = &rxoffset.captures(&elem).unwrap()[1];
    }
}

doesn’t work without any problems, one errror we get is the following:

 1  error[E0716]: temporary value dropped while borrowed
   --> src/main.rs:39:39
    |
 39 | ...ffset = &rxoffset.captures(&elem).unwrap()[1];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   - temporary value is freed at the end of this statement
    |             |
    |             creates a temporary which is freed while still in use
 ...
 50 | ...ched_register={:?} \t matched_variable={:?} \t matched_offset={:?}\n",matched_register, matched_variable, matched_offset );
    |                                                                                                              -------------- borrow later used here
    |
    = note: consider using a `let` binding to create a longer lived value

Weird that the lifetimes are problematic here, right(?), since matched_offset is supposed to be a slice of elem which we keep around. This is a somewhat common (and documented [click “[+]” next to impl <'t> Index]) problem with the Regex crate that is due to the indexing syntax (the “[1]”) being a bit too unflexible in the lifetimes. You can replace [1] with .get(1).unwrap().as_str() to get this problem out of the way

let matched_offset: &str;
match immediate_count {
    1 => {
        rxdigitvalue = rxdigit.captures(&elem).unwrap()[1]
            .parse::<i32>()
            .unwrap_or_default();
        if rxdigitvalue > 255 {
            panic!("Immediate value greater than 255 at: {:?}", elem);
        }
        use_immediate_value = true;
    }
    _ => {
        matched_offset = &rxoffset.captures(&elem).unwrap().get(1).unwrap().as_str();
    }
}

and all that’s left is

 1  error[E0381]: borrow of possibly-uninitialized variable: `matched_offset`
   --> src/main.rs:50:136
    |
 50 | ...matched_register, matched_variable, matched_offset );
    |                                        ^^^^^^^^^^^^^^ use of possibly-uninitialized `matched_offset`

Addint e.g. some default value (or any other way to initialize the variable) in the other path

let matched_offset;
match immediate_count {
    1 => {
        rxdigitvalue = rxdigit.captures(&elem).unwrap()[1]
            .parse::<i32>()
            .unwrap_or_default();
        if rxdigitvalue > 255 {
            panic!("Immediate value greater than 255 at: {:?}", elem);
        }
        use_immediate_value = true;

        matched_offset = "";
    }
    _ => {
        matched_offset = &rxoffset.captures(&elem).unwrap().get(1).unwrap().as_str();
    }
}

makes the code compile.


If you’re having more trouble with panics, please provide example inputs (in particular the value for elem) that are supposed to work. For more feedback about approaches you already tried yourself and error messages you encounter, such as

you also need to be more specific, best thing is you offer some complete code example and error message (and perhaps even a link to a playground) so that we can understand what is going on without having to guess too much.

1 Like

Thanks, that is the solution. The issue I was having with panics was a problem I knew, and why I put in the immediate_count check. In order to see if it was a number or not. But the way I was doing the capture was the problem.

I did read the docs, but never actually clicked the [+]

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.