Я играл с шаблоном дизайна посетителей в Rust. У моего первоначального посетителя не было параметра типа, поэтому я смог сделать что-то вроде этого:
impl<T> From<T> for Box<dyn VisitorElement>
where
T: VisitorElement + 'static,
{
fn from(elem: T) -> Box<dyn VisitorElement> {
Box::new(elem)
}
}
Поскольку мой посетитель был просто калькулятором f32
, я хотел сделать его более универсальным c путем замены f32
параметром типа. После передачи повсюду правильного параметра типа моя реализация From
не будет работать. Вот полный пример ( игровая площадка ):
/*
* Visitor traits
*/
trait Visitor<T> {
fn visit_literal(&mut self, literal: &Literal<T>);
}
trait VisitorElement<T> {
fn accept(&self, visitor: &mut dyn Visitor<T>);
}
/*
* Literal value
*/
struct Literal<T> {
value: T,
}
impl<T> Literal<T> {
fn new(value: T) -> Self {
Self { value: value }
}
}
impl<T> VisitorElement<T> for Literal<T> {
fn accept(&self, visitor: &mut dyn Visitor<T>) {
visitor.visit_literal(self)
}
}
impl<K, T> From<K> for Box<dyn VisitorElement<T>>
where
K: VisitorElement<T> + 'static,
{
fn from(elem: K) -> Box<dyn VisitorElement<T>> {
Box::new(elem)
}
}
fn main() {
let element = Literal::new(0.1);
let boxed: Box<dyn VisitorElement<_>> = element.into();
}
error[E0119]: conflicting implementations of trait `std::convert::From<std::boxed::Box<(dyn VisitorElement<_> + 'static)>>` for type `std::boxed::Box<(dyn VisitorElement<_> + 'static)>`:
--> src/main.rs:28:1
|
28 | / impl<K, T> From<K> for Box<dyn VisitorElement<T>>
29 | | where
30 | | K: VisitorElement<T> + 'static,
31 | | {
... |
34 | | }
35 | | }
| |_^
|
= note: conflicting implementation in crate `core`:
- impl<T> std::convert::From<T> for T;
= note: downstream crates may implement trait `VisitorElement<_>` for type `std::boxed::Box<(dyn VisitorElement<_> + 'static)>`
Моя цель состояла в том, чтобы разрешить автоматическую сортировку динамических типов c, чтобы сделать ввод кода менее подробным.
From Как возникает конфликтная реализация `From` при использовании типа generi c? , я вижу, что тип S
может привести к преобразованию трейта в себя, но в моем если тип K
ограничен VisitorElement
, но я все равно получаю конфликт с Box<dyn VisitorElement<_> + 'static>
.
Есть ли причина, по которой ограничение на K: VisitorElement<T> + 'static
позволяет Box<dyn VisitorElement<T> + 'static>
самому себе но K: VisitorElement<f32>
не делает?
Насколько я понимаю, тип K
не может быть Box
, потому что Box
не реализует VisitorElement<T>
, поэтому я никогда не должен a Box как K
.
Если проблема была вызвана автоматической реализацией Into
... Я бы использовал From> для Literal<_>
, затем Literal<_>
в Box<dyn VisitorElement<_>
, но это верно для любого типа. В моем случае это не делается явно, если только Box
не является специальным типом, который реализует ту же черту, что и его содержимое?