作为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 }
        }
    }
    

    请注意,我为decode_from函数添加了elided the lifetimes,并删除了冗余流参数。

    显然,该函数正在使用任意短生存期'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更长的时间,因此当我们尝试再次借用decode_from时,编译器应给我们一个错误。

    为了实现这一点,我们想写
    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]
    

    要解决此问题,我们需要让我们的特征了解到,您只能对某些生存期进行decoder编码,而不能对任意生命期进行'a编码。因此将解码更改为
    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);
    

    这是因为,现在为了对函数decode_from进行调用,对decoder的引用必须具有生存期decoder。注释掉违规行,然后其余示例将编译!现在,此代码是安全的,因为没有延长任何可变生命周期。

    在旁边:

    由于对decode_from的引用必须与解码器本身一样长,因此,在调用self之后,您根本无法使用&'a mut self。在这种情况下,最好采用ojit_code而不是ojit_code来表达这一点。然后,语法会更简洁一些,很明显,一旦使用了解码器,便无法再次使用它。
    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 }
        }
    }
    

    10-08 11:56