strum icon indicating copy to clipboard operation
strum copied to clipboard

IntoStaticStr but from immutable reference to an enum From<&MyEnum>

Open bitcoin-eagle opened this issue 2 years ago • 7 comments

I need IntoStaticStr but from immutable reference to an enum From<&MyEnum> for &'static str on an &Enum is it possible to add?

Because without it the only way is to clone the enum to get the static string by using .into() .as_ref() doesn't work either because it doesn't return the 'static lifetime

Or am I just missing some rust construct that can easily achieve this?

use strum_macros::{AsRefStr, IntoStaticStr};

#[derive(AsRefStr, IntoStaticStr)]
enum MyEnum {
    Foo,
}
fn main() {
    let v = MyEnum::Foo;
    let str2: &'static str = v.as_ref();
    let str: &'static str = v.into();
    drop(v);
}
error[E0597]: `v` does not live long enough
  --> src/main.rs:9:30
   |
8  |     let v = MyEnum::Foo;
   |         - binding `v` declared here
9  |     let str2: &'static str = v.as_ref();
   |               ------------   ^^^^^^^^^^ borrowed value does not live long enough
   |               |
   |               type annotation requires that `v` is borrowed for `'static`
...
12 | }
   | - `v` dropped here while still borrowed

error[E0505]: cannot move out of `v` because it is borrowed
  --> src/main.rs:10:29
   |
8  |     let v = MyEnum::Foo;
   |         - binding `v` declared here
9  |     let str2: &'static str = v.as_ref();
   |               ------------   ---------- borrow of `v` occurs here
   |               |
   |               type annotation requires that `v` is borrowed for `'static`
10 |     let str: &'static str = v.into();
   |                             ^ move out of `v` occurs here

error[E0505]: cannot move out of `v` because it is borrowed
  --> src/main.rs:11:10
   |
8  |     let v = MyEnum::Foo;
   |         - binding `v` declared here
9  |     let str2: &'static str = v.as_ref();
   |               ------------   ---------- borrow of `v` occurs here
   |               |
   |               type annotation requires that `v` is borrowed for `'static`
10 |     let str: &'static str = v.into();
11 |     drop(v);
   |          ^ move out of `v` occurs here

error[E0382]: use of moved value: `v`
   --> src/main.rs:11:10
    |
8   |     let v = MyEnum::Foo;
    |         - move occurs because `v` has type `MyEnum`, which does not implement the `Copy` trait
9   |     let str2: &'static str = v.as_ref();
10  |     let str: &'static str = v.into();
    |                               ------ `v` moved due to this method call
11  |     drop(v);
    |          ^ value used here after move
    |
note: `into` takes ownership of the receiver `self`, which moves `v`
   --> /home/lajos/snap/rustup/common/rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:448:13
    |
448 |     fn into(self) -> T;
    |             ^^^^

Some errors have detailed explanations: E0382, E0505, E0597.
For more information about an error, try `rustc --explain E0382`.

bitcoin-eagle avatar Aug 16 '23 02:08 bitcoin-eagle

#131 AsStr would solve it https://github.com/Peternator7/strum/issues/131#issuecomment-1286851891

bitcoin-eagle avatar Aug 16 '23 02:08 bitcoin-eagle

maybe also duplicate of #152 ?

bitcoin-eagle avatar Aug 16 '23 02:08 bitcoin-eagle

Aww, it actually works with the depracated feature. Can you undeprecate it? or maybe just rename to as_str as suggested in https://github.com/Peternator7/strum/issues/131#issuecomment-1286851891 ?

use strum::{AsStaticRef, AsStaticStr};

#[derive(AsStaticStr)]
enum MyEnum {
    Foo,
}
fn main() {
    let v = MyEnum::Foo;
    let str3: &'static str = v.as_static();
    println!("{}", str3);
    drop(v);
}

bitcoin-eagle avatar Aug 16 '23 03:08 bitcoin-eagle

How about AsStaticRef<str> -> AsStr and AsStaticStr -> AsStr

pub trait AsStr{
    fn as_str(&self) -> &'static str
}

Plus also if the From<&MyEnum> is possible for IntoStaticStr

bitcoin-eagle avatar Aug 16 '23 03:08 bitcoin-eagle

This should already work, but you might need to play with the de-refs to get rustc to pick the right impl. Check out this test for an example

Peternator7 avatar Aug 26 '23 22:08 Peternator7

you are correct, it works.

So I turn this into a question. I don't know how to declare Into<&'static str> trait so it works for both Enum and &Enum. Whereas with AsStaticStr it works. Here is the code I want to make work.

What trait should be added to EnumIntoStaticStr so it compiles?

use strum::{AsStaticRef, AsStaticStr, IntoStaticStr};

trait EnumIntoStaticStr: Into<&'static str> {}
impl<T: Into<&'static str>> EnumIntoStaticStr for T {}
trait EnumAsStaticStr: AsStaticRef<str> {}
impl<T: AsStaticRef<str>> EnumAsStaticStr for T {}

#[derive(AsStaticStr)]
enum MyEnum {
    Foo,
    Bar(String),
}

#[derive(IntoStaticStr)]
enum MyEnum2 {
    Foo2,
    Bar(String),
}

fn main() {
    let v = MyEnum::Foo;
    let str = borrow_as_str(&v);
    drop(v);
    println!("{}", str);

    let v2 = MyEnum2::Foo2;
    let str2 = borrow_into_str(&v2);
    drop(v2);
    println!("{}", str2);
}

fn move_as_str(v: impl EnumAsStaticStr) -> &'static str {
    v.as_static()
}

fn borrow_as_str(v: &impl EnumAsStaticStr) -> &'static str {
    v.as_static()
}

fn move_into_str(v: impl EnumIntoStaticStr) -> &'static str {
    v.into()
}

fn borrow_into_str(v: &impl EnumIntoStaticStr) -> &'static str {
    v.into()
}

Error:

error[E0277]: the trait bound `&str: From<&impl EnumIntoStaticStr>` is not satisfied
  --> src/main.rs:45:7
   |
45 |     v.into()
   |       ^^^^ the trait `From<&impl EnumIntoStaticStr>` is not implemented for `&str`
   |
   = note: required for `&impl EnumIntoStaticStr` to implement `Into<&str>`
help: consider dereferencing here
   |
45 |     (*v).into()
   |     ++ +

For more information about this error, try `rustc --explain E0277`.```

bitcoin-eagle avatar Sep 17 '23 05:09 bitcoin-eagle

I got my answer on stackoverflow https://stackoverflow.com/questions/77120723/how-to-declare-supertraits-intot-so-it-works-with-both-move-and-borrow/77122298#77122298

I would vouch for keeping AsStaticStr because there is a difference from IntoStaticStr as shown in previous comment.

Apart from that this issue can be closed from my side

bitcoin-eagle avatar Sep 18 '23 01:09 bitcoin-eagle