Как добавить аннотации типов к блоку generi c impl, где самой структуре не требуется параметр generi c? - PullRequest
0 голосов
/ 18 апреля 2020

Я застрял, пытаясь помочь компилятору определить тип блока c impl. Вот код:

pub struct Foo {
    /*some non generic fields*/
}

impl<T: AsBytes> Foo {
    pub fn new(/*some non generic params*/) -> Self {
        ...
        let size = std::mem::size_of::<T>();
        ...
    }

    pub fn update(&self, data: &T) {
        ...
        let data = data.as_bytes();
        ...
        let size = std::mem::size_of::<T>();
        ...
    }
}

При использовании Foo компилятор обычно может определить тип T, но в одном месте при вызове let var = Foo::new() я получаю эту ошибку:

error[E0282]: type annotations needed
  --> src/bar/foo.rs:98:13
   |
98 |             Foo::new(param1, param2);
   |             ^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`

error: aborting due to previous error

Как аннотировать тип c generi? Какой правильный синтаксис здесь?

1 Ответ

2 голосов
/ 18 апреля 2020

Вы не можете.


У вас в основном есть это:

struct Foo;

impl<T> Foo {
}

, что вызывает

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
 --> src/lib.rs:3:6
  |
3 | impl<T> Foo {
  |      ^ unconstrained type parameter

, потому что генерики не имеют смысла для элемент реализации сам по себе. Они имеют смысл только для типа или метода.

По сути, вам нужен

pub struct Foo {
    size: usize,
}

impl Foo {
    pub fn new<T>() -> Self {
        let size = std::mem::size_of::<T>();
        Self {
            size
        }
    }

    pub fn update<T>(self, data: &T) -> Self {
        self
    }
}

, который, например, можно назвать Foo::new::<String>(). Однако пользователь может обновить Foo, созданный для String, с другим типом:

let foo = Foo::new::<String>();
foo.update::<u32>();

Не ясно, что это то, что вам нужно.

Если вы этого не сделаете , тогда вам нужно сделать Foo generi c over T:

use core::marker::PhantomData;

pub struct Foo<T> {
    size: usize,
    _dummy: PhantomData<T>,
}

impl<T> Foo<T> {
    pub fn new() -> Self {
        let size = std::mem::size_of::<T>();
        Self {
            size,
            _dummy: PhantomData
        }
    }

    pub fn update(self, data: &T) -> Self {
        self
    }
}
...