2014-09-05 70 views
3

此代碼:你如何結合生鏽的生活?

struct Foo<'a> { 
    value: Option<&'a int>, 
    parent: Option<&'a Foo<'a>> 
} 

impl<'a> Foo<'a> { 
    fn bar<'a, 'b, 'c: 'a + 'b>(&'a self, other:&'b int) -> Foo<'c> { 
    return Foo { value: Some(other), parent: Some(self) }; 
    } 
} 

fn main() { 
    let e = 100i; 
    { 
    let f = Foo { value: None, parent: None }; 
    let g:Foo; 
    { 
     g = f.bar(&e); 
    } 
    // <--- g should be valid here 
    } 
    // 'a of f is now expired, so g should not be valid here. 

    let f2 = Foo { value: None, parent: None }; 
    { 
    let e2 = 100i; 
    let g:Foo; 
    { 
     g = f2.bar(&e2); 
    } 
    // <--- g should be valid here 
    } 
    // 'b of e2 is now expired, so g should not be valid here. 
} 

失敗,錯誤編譯:

<anon>:8:30: 8:35 error: cannot infer an appropriate lifetime due to conflicting requirements 
<anon>:8  return Foo { value: Some(other), parent: Some(self) }; 
             ^~~~~ 
<anon>:7:3: 9:4 note: consider using an explicit lifetime parameter as shown: fn bar<'a, 'b>(&'a self, other: &'b int) -> Foo<'b> 
<anon>:7 fn bar<'a, 'b, 'c: 'a + 'b>(&'a self, other:&'b int) -> Foo<'c> { 
<anon>:8  return Foo { value: Some(other), parent: Some(self) }; 
<anon>:9 } 

(圍欄:http://is.gd/vAvNFi

這顯然是一個人爲的例子,但它是我想做的事偶爾。

所以...

1)你如何結合生命期? (即返回一個Foo,它的壽命至少爲'a或'b,這個更短)

2)是否有某種方法來編寫測試資產壽命編譯失敗? (如嘗試編譯#[測試]使用在錯誤的道路的功能和失敗,一生錯誤)

+0

(順便說一句,在後的代碼不編譯,並在圍欄鏈接的代碼不匹配。)@dbaupp我的壞 – huon 2014-09-05 07:55:18

+0

。現在修復。 – Doug 2014-09-05 08:33:03

回答

8

界限'c: 'a + 'b意味着'c至少與'a一樣長,只要'b。但是,在這種情況下,Foo值正好適用於最短的'a'b:只要任一參考後面的數據超出範圍,整個Foo必須無效。 (這是說,數據的有效期爲'c工會'a'b有效。)

更具體而言,說'b = 'static,然後'c: 'a + 'static意味着'c也必須'static,因此,返回值將是Foo<'static>。這顯然是不正確的,因爲它會將有限的參考文獻「升級」爲永久持續的文獻。

這裏的正確行爲是採用壽命的交集:Foo僅在兩個函數參數都有效時纔有效。交集操作只是標註具有相同名稱的引用:

fn bar<'a>(&'a self, other: &'a int) -> Foo<'a> 
+0

我編輯了我的答案,用「最小」(交叉點)替換「最大」(聯合)。但是,因爲bar在這裏是一種方法,所以在方法上省略''a'生命週期參數並使用'impl'中的''a'不是更好嗎?我知道它在實現trait時會導致錯誤(生命週期參數必須與trait中定義的那些參數相匹配),但這只是一個簡單的'impl',所以這兩個選項都可以工作。 – 2014-09-05 04:57:24

+0

@FrancisGagné:至少我同意你的看法。似乎沒有必要爲該功能提供任何新的生命週期參數。 – sellibitze 2014-09-09 16:24:07

3

bar刪除所有limetime參數和從impl改用'a壽命參數。

impl<'a> Foo<'a> { 
    fn bar(&'a self, other:&'a int) -> Foo<'a> {     // ' 
    return Foo { value: Some(other), parent: Some(self) }; 
    } 
} 

'a將被編譯器推斷爲其中的所有引用是有效的最小的壽命。