Lifetime of variable in a match pattern

只谈情不闲聊 提交于 2019-12-12 03:15:31

问题


Trying to compile the following code:

#[derive(Show)]
pub enum E1 {
    A,
    B,
}
#[derive(Show)]
pub enum E2 {
    X(E1),
    Y(i32),
}

impl std::fmt::String for E1 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        std::fmt::Show::fmt(self, f)
    }
}

impl std::fmt::String for E2 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        std::fmt::Show::fmt(self, f)
    }
}

impl std::error::Error for E2 {
    fn description(&self) -> &'static str {
        match *self {
            E2::X(x) => {
                let d: &'static str = x.description();
                d
            },
            E2::Y(_) => "Unknown error",
        }
    }
}

impl std::error::Error for E1 {
    fn description(&self) -> &'static str {
        match *self {
            E1::A => "Error A",
            E1::B => "Error B",
        }
    }
}

fn main() { }

yields an error:

a.rs:17:39: 17:40 error: `x` does not live long enough
a.rs:17                 let d: &'static str = x.description();
                                              ^
note: reference must be valid for the static lifetime...
a.rs:15:9: 21:10 note: ...but borrowed value is only valid for the match at 15:8
a.rs:15         match *self {
a.rs:16             E2::X(x) => {
a.rs:17                 let d: &'static str = x.description();
a.rs:18                 d
a.rs:19             },
a.rs:20             E2::Y(_) => "Unknown error"
        ...
a.rs:15:15: 15:20 error: cannot move out of borrowed content
a.rs:15         match *self {
                      ^~~~~
a.rs:16:19: 16:20 note: attempting to move value to here
a.rs:16             E2::X(x) => {
                          ^
a.rs:16:19: 16:20 help: to prevent the move, use `ref x` or `ref mut x` to capture value by reference
a.rs:16             E2::X(x) => {
                          ^
error: aborting due to 2 previous errors

Changing the match pattern to E2::X(ref x) produces a perhaps more detailed error but leaves me just as confused:

a.rs:16:19: 16:24 error: cannot infer an appropriate lifetime for pattern due to conflicting requirements
a.rs:16             E2::X(ref x) => {
                          ^~~~~
a.rs:17:39: 17:40 note: first, the lifetime cannot outlive the expression at 17:38...
a.rs:17                 let d: &'static str = x.description();
                                              ^
a.rs:17:39: 17:40 note: ...so that pointer is not dereferenced outside its lifetime
a.rs:17                 let d: &'static str = x.description();
                                              ^
a.rs:15:9: 21:10 note: but, the lifetime must be valid for the match at 15:8...
a.rs:15         match *self {
a.rs:16             E2::X(ref x) => {
a.rs:17                 let d: &'static str = x.description();
a.rs:18                 d
a.rs:19             },
a.rs:20             E2::Y(_) => "Unknown error"
        ...
a.rs:16:19: 16:24 note: ...so that variable is valid at time of its declaration
a.rs:16             E2::X(ref x) => {
                          ^~~~~
error: aborting due to previous error

The way I see it, x only has to live until x.description() returns, but the compiler seems to thing it needs to outlive the whole match block. Why? Why does it also insist on treating x as a reference when copying would probably be more logical?


回答1:


As for x versus ref x, x won’t work because you have only a reference to self and so cannot move the E1 value out of it—all you can do is take a reference to it.

But now the more important thing: you’ve got your definition of the description method incorrect, and the Rust compiler isn’t warning you about that but is rather making life unpleasant for you.

This is the actual definition of the description method:

fn description(&self) -> &str;

Note carefully: &str, not &'static str. The compiler should have objected to the 'static in the signature, but alas, it did not. (This is the subject of https://github.com/rust-lang/rust/issues/21508, filed on account of this question.) Normally having specified a greater lifetime will be just fine, for it will just shrink it down to size, but in some situations it won’t do what you thought it would—specifically, it has changed E1’s description method to return a &str with its own lifetime, but in the E2 definition it is still wanting to return &'static str. Of course, the x reference is not 'static, so it fails to do it. Confusing, huh? Don’t worry, it’s mostly not your fault!

To fix this, remove all occurrences of 'static, to match the trait definition. Then because x is inside self the lifetimes will line up appropriately.



来源:https://stackoverflow.com/questions/28089695/lifetime-of-variable-in-a-match-pattern

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!