Trouble & Confusion with Diesel and Rust Traits - rust
I'm trying to use the Diesel crate (version 2.0.2; rustc 1.63.0) for an application and have some code that goes like this:
src/models.rs
use uuid::Uuid;
use diesel::prelude::*;
use crate::schema::entities::dsl::entities;
type DB = diesel::pg::Pg;
#[derive(Queryable, PartialEq, Debug)]
#[diesel(table_name = entities)]
pub struct Entity {
pub id: u16,
pub uuid: Uuid,
pub username: Option<String>
}
impl Entity {
pub fn get_all(connection: &mut PgConnection) -> QueryResult<Vec<Entity>> {
entities.load::<Entity>(connection)
}
}
src/schema.rs
// #generated automatically by Diesel CLI.
diesel::table! {
entities (id) {
id -> Int4,
uuid -> Uuid,
username -> Nullable<Text>,
}
}
diesel::allow_tables_to_appear_in_same_query!(
entities,
);
However, this will not compile. The following errors are thrown when I try:
error[E0277]: the trait bound `(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>): load_dsl::private::CompatibleType<Entity, _>` is not satisfied
--> src/models.rs:20:18
|
20 | entities.load::<Entity>(connection)
| ^^^^ the trait `load_dsl::private::CompatibleType<Entity, _>` is not implemented for `(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>)`
|
= help: the following other types implement trait `load_dsl::private::CompatibleType<U, DB>`:
(ST0, ST1)
(ST0, ST1, ST2)
(ST0, ST1, ST2, ST3)
(ST0, ST1, ST2, ST3, ST4)
(ST0, ST1, ST2, ST3, ST4, ST5)
(ST0, ST1, ST2, ST3, ST4, ST5, ST6)
(ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7)
(ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8)
and 24 others
= note: required because of the requirements on the impl of `LoadQuery<'_, _, Entity>` for `entities::table`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/username/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.2/src/query_dsl/mod.rs:1499:15
|
1499 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `diesel::RunQueryDsl::load`
error[E0277]: the trait bound `Entity: FromSqlRow<_, _>` is not satisfied
--> src/models.rs:20:18
|
20 | entities.load::<Entity>(connection)
| ^^^^ the trait `FromSqlRow<_, _>` is not implemented for `Entity`
|
= help: the following other types implement trait `FromSqlRow<ST, DB>`:
<(T1, T0) as FromSqlRow<(ST1, Untyped), __DB>>
<(T1, T2, T0) as FromSqlRow<(ST1, ST2, Untyped), __DB>>
<(T1, T2, T3, T0) as FromSqlRow<(ST1, ST2, ST3, Untyped), __DB>>
<(T1, T2, T3, T4, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, Untyped), __DB>>
<(T1, T2, T3, T4, T5, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, Untyped), __DB>>
<(T1, T2, T3, T4, T5, T6, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, Untyped), __DB>>
<(T1, T2, T3, T4, T5, T6, T7, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, Untyped), __DB>>
<(T1, T2, T3, T4, T5, T6, T7, T8, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8, Untyped), __DB>>
and 23 others
= note: required because of the requirements on the impl of `LoadQuery<'_, _, Entity>` for `entities::table`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/username/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.2/src/query_dsl/mod.rs:1499:15
|
1499 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `diesel::RunQueryDsl::load`
According to Diesel's documentation (specifically this page), deriving Queryable should be enough to run functions like load on entities.
From the error message, I gather that Diesel's FromSqlRow trait is not being implemented, but whenever I try to include that in the derive (and remove the conflicting Queryable derivation), I am only met by another, very similar, set of errors on compilation. A long walk through Diesel's available documentation hasn't helped me understand what is going on or how I might fix it as the typical documentation seems to be "derive it," and a google search is similarly unfruitful. Am I supposed to be implementing any traits by hand here? If so, what might that look like (I cannot find any examples)? Or is there something else I'm missing? More importantly, can anyone explain exactly what this error message is trying to communicate?
EDIT 1: Provide the relevant schema code; had provided it for a different model accidentally.
EDIT 2: Below update with clarified order of properties
Even when I change models.rs to the below to explicitly declare the order in which properties are selected, a similar error (see edit 4) still appears:
use uuid::Uuid;
use diesel::prelude::*;
use crate::schema::entities;
type DB = diesel::pg::Pg;
#[derive(Queryable, PartialEq, Debug)]
#[diesel(table_name = entities)]
pub struct Entity {
pub id: u16,
pub uuid: Uuid,
pub username: Option<String>
}
impl Entity {
pub fn get_all(connection: &mut PgConnection) -> QueryResult<Vec<Entity>> {
entities::dsl::entities
.select((entities::id, entities::uuid, entities::username))
.load::<Entity>(connection)
}
}
I have included the proper feature flags in Cargo.toml.
EDIT 3: Verified that versions are compatible; see changelog for Diesel
uuid < 0.7.0 not supported; using 1.2.2
rustc >= 1.56.0 required; using 1.63.0
EDIT 4: new error that is being thrown on compilation
error[E0277]: the trait bound `(u16, uuid::Uuid, Option<String>): FromStaticSqlRow<(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>), Pg>` is not satisfied
--> src/models.rs:22:14
|
22 | .load(connection)
| ^^^^ the trait `FromStaticSqlRow<(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>), Pg>` is not implemented for `(u16, uuid::Uuid, Option<String>)`
|
= help: the following other types implement trait `FromStaticSqlRow<ST, DB>`:
<(T0,) as FromStaticSqlRow<(ST0,), __DB>>
<(T1, T0) as FromStaticSqlRow<(ST1, ST0), __DB>>
<(T1, T2, T0) as FromStaticSqlRow<(ST1, ST2, ST0), __DB>>
<(T1, T2, T3, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST0), __DB>>
<(T1, T2, T3, T4, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST0), __DB>>
<(T1, T2, T3, T4, T5, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST0), __DB>>
<(T1, T2, T3, T4, T5, T6, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST0), __DB>>
<(T1, T2, T3, T4, T5, T6, T7, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST0), __DB>>
and 24 others
The linked documentation already gives a pretty strong hint what's wrong in your case:
Note: When this trait is derived, it will assume that all fields on your struct matches all fields in the query, including the order and count. This means that field order is significant if you are using #[derive(Queryable)]. Field name has no effect.
In your case the problem is a mismatch between the type of the id field and the corresponding database type. That's u16 on rust side vs Int4 on database side. According to the diesel documentation of Integer (Int4 is a type alias for this type), these two types are not compatible. You need to use a i32 in that position.
They are not considered compatible as not all possible database values of a Int4 field fit into a u16
Related
Trouble with function return type
I am having trouble with creating a function that returns the following Gradient type (https://docs.rs/nannou/latest/nannou/color/gradient/struct.Gradient.html) from the nannou. I now realize this is going to be a problem for me in general with complex generics types. I tried to use a trick I've seen, which is to call a non-existent function on a given type to have the compiler complain. 8 | gradient.asdfasdf(); | ^^^^^^^^ method not found in `nannou::color::Gradient<nannou::prelude::rgb::Rgb<nannou::color::encoding::Linear<Srgb>>>` So great! My type must be nannou::color::Gradient<nannou::prelude::rgb::Rgb<nannou::color::encoding::Linear<Srgb>>> So then I created the function with that as the return type: pub fn get_gradient(color_1: Rgb, color_2: Rgb) -> nannou::color::Gradient<nannou::prelude::rgb::Rgb<nannou::color::encoding::Linear<Srgb>>> { let (r1, g1, b1) = color_1.into_components(); let (r2, g2, b2) = color_2.into_components(); Gradient::new(vec![lin_srgb(r1 as f32, g1 as f32, b1 as f32), lin_srgb(r2 as f32, g2 as f32, b2 as f32)]); } But then the compiler gives a new error: error[E0277]: the trait bound `nannou::prelude::rgb::Rgb: RgbSpace` is not satisfied --> examples/utils/color.rs:3:52 | 3 | ...color_2: Rgb) -> nannou::color::Gradient<nannou::prelude::rgb::Rgb<nannou::color::encoding::Linear<Srgb>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `RgbSpace` is not implemented for `nannou::prelude::rgb::Rgb` | = help: the following other types implement trait `RgbSpace`: (P, W) nannou::color::encoding::Srgb = note: required because of the requirements on the impl of `RgbStandard` for `nannou::color::encoding::Linear<nannou::prelude::rgb::Rgb>` note: required by a bound in `nannou::prelude::rgb::Rgb` --> /Users/brittcagnina/.cargo/registry/src/github.com-1ecc6299db9ec823/palette-0.5.0/src/rgb/rgb.rs:46:19 | 46 | pub struct Rgb<S: RgbStandard = Srgb, T: Component = f32> { | ^^^^^^^^^^^ required by this bound in `nannou::prelude::rgb::Rgb` I'm unsure how to proceed or even interpret this error. Not just with this particular type but in general. I'm having trouble with several other types in this library that use generics. What is the general strategy or principles needed to figure this out? Thanks!
Turns out the naming in the nannou crate is quite a mess. There are multiple Rgb types: nannou_core::color::Rgb, re-exported as: nannou::color::Rgb nannou::prelude::Rgb palette::rgb::Rgb, re-exported as: nannou::color::rgb::Rgb nannou::prelude::rgb::Rgb Further, there are multiple Srgb types: palette::rgb::Srgb, re-exported as: nannou::color::rgb::Srgb nannou::prelude::rgb::Srgb palette::encoding::srgb::Srgb, re-exported as: nannou::color::encoding::Srgb Note that especially in the Rgb case, even the docs are confused and tend to link to the wrong Rgb type. Either way, the actual mistake you made is that you chose the wrong Srgb type: use nannou::{color::Gradient, prelude::*}; pub fn get_gradient( color_1: Rgb, color_2: Rgb, ) -> nannou::color::Gradient< nannou::prelude::rgb::Rgb<nannou::color::encoding::Linear<nannou::color::encoding::Srgb>>, > { let (r1, g1, b1) = color_1.into_components(); let (r2, g2, b2) = color_2.into_components(); Gradient::new(vec![ lin_srgb(r1 as f32, g1 as f32, b1 as f32), lin_srgb(r2 as f32, g2 as f32, b2 as f32), ]) } Alternatively, you don't even need the full form, because Rgb<Linear<Srgb>, f32> is just the long form of the actual return type of your lin_srgb, which is LinSrgb<f32>: use nannou::{color::Gradient, prelude::*}; pub fn get_gradient(color_1: Rgb, color_2: Rgb) -> Gradient<LinSrgb<f32>> { let (r1, g1, b1) = color_1.into_components(); let (r2, g2, b2) = color_2.into_components(); Gradient::new(vec![ lin_srgb(r1 as f32, g1 as f32, b1 as f32), lin_srgb(r2 as f32, g2 as f32, b2 as f32), ]) }
Rust can not infer type for Sub<RHS=Self> trait type of RHS. Why?
I am currently implementing the Sub trait for my custom newtypes, which add some compile-time safety mechanisms. I tried to implement the Sub trait for my new types, but they do not work without ugly casts. Here is what I have ( note I am working with ndarray, and before you recommend nalgebra, no I can not use nalgebra because I need fast matrix multiplications ) : use cauchy::Scalar; use ndarray_linalg::Lapack; use nalgebra::Dim; use ndarray::{Dimension, ArrayBase, OwnedRepr, Data}; use std::marker::PhantomData; pub struct States<A, N, D, R> where A: Scalar + Lapack, N: Dim, D: Dimension, R: Data<Elem=A> { pub(in super) _dim_phantom: PhantomData<N>, pub(in super) data: ArrayBase<R, D> } And here I have my implementation of the Sub trait : impl<'a, A, N, M, R1, R2> Sub<&'a States<A, N, Ix3, R1>> for &States<A, M, Ix2, R2> where A: Scalar + Lapack, N: Dim, M: Dim, R1: Data<Elem=A>, R2: Data<Elem=A>, ShapeConstraint: DimEq<M,N> { type Output = States3<A, N>; fn sub(self, rhs: &'a States<A, N, Ix3, R1>) -> Self::Output { let mut out = self.data.view().insert_axis(Axis(0)).to_owned(); out.sub_assign(&rhs.data); States { _dim_phantom: Default::default(), data: out } } } Now the following does not work (note that DimEq<N,M> is satisfied in method where this snippet is used: let states: &States<A, N, Ix2, OwnedRepr<A>> = ... let innovations_updated: States<A, M, Ix3, OwnedRepr<A>> = ... let output = states - &innovations_updated For the code above I get: error[E0308]: mismatched types --> src/filter/kalman.rs:71:39 | 35 | impl<T, S, M> Filter<T, S, M> for KalmanFilter<T, S, M> where | - expected type parameter ... 57 | fn update<N, Q>(&self, states: &States2<T, N>, covariances: &Covariances<T, N>, measurements: &States2<T, Q>) -> Self::Update | - found type parameter ... 71 | let updated_states = states - &innovation_updates; | ^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found type parameter `N` | = note: expected reference `&States<T, S, ndarray::Dim<[usize; 3]>, _>` found reference `&States<T, N, ndarray::Dim<[usize; 3]>, OwnedRepr<T>>` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters But when I use convoluted casts, then it works as follows: let states: &States<A, N, Ix2, OwnedRepr<A>> = ... let innovations_updated: States<A, M, Ix3, OwnedRepr<A>> = ... let output = <&States2<T, N> as Sub<&States<T, N, ndarray::Ix3, OwnedRepr<T>>>>::sub(states, &innovation_updates); Now this is confusing to me, because the IDE manages to annotate the line with correct output type. Further neither of the variables have anything to do with type parameter S. Why does it want something from type parameter S ?
how to use nix::mount::mount() replace with libc::mount() in Rust
I want to use the 'nix' library to replace with 'libc' in Rust FFI . I want to use nix::mount::mount() to replace with libc::mount(). Now I have the followed code : libc::mount(ptr::null(), path.as_ptr(), ptr::null(), libc:: MS_SLAVE, ptr::null()) I just want to know how to replace the ptr::null() in nix library, I try to use 'None' to do it, but failed. Please help me, thanks. Show the error: 39 | nix::mount::mount( | ^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `P1` declared on the function `mount` | ::: /root/.cargo/registry/src/mirrors.ustc.edu.cn-15f9db60536bad60/nix-0.19.0/src/mount.rs:57:27 | 57 | pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>( | ------- required by this bound in `nix::mount::mount` | = note: cannot satisfy `_: nix::NixPath`
nix::mount::mount has the function signature: pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>( source: Option<&P1>, target: &P2, fstype: Option<&P3>, flags: MsFlags, data: Option<&P4> ) -> Result<()> As you can see, the arguments source, fstype and data take options of generic type parameter. If you pass in Some(value), these type parameters can be inferred based on the type of value, but if you pass in None, the compiler doesn't have enough information to infer a type for these parameters. You can explicitly specify the type of the parameters to be some type that implements NixPath, such as Path: nix::mount::mount<Path, Path, Path, Path>(None, path, None, MsFlags::MS_SLAVE, None) Or you can specify a type parameter directly on None: nix::mount::mount(None::<Path>, path, None::<Path>, MsFlags::MS_SLAVE, None::<Path>)
How can I check if two large arrays are equal? [duplicate]
I have written some tests where I need to assert that two arrays are equal. Some arrays are [u8; 48] while others are [u8; 188]: #[test] fn mul() { let mut t1: [u8; 48] = [0; 48]; let t2: [u8; 48] = [0; 48]; // some computation goes here. assert_eq!(t1, t2, "\nExpected\n{:?}\nfound\n{:?}", t2, t1); } I get multiple errors here: error[E0369]: binary operation `==` cannot be applied to type `[u8; 48]` --> src/main.rs:8:5 | 8 | assert_eq!(t1, t2, "\nExpected\n{:?}\nfound\n{:?}", t2, t1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `[u8; 48]` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `[u8; 48]: std::fmt::Debug` is not satisfied --> src/main.rs:8:57 | 8 | assert_eq!(t1, t2, "\nExpected\n{:?}\nfound\n{:?}", t2, t1); | ^^ `[u8; 48]` cannot be formatted using `:?`; if it is defined in your crate, add `#[derive(Debug)]` or manually implement it | = help: the trait `std::fmt::Debug` is not implemented for `[u8; 48]` = note: required by `std::fmt::Debug::fmt` Trying to print them as slices like t2[..] or t1[..] doesn't seem to work. How do I use assert with these arrays and print them?
For the comparison part you can just convert the arrays to iterators and compare elementwise. assert_eq!(t1.len(), t2.len(), "Arrays don't have the same length"); assert!(t1.iter().zip(t2.iter()).all(|(a,b)| a == b), "Arrays are not equal");
With Iterator::eq, it is possible to compare anything that can be turned into an iterator for equality: let mut t1: [u8; 48] = [0; 48]; let t2: [u8; 48] = [0; 48]; assert!(t1.iter().eq(t2.iter()));
Using slices As a workaround, you can just use &t1[..] (instead of t1[..]) to make arrays into slices. You'll have to do this for both comparison and formatting. assert_eq!(&t1[..], &t2[..], "\nExpected\n{:?}\nfound\n{:?}", &t2[..], &t1[..]); or assert_eq!(t1[..], t2[..], "\nExpected\n{:?}\nfound\n{:?}", &t2[..], &t1[..]); Formatting arrays directly Ideally, the original code should compile, but it doesn't for now. The reason is that the standard library implements common traits (such as Eq and Debug) for arrays of only up to 32 elements, due to lack of const generics. Therefore, you can compare and format shorter arrays like: let t1: [u8; 32] = [0; 32]; let t2: [u8; 32] = [1; 32]; assert_eq!(t1, t2, "\nExpected\n{:?}\nfound\n{:?}", t2, t1);
You could make Vecs out of them. fn main() { let a: [u8; 3] = [0, 1, 2]; let b: [u8; 3] = [2, 3, 4]; let c: [u8; 3] = [0, 1, 2]; let va: Vec<u8> = a.to_vec(); let vb: Vec<u8> = b.to_vec(); let vc: Vec<u8> = c.to_vec(); println!("va==vb {}", va == vb); println!("va==vc {}", va == vc); println!("vb==vc {}", vb == vc); }
Why does Rust store i64s captured by a closure as i64*s in the LLVM IR closure environment?
In this simple example #[inline(never)] fn apply<F, A, B>(f: F, x: A) -> B where F: FnOnce(A) -> B { f(x) } fn main() { let y: i64 = 1; let z: i64 = 2; let f = |x: i64| x + y + z; print!("{}", apply(f, 42)); } the closure passed to apply is passed as a LLVM IR {i64*, i64*}*: %closure = type { i64*, i64* } define internal fastcc i64 #apply(%closure* noalias nocapture readonly dereferenceable(16)) unnamed_addr #0 personality i32 (i32, i32, i64, %"8.unwind::libunwind::_Unwind_Exception"*, %"8.unwind::libunwind::_Unwind_Context"*)* #rust_eh_personality { entry-block: %1 = getelementptr inbounds %closure, %closure* %0, i64 0, i32 1 %2 = getelementptr inbounds %closure, %closure* %0, i64 0, i32 0 %3 = load i64*, i64** %2, align 8 %4 = load i64*, i64** %1, align 8 %.idx.val.val.i = load i64, i64* %3, align 8, !noalias !1 %.idx1.val.val.i = load i64, i64* %4, align 8, !noalias !1 %5 = add i64 %.idx.val.val.i, 42 %6 = add i64 %5, %.idx1.val.val.i ret i64 %6 } (apply actually has a more complicated name in the generated LLVM code.) This causes two loads to get to each of the captured variables. Why isn't %closure just {i64, i64} (which would make the argument to apply {i64, i64}*)?
Closures capture by reference by default. You can change that behavior to capture by value by adding the move keyword before the parameter list: let f = move |x: i64| x + y + z; This generates much leaner code: define internal fastcc i64 #apply(i64 %.0.0.val, i64 %.0.1.val) unnamed_addr #0 personality i32 (i32, i32, i64, %"8.unwind::libunwind::_Unwind_Exception"*, %"8.unwind::libunwind::_Unwind_Context"*)* #rust_eh_personality { entry-block: %0 = add i64 %.0.0.val, 42 %1 = add i64 %0, %.0.1.val ret i64 %1 } Adding the move keyword means that any value that the closure uses will be moved into the closure's environment. In the case of integers, which are Copy, it doesn't make much difference, but in the case of other types like String, it means that you can't use the String anymore in the outer scope after creating the closure. It's an all-or-nothing deal, but you can manually take references to individual variables outside a move closure and have the closure use these references instead of the original values to get manual capture-by-reference behavior. Can you observe the value vs ref difference somehow in this code? If you take the address of the captured variable, you can observe the difference. Notice how the first and second output lines are the same, and the third is different.