2016-12-21 12 views
1

寿命についての私の理解に基づいて、関数の呼び出し側がパラメータの有効期間を指定すると、その有効期間のある型を返すことができます。fmt :: Argumentsを返すことができない理由<'a>& 'a T?

これはさえエリジオンと、動作します:

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

最初の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が作成されていますそれを参照しています。その参照を関数から返すことはできません。

第2のエラー:

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の値です。繰り返しますが、スタックに割り当てられたものへの参照を返すことはできません。

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

これは真実です。その入力パラメータの一部のみを返すことができます。完全に新しい値を作成してその生涯で返すことはできません。

+0

ああ..生成されたコードは何が起こっているかを示します。ありがとう。代わりにFormatArg <'a>を使用することにしました。 – kdy

関連する問題