【问题标题】:Overflow evaluating the requirement `_: Sized` when trying to use Diesel queries尝试使用 Diesel 查询时溢出评估要求`_:Sized`
【发布时间】:2021-08-12 00:55:55
【问题描述】:

我正在尝试为我正在构建的应用程序松散地实现存储库模式,但是我似乎无意中遇到了某种递归类型定义。

关于以下代码:

use diesel::{pg::Pg, Insertable, Queryable, QueryDsl, PgConnection, Identifiable, Table};
use std::marker::PhantomData;
use anyhow::anyhow;

pub struct Repository<Entity, SqlType, Tab> {
    _entity_phantom: PhantomData<Entity>,
    _type_phantom: PhantomData<SqlType>,
    table: Tab,
}

impl <Entity, SqlType, Tab> Repository<Entity, SqlType, Tab>
where
    Entity: Queryable<SqlType, Pg> + Insertable<Tab> + Identifiable,
    Tab: Table
{
    fn find_by_id(&self, id: i64, conn: &PgConnection) -> anyhow::Result<Entity> {
        match self.table.find(id).first::<Entity>(conn) {
            Ok(entity) => Ok(entity),
            Err(e) => Err(anyhow!("{}", e)),
        }
    }
}

我得到错误:

error[E0275]: overflow evaluating the requirement `_: Sized`
  --> support/src/lib.rs:18:26
   |
18 |         match self.table.find(id).first::<Entity>(conn) {
   |                          ^^^^
   |
   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`support`)
   = note: required because of the requirements on the impl of `FilterDsl<_>` for `<Tab as AsQuery>::Query`

我尝试增加 crate 顶部的递归限制,但无济于事。将+ Sized 洒在整个特征范围内,似乎也没有任何作用。

我错过了什么?

【问题讨论】:

  • 嗨,您有插入和更新的解决方案吗?柴油::insert_into(self.table) .values(data) .get_result::<:entity>(self.conn) 的特征是什么

标签: rust rust-diesel


【解决方案1】:

此类错误通常意味着 diesel 无法解决您的特征界限,因为限制不够。

Diesel 泛型编程通常有点复杂,但这里有一些提示可以在您下次遇到此错误时帮助您:

  • 每当您想使用特定方法(如 find)时,您必须确保检查相同的界限!
  • 更喜欢构建特定的可重用函数,让您得到想要的东西
  • 每次调用柴油方法时,您都在“包装”一个新语句,此新语句必须绑定,否则您会收到类似问题中的奇怪错误消息。
  • 这些方法的结果通常在下面的代码中有一个简写形式,例如 FindLimit
  • 您可以在第 27 行看到,我们必须嵌套 Limit&lt;Find&lt;..&gt;&gt;,对于您在查询链中调用的每个新方法,您都需要指定它。
use anyhow::anyhow;
use diesel::{
    associations::HasTable,
    dsl::{Find, Limit},
    query_dsl::{
        methods::{FindDsl, LimitDsl},
        LoadQuery,
    },
    PgConnection, RunQueryDsl, Table,
};
use std::marker::PhantomData;

pub struct Repository<Entity, Tab> {
    _entity_phantom: PhantomData<Entity>,
    _table_phantom: PhantomData<Tab>,
}

impl<Entity, Tab> Repository<Entity, Tab>
where
    Entity: HasTable<Table = Tab>,
    Tab: Table,
{
    fn find_by_id(&self, id: i64, conn: &PgConnection) -> anyhow::Result<Entity>
    where
        Tab: LimitDsl + FindDsl<i64>,
        Find<Tab, i64>: LimitDsl + Table,
        Limit<Find<Tab, i64>>: LoadQuery<PgConnection, Entity>,
    {
        match Entity::table().find(id).first::<Entity>(conn) {
            Ok(entity) => Ok(entity),
            Err(e) => Err(anyhow!("{}", e)),
        }
    }
}

我错过了什么?

通常人们可以猜到你试图做什么,我不认为你没有达到预期的结果是你的错。这种泛型编程很难理解,各种类型及其名称TU 很容易迷路。

  • 如果我正确理解了Entity 所指的内容,那么您绑定在Entity 上的特征是错误的:
    • Queryable&lt;Query, Database&gt; 表示可以在DatabaseQuery 中查询实现它的类型。如果你也不传入具体类型,那么“传入”类型 SqlQuery 是没有意义的!
  • Insertable&lt;Tab&gt; 我猜是其他方法的遗留物?
  • Identifiable 也一样?

【讨论】:

  • 多么有见地的答案啊,非常感谢! :D
猜你喜欢
  • 2019-09-15
  • 2018-10-15
  • 1970-01-01
  • 2019-10-13
  • 2017-09-02
  • 2019-05-28
  • 2021-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多