From 0c4fa63a01c9453d6ad9a5bad35f817626ef7cfa Mon Sep 17 00:00:00 2001 From: Thomas BESSOU Date: Fri, 20 Sep 2024 12:15:01 +0200 Subject: [PATCH 1/2] Add support of binary operators to auto_type This adds support for type inference of e.g. `some_timestamptz_column - some_pginterval_expression` --- .../auto_type/expression_type_inference.rs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/dsl_auto_type/src/auto_type/expression_type_inference.rs b/dsl_auto_type/src/auto_type/expression_type_inference.rs index a63bf225f80e..6ed70fbd3a7f 100644 --- a/dsl_auto_type/src/auto_type/expression_type_inference.rs +++ b/dsl_auto_type/src/auto_type/expression_type_inference.rs @@ -302,6 +302,54 @@ impl TypeInferrer<'_> { } } } + (syn::Expr::Binary(binary_expression), None) => { + let op_span = Span::mixed_site().located_at(binary_expression.op.span()); + let trait_name = match binary_expression.op { + syn::BinOp::Add(_) => "Add", + syn::BinOp::Sub(_) => "Sub", + syn::BinOp::Mul(_) => "Mul", + syn::BinOp::Div(_) => "Div", + syn::BinOp::Rem(_) => "Rem", + syn::BinOp::BitXor(_) => "BitXor", + syn::BinOp::BitAnd(_) => "BitAnd", + syn::BinOp::BitOr(_) => "BitOr", + syn::BinOp::Shl(_) => "Shl", + syn::BinOp::Shr(_) => "Shr", + syn::BinOp::And(_) + | syn::BinOp::Or(_) + | syn::BinOp::Eq(_) + | syn::BinOp::Lt(_) + | syn::BinOp::Le(_) + | syn::BinOp::Ne(_) + | syn::BinOp::Ge(_) + | syn::BinOp::Gt(_) => return Ok(parse_quote!(bool)), + syn::BinOp::AddAssign(_) + | syn::BinOp::SubAssign(_) + | syn::BinOp::MulAssign(_) + | syn::BinOp::DivAssign(_) + | syn::BinOp::RemAssign(_) + | syn::BinOp::BitXorAssign(_) + | syn::BinOp::BitAndAssign(_) + | syn::BinOp::BitOrAssign(_) + | syn::BinOp::ShlAssign(_) + | syn::BinOp::ShrAssign(_) => return Ok(parse_quote!(())), + _ => { + // This is here because the `BinOp` enum is marked as #[non_exhaustive], + // but in effect we really support all the variants + return Err(syn::Error::new( + op_span, + format_args!( + "unsupported binary operator for auto_type: {:?}", + binary_expression.op + ), + )); + } + }; + let trait_name_ident = syn::Ident::new(trait_name, op_span); + let left_type = self.infer_expression_type(&binary_expression.left, None); + let right_type = self.infer_expression_type(&binary_expression.right, None); + parse_quote!(<#left_type as ::core::ops::#trait_name_ident<#right_type>>::Output) + } (_, None) => { return Err(syn::Error::new( expr.span(), From cfd2a56ec9782c6beae9945da85bfc0f5f03b86c Mon Sep 17 00:00:00 2001 From: Thomas BESSOU Date: Fri, 20 Sep 2024 12:31:53 +0200 Subject: [PATCH 2/2] Add test and support for update(...) to auto_type --- diesel/src/lib.rs | 5 +++++ diesel_derives/tests/auto_type.rs | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/diesel/src/lib.rs b/diesel/src/lib.rs index bee28d0c5795..db16294a9d60 100644 --- a/diesel/src/lib.rs +++ b/diesel/src/lib.rs @@ -651,6 +651,11 @@ pub mod helper_types { #[allow(non_camel_case_types)] // required for `#[auto_type]` pub type insert_into = crate::query_builder::IncompleteInsertStatement; + /// Represents the return type of [`diesel::update`] + #[allow(non_camel_case_types)] // required for `#[auto_type]` + pub type update = + UpdateStatement<::Table, ::WhereClause>; + /// Represents the return type of [`diesel::insert_or_ignore_into`] #[allow(non_camel_case_types)] // required for `#[auto_type]` pub type insert_or_ignore_into = crate::query_builder::IncompleteInsertOrIgnoreStatement; diff --git a/diesel_derives/tests/auto_type.rs b/diesel_derives/tests/auto_type.rs index 015f533fe947..69f202fa2c69 100644 --- a/diesel_derives/tests/auto_type.rs +++ b/diesel_derives/tests/auto_type.rs @@ -481,6 +481,15 @@ fn delete_returning() -> _ { delete(users::table).returning(users::id) } +#[cfg(feature = "postgres")] +#[auto_type] +fn update_and_binary_operator_and_block() -> _ { + update(pg_extras::table).set(pg_extras::timestamp.eq(pg_extras::timestamp + { + let v: diesel::data_types::PgInterval = 1.year(); + v + })) +} + // #[auto_type] // fn test_sql_fragment() -> _ { // sql("foo")