为什么在第一种情况下显式注释所需的生命周期,而在第二种情况下却不需要?
Why is explicitly annotating the lifetime required in the first case, but not in the second?
此处,需要为 items
显式注释 'a
:
struct App<'a> {
items: StatefulList<'a, (&'a str, &'a str, usize)>,
}
impl<'a> App<'a> {
fn new(items: &'a Vec<(&'a str, &'a str, usize)>) -> App<'a> {
App {
items: StatefulList::with_items(items),
}
}
}
然而,这里不是:
struct StatefulList<'a, T> {
state: ListState,
items: &'a Vec<T>,
}
impl<'a, T> StatefulList<'a, T> {
fn with_items(items: &Vec<T>) -> StatefulList<T> {
StatefulList {
state: ListState::default(),
items,
}
}
}
这是为什么?
目前,我认为这是因为编译器无法在第一种情况下计算出生命周期。
问题是在第二个中你没有 return 任何必须处理生命周期的东西,而是 StatefulList
的自有版本。在第一个中,它需要将生命周期与您 returning 相匹配,以确保您 return 的数据可能足够长寿。
事实上你甚至不需要一些注释,因为编译器会为你强制生命周期。
impl<'a> App<'a> {
fn new(items: &'a Vec<(&str, &str, usize)>) -> App<'a> {
App {
items: StatefulList::with_items(items),
}
}
}
&str
需要至少活到 &'a Vec
。
因为这件小事:
fn with_items(items: &Vec<T>) -> StatefulList<T> {
// ^ here, where did the lifetime go?
StatefulList
声明为有生命周期。但是你省略了生命周期!省略时的寿命是多少?
它是被省略的生命周期,'_
,或者是“搞清楚”的生命周期。编译器通过简单的 liftime elision rules“弄清楚了”。这些规则的一部分是,当参数中只有一个生命周期时(如本例 - items: &Vec<T>
的隐式生命周期),return 类型中的生命周期全部继承它。这么写明了,签名是:
fn with_items<'b>(items: &'b Vec<T>) -> StatefulList<'b, T>
impl
块 的 'a
生命周期根本没有使用 。 returned StatefulList
与参数具有相同的生命周期 - 这非常好,因为您将参数用于其 items
!
另一方面,在第一种情况下,我们明确指定 impl
块的 'a
生命周期。您仍然使用该参数,因此参数的生命周期必须匹配 - 它也必须是 'a
。
有一个 lint 可以帮助您避免这种情况:它被称为 elided_lifetimes_in_paths
,并且是 rust_2018_idioms
lints 组的一部分,我强烈建议 #![forbid]
ing 用于新的项目。如果你这样做,编译器会抱怨:
error: hidden lifetime parameters in types are deprecated
--> src/lib.rs:12:51
|
12 | fn with_items(items: &Vec<T>) -> StatefulList<T> {
| ^ expected named lifetime parameter
|
note: the lint level is defined here
--> src/lib.rs:1:11
|
1 | #![forbid(rust_2018_idioms)]
| ^^^^^^^^^^^^^^^^
= note: `#[forbid(elided_lifetimes_in_paths)]` implied by `#[forbid(rust_2018_idioms)]`
help: consider using the `'_` lifetime
|
12 | fn with_items(items: &Vec<T>) -> StatefulList<'_, T> {
| +++
此处,需要为 items
显式注释 'a
:
struct App<'a> {
items: StatefulList<'a, (&'a str, &'a str, usize)>,
}
impl<'a> App<'a> {
fn new(items: &'a Vec<(&'a str, &'a str, usize)>) -> App<'a> {
App {
items: StatefulList::with_items(items),
}
}
}
然而,这里不是:
struct StatefulList<'a, T> {
state: ListState,
items: &'a Vec<T>,
}
impl<'a, T> StatefulList<'a, T> {
fn with_items(items: &Vec<T>) -> StatefulList<T> {
StatefulList {
state: ListState::default(),
items,
}
}
}
这是为什么?
目前,我认为这是因为编译器无法在第一种情况下计算出生命周期。
问题是在第二个中你没有 return 任何必须处理生命周期的东西,而是 StatefulList
的自有版本。在第一个中,它需要将生命周期与您 returning 相匹配,以确保您 return 的数据可能足够长寿。
事实上你甚至不需要一些注释,因为编译器会为你强制生命周期。
impl<'a> App<'a> {
fn new(items: &'a Vec<(&str, &str, usize)>) -> App<'a> {
App {
items: StatefulList::with_items(items),
}
}
}
&str
需要至少活到 &'a Vec
。
因为这件小事:
fn with_items(items: &Vec<T>) -> StatefulList<T> {
// ^ here, where did the lifetime go?
StatefulList
声明为有生命周期。但是你省略了生命周期!省略时的寿命是多少?
它是被省略的生命周期,'_
,或者是“搞清楚”的生命周期。编译器通过简单的 liftime elision rules“弄清楚了”。这些规则的一部分是,当参数中只有一个生命周期时(如本例 - items: &Vec<T>
的隐式生命周期),return 类型中的生命周期全部继承它。这么写明了,签名是:
fn with_items<'b>(items: &'b Vec<T>) -> StatefulList<'b, T>
impl
块 的 'a
生命周期根本没有使用 。 returned StatefulList
与参数具有相同的生命周期 - 这非常好,因为您将参数用于其 items
!
另一方面,在第一种情况下,我们明确指定 impl
块的 'a
生命周期。您仍然使用该参数,因此参数的生命周期必须匹配 - 它也必须是 'a
。
有一个 lint 可以帮助您避免这种情况:它被称为 elided_lifetimes_in_paths
,并且是 rust_2018_idioms
lints 组的一部分,我强烈建议 #![forbid]
ing 用于新的项目。如果你这样做,编译器会抱怨:
error: hidden lifetime parameters in types are deprecated
--> src/lib.rs:12:51
|
12 | fn with_items(items: &Vec<T>) -> StatefulList<T> {
| ^ expected named lifetime parameter
|
note: the lint level is defined here
--> src/lib.rs:1:11
|
1 | #![forbid(rust_2018_idioms)]
| ^^^^^^^^^^^^^^^^
= note: `#[forbid(elided_lifetimes_in_paths)]` implied by `#[forbid(rust_2018_idioms)]`
help: consider using the `'_` lifetime
|
12 | fn with_items(items: &Vec<T>) -> StatefulList<'_, T> {
| +++