- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
作为一个 Rust 新手,我可能有点天真地从这个开始:
...
pub trait Decode<T> {
fn decode_from<R: io::Read + ?Sized>(&mut self, stream: &mut R) -> T;
}
pub struct MQTTFrame<'a> {
pub payload: &'a Vec<u8>,
}
pub struct MQTTFrameDecoder<'a> {
pub payload: &'a mut Vec<u8>,
}
impl<'a> Decode<MQTTFrame<'a>> for MQTTFrameDecoder<'a> {
fn decode_from<R: io::Read + ?Sized>(&mut self, stream: &mut R) -> MQTTFrame<'a> {
stream.read(&mut self.payload);
MQTTFrame{ payload: self.payload }
}
}
在尝试编译时,遇到了:
src/testbed/mod.rs:31:24: 31:36 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements [E0495]
src/testbed/mod.rs:31 MQTTFrame{ payload: self.payload }
^~~~~~~~~~~~
src/testbed/mod.rs:29:5: 32:6 help: consider using an explicit lifetime parameter as shown: fn decode_from<R: io::Read + ?Sized>(&'a mut self, stream: &mut R)
-> MQTTFrame<'a>
src/testbed/mod.rs:29 fn decode_from<R: io::Read + ?Sized>(&mut self, stream: &mut R) -> MQTTFrame<'a> {
src/testbed/mod.rs:30 stream.read(&mut self.payload);
src/testbed/mod.rs:31 MQTTFrame{ payload: self.payload }
src/testbed/mod.rs:32 }
StackOverflow 上的某处 - 抱歉,我忘记了 - 类似案例中的某个人建议像这样添加生命周期参数(省略未更改的代码):
pub trait Decode<'a, T> {
fn decode_from<R: io::Read + ?Sized>(&'a mut self, stream: &mut R) -> T;
}
impl<'a> Decode<'a, MQTTFrame<'a>> for MQTTFrameDecoder<'a> {
fn decode_from<R: io::Read + ?Sized>(&'a mut self, stream: &mut R) -> MQTTFrame<'a> {
stream.read(&mut self.payload);
MQTTFrame{ payload: self.payload }
}
}
你瞧!它编译。现在,如果我能理解为什么 它可以编译。谁能解释一下
最佳答案
这是一个编译失败的精简测试用例 (playpen):
pub trait Decode<T> {
fn decode_from<'b>(&'b mut self) -> T;
}
pub struct MQTTFrame<'a> {
pub payload: &'a Vec<u8>,
}
pub struct MQTTFrameDecoder<'a> {
pub payload: &'a mut Vec<u8>,
}
impl<'a> Decode<MQTTFrame<'a>> for MQTTFrameDecoder<'a> {
fn decode_from<'b>(&'b mut self) -> MQTTFrame<'a> {
MQTTFrame{ payload: self.payload }
}
}
请注意,我有 elided the lifetimes对于 decode_from
函数并删除了多余的流参数。
很明显,该函数正在使用任意短生命周期的引用 'b
,然后将其扩展为具有生命周期 'a
.这是可变引用的问题,因为你可以同时以可变和不可变的方式借用一些东西:
fn main() {
let mut v = vec![];
/* lifetime 'a */ {
let mut decoder = MQTTFrameDecoder{ payload: &mut v };
let frame: MQTTFrame;
/* lifetime 'b */ {
frame = decoder.decode_from(); // borrows decoder just for lifetime 'b
}
// v is mutably borrowed (by decoder) and immutably borrowed (by frame) at the same time! oops!
decoder.payload.push(1);
println!("{:?}", frame.payload);
}
}
因此,借用检查器拒绝让函数编译。
如果您强制引用 decoder
拥有一生'a
,不过,那就不再有问题了。编译器不能使用生命周期较短的引用,它必须可变地借用 decoder
更长的时间,因此当我们再次尝试借用它时,编译器应该给我们一个错误。
为了实现这一点,我们想写
fn decode_from(&'a mut self) -> MQTTFrame<'a> {
MQTTFrame{ payload: self.payload }
}
但是现在我们得到一个错误:
<anon>:14:5: 16:6 error: method `decode_from` has an incompatible type for trait:
expected bound lifetime parameter 'b,
found concrete lifetime [E0053]
为了解决这个问题,我们需要让我们的 trait 知道你只能 decode_from
某些生命,而不是任意的生命。所以将解码更改为
pub trait Decode<'a, T> {
fn decode_from(&'a mut self) -> T;
}
并对实现进行适当的更改
impl<'a> Decode<'a, MQTTFrame<'a>> for MQTTFrameDecoder<'a> { ... }
现在如果我们尝试上面的代码 (playpen is.gd/BLStYq),借用检查器会提示:
<anon>:28:9: 28:24 error: cannot borrow `*decoder.payload` as mutable more than once at a time [E0499]
<anon>:28 decoder.payload.push(1);
那是因为,现在,对 decoder
的引用必须有生命周期 'a
当它被用来调用函数时 decode_from
.注释掉有问题的行,示例的其余部分可以编译!这段代码现在是安全的,因为没有任何可变生命周期被延长。
旁白:
作为引用decoder
必须与解码器本身一样长,你不能实际使用 decoder
在你调用decode_from
之后.在这种情况下,最好用 self
来表达。而不是 &'a mut self
.这样语法就更简洁了,而且很明显,一旦使用了解码器,就不能再使用了。
pub trait Decode<T> {
fn decode_from(self) -> T;
}
pub struct MQTTFrame<'a> {
pub payload: &'a Vec<u8>,
}
pub struct MQTTFrameDecoder<'a> {
pub payload: &'a mut Vec<u8>,
}
impl<'a> Decode<MQTTFrame<'a>> for MQTTFrameDecoder<'a> {
fn decode_from(self) -> MQTTFrame<'a> {
MQTTFrame{ payload: self.payload }
}
}
关于rust - 为什么我的特征需要生命周期参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36117966/
我正在开发一个使用多个 turtle 的滚动游戏。玩家 turtle 根据按键命令在 Y 轴上移动。当危害和好处在 X 轴上移动时,然后循环并改变 Y 轴位置。我尝试定义一个名为 colliding(
我不明白为什么他们不接受这个作为解决方案,他们说这是一个错误的答案:- #include int main(void) { int val=0; printf("Input:- \n
我正在使用基于表单的身份验证。 我有一个注销链接,如下所示: 以及对应的注销方法: public String logout() { FacesContext.getCurren
在 IIS7 应用程序池中有一个设置 Idle-time out 默认是 20 分钟,其中说: Amount of time(in minutes) a worker process will rem
我是一名优秀的程序员,十分优秀!