fn test<'a, T: 'a>(req: T) {
let abc: &'a T = &req;
}
132 | fn test<'a, T: 'a>(req: T) where T: 'a {
| -- --- binding `req` declared here
| |
| lifetime `'a` defined here
133 | let _: &'a T = &req;
| ----- ^^^^ borrowed value does not live long enough
| |
| type annotation requires that `req` is borrowed for `'a`
134 | }
| - `req` dropped here while still borrowed
1
共 7 条评论, 1 页
评论区
写评论鲁迅说过 标记的生命周期只是为了取悦编译器,让编译器不要难为我们, 哈哈哈
--
👇
Happy-Feet-hhh: 有帮助就好,Rust的生命周期确实有些麻烦。虽然Rust Book里面用 存活时间长短 来解释生命周期。但编译器最终还是通过类型来判断。
即使abc本身确实就是个函数内部的局部变量,可以安全的指向已经移动到函数内部的对象。但Rust编译器还是认死理,只要给出的类型标注超过了内部生命周期就报错。
让我想到当初学Rust时看《Rust圣经》里面作者的一句话:
今天回答您的问题才让我回想起当初怎么都看不懂的那句话。哈哈
--
👇
Clownsw: 感谢, 您说的没错, test<'a> 这个'a的生命周期超出了test, T被移动到了test内, test结束后就会被销毁掉, 把T改成借用就可以编译过了
--
👇
Happy-Feet-hhh: ```rust fn test<'a, T: 'a>(req: T) { let abc: &'a T = &req; }
展开后:
如果我写的东西题主能看懂的话,那么就能明白函数签名
fn test<'a, T: 'a>(req: T)
中的'a
是一个来自函数外部的生命周期,它比函数本身的生命周期要长, 即便'a
在test
调用后 马上结束,比如:明白这一点后再回到
fn test<'a, T: 'a>(req: T)
的函数体中,我们将函数体内有关生命周期的东西展开后,得到如下代码:显然,不能够编译正确,因为
'fn_test
为 函数体内部的生命周期, 在函数调用结束时结束。而'a
的生命周期大于函数生命周期。我们不能让一个拥有 更长生命周期的引用 指向 更短生命周期的对象, 因为在这可能会造成 悬垂引用。其实我也不是完全明白编译器怎么处理这些东西的,毕竟我现在也不能完全看懂MIR中间代码的。不过我可以推荐一些网址供题主参考: https://nomicon.purewhite.io/lifetimes.html https://doc.rust-lang.org/reference/subtyping.html#:~:text=Variance%20is%20a%20property%20that%20generic%20types%20have,the%20parameter%20affects%20the%20subtyping%20of%20the%20type.
谢谢
--
👇
github.com/shanliu/lsys: &req 在函数的栈上. test的在'a 外,让栈上引用生命周期等于他外面的栈一样长.
谢谢
--
👇
Happy-Feet-hhh: 有帮助就好,Rust的生命周期确实有些麻烦。虽然Rust Book里面用 存活时间长短 来解释生命周期。但编译器最终还是通过类型来判断。
即使abc本身确实就是个函数内部的局部变量,可以安全的指向已经移动到函数内部的对象。但Rust编译器还是认死理,只要给出的类型标注超过了内部生命周期就报错。
让我想到当初学Rust时看《Rust圣经》里面作者的一句话:
今天回答您的问题才让我回想起当初怎么都看不懂的那句话。哈哈
--
👇
Clownsw: 感谢, 您说的没错, test<'a> 这个'a的生命周期超出了test, T被移动到了test内, test结束后就会被销毁掉, 把T改成借用就可以编译过了
--
👇
Happy-Feet-hhh: ```rust fn test<'a, T: 'a>(req: T) { let abc: &'a T = &req; }
展开后:
如果我写的东西题主能看懂的话,那么就能明白函数签名
fn test<'a, T: 'a>(req: T)
中的'a
是一个来自函数外部的生命周期,它比函数本身的生命周期要长, 即便'a
在test
调用后 马上结束,比如:明白这一点后再回到
fn test<'a, T: 'a>(req: T)
的函数体中,我们将函数体内有关生命周期的东西展开后,得到如下代码:显然,不能够编译正确,因为
'fn_test
为 函数体内部的生命周期, 在函数调用结束时结束。而'a
的生命周期大于函数生命周期。我们不能让一个拥有 更长生命周期的引用 指向 更短生命周期的对象, 因为在这可能会造成 悬垂引用。其实我也不是完全明白编译器怎么处理这些东西的,毕竟我现在也不能完全看懂MIR中间代码的。不过我可以推荐一些网址供题主参考: https://nomicon.purewhite.io/lifetimes.html https://doc.rust-lang.org/reference/subtyping.html#:~:text=Variance%20is%20a%20property%20that%20generic%20types%20have,the%20parameter%20affects%20the%20subtyping%20of%20the%20type.
&req 在函数的栈上. test的在'a 外,让栈上引用生命周期等于他外面的栈一样长.
有帮助就好,Rust的生命周期确实有些麻烦。虽然Rust Book里面用 存活时间长短 来解释生命周期。但编译器最终还是通过类型来判断。
即使abc本身确实就是个函数内部的局部变量,可以安全的指向已经移动到函数内部的对象。但Rust编译器还是认死理,只要给出的类型标注超过了内部生命周期就报错。
让我想到当初学Rust时看《Rust圣经》里面作者的一句话:
今天回答您的问题才让我回想起当初怎么都看不懂的那句话。哈哈
--
👇
Clownsw: 感谢, 您说的没错, test<'a> 这个'a的生命周期超出了test, T被移动到了test内, test结束后就会被销毁掉, 把T改成借用就可以编译过了
--
👇
Happy-Feet-hhh: ```rust fn test<'a, T: 'a>(req: T) { let abc: &'a T = &req; }
展开后:
如果我写的东西题主能看懂的话,那么就能明白函数签名
fn test<'a, T: 'a>(req: T)
中的'a
是一个来自函数外部的生命周期,它比函数本身的生命周期要长, 即便'a
在test
调用后 马上结束,比如:明白这一点后再回到
fn test<'a, T: 'a>(req: T)
的函数体中,我们将函数体内有关生命周期的东西展开后,得到如下代码:显然,不能够编译正确,因为
'fn_test
为 函数体内部的生命周期, 在函数调用结束时结束。而'a
的生命周期大于函数生命周期。我们不能让一个拥有 更长生命周期的引用 指向 更短生命周期的对象, 因为在这可能会造成 悬垂引用。其实我也不是完全明白编译器怎么处理这些东西的,毕竟我现在也不能完全看懂MIR中间代码的。不过我可以推荐一些网址供题主参考: https://nomicon.purewhite.io/lifetimes.html https://doc.rust-lang.org/reference/subtyping.html#:~:text=Variance%20is%20a%20property%20that%20generic%20types%20have,the%20parameter%20affects%20the%20subtyping%20of%20the%20type.
感谢, 您说的没错, test<'a> 这个'a的生命周期超出了test, T被移动到了test内, test结束后就会被销毁掉, 把T改成借用就可以编译过了
--
👇
Happy-Feet-hhh: ```rust fn test<'a, T: 'a>(req: T) { let abc: &'a T = &req; }
展开后:
如果我写的东西题主能看懂的话,那么就能明白函数签名
fn test<'a, T: 'a>(req: T)
中的'a
是一个来自函数外部的生命周期,它比函数本身的生命周期要长, 即便'a
在test
调用后 马上结束,比如:明白这一点后再回到
fn test<'a, T: 'a>(req: T)
的函数体中,我们将函数体内有关生命周期的东西展开后,得到如下代码:显然,不能够编译正确,因为
'fn_test
为 函数体内部的生命周期, 在函数调用结束时结束。而'a
的生命周期大于函数生命周期。我们不能让一个拥有 更长生命周期的引用 指向 更短生命周期的对象, 因为在这可能会造成 悬垂引用。其实我也不是完全明白编译器怎么处理这些东西的,毕竟我现在也不能完全看懂MIR中间代码的。不过我可以推荐一些网址供题主参考: https://nomicon.purewhite.io/lifetimes.html https://doc.rust-lang.org/reference/subtyping.html#:~:text=Variance%20is%20a%20property%20that%20generic%20types%20have,the%20parameter%20affects%20the%20subtyping%20of%20the%20type.
我说一下自己的理解吧(有错的话请见谅,但是应该不会差很多),生命周期
lifetime
其实是一种类型,当调用test
函数的时候编译器会生成相应的具体的函数签名。其中 T: 'a 意味着 T 是 'a的子类型, 而 'a 标记着一个生命周期作用域(scope),那么 T 是 'a 的子类型这个约束其实就表明: T 的生命周期 必须 >= 'a标记的生命周期 (注: T本身也可能被推断为 &something)
比如: 当我在main函数中,声明一个引用和调用 test 时,会隐式的生成相关生命周期(作用域)的信息:
展开后:
如果我写的东西题主能看懂的话,那么就能明白函数签名
fn test<'a, T: 'a>(req: T)
中的'a
是一个来自函数外部的生命周期,它比函数本身的生命周期要长, 即便'a
在test
调用后 马上结束,比如:明白这一点后再回到
fn test<'a, T: 'a>(req: T)
的函数体中,我们将函数体内有关生命周期的东西展开后,得到如下代码:显然,不能够编译正确,因为
'fn_test
为 函数体内部的生命周期, 在函数调用结束时结束。而'a
的生命周期大于函数生命周期。我们不能让一个拥有 更长生命周期的引用 指向 更短生命周期的对象, 因为在这可能会造成 悬垂引用。其实我也不是完全明白编译器怎么处理这些东西的,毕竟我现在也不能完全看懂MIR中间代码的。不过我可以推荐一些网址供题主参考: https://nomicon.purewhite.io/lifetimes.html https://doc.rust-lang.org/reference/subtyping.html#:~:text=Variance%20is%20a%20property%20that%20generic%20types%20have,the%20parameter%20affects%20the%20subtyping%20of%20the%20type.