【问题标题】:Higher ranked trait bounds and function parameters更高等级的特征界限和函数参数
【发布时间】:2020-12-30 20:41:13
【问题描述】:

我试图了解 Bevy 的 IntoForEachSystem trait 的实现以及它与底层 Hecs Query and Fetch traits 的交互方式。 Hecs 具有查询类型(您在调用 query::<T> 时请求的内容)和项目类型(查询返回的内容)。这个想法是 IntoForEachSystem 是为查询类型与查询的项目类型匹配的闭包实现的,fn f(&i32) 之所以有效,是因为 &i32 查询返回一个 &i32 项目。

我想我在this snippet 中提取了设计的相关部分,但我无法对其进行类型检查:

// Hecs Query trait
trait Query {
    type Fetch: for<'a> Fetch<'a>;
}

// Hecs Query trait implementation for read-only references
impl<'a, T> Query for &'a T
where
    T: 'static,
{
    type Fetch = FetchRead<T>;
}

// Hecs Fetch trait
trait Fetch<'a>: Sized {
    type Item;
}

// Hecs Fetch trait implementation for read-only references
struct FetchRead<T>(std::marker::PhantomData<T>);

impl<'a, T> Fetch<'a> for FetchRead<T>
where
    T: 'static,
{
    type Item = &'a T;
}

// Bevy IntoForEachSystem trait, simplified
trait IntoForEachSystem<R> {
    fn system(self);
}

// Bevy IntoForEachSystem trait implementation for functions of one argument
impl<F, R> IntoForEachSystem<R> for F
where
    F: Fn(R),
    F: Fn(<<R as Query>::Fetch as Fetch>::Item),
    R: Query,
{
    fn system(self) {
        println!("hello");
    }
}

fn hmm(_x: &i32) {
    todo!()
}

fn main() {
    IntoForEachSystem::system(hmm)
}

错误:

error[E0631]: type mismatch in function arguments
   |
31 |     fn system(self);
   |     ---------------- required by `IntoForEachSystem::system`
...
46 | fn hmm(_x: &i32) {
   | ---------------- found signature of `for<'r> fn(&'r i32) -> _`
...
51 |     IntoForEachSystem::system(hmm)
   |                               ^^^ expected signature of `for<'r> fn(<FetchRead<i32> as Fetch<'r>>::Item) -> _`
   |
   = note: required because of the requirements on the impl of `IntoForEachSystem<&i32>` for `for<'r> fn(&'r i32) {hmm}`

我认为编译器将fn hmm&lt;'r&gt;(&amp;'r i32) 中的推断生命周期'r 视为与type Fetch: for&lt;'a&gt; Fetch&lt;'a&gt; 中的forall 生命周期'a 不同。我看不出 Bevy 用什么伎俩来达到同样的目的。

【问题讨论】:

    标签: rust higher-rank-types bevy


    【解决方案1】:

    你真的超级亲密!

    fn main() {
        hmm.system();
    }
    

    这...非常令人沮丧,因为就我而言,IntoForEachSystem::system(hmm) 应该等同于hmm.system()。也许这是 Rust 编译器中的一个错误?

    【讨论】:

    • 这很奇怪。事实上,这就是 Bevy 中真正的代码所做的事情。我只是将其更改为 UFCS 以使错误消息更清晰...
    猜你喜欢
    • 2021-08-23
    • 1970-01-01
    • 2016-07-17
    • 2022-12-11
    • 2023-03-25
    • 1970-01-01
    • 2020-03-28
    • 2022-11-20
    • 1970-01-01
    相关资源
    最近更新 更多