Как мне управлять выводом типа в коде, который имеет несколько цепных преобразований типов с чертой Into-like? - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть некоторые структуры, сгенерированные компилятором protobuf. Они имеют одинаковую структуру, и я заставил их действовать как дженерики с некоторыми чертами и макросами. Я также добавил некоторый код, чтобы я мог связать SingleResponse конструкция:

pub trait Response {
    type Success;
    type Fail;

    fn new_success(v: Self::Success) -> Self;
    fn new_fail(v: Self::Fail) -> Self;
}

pub trait IntoResponse<T>
where
    T: Response,
{
    fn into_response(self) -> T;
}

impl<T, U, K> IntoResponse<K> for Result<T, U>
where
    T: Into<K::Success>,
    U: Into<K::Fail>,
    K: Response,
{
    fn into_response(self) -> K {
        match self {
            Ok(v) => K::new_success(v.into()),
            Err(v) => K::new_fail(v.into()),
        }
    }
}

struct SingleResponse<T> {
    v: T,
}

trait IntoSingleResponse
where
    Self: std::marker::Sized,
{
    fn into_single_response(self) -> SingleResponse<Self>;
}

impl<T: std::marker::Sized> IntoSingleResponse for T {
    fn into_single_response(self) -> SingleResponse<Self> {
        SingleResponse { v: self }
    }
}

Это демонстрирует проблему:

struct ConcreteSuccess {}
struct ConcreteFail {}
struct ConcreteResponse {}

impl Response for ConcreteResponse {
    type Success = ConcreteSuccess;
    type Fail = ConcreteFail;

    fn new_success(_v: Self::Success) -> Self {
        // Logic not important
        ConcreteResponse {}
    }
    fn new_fail(_v: Self::Fail) -> Self {
        ConcreteResponse {}
    }
}

fn get_result() -> Result<ConcreteSuccess, ConcreteFail> {
    Ok(ConcreteSuccess {})
}

// works as expected
fn return_response() -> ConcreteResponse {
    get_result().into_response()
}

// works as expected
fn return_single_response() -> SingleResponse<ConcreteResponse> {
    return_response().into_single_response()
}

// this function does not compile
fn return_single_response_v_2() -> SingleResponse<ConcreteResponse> {
    get_result().into_response().into_single_response()
}
error[E0282]: type annotations needed
  --> src/lib.rs:80:18
   |
80 |     get_result().into_response().into_single_response()
   |     -------------^^^^^^^^^^^^^--
   |     |            |
   |     |            cannot infer type for type parameter `T` declared on the trait `IntoResponse`
   |     this method call resolves to `T`
   |
   = note: type must be known at this point

Как мне сделать return_single_response_v_2 компиляцию?

...