#[repr(packed(4))]pub struct Span(u64);Expand description
A compressed span.
SpanData is 16 bytes, which is too big to stick everywhere. Span is
only 8 bytes. A large majority of SpanData instances can be made to fit
within those 8 bytes. Any SpanData whose fields don’t fit into a Span
are stored in a separate interner table, and the Span will index into
that table.
An earlier version of this code used only 4 bytes for Span, but that was
slower because many fewer spans could be stored inline and the interner was
used a lot more. That version of the code also predated the storage of
parents.
Experiments with uncompressed spans yielded worse performance in most cases because memory usage and cache miss rates are significantly higher without compression.
There are four different span formats and each packs data into the 8 bytes
in a different way. A variable-length prefix in the high bits identifies
which format is being used. It is an invariant that we always use the first
listed format whose requirements are satisfied. len is hi - lo.
-
Inline-context format (requires 15-bit length, 16-bit context, and no parent):
[ prefix=0 | len:15 | ctxt:16 | lo:32 ] -
Inline-parent format (requires 14-bit length, root context, and 15-bit parent):
[ prefix=110 | len:14 | parent:15 | lo:32 ] -
Inline-pair format (requires 24-bit lo, 7-bit length, 15-bit context, 16-bit parent):
[ prefix=10 | len:7 | ctxt:15 | parent:16 | lo:24 ] -
Interned format (all cases not covered above):
[ prefix=111 | ctxt:29 | index:32 ]
Notes about this design.
-
This configuration was the best one found after many measurements of real-world crates, and replaced an earlier 8-byte design.
-
The size of
lodepends on the size of the crate and its dependencies. Crates whoselosize exceeds 24-bits are extremely rare. -
The most common numbers of bits needed for
lenare from 0 to 7, with a peak usually at 3 or 4, and then it drops off quickly from 8 onwards. Lengths larger than 14 bits are rare, but many crates will have a small number of such lengths (sometimes 20+ bits). -
The number of bits needed for
ctxtandparentvalues depend partly on the crate size and partly on the form of the code. For both fields, values needing more than 15 bits are very rare, and most crates won’t hit these limits. -
The ctxt is stored inline in every format (Every ctxt must fit in 29 bits; if we ever hit that we’d have many gigabytes of contexts, and certainly would have OOM’d anyway.) This means reading the ctxt never requires checking the interner. This is good because the ctxt is often consulted by itself. It also means we don’t need to store the ctxt in the interner table, which we achieve by using
SpanDataNoCtxt, which minimizes the number of unique values that need to be interned. -
The use of
repr(packed(4))meansSpanhas an alignment of 4 bytes, which keeps many types that contain spans (e.g. AST nodes) smaller.repr(packed(1))isn’t worth it; it only shrinks a few types and performance is a tiny bit worse.
In order to reliably use parented spans in incremental compilation,
accesses to lo and hi must introduce a dependency to the parent definition’s span.
This is performed using the callback SPAN_TRACK to access the query engine.
Tuple Fields§
§0: u64Implementations§
Source§impl Span
impl Span
Sourcepub fn mark_with_reason(
self,
allow_internal_unstable: Option<Arc<[Symbol]>>,
reason: DesugaringKind,
edition: Edition,
hcx: impl StableHashCtxt,
) -> Span
pub fn mark_with_reason( self, allow_internal_unstable: Option<Arc<[Symbol]>>, reason: DesugaringKind, edition: Edition, hcx: impl StableHashCtxt, ) -> Span
Reuses the span but adds information like the kind of the desugaring and features that are allowed inside this span.
Source§impl Span
impl Span
pub fn new( lo: BytePos, hi: BytePos, ctxt: SyntaxContext, parent: Option<LocalDefId>, ) -> Self
Sourcefn try_new_span_with_parent(
lo: u32,
len: u32,
ctxt: u32,
parent: LocalDefId,
) -> Option<Self>
fn try_new_span_with_parent( lo: u32, len: u32, ctxt: u32, parent: LocalDefId, ) -> Option<Self>
Tries to create an InlineParent or InlinePair format span. Returns None if the fields
won’t fit.
pub fn data(self) -> SpanData
Sourcepub fn data_untracked(self) -> SpanData
pub fn data_untracked(self) -> SpanData
Internal function to translate between an encoded span and the expanded representation. This function must not be used outside the incremental engine.
Sourcepub fn from_expansion(self) -> bool
pub fn from_expansion(self) -> bool
Returns true if this span comes from any kind of macro, desugaring or inlining.
Sourcepub fn is_dummy(self) -> bool
pub fn is_dummy(self) -> bool
Returns true if this is a dummy span with lo=0, hi=0. Any context value is allowed, which
means it’s not the same as an equality comparison with DUMMY_SP.
pub fn map_ctxt(self, map: impl FnOnce(SyntaxContext) -> SyntaxContext) -> Span
Sourcepub fn ctxt(self) -> SyntaxContext
pub fn ctxt(self) -> SyntaxContext
This function is used as a fast path when decoding the full SpanData is not necessary.
It’s a cut-down version of data_untracked and doesn’t require taking the interner lock.
pub fn eq_ctxt(self, other: Span) -> bool
pub fn with_parent(self, parent: Option<LocalDefId>) -> Span
pub fn parent(self) -> Option<LocalDefId>
pub(crate) fn to_raw_span(self) -> RawSpan
pub fn from_raw_span(RawSpan: RawSpan) -> Span
Source§impl Span
impl Span
pub fn lo(self) -> BytePos
pub fn with_lo(self, lo: BytePos) -> Span
pub fn hi(self) -> BytePos
pub fn with_hi(self, hi: BytePos) -> Span
pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span
Sourcepub fn lo_hi(self) -> (BytePos, BytePos)
pub fn lo_hi(self) -> (BytePos, BytePos)
When to use this:
- Use it instead of
==for span equality comparisons when either span could be generated code and you only care that they point to the same bytes of source text. - Use it (possibly via
OrdSpan) for span ordering comparisons of any kind.
pub fn is_visible(self, sm: &SourceMap) -> bool
Sourcepub fn in_external_macro(self, sm: &SourceMap) -> bool
pub fn in_external_macro(self, sm: &SourceMap) -> bool
Returns whether this span originates in a foreign crate’s external macro.
This is used to test whether a lint should not even begin to figure out whether it should be reported on the current node.
Sourcepub fn in_derive_expansion(self) -> bool
pub fn in_derive_expansion(self) -> bool
Returns true if span originates in a derive-macro’s expansion.
Sourcepub fn is_from_async_await(self) -> bool
pub fn is_from_async_await(self) -> bool
Return whether span is generated by async or await.
Sourcepub fn can_be_used_for_suggestions(self) -> bool
pub fn can_be_used_for_suggestions(self) -> bool
Gate suggestions that would not be appropriate in a context the user didn’t write.
pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span
Sourcepub fn shrink_to_lo(self) -> Span
pub fn shrink_to_lo(self) -> Span
Returns a new span representing an empty span at the beginning of this span.
Sourcepub fn shrink_to_hi(self) -> Span
pub fn shrink_to_hi(self) -> Span
Returns a new span representing an empty span at the end of this span.
Sourcepub fn substitute_dummy(self, other: Span) -> Span
pub fn substitute_dummy(self, other: Span) -> Span
Returns self if self is not the dummy span, and other otherwise.
Sourcepub fn overlaps_or_adjacent(self, other: Span) -> bool
pub fn overlaps_or_adjacent(self, other: Span) -> bool
Returns true if self touches or adjoins other.
Sourcepub fn trim_start(self, other: Span) -> Option<Span>
pub fn trim_start(self, other: Span) -> Option<Span>
Returns Some(span), where the start is trimmed by the end of other.
Sourcepub fn trim_end(self, other: Span) -> Option<Span>
pub fn trim_end(self, other: Span) -> Option<Span>
Returns Some(span), where the end is trimmed by the start of other.
Sourcepub fn source_callsite(self) -> Span
pub fn source_callsite(self) -> Span
Returns the source span – this is either the supplied span, or the span for the macro callsite that expanded to it.
Sourcepub fn parent_callsite(self) -> Option<Span>
pub fn parent_callsite(self) -> Option<Span>
Returns the call-site span of the last macro expansion which produced this Span.
(see ExpnData::call_site). Returns None if this is not an expansion.
Sourcepub fn find_ancestor_inside(self, outer: Span) -> Option<Span>
pub fn find_ancestor_inside(self, outer: Span) -> Option<Span>
Find the first ancestor span that’s contained within outer.
This method traverses the macro expansion ancestors until it finds the first span
that’s contained within outer.
The span returned by this method may have a different SyntaxContext than outer.
If you need to extend the span, use find_ancestor_inside_same_ctxt instead,
because joining spans with different syntax contexts can create unexpected results.
This is used to find the span of the macro call when a parent expr span, i.e. outer, is known.
Sourcepub fn find_ancestor_in_same_ctxt(self, other: Span) -> Option<Span>
pub fn find_ancestor_in_same_ctxt(self, other: Span) -> Option<Span>
Find the first ancestor span with the same SyntaxContext as other.
This method traverses the macro expansion ancestors until it finds a span
that has the same SyntaxContext as other.
Like find_ancestor_inside_same_ctxt, but specifically for when spans might not
overlap. Take care when using this, and prefer find_ancestor_inside or
find_ancestor_inside_same_ctxt when you know that the spans are nested (modulo
macro expansion).
Sourcepub fn find_ancestor_inside_same_ctxt(self, outer: Span) -> Option<Span>
pub fn find_ancestor_inside_same_ctxt(self, outer: Span) -> Option<Span>
Find the first ancestor span that’s contained within outer and
has the same SyntaxContext as outer.
This method traverses the macro expansion ancestors until it finds a span
that is both contained within outer and has the same SyntaxContext as outer.
This method is the combination of find_ancestor_inside and
find_ancestor_in_same_ctxt and should be preferred when extending the returned span.
If you do not need to modify the span, use find_ancestor_inside instead.
Sourcepub fn find_ancestor_not_from_extern_macro(self, sm: &SourceMap) -> Option<Span>
pub fn find_ancestor_not_from_extern_macro(self, sm: &SourceMap) -> Option<Span>
Find the first ancestor span that does not come from an external macro.
This method traverses the macro expansion ancestors until it finds a span that is either from user-written code or from a local macro (defined in the current crate).
External macros are those defined in dependencies or the standard library. This method is useful for reporting errors in user-controllable code and avoiding diagnostics inside external macros.
§See also
Sourcepub fn find_ancestor_not_from_macro(self) -> Option<Span>
pub fn find_ancestor_not_from_macro(self) -> Option<Span>
Find the first ancestor span that does not come from any macro expansion.
This method traverses the macro expansion ancestors until it finds a span that originates from user-written code rather than any macro-generated code.
This method is useful for reporting errors at the exact location users wrote code and providing suggestions at directly editable locations.
§See also
Sourcepub fn is_rust_2015(self) -> bool
pub fn is_rust_2015(self) -> bool
Is this edition 2015?
Sourcepub fn at_least_rust_2018(self) -> bool
pub fn at_least_rust_2018(self) -> bool
Are we allowed to use features from the Rust 2018 edition?
Sourcepub fn at_least_rust_2021(self) -> bool
pub fn at_least_rust_2021(self) -> bool
Are we allowed to use features from the Rust 2021 edition?
Sourcepub fn at_least_rust_2024(self) -> bool
pub fn at_least_rust_2024(self) -> bool
Are we allowed to use features from the Rust 2024 edition?
Sourcepub fn source_callee(self) -> Option<ExpnData>
pub fn source_callee(self) -> Option<ExpnData>
Returns the source callee.
Returns None if the supplied span has no expansion trace,
else returns the ExpnData for the macro definition
corresponding to the source callsite.
Sourcepub fn allows_unstable(self, feature: Symbol) -> bool
pub fn allows_unstable(self, feature: Symbol) -> bool
Checks if a span is “internal” to a macro in which #[unstable]
items can be used (that is, a macro marked with
#[allow_internal_unstable]).
Sourcepub fn is_desugaring(self, kind: DesugaringKind) -> bool
pub fn is_desugaring(self, kind: DesugaringKind) -> bool
Checks if this span arises from a compiler desugaring of kind kind.
Sourcepub fn desugaring_kind(self) -> Option<DesugaringKind>
pub fn desugaring_kind(self) -> Option<DesugaringKind>
Returns the compiler desugaring that created this span, or None
if this span is not from a desugaring.
Sourcepub fn allows_unsafe(self) -> bool
pub fn allows_unsafe(self) -> bool
Checks if a span is “internal” to a macro in which unsafe
can be used without triggering the unsafe_code lint.
(that is, a macro marked with #[allow_internal_unsafe]).
pub fn macro_backtrace(self) -> impl Iterator<Item = ExpnData>
Sourcepub fn split_at(self, pos: u32) -> (Span, Span)
pub fn split_at(self, pos: u32) -> (Span, Span)
Splits a span into two composite spans around a certain position.
Sourcepub(crate) fn try_metavars(
a: SpanData,
b: SpanData,
a_orig: Span,
b_orig: Span,
) -> (SpanData, SpanData)
pub(crate) fn try_metavars( a: SpanData, b: SpanData, a_orig: Span, b_orig: Span, ) -> (SpanData, SpanData)
Check if you can select metavar spans for the given spans to get matching contexts.
Sourcepub(crate) fn prepare_to_combine(
a_orig: Span,
b_orig: Span,
) -> Result<(SpanData, SpanData, Option<LocalDefId>), Span>
pub(crate) fn prepare_to_combine( a_orig: Span, b_orig: Span, ) -> Result<(SpanData, SpanData, Option<LocalDefId>), Span>
Prepare two spans to a combine operation like to or between.
Sourcepub fn with_neighbor(self, neighbor: Span) -> Span
pub fn with_neighbor(self, neighbor: Span) -> Span
This span, but in a larger context, may switch to the metavariable span if suitable.
Sourcepub fn to(self, end: Span) -> Span
pub fn to(self, end: Span) -> Span
Returns a Span that would enclose both self and end.
Note that this can also be used to extend the span “backwards”:
start.to(end) and end.to(start) return the same Span.
____ ___
self lorem ipsum end
^^^^^^^^^^^^^^^^^^^^Sourcepub fn between(self, end: Span) -> Span
pub fn between(self, end: Span) -> Span
Returns a Span between the end of self to the beginning of end.
____ ___
self lorem ipsum end
^^^^^^^^^^^^^Sourcepub fn until(self, end: Span) -> Span
pub fn until(self, end: Span) -> Span
Returns a Span from the beginning of self until the beginning of end.
____ ___
self lorem ipsum end
^^^^^^^^^^^^^^^^^Sourcepub fn within_macro(self, within: Span, sm: &SourceMap) -> Option<Span>
pub fn within_macro(self, within: Span, sm: &SourceMap) -> Option<Span>
Returns the Span within the syntax context of “within”. This is useful when
“self” is an expansion from a macro variable, since this can be used for
providing extra macro expansion context for certain errors.
macro_rules! m {
($ident:ident) => { ($ident,) }
}
m!(outer_ident);If “self” is the span of the outer_ident, and “within” is the span of the ($ident,)
expr, then this will return the span of the $ident macro variable.
pub fn from_inner(self, inner: InnerSpan) -> Span
Sourcepub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span
pub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span
Equivalent of Span::def_site from the proc macro API,
except that the location is taken from the self span.
Sourcepub fn with_call_site_ctxt(self, expn_id: ExpnId) -> Span
pub fn with_call_site_ctxt(self, expn_id: ExpnId) -> Span
Equivalent of Span::call_site from the proc macro API,
except that the location is taken from the self span.
Sourcepub fn with_mixed_site_ctxt(self, expn_id: ExpnId) -> Span
pub fn with_mixed_site_ctxt(self, expn_id: ExpnId) -> Span
Equivalent of Span::mixed_site from the proc macro API,
except that the location is taken from the self span.
Sourcepub(crate) fn with_ctxt_from_mark(
self,
expn_id: ExpnId,
transparency: Transparency,
) -> Span
pub(crate) fn with_ctxt_from_mark( self, expn_id: ExpnId, transparency: Transparency, ) -> Span
Produces a span with the same location as self and context produced by a macro with the
given ID and transparency, assuming that macro was defined directly and not produced by
some other macro (which is the case for built-in and procedural macros).
pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span
pub fn remove_mark(&mut self) -> ExpnId
pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId>
pub fn normalize_to_macros_2_0_and_adjust( &mut self, expn_id: ExpnId, ) -> Option<ExpnId>
pub fn normalize_to_macros_2_0(self) -> Span
pub fn normalize_to_macro_rules(self) -> Span
Trait Implementations§
impl !Ord for Span
impl !PartialOrd for Span
impl Copy for Span
impl Eq for Span
Source§impl StableHash for Span
impl StableHash for Span
fn stable_hash<Hcx: StableHashCtxt>( &self, hcx: &mut Hcx, hasher: &mut StableHasher, )
impl StructuralPartialEq for Span
Auto Trait Implementations§
impl DynSend for Span
impl DynSync for Span
impl Freeze for Span
impl RefUnwindSafe for Span
impl Send for Span
impl Sync for Span
impl Unpin for Span
impl UnsafeUnpin for Span
impl UnwindSafe for Span
Blanket Implementations§
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§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> 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<T> Pointable for T
impl<T> Pointable for 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> ⓘ
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: 8 bytes