匹配模式中变量的生命周期 [英] Lifetime of variable in a match pattern

查看:98
本文介绍了匹配模式中变量的生命周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试编译以下代码:

#[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() { }

产生错误:

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

将匹配模式更改为E2::X(ref x)可能会产生更详细的错误,但让我感到困惑:

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

以我的方式看,x只能生存直到x.description()返回,但是编译器似乎需要使整个match块的生存期延长.为什么?为什么在复制可能更合乎逻辑时,为什么还要坚持将x作为参考?

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?

推荐答案

对于xref x而言,x将不起作用,因为您仅引用了self,因此无法移动E1从中获得价值-您所能做的就是引用它.

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.

但是现在更重要的是:您对description方法的定义不正确,并且Rust编译器没有警告您 ,而是使您的生活变得不愉快

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.

这是description方法的 actual 定义:

fn description(&self) -> &str;

请注意:&str,而不是&'static str.编译器应该已经反对签名中的'static,但是,事实并非如此. (这是 https://github.com/rust-lang/rust/issues的主题/21508 (针对此问题提出).通常,指定更长的生存期就可以了,因为它会将其缩小到一定的大小,但是在某些情况下,它不会做您认为会做的事情-具体来说,它已更改E1description方法以返回具有其生命周期&str,但是在E2定义中,它仍想返回&'static str .当然,x引用不是'static,因此无法执行.令人困惑,是吗?不用担心,这主要不是你的错!

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!

要解决此问题,请删除所有出现的'static,以匹配特征定义.然后,由于x位于self内部,因此生存期会适当对齐.

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.

这篇关于匹配模式中变量的生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆