Skip to content

Commit

Permalink
Merge pull request #3662 from Ten0/bool_expression_helper_type_inference
Browse files Browse the repository at this point in the history
Allow ~type inference on `And` and `Or` helper types
  • Loading branch information
Ten0 authored Jul 4, 2023
2 parents d8cade5 + 628096e commit 575e63b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
6 changes: 4 additions & 2 deletions diesel/src/expression/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use super::array_comparison::{AsInExpression, In, NotIn};
use super::grouped::Grouped;
use super::select_by::SelectBy;
use super::{AsExpression, Expression};
use crate::expression_methods::PreferredBoolSqlType;
use crate::sql_types;

/// The SQL type of an expression
Expand Down Expand Up @@ -94,12 +95,13 @@ pub type AssumeNotNull<Expr> = super::assume_not_null::AssumeNotNull<Expr>;

/// The return type of
/// [`lhs.and(rhs)`](crate::expression_methods::BoolExpressionMethods::and())
pub type And<Lhs, Rhs, ST = sql_types::Bool> =
pub type And<Lhs, Rhs, ST = <Rhs as PreferredBoolSqlType>::PreferredSqlType> =
Grouped<super::operators::And<Lhs, AsExprOf<Rhs, ST>>>;

/// The return type of
/// [`lhs.or(rhs)`](crate::expression_methods::BoolExpressionMethods::or())
pub type Or<Lhs, Rhs, ST = sql_types::Bool> = Grouped<super::operators::Or<Lhs, AsExprOf<Rhs, ST>>>;
pub type Or<Lhs, Rhs, ST = <Rhs as PreferredBoolSqlType>::PreferredSqlType> =
Grouped<super::operators::Or<Lhs, AsExprOf<Rhs, ST>>>;

/// The return type of
/// [`lhs.escape('x')`](crate::expression_methods::EscapeExpressionMethods::escape())
Expand Down
58 changes: 57 additions & 1 deletion diesel/src/expression_methods/bool_expression_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::dsl;
use crate::expression::grouped::Grouped;
use crate::expression::operators::{And, Or};
use crate::expression::{AsExpression, Expression, TypedExpressionType};
use crate::sql_types::{BoolOrNullableBool, SqlType};
use crate::sql_types::{self, BoolOrNullableBool, SqlType};

/// Methods present on boolean expressions
pub trait BoolExpressionMethods: Expression + Sized {
Expand Down Expand Up @@ -103,3 +103,59 @@ where
T::SqlType: BoolOrNullableBool,
{
}

/// Allow ~type inference on [And](crate::helper_types::And) and [Or](crate::helper_types::Or)
/// helper types
///
/// This is used to be statistically correct as last generic parameter of `dsl::And` and `dsl::Or`
/// without having to specify an additional type parameter.
///
/// It works with types that are [Expression]s and have a [`SqlType`](Expression::SqlType) that is
/// either [`Bool`](sql_types::Bool) or [`Nullable<Bool>`](sql_types::Nullable), and with [`bool`]
/// (and `Option<bool>` and references to those).
///
/// Cases where an additional type parameter would still have to be specified in the helper type
/// generic parameters are:
/// - If this trait isn't implemented for the `other` parameter of the expression
/// (in that case the user (you?) probably wants to implement it)
/// - If the user actually was using the not-preferred implementation of `AsExpression`
/// (e.g. towards `Nullable<Bool>` instead of `Bool`)
pub trait PreferredBoolSqlType {
/// The preferred `Bool` SQL type for this AsExpression implementation.
///
/// That should be either `Bool` or `Nullable<Bool>`.
type PreferredSqlType;
}

impl<E: Expression> PreferredBoolSqlType for E
where
E::SqlType: BoolOrNullableBool,
{
type PreferredSqlType = <E as Expression>::SqlType;
}

/// This impl has to live in Diesel because otherwise it would conflict with the blanket impl above
/// because "diesel might add an implementation of Expression for bool"
impl PreferredBoolSqlType for bool {
type PreferredSqlType = sql_types::Bool;
}

impl PreferredBoolSqlType for &bool {
type PreferredSqlType = sql_types::Bool;
}

impl PreferredBoolSqlType for &&bool {
type PreferredSqlType = sql_types::Bool;
}

impl PreferredBoolSqlType for Option<bool> {
type PreferredSqlType = sql_types::Nullable<sql_types::Bool>;
}

impl PreferredBoolSqlType for &Option<bool> {
type PreferredSqlType = sql_types::Nullable<sql_types::Bool>;
}

impl PreferredBoolSqlType for &&Option<bool> {
type PreferredSqlType = sql_types::Nullable<sql_types::Bool>;
}
2 changes: 1 addition & 1 deletion diesel/src/expression_methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod global_expression_methods;
mod text_expression_methods;

#[doc(inline)]
pub use self::bool_expression_methods::BoolExpressionMethods;
pub use self::bool_expression_methods::{BoolExpressionMethods, PreferredBoolSqlType};
#[doc(hidden)]
pub use self::eq_all::EqAll;
#[doc(inline)]
Expand Down

0 comments on commit 575e63b

Please sign in to comment.