Bug reports _must_ include:
The version of Rocket you're using: 0.4.1
The operating system: MacOs Mojave
A brief description of the bug:
When trying to return a response using std::Result<T, E>, I received the following error:
the trait `rocket::response::Responder<'_>` is not implemented for `std::result::Result<rocket_contrib::json::Json<std::vec::Vec<user_module::Users>>, rocket::http::Status>
I am assuming this is not an actual bug, and just confusion on my part after reading the docs. I had thought that the std::Result did implement the Responder correctly, as well as rocket::httpStatus.
I am using Diesel as an ORM.
Here is the following code block that errors.
use diesel::result::Error;
use rocket::http::Status;
use rocket_contrib::json::Json;
use crate::connection::DbConn;
use crate::user_module;
use crate::user_module::Users;
#[get("/test")]
pub fn test() -> Json<&'static str> {
Json("hello world")
}
/// line 16 errors
#[get("/")]
pub fn all(connection: DbConn) -> Result<Json<Vec<Users>>, Status> {
user_module::repository::all(&connection)
.map(|users| Json(users))
.map_err(|error| error_status(error))
}
fn error_status(error: Error) -> Status {
match error {
Error::NotFound => Status::NotFound,
_ => Status::InternalServerError
}
}
Here is my Users model implementation:
#![allow(proc_macro_derive_resolution_fallback)]
use chrono::NaiveDateTime;
pub mod handler;
pub mod router;
pub mod repository;
#[derive(Queryable, Deserialize)]
pub struct Users {
pub id: i32,
pub auth0_identifier: String,
pub first_name: String,
pub last_name: String,
pub bio: Option<String>,
pub created_on: NaiveDateTime,
pub last_login: Option<NaiveDateTime>,
pub profile_picture: Option<String>,
}
Here is my repository method:
use diesel;
use diesel::prelude::*;
use crate::schema::users;
use crate::user_module::Users;
pub fn all(connection: &PgConnection) -> QueryResult<Vec<Users>> {
users::table.load::<Users>(&*connection)
}
Here is a more in depth error description:
error[E0277]: the trait bound `std::result::Result<rocket_contrib::json::Json<std::vec::Vec<user_module::Users>>, rocket::http::Status>: rocket::response::Responder<'_>` is not satisfied
--> src/user_module/handler.rs:14:1
|
14 | #[get("/")]
| ^^^^^^^^^^^ the trait `rocket::response::Responder<'_>` is not implemented for `std::result::Result<rocket_contrib::json::Json<std::vec::Vec<user_module::Users>>, rocket::http::Status>`
|
= help: the following implementations were found:
<std::result::Result<R, E> as rocket::response::Responder<'r>>
<std::result::Result<R, E> as rocket::response::Responder<'r>>
= note: required by `rocket::handler::<impl rocket::Outcome<rocket::Response<'r>, rocket::http::Status, rocket::Data>>::from`
error: aborting due to previous error
I am loving this framework, so thank you all for your hard work.
The problem is actually that Serialize is not implemented for Users: https://api.rocket.rs/v0.4/rocket_contrib/json/struct.Json.html#sending-json
I think if you had tried to return -> Json<Vec<Users>>, the error message would say that. The implementation of Responder for Result uses the unstable specialization feature, which has the side effect of making the error message less helpful.
@jebrosen WOW, I apologize for missing that. Thank you very much!
It's weird how just flipping the types makes it clearer. I had the same problem using Diesel's QueryResult type:
QueryResult<Json<Vec<Post>>> -> Json<QueryResult<Vec<Post>>>
Second one displays the nice error:
The trait bound `diesel::result::Error: serde::ser::Serialize` is not satisfied"
In that example the requirements on diesel::result::Error are arrived at in very different ways:
Json<Result<Vec<Post>, diesel::result::Error>>: Responder
Result<Vec<Post>, diesel::result::Error>: SerializeVec<Post>: Serialize and diesel::Result::Error: Serialize.Result<Json<Vec<Post>>, diesel::result::Error>: Responder
Json<Vec<Post>>: Responder and diesel::result::Error: DebugJson<Vec<Post>>: Responder and diesel::result::Error: Debug + Responderimpl Responder for Result uses the specialization feature, and I believe that's why the error message is incomplete. If impl Responder for Result was not specialized and required just one of Debug or Responder, I'm pretty sure the error message would say `diesel::result::Error: Debug` is not satisfied as expected.but why I get similar error even if I derive Serialize for both Ok and Err?
use rocket::post;
use rocket::response::status;
use rocket::http::Status;
use rocket_contrib::json::Json;
use serde::{ Serialize, Deserialize };
#[derive(Deserialize)]
pub(crate) struct PostUser {
phone: String,
password: String,
}
#[derive(Serialize)]
pub(crate) struct NewUser {
uid: u64,
phone: String,
}
#[derive(Serialize)]
pub(crate) struct ErrRegistered {
err: &'static str,
phone: String,
}
#[post("/users", data = "<user>")]
pub(crate) fn create(user: Json<PostUser>)
-> Result<status::Created<Json<NewUser>>, status::Custom<Json<ErrRegistered>>> {
let PostUser { phone, password } = user.deref();
if let Some(_uid) = find_registered(&phone) {
let err = Json(ErrRegistered {
err: "PHONE_NUMBER_RIGISTERED",
phone: phone.to_string(),
});
return Err(status::Custom(Status::Conflict, err));
}
let uid = register(&phone, &password).expect("Register failed!");
let new_user = Json(NewUser {
uid,
phone: phone.to_string(),
});
let uri = format!("/users/{}", uid).to_string();
Ok(status::Created(uri, Some(new_user)))
}
fn find_registered(p: &str) -> Option<u64> {
Some(10086)
}
fn register(phone: &str, pass: &str) -> Result<u64, ()> {
Ok(10086)
}
Here is the Error:
error[E0277]: the trait bound `std::result::Result<rocket::response::status::Created<rocket_contrib::json::Json<users::NewUser>>, rocket::response::status::Custom<rocket_contrib::json::Json<users::ErrRegistered>>>: rocket::response::responder::Responder<'_>` is not satisfied
--> src\users.rs:27:1
|
27 | #[post("/users", data = "<user>")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `rocket::response::responder::Responder<'_>` is not implemented for `std::result::Result<rocket::response::status::Created<rocket_contrib::json::Json<users::NewUser>>, rocket::response::status::Custom<rocket_contrib::json::Json<users::ErrRegistered>>>`
|
::: C:\Users\34937\.cargo\registry\src\mirrors.sjtug.sjtu.edu.cn-7a04d2510079875b\rocket-0.4.2\src\handler.rs:202:20
|
202 | pub fn from<T: Responder<'r>>(req: &Request, responder: T) -> Outcome<'r> {
| ------------- required by this bound in `rocket::handler::<impl rocket::outcome::Outcome<rocket::response::response::Response<'r>, rocket_http::status::Status, rocket::data::data::Data>>::from`
|
= help: the following implementations were found:
<std::result::Result<R, E> as rocket::response::responder::Responder<'r>>
<std::result::Result<R, E> as rocket::response::responder::Responder<'r>>
error: aborting due to previous error
Since that u64, String or &'_ str is primitive type, Responder should be impled. Therefore, theJsons andstatus::Created/status::Customshould implementRespondertoo, And I've checked. EvenResult<(), ()>` can pass the compile. Why this error comes out? Is there anything I'm missing?
That error is appearing because the Error type has to implement Debug, even though you are using the Responder implementation.
That error is appearing because the Error type has to implement Debug, even though you are using the Responder implementation.
@jebrosen Yes, I added Debug and issue is solved! Thanks!
That error is appearing because the Error type has to implement
Debug, even though you are using theResponderimplementation.
@jebrosen If you ever happen to have the time, I was wondering if you could explain why the compiler gives such a seemingly counter intuitive error? Why is it complaining about the Responder trait instead of the Debug trait?
@rainyday In 0.4, rocket used the specialization feature so that it could implement both of these:
impl<T, E> Responder for Result<T, E> where T: Responder, E: Debugimpl<T, E> Responder for Result<T, E> where T: Responder, E: Debug + ResponderOne of the side effects of the specialization feature seems to be incomplete error messages like the one above - usually rustc prints out some kind of hint about which part of the where is not satisfied. As specialization gets closer to being stable, I expect these and similar error messages to improve.
But, the master branch (upcoming for 0.5) does not use specialization anymore since it is an unstable feature. Only this impl exists now:
impl<T, E> Responder for Result<T, E> where T: Responder, E: ResponderThe previous behavior can be restored by using https://api.rocket.rs/master/rocket/response/struct.Debug.html. This type was also backported to 0.4 for an easier migration path, and there is a runtime warning if using the removed impl: https://github.com/SergioBenitez/Rocket/commit/436a5aad579f7f9e0053ec4fc35c068baf148d64
Most helpful comment
That error is appearing because the Error type has to implement
Debug, even though you are using theResponderimplementation.