Mismatched types: expected &str found String when assigning string

17,949

Solution 1

You initialized out_filename with a string literal. The type of a string literal is &str (or, more specifically, &'static str), which is different from String.

The simplest solution is to assign out_filename to the result of the match expression directly:

use std::env;

fn main() {
    let args: Vec<_> = env::args().collect();
    let out_filename = match args.len() {
        2 => &args[1],
        3 => &args[2],
        _ => panic!("Too many params !"),
    };
}

[...] what if I wanted to make group of assignments based on args count like inside code block {} ? [...] Is there any way to get working code with basic match without let var = match { assign ?

You can simply put some let statements with no initializers before the match expression and initialize the variables as appropriate in each arm. You'll get a compiler error if you try to use a variable that might be left undefined and, unless you define the variables with let mut, you'll also get an error if you try to assign a variable more than once on a particular code path.

use std::env;

fn main() {
    let args: Vec<_> = env::args().collect();
    let out_filename;
    match args.len() {
        2 => out_filename = &args[1],
        3 => out_filename = &args[2],
        _ => panic!("Too many params !"),
    };
}

Solution 2

As Francis Gagné mentioned, String and &str are not the same. The easiest way to convert them is to just use to_string(). It isn't always the best thing to do, but it will do while you are just learning because it will mostly work. You can read more about strings here.

let mut out_filename = "".to_string();
let args: Vec<_> = env::args().collect();
match args.len() {
    2 => out_filename = args[1].clone(),
    3 => out_filename = args[2].clone(),
    _ => panic!("To many params !"),
};

Note, I also fixed another error you would have come across, because of moving a value out of args. Explicitly cloning them, as I have done above, is one way of fixing that, and probably the easiest because you won't have to worry about lifetimes either.

Share:
17,949

Related videos on Youtube

MrSpock
Author by

MrSpock

Updated on September 15, 2022

Comments

  • MrSpock
    MrSpock over 1 year

    I'm trying to assign variable value (type String) based on the number of args:

    let mut out_filename = "";
    let args: Vec<_> = env::args().collect();
    match args.len() {
        2 => out_filename = args[1],
        3 => out_filename = args[2],
        _ => panic!("To many params !"),
    };
    

    And I'm getting

    src/main.rs:39:29: 39:36 error: mismatched types:
     expected `&str`,
        found `collections::string::String`
    (expected &-ptr,
        found struct `collections::string::String`) [E0308]
    src/main.rs:39         2 => out_filename = args[1],
    

    How to make a match statement where the match value (1,2,3) is just a selector and the returned type is different? There is no let var = match ..