2016-12-21 88 views
1

基於我對生命週期的理解,如果函數的調用者指定了參數的生命週期,我可以返回具有該生命週期的類型。爲什麼我不能從'T'返回fmt ::參數<'a>?

這工作,即使有省音:

pub fn substr(s: &str) -> &str { 
    &s[0..1] 
} 

pub fn substr_ex<'a>(s: &'a str) -> &'a str { 
    &s[0..1] 
} 

但這並不:

use std::fmt::Arguments; 

pub fn as_format_arg<'a, T: 'a + ?Sized + Debug>(t: &'a T) -> Arguments<'a> { 
    format_args!("{:?}", t) 
} 
error: borrowed value does not live long enough 
    --> <anon>:16:18 
    | 
16 |  format_args!("{:?}", t) 
    |     ^^^^^^ does not live long enough 
17 | } 
    | - temporary value only lives until here 
    | 
    = note: borrowed value must be valid for the lifetime 'a as defined on unknown free region bounded by scope CodeExtent(38/CallSiteScope { fn_id: NodeId(42), body_id: NodeId(92) })... 

error: `t` does not live long enough 
    --> <anon>:16:26 
    | 
16 |  format_args!("{:?}", t) 
    |      ^does not live long enough 
17 | } 
    | - borrowed value only lives until here 
    | 
    = note: borrowed value must be valid for the lifetime 'a as defined on unknown free region bounded by scope CodeExtent(38/CallSiteScope { fn_id: NodeId(42), body_id: NodeId(92) })... 

這是一個錯誤?或者我誤解了一生?

圍欄:https://play.rust-lang.org/?gist=5a7cb4c917b38e012f20c771893f8b3b&version=nightly

+2

你的前兩個例子返回一個引用,所以它們與返回擁有對象的最後一個沒有真正的可比性。 – ljedrz

回答

2

要了解發生了什麼,讓我們來看看macro-expanded version

fn as_format_arg<'a, T: 'a + ?Sized + Debug>(t: &'a T) -> Arguments<'a> { 
    ::std::fmt::Arguments::new_v1({ 
             static __STATIC_FMTSTR: 
              &'static [&'static str] = 
              &[""]; 
             __STATIC_FMTSTR 
            }, 
            &match (&t,) { 
             (__arg0,) => 
             [::std::fmt::ArgumentV1::new(__arg0, 
                    ::std::fmt::Debug::fmt)], 
            }) 
} 

這有助於解釋的第一個錯誤:

error: borrowed value does not live long enough 
    --> src/main.rs:9:36 
    | 
9 |         &match (&t,) { 
    |         ^temporary value created here 
... 
15 | } 
    | - temporary value only lives until here 
    | 
note: borrowed value must be valid for the lifetime 'a as defined on the block at 4:72... 
    --> src/main.rs:4:73 
    | 
4 | fn as_format_arg<'a, T: 'a + ?Sized + Debug>(t: &'a T) -> Arguments<'a> { 
    |                  ^

具體來說,正在創建ArgumentV1在堆棧上並且正在參考它。您不能從該函數返回該引用。

第二誤差:

error: `t` does not live long enough 
    --> src/main.rs:9:44 
    | 
9 |         &match (&t,) { 
    |           ^does not live long enough 
... 
15 | } 
    | - borrowed value only lives until here 
    | 
note: borrowed value must be valid for the lifetime 'a as defined on the block at 4:72... 
    --> src/main.rs:4:73 
    | 
4 | fn as_format_arg<'a, T: 'a + ?Sized + Debug>(t: &'a T) -> Arguments<'a> { 
    |                  ^

注意,format! family of macros doesn't take their arguments by value;他們會自動插入參考。您不希望println!獲得您的價值所有權!

這意味着打印的值實際上是一個&&'a T -a 參考到堆棧分配的t值!同樣,你不能返回一個對堆棧中分配的東西的引用。

if the caller of a function specifies a lifetime on a parameter, I can return a type with that lifetime.

這是一半的事實。您只能返回一個輸入參數。您無法創建一個全新的值並在該生命週期內返回。

+0

哦..生成的代碼顯示了最新的情況..謝謝。我只是決定改用FormatArg <'a>。 – kdy

相關問題