How to do a borrow in match?

Hello All,

I'm new to rust and was playing around with the code below. When I do the match on data.s1 it is moved. How to do a borrow instead, so the the following println! calls will compile? It looks like the following println! calls do a move also. I can't seem to find any info on this case. Thanks -S

BTW: Sorry, I couldn't figure out how to quote the code. I searched Google and the forum to no avail.

#[derive(Default)]
struct OptionStruct {
s1: Option,
s2: Option,
}

pub fn option_struct_test()
{
let mut data: OptionStruct = OptionStruct::default();

data.s1 = Some(String::new());

data.s1 = Some("test".to_string());

let sval = match data.s1 {
Some(s) => s,
None => "None".to_string()
};

println!("sval = {}", sval);

println!("s1 = {}", match data.s1 {
Some(s) => s,
None => "None".to_string()
});

println!("s1 = {}", data.s1.unwrap()); // this doesn't compile due to move in Some above

}

let sval = match data.s1 {
    Some(ref s) => s,
    None => "None"
};

The ref modifier makes the binding take a reference to the inside of the matched pattern.

(Note that in order for this to work, you should also change the type of the string "None" from owned to borrowed, so I omitted the .to_string() part.)

2 Likes

This forum uses markdown as a markup language, so you can used fenced code blocks:

```rs
// Code
```

Other than that, you can use ref inside a match to create a reference for the match arm.

3 Likes

Note that the ref keyword is no longer recommended since Rust 2018 (issue).
Instead you can write:

let sval = match &data.s1 {
    Some(s) => s,
    None => "None",
};

I have serious concerns about the downsides of default binding modes (that I'm not going to reiterate here), therefore I'm suggesting the clearer, explicit alternative.

1 Like

Hi H2C03, farnbams, and NobbZ,

The ref annotation works, but I get a compile error on &data.s1 "match arm incompatible type" for None. I guess this is because the & is turning the whole option to a reference as opposed to the Some(s). I'm not sure how to dereference the None though. I'll have to play around with it some more.

Thanks for the help guys. -S

I don't know what's your exact code but I guess you still have "None".to_string(). The problem is that in your example you try to return an owned String while the match &data.s1 {} solution returns a reference, i.e. &String. If the .to_string() is omitted you return "None" directly which is of type &'static str like every "String" literal in Rust. To prevent confusion: In this context &'static str will be cast into &String automaticlly. see what @KrishnaSannasi wrote.

Nope, both will be converted to &str. The string literal gets a shorter lifetime, and the &String gets coerced.

A &str will never automatically convert to a &String

2 Likes