如何告诉编译器我返回的枚举的变体总是没有生命周期?

How to tell the compiler the variant of the enum I'm returning always has no lifetime?

下面的代码不会编译,因为编译器认为我不应该分配给 t1 因为它是借用的,但实际上函数 always_returns_no_lifetime 总是返回enum其实是没有生命周期的,所以我修改t1也没问题。我怎样才能让编译器理解这个或者我应该如何重新组织我的代码来避免这个错误发生?

#[derive(Clone)]
enum Types<'a> {
    NoLifetime(i32),
    AlsoNoLifetime(i32),
    AlsoAlsoNoLifetime(i32),
    HasLifetime(&'a str)
}

fn always_returns_no_lifetime<'a>(some_type: &'a Types) -> Types<'a> {
    match *some_type {
        Types::HasLifetime(text) => panic!("I only return the type that has no lifetime"),
        _ => some_type.clone()
    }
}


fn main() {
    let mut t1 = Types::NoLifetime(20);

    let copy = always_returns_no_lifetime(&t1);

    t1 = Types::NoLifetime(30);

}

playground

错误是:

error[E0506]: cannot assign to `t1` because it is borrowed
  --> src/main.rs:23:5
   |
21 |     let copy = always_returns_no_lifetime(&t1);
   |                                            -- borrow of `t1` occurs here
22 |     
23 |     t1 = Types::NoLifetime(30);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `t1` occurs here

不要在 reference 上应用 'a 生命周期参数,而是在 Types 上应用它,就像您已经对 return 所做的那样类型。当您调用 .clone() 时,引用的生命周期并不重要。

fn always_returns_no_lifetime<'a>(some_type: &Types<'a>) -> Types<'a> {
    match *some_type {
        Types::HasLifetime(text) => panic!("I only return the type that has no lifetime"),
        _ => some_type.clone()
    }
}

你的函数的 return 类型是错误的。如果 return 值保证没有任何生命周期,那么它应该被标记为这样,而不是绑定到任意生命周期:

fn always_returns_no_lifetime(...) -> Types<'static>;

通过此更改,您实际上也不再需要任何 input 生命周期,因为它们仅用于绑定输入和输出,引导以下签名:

fn always_returns_no_lifetime(some_type: &Types) -> Types<'static>;

不幸的是,这意味着 clone 现在超出了 table,因为它克隆了生命周期,所以实现也必须改变:

fn always_returns_no_lifetime(some_type: &Types) -> Types<'static> {
    match *some_type {
        Types::HasLifetime(_)
            => panic!("I only return values that have no lifetime"),
        Types::NoLifetime(i) => Types::NoLifetime(i),
        Types::AlsoNoLifetime(i) => Types::AlsoNoLifetime(i),
        Types::AlsoAlsoNoLifetime(i) => Types::AlsoAlsoNoLifetime(i),
    }
}

此实施的好处可以在以下示例中展示:

fn tie<'a>(text: &'a str) -> Types<'a> {
    if text[0] == 'a' {
        Types::HasLifetime(text)
    } else {
        Types::NoLifetime(0)
    }
}

fn main() {
    let no_lifetime = {
        let string = String::from("Hello, world");
        let has_lifetime = tie(&*string);
        always_returns_no_lifetime(&has_lifetime)
    };

    //  Requires deriving Debug, all structs really should...
    println!("{:?}", no_lifetime);
}

如果你在不需要的时候保留生命周期,你就不能编译这个例子,这是一个不必要的限制。