Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using an enum for the default_value or the possible_values #3287

Closed
2 tasks done
Vagelis-Prokopiou opened this issue Jan 12, 2022 · 2 comments
Closed
2 tasks done

Using an enum for the default_value or the possible_values #3287

Vagelis-Prokopiou opened this issue Jan 12, 2022 · 2 comments
Labels
A-derive Area: #[derive]` macro API C-bug Category: Updating dependencies S-duplicate Status: Closed as Duplicate

Comments

@Vagelis-Prokopiou
Copy link

Vagelis-Prokopiou commented Jan 12, 2022

Please complete the following tasks

  • I have searched the discussions
  • I have searched the existing issues

Rust Version

rustc 1.57.0 (f1edd0429 2021-11-29)

Clap Version

3.0.6

Minimal reproducible code

use std::str::FromStr;
use clap::{Parser};


#[derive(Debug)]
pub enum TranslationProvider { DeepL, Amazon, Google }

impl std::fmt::Display for TranslationProvider {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            TranslationProvider::DeepL => { write!(f, "deepl") }
            TranslationProvider::Amazon => { write!(f, "amazon") }
            TranslationProvider::Google => { write!(f, "google") }
        }
    }
}

impl FromStr for TranslationProvider {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s == "deepl" { return Ok(Self::DeepL); }
        if s == "amazon" { return Ok(Self::Amazon); }
        if s == "google" { return Ok(Self::Google); }
        return Err("This translation provider is not valid".to_owned());
    }
}

/// File translator using DeepL
#[derive(Parser, Debug)]
#[clap(about, version, author)]
struct Args {
    /// The translation provider to use
    #[clap(
    long,
    default_value(&TranslationProvider::DeepL.to_string().as_str()),
    possible_values([
    clap::PossibleValue::new(TranslationProvider::DeepL.to_string().as_str()),
    ]))]
    translation_provider: TranslationProvider,
}

fn main() {
    let args = Args::parse();
}

Steps to reproduce the bug with the above code

cargo run -- --help

Actual Behaviour

I get a build error:

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:38:20
   |
32 | #[derive(Parser, Debug)]
   |          ------
   |          |
   |          lifetime `'b` defined here
   |          argument requires that borrow lasts for `'b`
...
35 |     /// The translation provider to use
   |                                       - temporary value is freed at the end of this statement
...
38 |     default_value(&TranslationProvider::DeepL.to_string().as_str()),
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:40:30
   |
32 | #[derive(Parser, Debug)]
   |          ------
   |          |
   |          lifetime `'b` defined here
   |          argument requires that borrow lasts for `'b`
...
35 |     /// The translation provider to use
   |                                       - temporary value is freed at the end of this statement
...
40 |     clap::PossibleValue::new(TranslationProvider::DeepL.to_string().as_str()),
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use

Expected Behaviour

I think that we should be able to use the string representation of enums some way. Either as String or as String.as_str() or as &String.

Additional Context

No response

Debug Output

No response

@Vagelis-Prokopiou Vagelis-Prokopiou added the C-bug Category: Updating dependencies label Jan 12, 2022
@epage
Copy link
Member

epage commented Jan 12, 2022

In #1041, we plan to evaluate removing the lifetime parameter, most likely with a type like Cow<'static, str> so we can have &'static str and String together. This would help in your case.

We already provide default_value_t (see also the tutorial) which resolves the first problem you had.

Personally, when an enum maps to string values, I do something like

impl TranslationProvider {
    fn as_str(self) -> &'static str {
        match self {
            ...
        }
    }
}


impl std::fmt::Display for TranslationProvider {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.as_str().fmt(f)
    }
}

This is an alternative that resolves your second lifetime issue because you can just call as_str() rather than to_string().as_str().

Alternatively, you could derive or impl the ArgEnum trait (see also the tutorial).

@epage epage added A-derive Area: #[derive]` macro API S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 12, 2022
@Vagelis-Prokopiou
Copy link
Author

Thanks for the feedback @epage.
Removing the lifetime parameter is the best solution to my mind too.
For now, I will try your suggestions out, or will use any other workaround.

If you need anything else from me, let me know.

This issue can be linked to the issue you mentioned, and can be closed, I suppose.

@epage epage added S-duplicate Status: Closed as Duplicate and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 12, 2022
@epage epage closed this as completed Jan 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-derive Area: #[derive]` macro API C-bug Category: Updating dependencies S-duplicate Status: Closed as Duplicate
Projects
None yet
Development

No branches or pull requests

2 participants