rusttraitsborrow-checkerboundsrust-diesel

Rust add bound to borrowed type


Is there a way to take a borrow of a type and add a trait bound on the inner type (i.e. you have type &T but want to say where T something)

I was assuming I could require &T to have ToOwned and then add the constraint to the Owned type but that seems to keep the borrow e.g. in this little example. Why does the below not work and is there a way I can get the inner type?

let c: <&i32 as ToOwned>::Owned = 1;
//                                ^ expected &i32, found i32

My ultimate goal here is to be able to take in a type which implemented diesel::Identifiable and the Id of that Identifiable must implement Deserialize. Currently I have a struct like this

#[derive(Queryable, Selectable, Identifiable, serde::Serialize, serde::Deserialize)]
#[diesel(table_name = crate::schema::my_models)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct MyDieselModel {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub published: bool,
}

and a function along these lines:

fn use_model<'ident, T>(model: T)
where
    T: HasTable,
    &'ident T: Identifiable
    <&'ident TModel as Identifiable>::Id: Send + ToOwned,
    <<&'ident TModel as Identifiable>::Id as ToOwned>::Owned: Deserialize<'ident>,
{
   ...
}

If I call use_model<MyDieselModel>() it fails saying

the trait bound `&i32: Deserialize<'_>` is not satisfied
the trait `Deserialize<'_>` is implemented for `i32`
for that trait implementation, expected `i32`, found `&i32`

which makes total sense given the above example where ::Owned isn't giving the type inside the borrow... Any ideas on how I can achieve this ?


Solution

  • Note that ToOwned is implemented for T, not for &T and that <T as ToOwned>::Owned is T itself. You can get the pointed type for a reference with Deref::Target:

    use std::ops::Deref;
    
    fn main() {
        let _c: <&i32 as Deref>::Target = 1;
    }
    

    Playground