Skip to content

Cannot derive AsChangeset when a #[diesel(embed)]-ded field does not implement &T: AsChangeset #5001

@RBerga06

Description

@RBerga06

Rust Version

1.94.0

Diesel Version

2.3.7

Diesel Features

sqlite returning_clauses_for_sqlite_3_35 uuid chrono

Database Version

Sqlite 3.43.2

Operating System Version

macOS 15.7.3 (Sequoia) arm64

What happened?

See the reproduction example below.

To me, it looks like, if #[diesel(serialize_as)] or #[diesel(deserialize_as)] is present in the struct definition (in this example, MyTable), the derive macro #[derive(AsChangeset)] always tries to implement AsChangeset for &'update MyTable.

However, if the struct contains a field with #[diesel(embed)] and its type (I've called it Embed) does not implement &'update Embed: AsChangeset, this leads to a compilation error.

The error goes away in both the following cases:

  • if I comment the line marked with (1): &'update Embed: AsChangeset is now derived and the implementation of &'update MyTable: AsChangeset works;
  • if I uncomment the line marked with (2): #[derive(AsChangeset)] detects the use of #[diesel(serialize_as)]/#[diesel(deserialize_as)] and doesn't try to implement &'update MyTable: AsChangeset.

What did you expect to happen?

I think #[derive(AsChangeset)] should not try and implement &'update MyTable: AsChangeset if at least one field has a type that does not implement the trait by reference (especially #[diesel(embed)]ded fields).
However, it should implement MyTable: AsChangeset correctly.

Additional details

No response

Steps to reproduce

use diesel::{
    deserialize::{FromSql, FromSqlRow},
    expression::AsExpression,
    prelude::*,
    serialize::ToSql,
    sql_types::Text,
    sqlite::Sqlite,
};

#[derive(Debug, Clone, PartialEq, Eq, AsExpression, FromSqlRow)]
#[diesel(sql_type = Text)]
struct Foo(String);
impl From<String> for Foo {
    fn from(value: String) -> Self {
        Foo(value)
    }
}
impl Into<String> for Foo {
    fn into(self) -> String {
        self.0
    }
}
impl FromSql<Text, Sqlite> for Foo {
    fn from_sql(
        bytes: <Sqlite as diesel::backend::Backend>::RawValue<'_>,
    ) -> diesel::deserialize::Result<Self> {
        <String as FromSql<Text, Sqlite>>::from_sql(bytes).map(Self)
    }
}
impl ToSql<Text, Sqlite> for Foo {
    fn to_sql<'b>(
        &'b self,
        out: &mut diesel::serialize::Output<'b, '_, Sqlite>,
    ) -> diesel::serialize::Result {
        ToSql::<Text, Sqlite>::to_sql(&self.0, out)
    }
}

diesel::table! {
    my_table(id) {
        id -> Text,
        foo -> Text,
        bar -> Text,
    }
}

#[derive(Queryable, Selectable, AsChangeset)]
#[diesel(table_name = my_table)]
struct Embed {
    #[diesel(serialize_as = String, deserialize_as = String)] // <-- (1)
    foo: Foo,
}

#[derive(HasQuery, AsChangeset)]
#[diesel(table_name = my_table)]
struct MyTable {
    id: String,
    //#[diesel(serialize_as = String, deserialize_as = String)] // <-- (2)
    bar: Foo,
    #[diesel(embed)]
    embed: Embed,
}

Compile time error

error[E0277]: the trait bound `&'update Embed: diesel::AsChangeset` is not satisfied
  --> src/lib/test.rs:54:20
   |
54 | #[derive(HasQuery, AsChangeset)]
   |                    ^^^^^^^^^^^ the trait `diesel::AsChangeset` is not implemented for `&'update Embed`
   |
help: the trait `diesel::AsChangeset` is implemented for `Embed`
  --> src/lib/test.rs:47:33
   |
47 | #[derive(Queryable, Selectable, AsChangeset)]
   |                                 ^^^^^^^^^^^
   = note: required for `(Grouped<Eq<bar, Bound<Text, &Foo>>>, &Embed)` to implement `diesel::AsChangeset`
   = note: the full name for the type has been written to '…'
   = note: consider using `--verbose` to print the full type name to the console
   = note: this error originates in the derive macro `AsChangeset` (in Nightly builds, run with -Z macro-backtrace for more info)

Checklist

  • I have already looked over the issue tracker and the discussion forum for similar possible closed issues.

  • This issue can be reproduced on Rust's stable channel. (Please submit the issue in the Rust issue tracker instead if that's not the case)

  • This issue can be reproduced without requiring a third party crate

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions