- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
将特征对象传递给函数时,如何处理生存期?
struct Planet<T> {
i: T,
}
trait Spinner<T> {
fn spin(&self, value: T);
}
impl<T> Spinner<T> for Planet<T> {
fn spin(&self, value: T) {}
}
// foo2 fails: Due to lifetime of local variable being less than 'a
fn foo2<'a>(t: &'a Spinner<&'a i32>) {
let x: i32 = 10;
t.spin(&x);
}
// foo1 passes: But here also the lifetime of local variable is less than 'a?
fn foo1<'a>(t: &'a Planet<&'a i32>) {
let x: i32 = 10;
t.spin(&x);
}
error[E0597]: `x` does not live long enough
--> src/main.rs:16:17
|
16 | t.spin(&x);
| ^ borrowed value does not live long enough
17 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 14:5...
--> src/main.rs:14:5
|
14 | fn foo2<'a>(t: &'a Spinner<&'a i32>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
foo1
的功能签名与
foo2
几乎相同。一个接收对struct的引用,另一个接收trait对象。
foo2(t: &for<'a> Spinner<&'a i32>)
会编译代码,但是我不明白为什么。
'a
不会缩小为
x
?
How on earth are we supposed to express the lifetimes on
F
's trait bound? We need to provide some lifetime there, but the lifetime we care about can't be named until we enter the body of call! Also, that isn't some fixed lifetime;call
works with any lifetime&self
happens to have at that point.
最佳答案
简而言之: foo1
可以进行编译,因为大多数类型都是其通用参数的变体,并且编译器仍可以为Spinner
选择t
impl。 foo2
无法编译,因为特征对其通用参数不变,并且Spinner
impl已修复。
一些解释
让我们看一下foo
的第三个版本:
fn foo3<'a>(t: &'a Planet<&'a i32>) {
let x: i32 = 10;
Spinner::<&'a i32>::spin(t, &x);
}
foo2
相同的错误。那里发生了什么事?
Spinner::<&'a i32>::spin
,我们强制编译器使用
Spinner
特性的特定实现。
Spinner::<&'a i32>::spin
的签名是
fn spin(&self, value: &'a i32)
。时期。生命周期
'a
由调用者给定;
foo
无法选择它。因此,我们必须传递一个至少存在
'a
的引用。这就是为什么发生编译器错误。
foo1
会编译? 提醒一下:
fn foo1<'a>(t: &'a Planet<&'a i32>) {
let x: i32 = 10;
t.spin(&x);
}
'a
也是由调用方提供的,不能由
foo1
选择。但是,
foo1
可以选择要使用的
Spinner
的暗示!请注意,
impl<T> Spinner<T> for Planet<T>
基本上定义了许多特定的实现(每个
T
一个)。因此,编译器也知道
Planet<&'x i32>
确实实现了
Spinner<&'x i32>
(其中
'x
是函数中
x
的特定生存期)!
Planet<&'a i32>
转换为
Planet<&'x i32>
。是的,它可以,因为
Planet<&'a i32>
是
Planet<&'x i32>
的子类型(实际上是
most types are variant over their generic parameters),因此
'a
也是
'x
的子类型。因此,编译器仅将
t
转换为
Planet<&'x i32>
,然后可以使用
Spinner<&'x i32>
impl。
foo2
不能编译?再次提醒您:fn foo2<'a>(t: &'a Spinner<&'a i32>) {
let x: i32 = 10;
t.spin(&x);
}
'a
由调用方提供,而foo2
无法选择它。不幸的是,现在我们已经有一个特定的实现!即Spinner<&'a i32>
。我们不能仅仅假设我们被传递的东西还为其他任何生命周期Spinner<&'o i32>
实现了'o != 'a
! Traits are invariant over their generic parameters。'a
一样长。但是我们不能认为我们得到的东西也可以处理比'a
短的生命期!struct Star;
impl Spinner<&'static i32> for Star {
fn spin(&self, value: &'static i32) {}
}
static SUN: Star = Star;
foo2(&SUN);
'a
的foo2
是'static
。实际上,Star
仅对Spinner
的'static
引用实现i32
。foo
的第四个版本:fn foo4<'a, S: Spinner<&'a i32>>(t: &'a S) {
let x: i32 = 10;
t.spin(&x);
}
Spinner
impl已经修复!与trait对象一样,我们只知道S
实现Spinner<&'a i32>
,不一定更多。fn foo2(t: &for<'a> Spinner<&'a i32>)
fn foo4<S: for<'a> Spinner<&'a i32>>(t: &S)
Spinner
的具体含义!取而代之的是,我们又有无限多个提示可供选择(每个'a
一个)。因此,我们可以选择impl where 'a == 'x
。
关于rust - 为什么作为参数传递的特征对象的生存期需要较高的特质界限,而结构却不需要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66085790/
我浏览了该网站和其他网站,找不到关于这种特质的任何解释,也找不到任何解决方案。 尽管在这些站点上有各种说法,但是Javascript和HTML5 DOM音频似乎无法在所有浏览器上正常工作,正如在各个站
beginGeneratingDeviceOrientationNotifications是否将状态栏重置回纵向? 在我的应用程序中,在下面记录 o 和 p: UIInterfaceOrientati
我开始意识到这是为初学者准备的: package Bad; has 'arr' => ( is => 'rw', 'ArrayRef[Str]' ); package main; my $bad =
只是想知道如何将的特征与放入vec中?我以为这应该是一个常见的问题,但我从未搜索过答案。 这是代码: use tokio::time::{delay_for, Duration}; #[async_t
更新 我的真正问题是由我的IDE自动导入了use std::borrow::{Borrow, BorrowMut};引起的。 在此行中,接受的答案为also doesn't compile。 解决方案
我正在尝试为 P/Invoke 正确编码(marshal)一些结构,但在 64 位操作系统上测试时发现奇怪的行为。 我有一个结构定义为: /// http://msdn.microsoft.com/e
说我有: abstract class D[T] {} trait A[T] { self => D[T] without B } trait B[T] { self => D[T] without
我尝试使用clap库创建一个简单的应用程序来解析命令行参数,并将其转换为Config自定义结构。我为我的结构实现了From特征,但是,当我尝试调用from函数时,收到以下错误: the trait b
在 Laravel 5.0 中,trait AuthenticatesAndRegistersUsers 中的方法 redirectPath 检查属性 redirectPath 或 redirectT
虽然这个问题有点与语言无关(就支持 Traits 的 OOP 语言而言)我一直在修补 PHP 5.4a 的夜间构建,并遇到了一个奇怪的场景。我似乎无法再运行我的安装,但那是另一回事了。 给定以下代码段
我是一名优秀的程序员,十分优秀!