Explain Cursor and StepCursor lifetimes
diff --git a/src/buffer.rs b/src/buffer.rs
index b918a9a..57e43af 100644
--- a/src/buffer.rs
+++ b/src/buffer.rs
@@ -144,13 +144,13 @@
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Cursor<'a> {
- /// The current entry which the `Cursor` is pointing at.
+ // The current entry which the `Cursor` is pointing at.
ptr: *const Entry,
- /// This is the only `Entry::End(..)` object which this cursor is allowed to
- /// point at. All other `End` objects are skipped over in `Cursor::create`.
+ // This is the only `Entry::End(..)` object which this cursor is allowed to
+ // point at. All other `End` objects are skipped over in `Cursor::create`.
scope: *const Entry,
- /// This uses the &'a reference which guarantees that these pointers are
- /// still valid.
+ // Cursor is covariant in 'a. This field ensures that our pointers are still
+ // valid.
marker: PhantomData<&'a Entry>,
}
diff --git a/src/parse.rs b/src/parse.rs
index c432967..17a9d3c 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -301,7 +301,16 @@
#[derive(Copy, Clone)]
pub struct StepCursor<'c, 'a> {
scope: Span,
+ // This field is covariant in 'c.
cursor: Cursor<'c>,
+ // This field is contravariant in 'c. Together these make StepCursor
+ // invariant in 'c. Also covariant in 'a. The user cannot cast 'c to a
+ // different lifetime but can upcast into a StepCursor with a shorter
+ // lifetime 'a.
+ //
+ // As long as we only ever construct a StepCursor for which 'c outlives 'a,
+ // this means if ever a StepCursor<'c, 'a> exists we are guaranteed that 'c
+ // outlives 'a.
marker: PhantomData<fn(Cursor<'c>) -> Cursor<'a>>,
}
@@ -325,6 +334,10 @@
impl private {
pub fn advance_step_cursor<'c, 'a>(proof: StepCursor<'c, 'a>, to: Cursor<'c>) -> Cursor<'a> {
+ // Refer to the comments within the StepCursor definition. We use the
+ // fact that a StepCursor<'c, 'a> exists as proof that 'c outlives 'a.
+ // Cursor is covariant in its lifetime parameter so we can cast a
+ // Cursor<'c> to one with the shorter lifetime Cursor<'a>.
let _ = proof;
unsafe { mem::transmute::<Cursor<'c>, Cursor<'a>>(to) }
}