简体   繁体   English

为什么Foo <'a,P <'b >>与Foo2 <'a>不同?

[英]Why is Foo<'a, P<'b>> not the same as Foo2<'a>?

use std::collections::{HashMap, HashSet};

pub struct P<'a> {
    x: &'a str
}

pub struct Foo<'a, T> {
    callbacks: Vec<Box<'a + FnMut(&T)>>
}

impl<'a, T> Foo<'a, T>{
    pub fn foo(&mut self, payload: T) {
    }

}

pub struct Foo2<'a> {
    callbacks: Vec<Box<'a + FnMut(&P)>>
}

impl<'a> Foo2<'a>{
    pub fn foo(&mut self, payload: P) {
    }

}


struct Bar<'a, 'b> {
    x: Foo<'a, P<'b>>,
    y: Foo2<'a>,
    data: HashMap<String, String>
}


impl<'a, 'b> Bar<'a, 'b> {
    // fn test(&mut self) {
    //     // Cannot infer an appropriate lifetime.
    //     match self.data.get("foo") {
    //         Some(x) => {
    //             let p = P {x};
    //             self.x.foo(p);
    //         },
    //         None => {}
    //     }
    // }

    fn test2(&mut self) {
        match self.data.get("foo") {
            Some(x) => {
                let p = P {x};
                self.y.foo(p);
            },
            None => {}
        }
    }

}

Playground . 操场 I'm using rustc 1.19.0-nightly. 我每晚使用rustc 1.19.0。

Why does test2 work but test does not? 为什么test2工作但是test不能工作? How can I correctly make the generic struct Foo ? 我如何正确地使泛型结构Foo

I do not think this example involves Why can't I store a value and a reference to that value in the same struct? 我不认为此示例涉及为什么不能在同一结构中存储值和对该值的引用? and is not a duplicate. 并且不是重复的。

What is 'a , what is 'b ? 什么是'a ,什么是'b

If we isolate the failing case ( note that I introduced a lifetime for self to make it easier ): 如果我们隔离失败的案例( 请注意,我引入了self的生存期以使其变得更容易 ):

pub struct P<'a> {
    x: &'a str
}

pub struct Foo<'a, T> {
    callbacks: Vec<Box<'a + FnMut(&T)>>
}

impl<'a, T> Foo<'a, T>{
    pub fn foo(&mut self, payload: T) {
    }
}

struct Bar<'a, 'b> {
    x: Foo<'a, P<'b>>,
    data: HashMap<String, String>
}


impl<'a, 'b> Bar<'a, 'b> {
    fn test<'c>(&'c mut self) {
        // Cannot infer an appropriate lifetime.
        match self.data.get("foo") {
            Some(x) => {
                let p = P {x};
                self.x.foo(p);
            },
            None => {}
        }
    }
}

The problem here is that when you instantiate Bar , you fix what 'a and 'b is. 这里的问题是当实例化 Bar ,您修复'a'b是什么。

Specifically, this lifetime is NOT 'c , which is totally unrelated. 具体而言,此生存期不是'c ,这是完全无关的。

The compiler sees: 编译器看到:

  • the argument to self.x.foo must have type P<'b> , self.x.foo的参数必须具有P<'b>类型,
  • it has type P<'unknown> , where 'unknown is any lifetime less than 'c , 它的类型为P<'unknown> ,其中'unknown小于 'c生命周期,
  • it has type P<'unknown> , so 'unknown must be greater than 'b , 它的类型为P<'unknown> ,因此'unknown必须大于'b
  • 'b and 'c are unrelated. 'b'c无关。

and has no idea what 'unknown should be. 并且不知道什么是'unknown


A potential solution is to avoid fixing 'b : 一个可能的解决方案是避免修复'b

pub struct Foo<'a> {
    callbacks: Vec<Box<'a + FnMut(&P)>>,
}

impl<'a> Foo<'a> {
    pub fn foo(&mut self, payload: P) {}
}

struct Bar<'a> {
    x: Foo<'a>,
    data: HashMap<String, String>,
}

Note: and at this point, 'a seems superfluous as well. 注意:在这一点上, 'a似乎也是多余的。

However this requires us fixing T as well, because when using a type parameter (as we had with Foo<'a, T> ), then we need to fully specify the type and thus name the lifetime that P will contain. 但是,这也需要我们固定T ,因为在使用类型参数时(就像我们对Foo<'a, T>所做的那样),我们需要完全指定类型,从而命名P将包含的生存期。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM