2016-09-18 57 views
1

在這裏的代碼更高級別的壽命和仿製藥不玩很好

trait Foo { 
    type Output; 
    fn foo(self) -> Self::Output; 
} 

impl<'a> Foo for &'a() { 
    type Output = &'a(); 
    fn foo(self) -> Self::Output { 
     self 
    } 
} 

fn func<F: Foo>(f: F) -> F::Output { 
    f.foo() 
} 

fn func2<'a>(f: &'a()) -> &'a() { 
    func::<&'a()>(f) 
} 

fn has_hrl<F: Fn(&()) -> &()>(f: F) {} 

fn main() { 
    //has_hrl(func); // FAILS 
    has_hrl(func2); 
    has_hrl(|x| func(x)); 
} 

我們願做has_hrl(func),但鏽病只接受封閉has_hrl(|x| func(x))。這是爲什麼?因爲它適用於func2等具體類型,但不適用於泛型類型。

+0

如果你聲明'has_hrl'就像'fn has_hrl <'a,F:Fn(&'a()) - >&'a()>(_:F){}',這就可以工作。不過,我的權力水平並不足以解釋爲什麼一生需要明確。 – ljedrz

回答

7

在該表達式中:

has_hrl(func) 

編譯器被迫挑func一個特定實例。 func通用於F: Foo,並且對於所有'a,&'a()實現Foo,但編譯器只能選擇一個特定的'a來實例化func,因爲類型變量不能表示多種類型。因此,func::<&'a()>不實現for<'a> Fn(&'a()) -> &'a(),它只執行Fn(&'x()) -> &'x()一個特定的生命期'x

這將工作,如果你宣佈has_hrl喜歡fn has_hrl<'a, F: Fn(&'a()) -> &'a()>(_: F) {}。不過,我的權力水平並不足以解釋爲什麼一生需要明確。 - ljedrz

這是因爲原來的聲明有必然隱含的排名更高的壽命(綁定相當於F: for<'a> Fn(&'a()) -> &'a()),這意味着F必須實現Fn(&'a()) -> &'a()所有壽命'a。您的版本只需要F即可在一個具體生命週期中實施Fn(&'a()) -> &'a()。您還會發現,如果has_hrl嘗試調用具有本地於has_hrl函數的生命週期的閉包,則此版本不起作用,因爲調用方不可能將該生存期作爲參數傳遞(這就是爲什麼排名更高的生存期限被引入)。

+0

我只是試圖將has_hrl(| x | func(x));語句拆分爲2個語句:'let f = | x | FUNC(X); has_hrl(f);'並且出現同樣的錯誤。不知何故,作爲參數出現的方式與變量綁定的處理方式不同(綁定應該固定爲完全具體的類型)。所以我猜,甚至更高的生命週期還沒有被Rust的當前類型系統很好地捕獲(並且在幕後使用了一些有點技巧)? – John

+0

我知道它有更高的排名壽命,但我仍然不明白爲什麼它不起作用,似乎這是應該起作用的。 – iopq

+0

@iopq:[你並不孤單...](https://internals.rust-lang.org/t/higher-kinded-types-the-difference-between-giving-up-and-moving-forward/3908/4) –