入力パラメータの有効期間を戻り値の有効期間にバインドするには、関数の有効期間パラメータを定義し、入力パラメータと戻り値の型で参照する必要があります。この生涯パラメータに任意の名前を付けることができます。多くの場合、いくつかのパラメータがあるとき、私達はちょうどそれらに名前を付ける'a
、'b
、'c
など
あなたDb
タイプは寿命パラメータを取りますが、それはいけません:Db
は、既存のオブジェクトを参照するので、それはありません寿命の制約はありません。
が正しくQuery
より長生きするDb
を強制するために、我々はむしろ我々がちょうど取り除かDb
の寿命パラメータに比べて、借りたポインタに'a
を記述する必要があります。
pub fn create_query<'a>(db: &'a Db, query_string: &str) -> Query<'a>
しかし、これでは不十分です。あなたのnewtypesが全く彼らの'a
パラメータを参照しない場合は、Query
が実際より長生きできることがわかりますDb
:デフォルトでは、寿命パラメータは二変ある、ため、コンパイラつまり、だ
struct Db(*mut());
struct Query<'a>(*mut()); // '
fn create_query<'a>(db: &'a Db, query_string: &str) -> Query<'a> { // '
Query(0 as *mut())
}
fn main() {
let query;
{
let db = Db(0 as *mut());
let q = create_query(&db, "");
query = q; // shouldn't compile!
}
}
かもしれません呼び出し元の要件を満たすために、パラメータをより短いまたはに置き換えてください。コンパイラはなく、長い寿命を持つ、短い生涯でパラメータを置換してもよい意味:あなたは構造体で借りポインタを格納する場合
は、寿命パラメータは、反変として扱われます。
私たちは、構造体へContravariantLifetime
マーカーを追加することにより、手動で反変としてあなたの寿命パラメータを治療するためのコンパイラを依頼することができます。今すぐ
use std::marker::ContravariantLifetime;
struct Db(*mut());
struct Query<'a>(*mut(), ContravariantLifetime<'a>);
fn create_query<'a>(db: &'a Db, query_string: &str) -> Query<'a> { // '
Query(0 as *mut(), ContravariantLifetime)
}
fn main() {
let query;
{
let db = Db(0 as *mut());
let q = create_query(&db, ""); // error: `db` does not live long enough
query = q;
}
}
、コンパイラが正しくdb
をoutlivesれ、query
への割り当てを拒否します。
ボーナス:我々はDb
の方法ではなく、自由に機能するcreate_query
を変更した場合、我々はコンパイラの生涯の推論規則を利用してcreate_query
上ですべての'a
を書き込むことはできません。
use std::marker::ContravariantLifetime;
struct Db(*mut());
struct Query<'a>(*mut(), ContravariantLifetime<'a>);
impl Db {
//fn create_query<'a>(&'a self, query_string: &str) -> Query<'a>
fn create_query(&self, query_string: &str) -> Query {
Query(0 as *mut(), ContravariantLifetime)
}
}
fn main() {
let query;
{
let db = Db(0 as *mut());
let q = db.create_query(""); // error: `db` does not live long enough
query = q;
}
}
メソッドにself
パラメータがある場合、コンパイラは、存続期間を持つ他のパラメータがある場合でも、そのパラメータの有効期間を結果とリンクすることをお勧めします。しかし、自由な関数の場合、推論は、1つのパラメータに存続期間がある場合にのみ可能です。ここでは、タイプ&'a str
のquery_string
パラメータのため、2つのパラメータが存続するため、コンパイラは結果をリンクするパラメータを推測できません。
ありがとう!この設計では、私は悪い生涯で書いたテスト関数は、コンパイラによって正しく拒否されるようになりました。 –