为什么我无法返回fmt :: Arguments<' a>来自&&#;; T?

时间:2016-12-21 13:40:43

标签: rust lifetime

根据我对生命周期的理解,如果函数的调用者指定参数的生命周期,我可以返回具有该生命周期的类型。

即使有了省略,这也有效:

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

1 个答案:

答案 0 :(得分: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值的t - 引用!同样,您不能返回对堆栈中分配的内容的引用。

  

如果函数的调用者指定参数的生命周期,我可以返回具有该生命周期的类型。

这是正确的一半。您只能返回返回该输入参数的一部分。您不能创建一个全新的值并在该生命周期内返回它。