pub struct Slice {
pub(crate) array_len: Option<usize>,
pub(crate) kind: SliceKind,
}
Expand description
A constructor for array and slice patterns.
Fields§
§array_len: Option<usize>
None
if the matched value is a slice, Some(n)
if it is an array of size n
.
kind: SliceKind
The kind of pattern it is: fixed-length [x, y]
or variable length [x, .., y]
.
Implementations§
source§impl Slice
impl Slice
pub fn new(array_len: Option<usize>, kind: SliceKind) -> Self
pub fn arity(self) -> usize
sourcefn is_covered_by(self, other: Self) -> bool
fn is_covered_by(self, other: Self) -> bool
See Constructor::is_covered_by
sourcefn split(
self,
column_slices: impl Iterator<Item = Slice>,
) -> impl Iterator<Item = (Presence, Slice)>
fn split( self, column_slices: impl Iterator<Item = Slice>, ) -> impl Iterator<Item = (Presence, Slice)>
This computes constructor splitting for variable-length slices, as explained at the top of the file.
A slice pattern [x, .., y]
behaves like the infinite or-pattern [x, y] | [x, _, y] | [x, _, _, y] | etc
. The corresponding value constructors are fixed-length array constructors of
corresponding lengths. We obviously can’t list this infinitude of constructors.
Thankfully, it turns out that for each finite set of slice patterns, all sufficiently large
array lengths are equivalent.
Let’s look at an example, where we are trying to split the last pattern:
match x {
[true, true, ..] => {}
[.., false, false] => {}
[..] => {}
}
Here are the results of specialization for the first few lengths:
// length 0
[] => {}
// length 1
[_] => {}
// length 2
[true, true] => {}
[false, false] => {}
[_, _] => {}
// length 3
[true, true, _ ] => {}
[_, false, false] => {}
[_, _, _ ] => {}
// length 4
[true, true, _, _ ] => {}
[_, _, false, false] => {}
[_, _, _, _ ] => {}
// length 5
[true, true, _, _, _ ] => {}
[_, _, _, false, false] => {}
[_, _, _, _, _ ] => {}
We see that above length 4, we are simply inserting columns full of wildcards in the middle.
This means that specialization and witness computation with slices of length l >= 4
will
give equivalent results regardless of l
. This applies to any set of slice patterns: there
will be a length L
above which all lengths behave the same. This is exactly what we need
for constructor splitting.
A variable-length slice pattern covers all lengths from its arity up to infinity. As we just
saw, we can split this in two: lengths below L
are treated individually with a
fixed-length slice each; lengths above L
are grouped into a single variable-length slice
constructor.
For each variable-length slice pattern p
with a prefix of length plₚ
and suffix of
length slₚ
, only the first plₚ
and the last slₚ
elements are examined. Therefore, as
long as L
is positive (to avoid concerns about empty types), all elements after the
maximum prefix length and before the maximum suffix length are not examined by any
variable-length pattern, and therefore can be ignored. This gives us a way to compute L
.
Additionally, if fixed-length patterns exist, we must pick an L
large enough to miss them,
so we can pick L = max(max(FIXED_LEN)+1, max(PREFIX_LEN) + max(SUFFIX_LEN))
.
max_slice
below will be made to have this arity L
.
If self
is fixed-length, it is returned as-is.
Additionally, we track for each output slice whether it is covered by one of the column slices or not.
Trait Implementations§
impl Copy for Slice
impl Eq for Slice
impl StructuralPartialEq for Slice
Auto Trait Implementations§
impl DynSend for Slice
impl DynSync for Slice
impl Freeze for Slice
impl RefUnwindSafe for Slice
impl Send for Slice
impl Sync for Slice
impl Unpin for Slice
impl UnwindSafe for Slice
Blanket Implementations§
source§impl<'tcx, T> ArenaAllocatable<'tcx, IsCopy> for Twhere
T: Copy,
impl<'tcx, T> ArenaAllocatable<'tcx, IsCopy> for Twhere
T: Copy,
fn allocate_on(self, arena: &'tcx Arena<'tcx>) -> &'tcx mut T
fn allocate_from_iter( arena: &'tcx Arena<'tcx>, iter: impl IntoIterator<Item = T>, ) -> &'tcx mut [T]
source§impl<'tcx, T> ArenaAllocatable<'tcx, IsCopy> for Twhere
T: Copy,
impl<'tcx, T> ArenaAllocatable<'tcx, IsCopy> for Twhere
T: Copy,
fn allocate_on(self, arena: &'tcx Arena<'tcx>) -> &'tcx mut T
fn allocate_from_iter( arena: &'tcx Arena<'tcx>, iter: impl IntoIterator<Item = T>, ) -> &'tcx mut [T]
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T, R> CollectAndApply<T, R> for T
impl<T, R> CollectAndApply<T, R> for T
source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.source§impl<T> Filterable for T
impl<T> Filterable for T
source§fn filterable(
self,
filter_name: &'static str,
) -> RequestFilterDataProvider<T, fn(_: DataRequest<'_>) -> bool>
fn filterable( self, filter_name: &'static str, ) -> RequestFilterDataProvider<T, fn(_: DataRequest<'_>) -> bool>
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§impl<P> IntoQueryParam<P> for P
impl<P> IntoQueryParam<P> for P
fn into_query_param(self) -> P
source§impl<T> MaybeResult<T> for T
impl<T> MaybeResult<T> for T
source§impl<T> Pointable for T
impl<T> Pointable for T
source§impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
source§impl<I, T> UpcastFrom<I, T> for T
impl<I, T> UpcastFrom<I, T> for T
fn upcast_from(from: T, _tcx: I) -> T
source§impl<Tcx, T> Value<Tcx> for Twhere
Tcx: DepContext,
impl<Tcx, T> Value<Tcx> for Twhere
Tcx: DepContext,
default fn from_cycle_error( tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed, ) -> T
source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<'a, T> Captures<'a> for Twhere
T: ?Sized,
impl<'a, T> Captures<'a> for Twhere
T: ?Sized,
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<T> MaybeSendSync for T
Layout§
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...)
attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.
Size: 40 bytes