summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadrieril2019-04-14 19:16:26 +0200
committerNadrieril2019-04-14 19:16:26 +0200
commit2223c8ff253fe59fcf365c15221f77b1fc86bd3b (patch)
treeff702ab9be56c4ff24160ff7deabb754b6f38c27
parent7aaa3f1747e6012e51e67edb268414e2c2fb51cd (diff)
Document why Visitor is needed
Diffstat (limited to '')
-rw-r--r--dhall_core/src/visitor.rs12
1 files changed, 12 insertions, 0 deletions
diff --git a/dhall_core/src/visitor.rs b/dhall_core/src/visitor.rs
index 5eb17f6..3efd920 100644
--- a/dhall_core/src/visitor.rs
+++ b/dhall_core/src/visitor.rs
@@ -2,10 +2,21 @@ use std::collections::BTreeMap;
use crate::*;
+/// A way too generic Visitor trait.
pub trait GenericVisitor<Input, Return>: Sized {
fn visit(self, input: Input) -> Return;
}
+/// A visitor trait that can be used to traverse `ExprF`s. We need this pattern
+/// so that Rust lets us have as much mutability as we can.
+/// For example, `traverse_embed` cannot be made using only `traverse_ref`, because
+/// `traverse_ref` takes a `FnMut` so we would need to pass multiple mutable
+/// reverences to this argument to `traverse_ref`. But Rust's ownership system
+/// is all about preventing exactly this ! So we have to be more clever.
+/// The visitor pattern allows us to have only one mutable thing the whole
+/// time: the visitor itself. The visitor can then carry around multiple closures
+/// or just one, and Rust is ok with either. See for example TraverseRefVisitor
+/// and TraverseEmbedVisitor.
pub trait ExprFFallibleVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>:
Sized
{
@@ -160,6 +171,7 @@ where
}
}
+/// Like ExprFFallibleVisitor, but without the error handling.
pub trait ExprFInFallibleVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>:
Sized
{