Neden birden fazla değiştirilebilir referans bir yapı üyesini kendisine atamayı imkansız kılıyor? [çiftleme]
Yapabileceğimi düşündüğüm yerden ödünç alamıyorum. Sorunu şu duruma indirgedim:
struct A<'a> {
borrow: &'a mut u8,
}
fn does_nothing<'b, 'c>(a: &'b mut A<'c>) {
a.borrow = a.borrow;
}
error[E0623]: lifetime mismatch
--> src/lib.rs:6:16
|
5 | fn does_nothing<'b, 'c>(a: &'b mut A<'c>) {
| -------------
| |
| these two types are declared with different lifetimes...
6 | a.borrow = a.borrow;
| ^^^^^^^^ ...but data from `a` flows into `a` here
Öyle görünüyor ki a.borrow
, kesişme noktasına sahip 'b
ve 'c
bu nedenle hala ömür boyu olacağı garanti edilemez 'c
.
Bununla ilgili gerçek bir problemim yok ve her iki yaşamı da aynı yaparak bunun üstesinden gelebilirim, ama bu neden kontrol ödünç almıyor?
Görünüşe göre yapılar bu sorunu göstermek için önemsiz ve çift ödünç almalar bunu kolayca gösteriyor.
Oldukça benzer olan üç fonksiyonum var, ancak hangisinin derlendiğini ve derlenmeyenlerin hangi hatayı vereceğini bilmekte zorlanırım.
Basit genel işlev:
fn only_borrow<T>(a: &mut T) {
*a = *a;
}
hataya neden olur:
error[E0507]: cannot move out of `*a` which is behind a mutable reference
--> src/lib.rs:2:10
|
2 | *a = *a;
| ^^ move occurs because `*a` has type `T`, which does not implement the `Copy` trait
Ekstra bir yönlendirme seviyesi dahil etmek hatayı değiştirir
fn only_borrow_double<T>(a: &mut &mut T) {
*a = *a;
}
error[E0623]: lifetime mismatch
--> src/lib.rs:2:10
|
1 | fn only_borrow_double<T>(a: &mut &mut T) {
| -----------
| |
| these two types are declared with different lifetimes...
2 | *a = *a;
| ^^ ...but data from `a` flows into `a` here
Belirtilen yaşam sürelerinden farklı bir yere gitmek hatayı düzeltebilir:
fn working_double<'b, T>(a: &'b mut &'b mut T) {
*a = *a;
}
Yanıtlar
Yaşam sürelerinize bir göz atmanız gerekecek 'b
ve 'c
:
&'b mut ...
canlı ve bir "süre" için geçerli bir referansınız olduğu anlamına gelir'b
.A<'c>
canlı ve geçerli bir nesneye sahip olduğunuz anlamına gelir'c
.
Sahip olmadığınız şey, bu iki yaşam arasındaki belirli bir ilişkidir. Derleyicinin çıkarabileceği tek şey, a'nın A<'c>
arkasında olduğu için &'b
, 'c
daha uzun ömürlü olması 'b
, yani ne zaman 'b
geçerli olursa olsun öyle olmasıdır 'c
. Yine de, en önemlisi, tam tersi değil.
Göstermek gibi, derleyici gerektirir 'b
ve 'c
aynı ömrün nasıl. Bu neden?
İmkanlarımıza bir göz atalım:
'c
ve'b
hiçbir ilişkisi yoktur: Herhangi bir ilişki olmadan derleyicinin neyin konulacağı hakkında hiçbir şey garanti edemeyeceğiniA.borrow
ve bu nedenle buna izin vermeyeceğini görmek kolaydır .'c
kesinlikle outlives'b
bazı yerlerde, yani'c
geçerlidir'b
değildir:
a.borrow = a.borrow
bir reborrow olura
kullanarak'b
ömrünü. Bu cevap bunun neden olduğunu açıklıyor . Bununla birlikte, bua
artık'b
yaşam süresine bağlı olduğu anlamına gelir, bu da bir sürea
için geçerli değildir (çünküa
yaşam süresi de vardır'c
). Bu hatayı verir.'b
kesinlikle uzun ömürlüdür'c
: Bu ilişkimiz olsaydı, işe yarayabilirdi. Yeniden ödünç alma geçerli olacaktır, çünkü istediğimizden ('b
) "daha büyük" bir ömür ( ) elde ederiz'c
. Bununla birlikte,'c: 'b
derleyici tarafından perde arkasından zaten çıkardık. Bu nedenle, bu yaşamı eklemek, iki yaşamın eşit olduğu ve o zaman başladığımız yere geri döndüğümüz anlamına gelir:
struct A<'a> {
borrow: &'a mut u8,
}
/// We add the relation 'b: 'c
fn does_nothing<'b: 'c, 'c>(a: &'b mut A<'c>) {
a.borrow = a.borrow;
}