- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
几天前,在a question中,有人对可变引用的类型的链接生命周期存在疑问,该类型本身包含借来的数据。问题在于为该类型的引用提供了与该类型内部的借用数据具有相同生存期的借用。
我试图重新创建问题:
struct VecRef<'a>(&'a Vec<u8>);
struct VecRefRef<'a>(&'a mut VecRef<'a>);
fn main() {
let v = vec![8u8, 9, 10];
let mut ref_v = VecRef(&v);
create(&mut ref_v);
}
fn create<'b, 'a>(r: &'b mut VecRef<'a>) {
VecRefRef(r);
}
'b
中显式注释了
create()
。这不会编译:
error[E0623]: lifetime mismatch
--> src/main.rs:12:15
|
11 | fn create<'b, 'a>(r: &'b mut VecRef<'a>) {
| ------------------
| |
| these two types are declared with different lifetimes...
12 | VecRefRef(r);
| ^ ...but data from `r` flows into `r` here
'b
类似于
'b < 'a
,因此违反了
VecRefRef<'a>
中的约束,使其与被称为
VecRef<'a>
的生存期完全相同。
VecRef<'a>
中的借入数据关联起来:
fn create<'a>(r: &'a mut VecRef<'a>) {
VecRefRef(r);
}
r
中的可变引用
create()
具有
VecRef<'a>
的生存期,而不是
'a
。为什么问题没有推送到函数
create()
的调用端?
VecRefRef<'a>
结构中使用了不可变的引用,那么在提供具有不同
'a
生存期的引用时,无论如何就不再重要了:
struct VecRef<'a>(&'a Vec<u8>);
struct VecRefRef<'a>(&'a VecRef<'a>); // now an immutable reference
fn main() {
let v = vec![8u8, 9, 10];
let mut ref_v = VecRef(&v);
create(&mut ref_v);
}
fn create<'b, 'a>(r: &'b mut VecRef<'a>) {
VecRefRef(r);
}
VecRefRef<'a>
可变引用了
VecRef<'a>
。我知道可变引用具有不同的别名规则(根本没有别名),但这与链接的生存期有什么关系?
最佳答案
Warning: I'm speaking from a level of expertise that I don't really have. Given the length of this post, I'm probably wrong a large number of times.
TL;DR: Lifetimes of top-level values are covariant. Lifetimes of referenced values are invariant.
VecRef<'a>
替换为
&'a mut T
,可以大大简化您的示例。
main
,因为谈论某个函数的一般行为比某些特定的生存期实例更完整。
VecRefRef
的构造函数:
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
Aside: I say "explicitly annotated" because in implicit cases like
let x = y
orfn f<T>(_: T) {}
, reborrowing doesn't seem to happen. It is not clear whether this is intended.
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
error[E0623]: lifetime mismatch
--> src/main.rs:5:26
|
4 | fn use_ref_ref<'a, 'b>(reference: &'a mut &'b mut ()) {
| ------------------
| |
| these two types are declared with different lifetimes...
5 | use_same_ref_ref(reference);
| ^^^^^^^^^ ...but data from `reference` flows into `reference` here
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a>(reference: &'a mut &'a mut ()) {
use_same_ref_ref(reference);
}
let mut val = ();
let mut reference = &mut val;
let ref_ref = &mut reference;
use_ref_ref(ref_ref);
&'a mut &'a mut ()
。
'a: 'b
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a: 'b, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
&'a mut &'b mut ()
无法转换为&'c mut &'c mut ()
或&'a mut &'a mut ()
好。 'b: 'a
不能解决问题。
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a, 'b: 'a>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c &'c mut ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c mut &'c ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a mut &'b ()) {
use_same_ref_ref(reference);
}
║ Name │ Type │ Value
───╫───────────┼─────────────────────┼───────
1 ║ val │ i32 │ -1
───╫───────────┼─────────────────────┼───────
2 ║ reference │ &'x mut i32 │ 0x1
reference
堆栈位置是在
val
之后创建的,并且将在
val
之前被删除。
let new_ref = reference;
║ Name │ Type │ Value
───╫───────────┼─────────────┼───────
1 ║ val │ i32 │ -1
───╫───────────┼─────────────┼───────
2 ║ reference │ &'x mut i32 │ 0x1
───╫───────────┼─────────────┼───────
3 ║ new_ref │ &'y mut i32 │ 0x1
'y
的有效期限是多少?
'y
增长,因为
'x
引用仅保证对象在
'x
范围内保持 Activity 状态。但是,
读取不会阻止
'y
缩小,因为在指向值处于 Activity 状态时进行的任何读取都将导致独立于生存期
'y
的值。
'y
增长,因为无法写入无效的指针。但是,
写入不会阻止
'y
缩小,因为对指针的任何写操作都会复制该值,这使其与生命周期
'y
无关。
║ Name │ Type │ Value
───╫───────────┼─────────────────────┼───────
1 ║ val │ i32 │ -1
───╫───────────┼─────────────────────┼───────
2 ║ reference │ &'a mut i32 │ 0x1
───╫───────────┼─────────────────────┼───────
3 ║ ref_ref │ &'x mut &'a mut i32 │ 0x2
let new_ref_ref = ref_ref;
║ Name │ Type │ Value
───╫─────────────┼─────────────────────┼───────
1 ║ val │ i32 │ -1
───╫─────────────┼─────────────────────┼───────
2 ║ reference │ &'a mut i32 │ 0x1
───╫─────────────┼─────────────────────┼───────
3 ║ ref_ref │ &'x mut &'a mut i32 │ 0x2
───╫─────────────┼─────────────────────┼───────
4 ║ new_ref_ref │ &'y mut &'b mut i32 │ 0x2
'y
? 'b
? 'y
:
'y
增长,因为
'x
引用仅保证对象在
'x
范围内保持 Activity 状态。但是,
读取不会阻止
'y
缩小,因为在指向值处于 Activity 状态时进行的任何读取都将导致独立于生存期
'y
的值。
'y
增长,因为无法写入无效的指针。但是,
写入不会阻止
'y
缩小,因为对指针的任何写操作都会复制该值,这使其与生命周期
'y
无关。
'b
'b
增长,因为如果要从外部指针中提取内部指针,则可以在
'a
过期后读取它。
'b
的增长,因为如果要从外部指针中提取内部指针,则可以在
'a
过期后对其进行写操作。
'b
缩小,因为这种情况:
let ref_ref: &'x mut &'a mut i32 = ...;
{
// Has lifetime 'b, which is smaller than 'a
let new_val: i32 = 123;
// Shrink 'a to 'b
let new_ref_ref: &'x mut &'b mut i32 = ref_ref;
*new_ref_ref = &mut new_val;
}
// new_ref_ref is out of scope, so ref_ref is usable again
let ref_ref: &'a mut i32 = *ref_ref;
// Oops, we have an &'a mut i32 pointer to a dropped value!
'b
不能缩小,也不能从'a
增长,所以'a == 'b
恰好。 这意味着
&'y mut &'b mut i32
在生存期'b中是不变的。
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
use_same_ref_ref
时,尝试进行强制转换
&'a mut &'b mut () → &'c mut &'c mut ()
'b == 'c
,因为我们讨论了方差。因此,我们实际上是在类型转换
&'a mut &'b mut () → &'b mut &'b mut ()
&'a
只能收缩。为了做到这一点,编译器需要知道
'a: 'b
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a>(reference: &'a mut &'a mut ()) {
use_same_ref_ref(reference);
}
'a: 'b
而不是
'a: 'a
,这确实是正确的。
'a: 'b
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a: 'b, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
'b: 'a
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a, 'b: 'a>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c &'c mut ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a &'b mut ()) {
use_same_ref_ref(reference);
}
&'b
的问题:
Read and write together also prevent
'b
from shrinking, because of this scenario:let ref_ref: &'x mut &'a mut i32 = ...;
{
// Has lifetime 'b, which is smaller than 'a
let new_val: i32 = 123;
// Shrink 'a to 'b
let new_ref_ref: &'x mut &'b mut i32 = ref_ref;
*new_ref_ref = &mut new_val;
}
// new_ref_ref is out of scope, so ref_ref is usable again
let ref_ref: &'a mut i32 = *ref_ref;
// Oops, we have an &'a mut i32 pointer to a dropped value!Ergo,
'b
cannot shrink and it cannot grow from'a
, so'a == 'b
exactly.
fn use_same_ref_ref<'c>(reference: &'c mut &'c ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a mut &'b ()) {
use_same_ref_ref(reference);
}
let ref_ref: &'x mut &'a i32 = ...;
{
// Has lifetime 'b, which is smaller than 'a
let new_val: i32 = 123;
// Shrink 'a to 'b
let new_ref_ref: &'x mut &'b i32 = ref_ref;
*new_ref_ref = &new_val;
}
// new_ref_ref is out of scope, so ref_ref is usable again
let ref_ref: &'a i32 = *ref_ref;
// Oops, we have an &'a i32 pointer to a dropped value!
One can instead enforce
'a: 'b
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a: 'b, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}This means that the lifetime of the outer reference is at least as large as the lifetime of the inner one.
It's not obvious
why
&'a mut &'b mut ()
is not castable to&'c mut &'c mut ()
, orwhether this is better than
&'a mut &'a mut ()
.I hope to answer these questions.
'a: 'b
是否允许超过
'a == 'b
?
&'x mut &'y mut ()
的调用者。如果是
'x : 'y
,那么它将自动转换为
&'y mut &'y mut ()
。相反,如果
'x == 'y
,那么
'x : 'y
已经成立!因此,仅当您希望将包含
'x
的类型返回给调用者时才是重要的,调用者是唯一可以区分两者的人。由于这里不是这种情况,因此两者是等效的。
let mut val = ();
let mut reference = &mut val;
let ref_ref = &mut reference;
use_ref_ref(ref_ref);
use_ref_ref
的地方
fn use_ref_ref<'a: 'b, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
'a: 'b
?看起来相反,这在检查中是正确的!
let reference = &mut val;
val
实际生存期的生存期!
关于rust - 为什么链接生存期仅与可变引用有关?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55849717/
我有一个网站,并且我使用 javascript sdk 添加了“点赞”按钮。 这是代码 (function(d, s, id) { var js, fjs = d.g
我知道 HTML 是逐行读取的。当您链接多个 css 文件(如规范化文件和样式表文件)时,由于 CSS 重要性特异性和源顺序,样式表文件应链接在规范化文件之后。看起来这不会影响链接的 JavaScri
我正在使用官方 Bootstrap site 提供的 CDN 链接在我的网络应用程序中使用面板进行测试 在彻底检查我的代码后,面板没有显示。 但是我在 SO 上看到了类似的帖子并且 CDN 链接不同
这里是编码初学者。我正在尝试为我的移动设备网站设置断点,以便我的网站适合小屏幕。我只是想检查如果我缩小视口(viewport)的宽度,背景颜色是否会改变,但没有发生任何变化。也许我只是对一个简单的错误
举一个我想要的例子,想象一下这个字符串: $text = 'lorem ipsum About us lorem ipsum'; 如果此字符串包含一个 href 以 / 开头的 anchor 链接,则
如何链接到 LaTeX 文档的另一部分或子部分?这种链接的常规范式是什么,像[链接名称]那样写,或者像网页超链接那样写? 最佳答案 链接到另一个部分需要您的部分进行一些额外的标记。要使用的命令是: \
我有一个订单表,其中包含订单号、客户 ID 和代理 ID。然后有一个带有 id 的客户表和一个带有 id 的代理表。 我需要获取所有具有来自代理 ID 'a03' 和代理 ID 'a05' 的订单的客
假设我有: dic = {"z":"zv", "a":"av"} ## Why doesn't the following return a sorted list of keys? keys = d
我在尝试链接到外部库时得到了一些奇怪的结果。如果我从命令行运行以下命令: gcc fftwTest.c -I../extlib/fftw-3.3.5-dll32 -L../extlib/fftw-3.
我认为我没有正确理解 jQuery 链接。我正在遍历一个数组并尝试将 div 元素添加到我的包装器 CSS 类中,每个 div 元素都有一个“click”类和自定义 css top 和 left 属性
HTML 使用超级链接与网络上的另一个文档相连。几乎可以在所有的网页中找到链接。点击链接可以从一张页面跳转到另一张页面。 HTML 超链接(链接) HTML使用标签 a 来设置超文本链接。 超链
这个问题在这里已经有了答案: How do I link to part of a page? (hash?) (7 个答案) Scroll Automatically to the Bottom
我想创建一个 Docker Swarm 集群,运行一个 Elasticsearch 实例、一个 MongoDB 实例和一个 grails 应用程序,每个都在单独的机器上。我正在使用 Docker Ma
我正在尝试将 CakePHP HTML Linker 用于以下代码 Add Cuisine 由于 span 标签需要在 a 标签内。我无法根据需要获得输出。关于如何完成它的任何建议? 最佳答案 禁用链
大家好, 我最近开发了一个应用程序,很快就会提交到 App Store。我想免费提交这个应用程序,并想知道我是否可以实现一个带有 PayPal 捐赠标志的按钮,上面基本上写着“捐赠用于开发”或与此相关
我想尝试在 dlang 中使用 libuv。我下载了这样的 dlang 绑定(bind): git clone git@github.com:tamediadigital/libuv.git 现在我接
我有一个节点(节点 a),各种其他节点(节点 b/c/d/e)与之引用。 我可以创建一个带有参数的 View 作为我正在查看的节点(节点 a),并获取引用该节点的节点列表。 基本上在节点 a 查看节点
我正在尝试建立一个常见问题页面,上面有目录,下面有答案。我想点击目录中的一个问题,并在同一页面上链接到相应的答案。我如何在 CakePHP 中使用 $this->Html->link() 执行此操作方
在 WooCommerce 3.0+ 中,我使用 js 创建了一些选项卡,每个选项卡中包含来自不同类别的产品。我已经设法修改了简单产品的添加到购物车链接,其中点击了 addtocart 按钮它进入下一
Delphi 2007/2009 奇怪的问题在这里: 根据设计时定义的组件属性,是否可以在链接中包含文件或保留文件? 示例:如果我将 SomeProperty 保留为真,则在编译时,单元 SomeUn
我是一名优秀的程序员,十分优秀!