rust-quiz:011-function-pointer-comparison.rs

godme發表於2022-07-11
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沒有問題,因為宣告當中,它的生命週期有明顯的受限宣告。

errorshit!

改動一下展示的例子,展示”受限”,這和我們平時的型別限定沒有什麼區別

fn  f<'a:'a>(a: &'a  u32) ->  &'a  u32 {
    a
}
fn  main() {
    f::<'static>(&1);
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章