2016-09-18 38 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) –