What does this `impl` block means

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.

3 Likes

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.

4 Likes

Oh, i see now. The where constraint is bidirectional.

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).