LINUX.ORG.RU

Ещё один вопрос по generics в раст

 ,


0

2

Добрый день,

Есть один вопрос, который я задавал на stackoverflow (https://stackoverflow.com/questions/70758445/nested-generics-arguments-in-struct-rust),

но не получил внятного ответа. Первый ответ был «неправильное использование дженериков», а другой "T - конкретный тип, и T : io::Write - недостачно. Первый ответ, конечно достаточно внятный, но всё же хотелось понять почему.

Я написал небольшой гист - где по-моему аналогичная идея вполне себе компилируется и работает : https://gist.github.com/xxxxxion/ba438aedef23091256624dc84c44dff7 .

============== [ Дублирую вопрос - перевёл гугл ] ==============

я пишу программу, которая использует текстовый пользовательский интерфейс, и я перенес функциональность TUI в отдельный модуль, который содержит структуру с логикой/переменными TUI.

Объявление структуры:

struct App<'a, T: io::Write>
where
    T: io::Write,
{
    items_left: StatefulList<String>,
    items_right: StatefulList<String>,
    input_mode: InputMode,
    parser: &'a parser::Parser,
    // --- [ Tui Backend ] ---
    backend: TermionBackend<T>,
}

and the constructor function implementation is :

impl<'a, T> App<'a, T>
where
    T: io::Write,
{
    fn new(parser: &'a parser::Parser) -> App<'a, T> {
        let stdout = io::stdout().into_raw_mode().unwrap();
        let stdout = MouseTerminal::from(stdout);
        let stdout = AlternateScreen::from(stdout);
        let backend = TermionBackend::new(stdout);
        let mut terminal = Terminal::new(backend).unwrap();
        let events = Events::new();

        App {
            items_left: StatefulList::with_items(vec![]),
            items_right: StatefulList::with_items(vec![]),
            input_mode: InputMode::Normal,
            parser,
            backend,
        }
}

Но я получил ошибку от rust-analyzer :

mismatched types expected struct TermionBackend<T> found struct TermionBackend<AlternateScreen<MouseTerminal<RawTerminal<Stdout>>>>>

Я хочу использовать дженерики, потому что в TermionBackend много вложенных классов, а его объявление очень большое.

Также я почитал исходник и структура AlternateScreen, то есть T, реализует io::Write типаж, и поэтому я не понимаю, почему возникает ошибка.

============== [ Дублирую вопрос - перевёл гугл ] ==============

Также сейчас немного поменял декларацию на

let backend: TermionBackend<T> = TermionBackend::new(stdout);

И rust-analyzer ругается :

mismatched types expected type parameter T found struct AlternateScreen<MouseTerminal<RawTerminal<Stdout>>>

Опять же AlternateScreen реализует trait io::Write.



Последнее исправление: xionovermazes (всего исправлений: 1)
       let stdout = io::stdout().into_raw_mode().unwrap();
       let stdout = MouseTerminal::from(stdout);
       let stdout = AlternateScreen::from(stdout);
       let backend = TermionBackend::new(stdout);

Ты сказал, что backend: TermionBackend<T>, а пихаешь в него конкретный тип.

Тогда уж

fn new(parser: &'a parser::Parser, backend: TermionBackend<T>) -> App<'a, T> {
...
}

        let stdout = io::stdout().into_raw_mode().unwrap();
        let stdout = MouseTerminal::from(stdout);
        let stdout = AlternateScreen::from(stdout);
        let backend = TermionBackend::new(stdout);
        let app = App::new(parser, backend);
AlexVR ★★★★★
()

Дженерик в возвращаемом типе означает, что вызывающий код может подставить туда любой тип (удовлетворяющий ограничениям) и получить результат этого типа. А функция new() возвращает значение конкретного типа, а не того, что задан вызывающим кодом.

Чтобы это заработало, нужно в сигнатуре new() указать возвращаемый тип (AlternateScreen<MouseTerminal<RawTerminal<Stdout>>>) или использовать impl Trait: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1b01682269cab4f5c73bea56280c5112

red75prim ★★★
()

Если причина использовать дженерики только в том чтобы не писать длинный тип, то это не обязательно – можно определить алиас type MyTUIBackend = TermionBackend<AlternateScreen<MouseTerminal<RawTerminal<Stdout>>>>> и дженерики не нужны.

k_andy ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.