I read some example code from the diesel library, and found an example below. What does where clause i32: FromSql<Integer, DB> means, it seems like a redundant declaration.
#[repr(i32)]
#[derive(Debug, Clone, Copy)]
pub enum MyEnum {
A = 1,
B = 2,
}
impl<DB> FromSql<Integer, DB> for MyEnum
where
DB: Backend,
i32: FromSql<Integer, DB>,
{
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
match i32::from_sql(bytes)? {
1 => Ok(MyEnum::A),
2 => Ok(MyEnum::B),
x => Err(format!("Unrecognized variant {}", x).into()),
}
}
}
It is the restriction on the type parameter. It's possible that not all types which implement Backend will provide the implementation for i32: FromSql<Integer, Db>, so the second requirement allows to explicitly narrow down the set of possible types.
Note that bounds (where clauses) are a general set of constraints to be satisfied. More often than not, a generic left-side is limited by the right-side; perhaps this is why your intuition was that the bound is redundant. But it's also possible for the right-side to limit the left-side (no matter where the generics are).
In this case, DB is limited to concrete types which satisfy i32: FromSql<Integer, DB> (and also DB: Backend). If that wasn't the case, i32::from_sql(bytes) could not be called.
I like to think of where-clauses as "equations" you write with the type system. Sometimes you can have your "variables" on the right-hand side (e.g. the DB in i32: FromSql<Integer, DB>), and other times they might be on the left-hand side (e.g. DB in DB: Backend).