Search code examples
rustclap

How do I pass a String to a method accepting Into<&str>?


I'm trying to pass a String to clap's builder methods:

extern crate clap; // 2.32.0

use clap::App;

const NAME: &'static str = "example";
const DESC_PART_1: &'static str = "desc";
const DESC_PART_2: &'static str = "ription";

fn main() {
    let description: String = format!("{}{}", DESC_PART_1, DESC_PART_2);
    let matches = App::new(NAME).about(description).get_matches();
}

I get the error:

error[E0277]: the trait bound `&str: std::convert::From<std::string::String>` is not satisfied
  --> src/main.rs:11:34
   |
11 |     let matches = App::new(NAME).about(description).get_matches();
   |                                  ^^^^^ the trait `std::convert::From<std::string::String>` is not implemented for `&str`
   |
   = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String`

Live example

I get a similar error if I pass &description. I'm struggling to understand the origin of this error and the reasoning behind clap using the signature pub fn about<S: Into<&'b str>>(self, about: S) -> Self.


Solution

  • With the given (unusual) constraint of Into<&str>, the compiler is unable to turn a String or a &String directly into the requested string slice. There is no such implementation of either From<String>, nor From<&String>, for a string slice. Conversions from an owned string or string-like value to a slice is usually done through other traits.

    Instead, you can:

    1. Use String::as_str(), which always provides &str;
    2. Call as_ref() from the AsRef trait, leading the compiler to choose the implementation AsRef<str> for String;
    3. Or re-borrow the string, thus forcing a conversion to &str.
    let matches = App::new(NAME).about(description.as_str()).get_matches(); // (1)
    let matches = App::new(NAME).about(description.as_ref()).get_matches(); // (2)
    let matches = App::new(NAME).about(&*description).get_matches(); // (3)