2016-12-21 59 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

相关问题