为啥在将使用 Diesel 特征的函数重写为特征方法时会出现“溢出评估需求”?

Posted

技术标签:

【中文标题】为啥在将使用 Diesel 特征的函数重写为特征方法时会出现“溢出评估需求”?【英文标题】:Why do I get "overflow evaluating the requirement" when rewriting a function using Diesel's traits into a trait method?为什么在将使用 Diesel 特征的函数重写为特征方法时会出现“溢出评估需求”? 【发布时间】:2019-10-13 21:57:04 【问题描述】:

我正在尝试使用 Diesel 添加分页。如果我使用函数,编译器能够检查泛型类型的边界,但如果我尝试与 trait 的实现做同样的事情,编译器就不能。

这是一个简单的工作示例:

use diesel::query_dsl::methods::LimitDsl, OffsetDsl;

pub fn for_page<T>(query: T)
where
    T: OffsetDsl,
    T::Output: LimitDsl,

    query.offset(10).limit(10);

OffsetDslLimitDsl 是 Diesel 的特征,它提供了方法 offsetlimit

当我尝试将此方法提取为特征并像这样实现它时

use diesel::query_dsl::methods::LimitDsl, OffsetDsl;

trait Paginator 
    fn for_page(self);


impl<T> Paginator for T
where
    T: OffsetDsl,
    <T as OffsetDsl>::Output: LimitDsl,

    fn for_page(self) 
        self.offset(10).limit(10);
    

我收到一条不太清楚的错误消息。

error[E0275]: overflow evaluating the requirement `<Self as diesel::query_dsl::offset_dsl::OffsetDsl>::Output`
 --> src/main.rs:3:1
  |
3 | / trait Paginator 
4 | |     fn for_page(self);
5 | | 
  | |_^
  |
  = note: required because of the requirements on the impl of `Paginator` for `Self`
note: required by `Paginator`
 --> src/main.rs:3:1
  |
3 | trait Paginator 
  | ^^^^^^^^^^^^^^^

error[E0275]: overflow evaluating the requirement `<Self as diesel::query_dsl::offset_dsl::OffsetDsl>::Output`
 --> src/main.rs:4:5
  |
4 |     fn for_page(self);
  |     ^^^^^^^^^^^^^^^^^^
  |
  = note: required because of the requirements on the impl of `Paginator` for `Self`
note: required by `Paginator`
 --> src/main.rs:3:1
  |
3 | trait Paginator 
  | ^^^^^^^^^^^^^^^

我了解这意味着编译器无法检查T::Output 上的条件,但不清楚与具有相同条件的简单函数有什么区别。

我正在使用 Rust 1.35.0 和 Diesel 1.4。

【问题讨论】:

如果使用T::Output: LimitDsl 而不是&lt;T as OffsetDsl&gt;::Output: LimitDsl 是否有效?我尝试reproduce the issue in rust playground,但它似乎工作正常 - 操场上似乎不支持柴油,所以我还没有尝试用真正的库测试它 您使用的是哪个版本的 rust 以及哪个渠道?还有哪个版本的柴油? 不。 :( 我想这可能与 Diesel 定义这些特征的方式有关,但我不知道如何。 Rust 编译器中的约束求解器有时可能有点脆弱 - 另请参阅 this question on URLO 以获取另一个示例。 您可以尝试将您的实现限制为某些类型,而不是所有OffsetDsls? Have a look at how LimitDsl is implemented for Table for example - 它与您的 Paginator 类似,但在正文中定义了输出并相对于输入类型 【参考方案1】:

我无法回答为什么他们不同。我可以说重复 trait 定义的界限可以编译:

use diesel::query_dsl::methods::LimitDsl, OffsetDsl;

trait Paginator
where
    Self: OffsetDsl,
    Self::Output: LimitDsl,

    fn for_page(self);


impl<T> Paginator for T
where
    T: OffsetDsl,
    T::Output: LimitDsl,

    fn for_page(self) 
        self.offset(10).limit(10);
    

您可能还对extending Diesel guide 感兴趣,它讨论了如何最好地添加paginate 方法。

【讨论】:

有效!谢谢!应该自己试试。不过这有点奇怪,因为在这种情况下,我可以在 trait 定义中实现这个方法,而我根本不需要实现。感谢您的链接!我读过它,但对于我想要它完成的简单任务来说似乎有点过于复杂了。

以上是关于为啥在将使用 Diesel 特征的函数重写为特征方法时会出现“溢出评估需求”?的主要内容,如果未能解决你的问题,请参考以下文章

了解 Diesel 中的特征绑定错误

&diesel::MysqlConnection 没有实现特征diesel::Connection

`DbConnection` 没有实现特征`diesel::Connection`

`bigdecimal::BigDecimal` 没有实现特征 `diesel::Expression`

<Struct> 没有实现特征 `diesel::Insertable<schema::trd::table>`

`diesel_geography::types::GeogPoint` 没有实现特征 `serde::Deserialize<'_>`