error: type parameter `D` must be used as the type parameter for some local type

百般思念 提交于 2019-11-30 09:23:32

问题


I'm using Nickel.rs with MongoDB to build a RESTful api. I'd like to implement a generic Responder for the type mongodb::error::Result<Option<bson::Document>>.

This is the implementation I wrote based on the examples I found for Responder:

impl<D> Responder<D> for Result<Option<Document>> {

    fn respond<'a>(self, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
        response.set(MediaType::Json);

        match self {
            Ok(Some(doc))=>{
                ApiResponse{data: Bson::Document(doc).to_json()}.to_json()
            },
            Ok(None)=>{
                response.set(StatusCode::NotFound);
                ApiError{error: "Not found".to_string()}.to_json()
            },
            Err(e)=>{
                response.set(StatusCode::InternalServerError);
                ApiError{error: format!("{}",e)}.to_json()
            }

        }
    }
}

and I'm getting the following error:

error: type parameter D must be used as the type parameter for some local type (e.g. MyStruct<T>); only traits defined in the current crate can be implemented for a type parameter [E0210]

I ran rustc --explain E0210 for an explanation and if my understanding is correct, I need to provide a trait D as a type argument to impl<D>, but I don't understand which trait to provide.

I tried impl<D: =()> but that produced the same error.


回答1:


When you implement a trait then either the trait or the type you are implementing it for must be defined in the same crate. In you example that is not the case: the trait Responder is defined by nickel, and Result is defined by mongodb.

The common way to work around this is to define your own type, by wrapping the desired type into a tuple struct with a single component (the so-called newtype pattern):

struct Result(mongodb::error::Result<Option<Document>>);

impl Responder for Result {
    ...



回答2:


Based on starblue's answer, I replaced ApiResponse and ApiError with a tuple struct and refactored my code as follows:

struct ApiResponse<T>(T);

impl<D> Responder<D> for ApiResponse<Result<Option<Document>>> {

    fn respond<'a>(self, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {

        let mut d = BTreeMap::new();
        match self.0 {
            Ok(Some(doc))=>{
                d.insert("data".to_string(),Bson::Document(doc).to_json());
            },
            Ok(None)=>{
                response.set(StatusCode::NotFound);
                d.insert("error".to_string(),"Not Found".to_json());
            },
            Err(e)=>{
                response.set(StatusCode::InternalServerError);
                d.insert("error".to_string(),format!("{}",e).to_json());
            }

        }
        response.set(MediaType::Json);
        response.send(Json::Object(d))
    }
}


来源:https://stackoverflow.com/questions/35363810/error-type-parameter-d-must-be-used-as-the-type-parameter-for-some-local-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!