Description
Feature request by @fasterthanlime
Implementation notes:
-
pointer-to-pointer arithmetic is, according to C++ and thus likely LLVM,
defined only between two pointers known to be in the same allocation region.
(article 1) I do not know at this time what Miri thinks of pointer-to-pointer
arithmetic, but I strongly suspect, given Miri’s implementation of pointers in
its evaluator model (article 2) that this is suspect at best and a candidate
for rejection at worst.Given that the rest of the crate is also UB in Miri that the compiler merely
happens to not yet reject, I am not too concerned about adding yet more
pointer operations that cause errors in Miri.See @RalfJung’s blog article (article 3) for more about how Miri (and by
extension, eventually, rustc) treats pointer manipulation. -
BitPtr
-to-BitPtr
arithmetic is required by the constraints above to only
be meaningful within the same allocation region, and thus, with the same type.
This means that the function signature is not required to generalize asfn BitPtr<T: BitStore>::ptr_diff<U: BitStore>(self, other: BitPtr<U)>) -> _;
but may be kept specific as just
fn BitPtr<T: BitStore>::ptr_diff(self, other: Self) -> _;
We cannot enforce this in the type system, but this is an
unsafe fn
with the
precondition thatother
andself
be derived from the same overarching
BitSlice<_, T>
region. It is firmly undefined behavior, even by the
UB-adjacent standards of this crate, to callptr_diff
with pointers from two
different regions. -
Prior art in
fn store::BitStore::offset
indicates that the return type
should be the anonymous record{ elts: isize, bits: i8 }
(canonicalized as
the tuple(isize, i8)
). That function produces(isize, BitIdx)
because it
computes a jump value forptr::offset
and an absolute bit index in the
element to which the jump value refers. This function produces a jump value,
and a bit distance between the start pointerself
and the end pointer
other
. -
BitPtr<T: BitStore>
is notably missing aC: Cursor
type parameter. It is
defined behavior for twoBitSlice<C: Cursor, T: BitStore>
handles drawn from
the same region to have differentC
type parameters. How should this be
handled?-
BitPtr::ptr_diff
can only computeBitIdx
differences. This will
necessarily produce a bit distance that describes the index difference
rather than the electrical difference, but, this is unavoidable with the
information available. -
fn BitSlice<C: Cursor, T>::offset<D: Cursor>(&self, other: &BitSlice<D, T>) -> _;
could convert both
self
andother
’sBitIdx
values toBitPos
using
their providedCursor
implementations, then constructBitPtr<T>
pointers
from theBitPos
values and callptr_diff
on them. This would compute the
electrical bit distance between the twoBitSlice
handles.
-
Nom integration notes
-
bitvec
currently relies on behavior that is compiled as expected in current
rustc
but is marked as UB in Miri, and will likely eventually be rejected by
the compiler. For this reason, I am hesitant to encourage thenom
crate to
begin depending onbitvec
for its bit-stream parsing.However, it is advantageous to have
BitSlice
integrate withnom
’s traits,
so that clients who wish to usebitvec
for bitstreamnom
parsing are able
to dropBitSlice
into any trait-drivennom
functions. -
Once
bitvec
depends onnom
, it becomes illegal fornom
to also depend on
bitvec
. I don’t know the dependency rules offhand, but I am hoping that if
bitvec
depends onnom
optionally, the default feature set ofbitvec
is
dependable bynom
without creating a dependency cycle.If
nom
elects to depend onbitvec
,bitvec
’s nom integration will be
removed and placed innom
instead. This may constitute a major-breaking
change if I release a1.0
.