当泛型类型受泛型生命周期限制时,这意味着什么?
What does it mean when a generic type is bounded by a generic lifetime?
我正在研究 Rust 的生命周期。生命周期用 'a
表示,可以这样使用:
fn function1<'a>(param1: &'a str) -> &'a str
然而我找到了这段代码:
impl<'a, T: 'a> RingBuffer<'a, T> {
T
的类型 'a
对我来说毫无意义。类型和生命周期对我来说不是一回事。发生什么事了?
T: 'a
的生命周期为 T
。来自 rust reference:
T: 'a
means that all lifetime parameters of T
outlive 'a
. For example
if 'a
is an unconstrained lifetime parameter then i32: 'static
and
&'static str: 'a
are satisfied but Vec<&'a ()>: 'static
is not.
在您提供的特定代码中,生命周期限制 T: 'a
表示您放入环形缓冲区的内容的生命周期必须至少与 RingBuffer
的生命周期一样长.
当您看到一个泛型类型参数后跟一个冒号和一个生命周期时,这意味着生命周期绑定被放置在该类型上。
例如,在您引用的案例中:
impl<'a, T: 'a> RingBuffer<'a, T> {
类型 T
必须至少与生命周期 'a
一样长(请注意,编译器不知道 T 是什么 - T 本身可能包含引用或包含其他包含引用的类型).
仔细观察 implementation of RingBuffer (which I assume you found in the smoltcp crate), you can see the reason: the RingBuffer
may contain a reference to a borrowed buffer (via ManagedSlice)。这是有道理的:如果你创建一个 RingBuffer
使用可能是堆栈分配的缓冲区,缓冲区必须至少持续到 RingBuffer
.
有一个标题为“Advanced Lifetimes" in an older version of "the book". I could not find it in the newer editions, but I found it useful in understanding this. You might also want to refer to the rust reference section "Trait and lifetime bounds”的部分
T: 'a
应理解为 "T
受 'a
" 的限制而不是 "T
的生命周期为 'a
".
此外,T
包括所有可能的类型,包括具有生命周期的引用类型。 &str
、&i32
等都是 T
中的有效类型。此外,要使用示例的简化版本,您可以拥有一个在生命周期内通用的自有类型,因为它包含一个引用类型,如下所示:
struct Ref<'a, T: 'a>(&'a T);
该结构在 'a
和 T
上是通用的,因为它可以容纳 &'a T
个引用。
还有一点:&'a T
需要 T: 'a
,因为 T
要对 'a
有效,它必须比 'a
长。例如,这种类型的构造将被编译器 &'static Ref<'a, i32>
拒绝,因为如果 Ref
仅对 'a
有效,我们不能对它进行 'static
引用。
我正在研究 Rust 的生命周期。生命周期用 'a
表示,可以这样使用:
fn function1<'a>(param1: &'a str) -> &'a str
然而我找到了这段代码:
impl<'a, T: 'a> RingBuffer<'a, T> {
T
的类型 'a
对我来说毫无意义。类型和生命周期对我来说不是一回事。发生什么事了?
T: 'a
的生命周期为 T
。来自 rust reference:
T: 'a
means that all lifetime parameters ofT
outlive 'a
. For example if'a
is an unconstrained lifetime parameter theni32: 'static
and&'static str: 'a
are satisfied butVec<&'a ()>: 'static
is not.
在您提供的特定代码中,生命周期限制 T: 'a
表示您放入环形缓冲区的内容的生命周期必须至少与 RingBuffer
的生命周期一样长.
当您看到一个泛型类型参数后跟一个冒号和一个生命周期时,这意味着生命周期绑定被放置在该类型上。
例如,在您引用的案例中:
impl<'a, T: 'a> RingBuffer<'a, T> {
类型 T
必须至少与生命周期 'a
一样长(请注意,编译器不知道 T 是什么 - T 本身可能包含引用或包含其他包含引用的类型).
仔细观察 implementation of RingBuffer (which I assume you found in the smoltcp crate), you can see the reason: the RingBuffer
may contain a reference to a borrowed buffer (via ManagedSlice)。这是有道理的:如果你创建一个 RingBuffer
使用可能是堆栈分配的缓冲区,缓冲区必须至少持续到 RingBuffer
.
有一个标题为“Advanced Lifetimes" in an older version of "the book". I could not find it in the newer editions, but I found it useful in understanding this. You might also want to refer to the rust reference section "Trait and lifetime bounds”的部分
T: 'a
应理解为 "T
受 'a
" 的限制而不是 "T
的生命周期为 'a
".
此外,T
包括所有可能的类型,包括具有生命周期的引用类型。 &str
、&i32
等都是 T
中的有效类型。此外,要使用示例的简化版本,您可以拥有一个在生命周期内通用的自有类型,因为它包含一个引用类型,如下所示:
struct Ref<'a, T: 'a>(&'a T);
该结构在 'a
和 T
上是通用的,因为它可以容纳 &'a T
个引用。
还有一点:&'a T
需要 T: 'a
,因为 T
要对 'a
有效,它必须比 'a
长。例如,这种类型的构造将被编译器 &'static Ref<'a, i32>
拒绝,因为如果 Ref
仅对 'a
有效,我们不能对它进行 'static
引用。