Search code examples
rustclap

The trait `std::convert::From<cli::Opts>` is not implemented


I try to create a simple application parsing command line arguments using clap library and converting them to a Config custom structure. I implemented From trait for my structure, however, when I try to call from function, I receive the following error:

the trait bound `minimal_example::Config: std::convert::From<cli::Opts>` is not satisfied
the following implementations were found:
  <minimal_example::Config as std::convert::From<minimal_example::cli::Opts>>
required by `std::convert::From::from` 

Here is the code:

main.rs:

mod cli;

use clap::Clap;
use minimal_example::Config;

fn main() {
    println!("Hello, world!");
    let opts = cli::Opts::parse();
    let config = Config::from(opts);
}

cli.rs:

use clap::{Clap, crate_version};

/// This doc string acts as a help message when the user runs '--help'
/// as do all doc strings on fields
#[derive(Clap)]
#[clap(version = crate_version!(), author = "Yury")]
pub struct Opts {
    /// Simple option
    pub opt: String,
}

lib.rs:

mod cli;

pub struct Config {
    pub opt: String,
}

impl From<cli::Opts> for Config {
    fn from(opts: cli::Opts) -> Self {
        Config {
            opt: opts.opt,
        }
    }
}

cargo.toml:

[package]
name = "minimal_example"
version = "0.1.0"
authors = ["Yury"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
clap = {version="3.0.0-beta.2", features=["wrap_help"]}

What am I doing wrong?


Solution

  • You have added mod cli to both lib.rs and main.rs.

    They are different from the standpoint of each other.

    Rust modules confusion when there is main.rs and lib.rs may help in understanding that.

    That's what the error says. It's satisfied for std::convert::From<minimal_example::cli::Opts> but not for std::convert::From<cli::Opts>.

    A simple fix:

    main.rs

    mod cli;
    use clap::Clap;
    use minimal_example::Config;
    
    impl From<cli::Opts> for Config {
        fn from(opts: cli::Opts) -> Self {
            Config {
                opt: opts.opt,
            }
        }
    }
    
    fn main() {
        println!("Hello, world!");
        let opts = cli::Opts::parse();
        let config = Config::from(opts);
    }
    

    Now std::convert::From<cli::Opts> is implemented for Config.

    How you actually want to place all this depends on your package architecture.