2017-08-29 50 views
0

我想使用我可以修改reg的API:FN爲特徵的混凝土壽命要求

struct Ctx; 
trait Foo {} 

trait Ex { 
    fn do_<'a>(&self, cx: &'a mut Ctx) -> Box<Foo + 'a>; 
} 

impl<F> Ex for F 
where 
    F: for<'a> Fn(&'a mut Ctx) -> Box<Foo + 'a>, 
{ 
    fn do_<'a>(&self, ecx: &'a mut Ctx) -> Box<Foo + 'a> { 
     (*self)(ecx) 
    } 
} 

fn reg<F>(name: &str, ext: F) 
where 
    F: Ex + 'static, 
{ 
} 

//My code starts here 
struct Boo; 

impl Boo { 
    fn f1<'a>(&self, cx: &'a mut Ctx) -> Box<Foo + 'a> { 
     unimplemented!(); 
    } 
} 

fn main() { 
    let boo = Boo; 
    reg("aaa", move |cx| boo.f1(cx)); 
} 

但我得到了一個錯誤:

error[E0271]: type mismatch resolving `for<'a> <[[email protected]/main.rs:33:16: 33:36 boo:_] as std::ops::FnOnce<(&'a mut Ctx,)>>::Output == std::boxed::Box<Foo + 'a>` 
    --> src/main.rs:33:5 
    | 
33 |  reg("aaa", move |cx| boo.f1(cx)); 
    |  ^^^ expected bound lifetime parameter 'a, found concrete lifetime 
    | 
    = note: concrete lifetime that was found is lifetime '_#9r 
    = note: required because of the requirements on the impl of `Ex` for `[[email protected]/main.rs:33:16: 33:36 boo:_]` 
    = note: required by `reg` 

error[E0281]: type mismatch: `[[email protected]/main.rs:33:16: 33:36 boo:_]` implements the trait `std::ops::Fn<(&mut Ctx,)>`, but the trait `for<'a> std::ops::Fn<(&'a mut Ctx,)>` is required 
    --> src/main.rs:33:5 
    | 
33 |  reg("aaa", move |cx| boo.f1(cx)); 
    |  ^^^  -------------------- implements `std::ops::Fn<(&mut Ctx,)>` 
    |  | 
    |  requires `for<'a> std::ops::Fn<(&'a mut Ctx,)>` 
    |  expected concrete lifetime, found bound lifetime parameter 'a 
    | 
    = note: required because of the requirements on the impl of `Ex` for `[[email protected]/main.rs:33:16: 33:36 boo:_]` 
    = note: required by `reg` 

我該如何解決這個問題?

在實際的代碼我struct Boo包含了一些數據, 並要撥打reg它的兩倍,因此我不落實trait Ex,但 嘗試使用封閉。

+0

您是否閱讀過https://stackoverflow.com/q/31362206/155423; https://stackoverflow.com/q/41087239/155423; https://stackoverflow.com/q/24847331/155423; https://stackoverflow.com/q/24162518/155423; https://stackoverflow.com/q/40535543/155423?這些是我發現的錯誤文本「找到的具體生命週期」中的* first * 5 SO問題。請[編輯]你的問題來解釋它與這些不同之處。 – Shepmaster

+0

@Shepmaster即使帶結構,變量,特徵,函數命名我的代碼完全不同於你的建議。我的問題與來自https://stackoverflow.com/questions/32194367/expected-bound-lifetime-parameter-found-concrete-lifetime的**答案**很相似,但實際上解決方案中的代碼會導致問題。 – user1244932

回答

1

看起來像issue #38714

正在修復時,您可以直接爲Boo實施Ex

impl Ex for Boo { 
    fn do_<'a>(&self, ecx: &'a mut Ctx) -> Box<Foo + 'a> { 
     self.f1(ecx) 
    }  
} 

fn main() { 
    let boo = Boo; 
    reg("aaa", boo); 
} 

In real code my struct Boo contains some data, and want to call reg for it twice, so I not implement trait Ex, but try to use closure.

你不能這樣做與你的代碼提供。 move |cx| boo.f1(cx)boo移動到關閉位置,之後您不能使用boo

如果你想分享數據,你需要在Boo中使用Rc

+0

是的,在真實的代碼中我使用'Rc',所以對我來說不是問題。雖然兩次爲'Boo'實現'Ex',另一個爲struct XXX(Boo)'不好,所以我嘗試使用閉包。 – user1244932