Visitor pattern: Adding Associated Type to Visitable

I'm trying to add an associated type to the visitor pattern, but am missing the wood for the trees.

Appreciate any tips on the correct way to go about this. The reduced example is here in the playground:

pub trait Visitor<T> {
    fn visit(&mut self, t:&T);
}

pub trait Visitable: Sized {
    type R;
    
    fn accept<T>(&self, t: &mut T) 
       where T: Visitor<Self>
    {
        let _ = &Self::R::store(t.visit(self));
    }
}

struct Expr;
impl Visitable for Expr {
    type R = Repo;
}

struct Term;
impl Visitable for Term {
    type R = Repo;
}

struct Vis;

struct Repo;

impl Repo {
    fn store(_e: ()) {
        println!("Stored.")
    }
}

impl Visitor<Expr> for Vis {
    fn visit(&mut self, _: &Expr) {
        println!("Visiting an Expression");
    }
}

impl Visitor<Term> for Vis {
    fn visit(&mut self, _: &Term) {
        println!("Visiting a Term");
    }
}

fn main() {
    let mut v = Vis;
    Expr.accept(&mut v);
    Term.accept(&mut v);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0599]: no function or associated item named `store` found for associated type `<Self as Visitable>::R` in the current scope
  --> src/main.rs:13:27
   |
13 |         let _ = &Self::R::store(t.visit(self));
   |                           ^^^^^ function or associated item not found in `<Self as Visitable>::R`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` due to previous error

store is the method of struct Repo, not the method of <SomeType as Visitable>::R, thus you get an error.

One solution is:

pub trait Visitable: Sized {
-    type R;
+    type R: Store;
    
    ...
}

-impl Repo {
-    fn store(_e: ()) {
-        println!("Stored.")
-    }
-}
+pub trait Store {
+    fn store(_e: ()) {
+        println!("Stored.")
+    }
+}
+impl Store for Repo { }

playground

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.