fn f<'a>() {}
fn g<'a: 'a>() {}
fn main() {
let pf = f::<'static> as fn();
let pg = g::<'static> as fn();
print!("{}", pf == pg);
}
資料限定
我們經常使用let a: u32
這種辦法去限定一個資料的型別,這算是資料的限定。型別限定
A:T
這種形式,就是型別限定,它決定了一個型別的最基礎要求。
當然,也有T
的無要求資料型別。生命週期
lifetime
算是資料還是型別呢,它是一種特殊的資料型別。
它可以被省略,被自動推導;也可以手動宣告,還可以手動限定。
生命週期本身是可以自動推導的。
fn f<'b, 'a:'b>(a: &'a u32) -> &'b u32 {
a
}
這裡出現了限定,更簡略一些
fn f<'a>(a: &'a u32) -> &'a u32 {
a
}
但是,這裡最簡應該是
fn f(a: &u32) -> &u32 {
a
}
簡單總結出來,輸出的引用的生命週期始終是受限於輸入的生命週期。
但是輸入的生命週期是上下文就可以進行推匯出來的,某些場景下無需手動宣告。
就算手動宣告,如果和推導的結果一致,也無大用處。
關鍵在於:怎麼宣告,才和推導的不一樣?
最關鍵的一處在於:推導的入參生命週期來源於上下文,我們是可以重新指定的。
- 生命週期在函式簽名之外宣告
- 生命週期引數以它必須超過的其他生命週期為界
這叫做early bound
,也就是說,無非等到自動推導,提前指定了生命週期。
fn f<'a>() {}
如果方法有生命週期,這裡只不過是顯式寫了出來,並沒有額外的操作。fn g<'a: 'a>() {}
這裡限定了一個宣告週期,也就是執行時需要指定一個宣告週期。
fn main() {
let pf = f::<'static> as fn();
let pg = g::<'static> as fn();
print!("{}", pf == pg);
}
因此,pf
其實本身並不能透過編譯,因為它並沒有實現early bound
的語法。
不能夠以指定生命週期的形式進行呼叫。
而pg
沒有問題,因為宣告當中,它的生命週期有明顯的受限宣告。
error
,shit!
改動一下展示的例子,展示”受限”,這和我們平時的型別限定沒有什麼區別
fn f<'a:'a>(a: &'a u32) -> &'a u32 {
a
}
fn main() {
f::<'static>(&1);
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結