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
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 implementAsChangesetfor&'update MyTable.However, if the struct contains a field with
#[diesel(embed)]and its type (I've called itEmbed) does not implement&'update Embed: AsChangeset, this leads to a compilation error.The error goes away in both the following cases:
(1):&'update Embed: AsChangesetis now derived and the implementation of&'update MyTable: AsChangesetworks;(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: AsChangesetif 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: AsChangesetcorrectly.Additional details
No response
Steps to reproduce
Compile time error
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