ссылки на некоторый тип, но при этом вложенность ссылок может быть хоть какой, т.е. от &T до, скажем, &&&&&T. Какими трейтами воспользоваться, чтобы описать тип, возвращаемый итератором?
enum? &T и &&T - это два разных типа, и объединить их в одном типе можно например через enum enum TRef<T> { R1(&T), R2(&&T), R3(&&&T), ... }
Iter: Iterator<Item = Item>, Item: std::ops::Deref<Target=T>,
Мне не нужно объединять в один тип. Немного больше контекста: fn set_matches_from_actions<Callback, Actions, ActionRef>( matches: &mut Rc<slint::VecModel<ListItem>>, actions: Actions, ) where ActionRef: AsRef<Action<Callback>>, Actions: Iterator<Item = ActionRef>, { matches.set_vec( actions .map(|action| ListItem { text: action.as_ref().name.into(), }) .collect::<Vec<_>>(), ); } Итератор должен иметь возможность возвращать ссылку на Action любой глубины, т.к. поле name нужно лишь иммутабельное. При вызове функции выше как set_matches_from_actions(&mut matches, all_actions.iter());, где all_actions - Vec<Action>, получаю следующее: the trait bound `Action<[closure@src\main.rs:41:9: 43:10]>: std::convert::AsRef<Action<_>>` is not satisfied required because of the requirements on the impl of `std::convert::AsRef<Action<_>>` for `&Action<[closure@src\main.rs:41:9: 43:10]>
Попробовал это, на строчке set_matches_from_actions(&mut matches, matching_actions.iter());, где matching_actions - Vec<&mut Action>, получаю ```type mismatch resolving <&&mut Action<[closure@src\main.rs:41:9: 43:10]> as std::ops::Deref>::Target == Action<_> expected struct Action<_> found mutable reference `&mut Action<[closure@src\main.rs:41:9: 43:10]>````
Для ссылок разной глубины надо разный код для получения значения по этой ссылке. Просто так не получится сделать общий код, который будет работать с ссылками любой глубины вложенности. Только если в где-то в рантайме будет храниться информация о глубине ссылок и тогда можно будет замутить что-то для deref-а такой ссылки (например match по enum-у, или какую-ту рекурсивную функцию с unsafe-ами).
Ещё больше контекста: Код: https://www.toptal.com/developers/hastebin/isimecerer.rust (на плейграунде всё равно не запустится) Ошибка: https://www.toptal.com/developers/hastebin/oyiyobepid.rust
В итераторе ссылки всегда будут одной и той же глубины, я просто не хочу писать несколько функций для обработки ссылок разной вложенности, т.е. тут нужно что-то сделать с дженериками
Рекурсивные дженерики? Хм, интересная мысля. Это наверное что бы совсем было больно от работы с дженериками в расте 😊
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8cfa24ad35ce68cea4c3992a91000ebb Должно работать
Хм. Значит, у меня что-то не так. Судя по ошибке от самого rustc (была отправлена выше на hastebin, отправляю картинкой для удобства; до отправки ошибки я смотрел только на выдачу rust-analyzer'a на конкретной строке), происходит что-то не очень тривиальное. Пойду копать, т.к. если у вас работает, то у меня тоже должно заработать, если написать нормально
Если что, те же самые код и ошибка лежат здесь
Может оно работает по той же причине по которой работает вот это? fn main() { let v = 1; println!("{:?}", &v); println!("{:?}", &&v); } Т.е. в твоём примере на самом деле у нас в результате дерефа не получается на выходе &T или T. Хотя видимо я не правильно понял что требуется.
Да, действительно. Там для T выводится не тот тип.
У тебя достаточно вот так сделать, и тоже будет работать fn foo<Iter, Item>(it: Iter) where Iter: Iterator<Item = Item>, Item: std::fmt::Debug, { for i in it { println!("{i:?}"); } }
Вот, погляди - может тебе так же сделать? https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b5a857c80518972122cdb37522512072
Обсуждают сегодня