Rust 函数与结构的类型参数(生存期问题)

Rust 函数与结构的类型参数(生存期问题),rust,lifetime,Rust,Lifetime,考虑以下测试用例: #![allow(unstable)] trait Choose<'o> { fn choose(a: &'o u64, b: &'o u32) -> Self; } impl<'o> Choose<'o> for &'o u64 { fn choose(a: &'o u64, _b: &'o u32) -> &'o u64 { a } } impl<

考虑以下测试用例:

#![allow(unstable)]
trait Choose<'o> { 
    fn choose(a: &'o u64, b: &'o u32) -> Self; 
}

impl<'o> Choose<'o> for &'o u64 { 
    fn choose(a: &'o u64, _b: &'o u32) -> &'o u64 { a }
}

impl<'o> Choose<'o> for &'o u32 { 
    fn choose(_a: &'o u64, b: &'o u32) -> &'o u32 { b }
} // '

struct Handler {
    a: u64,
    b: u32,
}

impl Handler {
    fn new() -> Handler {
        Handler { a: 14, b: 15 }
    }

    fn find<'a, V, W>(&'a mut self, value: W) -> Option<V> where V: Choose<'a>, W: PartialEq<V> { // '
        let v = Choose::choose(&self.a, &self.b);
        if value == v {
            Some(v)
        } else {
            None
        }
    }
}

fn main() {
    let mut h = Handler::new();

    {
        let v_a = h.find::<&u64, &u64>(&14u64);
        println!("v_a = {:?}", v_a);
    }

    {
        let v_b = h.find::<&u64, &u64>(&15u64);
        println!("v_b = {:?}", v_b);
    }
}


我真的无法理解其中的区别。变量v_a死后为什么不释放可变借用?

这是我对问题的理解,其他人可能会提供更具体的解释


通过向结构中添加类型参数,可以将该类型存储在结构中。由于您还指定您的类型具有trait
Choose选项,其中V:Choose我认为这里发生的是:
在
main
中,当执行
时,让mut h=Handler:::new(),您的处理程序现在绑定到对
u64
的引用的生存期。 因此,即使
v_a
在下面的块中死亡,v的生存期也必须是
h
的生存期,该生存期仍然有效

顺便说一句,问题不在于您已经编写的代码,而在于您或其他人仍然可以编写的代码。 根据你对具有无约束V的Handler的定义,我可以继续执行以下操作:

// in the meanwhile, in another crate...
// I create another trait
trait MyTrait {
    fn foo(&self) -> &u64;
}

// and implement it for Handler<&u64>
impl<'a> MyTrait for Handler<&'a u64> {
    fn foo(&self) -> &u64 { &self.a }
}

“但随后我将参数V移动到处理程序类型签名中”当
处理程序
没有该类型的任何成员时,为什么要这样做?因为对于方法签名中的参数,我可以对一个处理程序实例同时使用find::和find::,我想强制编译器禁止它。但有一个特征函数签名:“fn choose”(a:&'o u64,UB:&'o u32)->&'o u64“也就是说,结果的生存期与参数的生存期相同,与&self的生存期相同?即使在对象中存储对结构的引用,还会发生什么坏事?@Shepmaster,不可能像您所描述的那样,因为您无法将引用存储到该结构中的结构中。@vladimirtaveev我一定是误解了你。我粘贴的代码是编译和运行的(在操作代码的上下文中)。这里还描述了一些保持对你自己的结构的引用的技巧(无论是好是坏)这似乎是一个类似的解决方案,我发誓OP的另一个问题以稍微不同的方式问了同样的问题,但我找不到。
fn find<'a, W>(&'a mut self, value: W) -> Option<V> where V: Choose<'a>, W: PartialEq<V> { //'
    let v = Choose::choose(&self.a, &self.b);

    self.c = Some(Choose::choose(&self.a, &self.b)); // saved

    if value == v {
        Some(v)
    } else {
        None
    }
}
// in the meanwhile, in another crate...
// I create another trait
trait MyTrait {
    fn foo(&self) -> &u64;
}

// and implement it for Handler<&u64>
impl<'a> MyTrait for Handler<&'a u64> {
    fn foo(&self) -> &u64 { &self.a }
}
let h = Handler::<&u64>::new();    
println!("{}", h.foo()); // prints 14
trait Choose<'o> { 
    fn choose(a: &'o u64, b: &'o u32) -> &'o Self; 
}

impl<'o> Choose<'o> for u64 { 
    fn choose(a: &'o u64, _b: &'o u32) -> &'o u64 { a }
}

impl<'o> Choose<'o> for u32 { 
    fn choose(_a: &'o u64, b: &'o u32) -> &'o u32 { b }
}

struct Handler<V> {
    a: u64,
    b: u32,
}

impl<V> Handler<V> {
    fn new() -> Handler<V> {
        Handler { a: 14, b: 15 }
    }

    fn find<'a, W>(&'a mut self, value: W) -> Option<&'a V> where V: Choose<'a>, W: PartialEq<&'a V> {
        let v = Choose::choose(&self.a, &self.b);
        if value == v {
            Some(v)
        } else {
            None
        }
    }
}

fn main() {
    let mut h = Handler::<u64>::new();

    {
        let v_a = h.find(&14u64);
        println!("v_a = {:?}", v_a);
    }

    {
        let v_b = h.find(&15u64);
        println!("v_b = {:?}", v_b);
    }
}