Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 38 additions & 38 deletions crates/oxc_ast/src/generated/assert_layouts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ use crate::ast::*;

#[cfg(target_pointer_width = "64")]
const _: () = {
assert!(size_of::<BooleanLiteral>() == 12usize);
assert!(align_of::<BooleanLiteral>() == 4usize);
assert!(size_of::<BooleanLiteral>() == 16usize);
assert!(align_of::<BooleanLiteral>() == 8usize);
assert!(offset_of!(BooleanLiteral, span) == 0usize);
assert!(offset_of!(BooleanLiteral, value) == 8usize);

assert!(size_of::<NullLiteral>() == 8usize);
assert!(align_of::<NullLiteral>() == 4usize);
assert!(align_of::<NullLiteral>() == 8usize);
assert!(offset_of!(NullLiteral, span) == 0usize);

assert!(size_of::<NumericLiteral>() == 40usize);
Expand Down Expand Up @@ -88,7 +88,7 @@ const _: () = {
assert!(offset_of!(LabelIdentifier, name) == 8usize);

assert!(size_of::<ThisExpression>() == 8usize);
assert!(align_of::<ThisExpression>() == 4usize);
assert!(align_of::<ThisExpression>() == 8usize);
assert!(offset_of!(ThisExpression, span) == 0usize);

assert!(size_of::<ArrayExpression>() == 56usize);
Expand All @@ -101,7 +101,7 @@ const _: () = {
assert!(align_of::<ArrayExpressionElement>() == 8usize);

assert!(size_of::<Elision>() == 8usize);
assert!(align_of::<Elision>() == 4usize);
assert!(align_of::<Elision>() == 8usize);
assert!(offset_of!(Elision, span) == 0usize);

assert!(size_of::<ObjectExpression>() == 56usize);
Expand Down Expand Up @@ -312,7 +312,7 @@ const _: () = {
assert!(offset_of!(SequenceExpression, expressions) == 8usize);

assert!(size_of::<Super>() == 8usize);
assert!(align_of::<Super>() == 4usize);
assert!(align_of::<Super>() == 8usize);
assert!(offset_of!(Super, span) == 0usize);

assert!(size_of::<AwaitExpression>() == 24usize);
Expand Down Expand Up @@ -375,7 +375,7 @@ const _: () = {
assert!(offset_of!(VariableDeclarator, definite) == 64usize);

assert!(size_of::<EmptyStatement>() == 8usize);
assert!(align_of::<EmptyStatement>() == 4usize);
assert!(align_of::<EmptyStatement>() == 8usize);
assert!(offset_of!(EmptyStatement, span) == 0usize);

assert!(size_of::<ExpressionStatement>() == 24usize);
Expand Down Expand Up @@ -499,7 +499,7 @@ const _: () = {
assert!(offset_of!(CatchParameter, pattern) == 8usize);

assert!(size_of::<DebuggerStatement>() == 8usize);
assert!(align_of::<DebuggerStatement>() == 4usize);
assert!(align_of::<DebuggerStatement>() == 8usize);
assert!(offset_of!(DebuggerStatement, span) == 0usize);

assert!(size_of::<BindingPattern>() == 32usize);
Expand Down Expand Up @@ -898,59 +898,59 @@ const _: () = {
assert!(align_of::<TSTupleElement>() == 8usize);

assert!(size_of::<TSAnyKeyword>() == 8usize);
assert!(align_of::<TSAnyKeyword>() == 4usize);
assert!(align_of::<TSAnyKeyword>() == 8usize);
assert!(offset_of!(TSAnyKeyword, span) == 0usize);

assert!(size_of::<TSStringKeyword>() == 8usize);
assert!(align_of::<TSStringKeyword>() == 4usize);
assert!(align_of::<TSStringKeyword>() == 8usize);
assert!(offset_of!(TSStringKeyword, span) == 0usize);

assert!(size_of::<TSBooleanKeyword>() == 8usize);
assert!(align_of::<TSBooleanKeyword>() == 4usize);
assert!(align_of::<TSBooleanKeyword>() == 8usize);
assert!(offset_of!(TSBooleanKeyword, span) == 0usize);

assert!(size_of::<TSNumberKeyword>() == 8usize);
assert!(align_of::<TSNumberKeyword>() == 4usize);
assert!(align_of::<TSNumberKeyword>() == 8usize);
assert!(offset_of!(TSNumberKeyword, span) == 0usize);

assert!(size_of::<TSNeverKeyword>() == 8usize);
assert!(align_of::<TSNeverKeyword>() == 4usize);
assert!(align_of::<TSNeverKeyword>() == 8usize);
assert!(offset_of!(TSNeverKeyword, span) == 0usize);

assert!(size_of::<TSIntrinsicKeyword>() == 8usize);
assert!(align_of::<TSIntrinsicKeyword>() == 4usize);
assert!(align_of::<TSIntrinsicKeyword>() == 8usize);
assert!(offset_of!(TSIntrinsicKeyword, span) == 0usize);

assert!(size_of::<TSUnknownKeyword>() == 8usize);
assert!(align_of::<TSUnknownKeyword>() == 4usize);
assert!(align_of::<TSUnknownKeyword>() == 8usize);
assert!(offset_of!(TSUnknownKeyword, span) == 0usize);

assert!(size_of::<TSNullKeyword>() == 8usize);
assert!(align_of::<TSNullKeyword>() == 4usize);
assert!(align_of::<TSNullKeyword>() == 8usize);
assert!(offset_of!(TSNullKeyword, span) == 0usize);

assert!(size_of::<TSUndefinedKeyword>() == 8usize);
assert!(align_of::<TSUndefinedKeyword>() == 4usize);
assert!(align_of::<TSUndefinedKeyword>() == 8usize);
assert!(offset_of!(TSUndefinedKeyword, span) == 0usize);

assert!(size_of::<TSVoidKeyword>() == 8usize);
assert!(align_of::<TSVoidKeyword>() == 4usize);
assert!(align_of::<TSVoidKeyword>() == 8usize);
assert!(offset_of!(TSVoidKeyword, span) == 0usize);

assert!(size_of::<TSSymbolKeyword>() == 8usize);
assert!(align_of::<TSSymbolKeyword>() == 4usize);
assert!(align_of::<TSSymbolKeyword>() == 8usize);
assert!(offset_of!(TSSymbolKeyword, span) == 0usize);

assert!(size_of::<TSThisType>() == 8usize);
assert!(align_of::<TSThisType>() == 4usize);
assert!(align_of::<TSThisType>() == 8usize);
assert!(offset_of!(TSThisType, span) == 0usize);

assert!(size_of::<TSObjectKeyword>() == 8usize);
assert!(align_of::<TSObjectKeyword>() == 4usize);
assert!(align_of::<TSObjectKeyword>() == 8usize);
assert!(offset_of!(TSObjectKeyword, span) == 0usize);

assert!(size_of::<TSBigIntKeyword>() == 8usize);
assert!(align_of::<TSBigIntKeyword>() == 4usize);
assert!(align_of::<TSBigIntKeyword>() == 8usize);
assert!(offset_of!(TSBigIntKeyword, span) == 0usize);

assert!(size_of::<TSTypeReference>() == 32usize);
Expand Down Expand Up @@ -1272,7 +1272,7 @@ const _: () = {
assert!(offset_of!(JSDocNonNullableType, postfix) == 24usize);

assert!(size_of::<JSDocUnknownType>() == 8usize);
assert!(align_of::<JSDocUnknownType>() == 4usize);
assert!(align_of::<JSDocUnknownType>() == 8usize);
assert!(offset_of!(JSDocUnknownType, span) == 0usize);

assert!(size_of::<JSXElement>() == 56usize);
Expand Down Expand Up @@ -1303,11 +1303,11 @@ const _: () = {
assert!(offset_of!(JSXFragment, children) == 24usize);

assert!(size_of::<JSXOpeningFragment>() == 8usize);
assert!(align_of::<JSXOpeningFragment>() == 4usize);
assert!(align_of::<JSXOpeningFragment>() == 8usize);
assert!(offset_of!(JSXOpeningFragment, span) == 0usize);

assert!(size_of::<JSXClosingFragment>() == 8usize);
assert!(align_of::<JSXClosingFragment>() == 4usize);
assert!(align_of::<JSXClosingFragment>() == 8usize);
assert!(offset_of!(JSXClosingFragment, span) == 0usize);

assert!(size_of::<JSXElementName>() == 16usize);
Expand Down Expand Up @@ -1337,7 +1337,7 @@ const _: () = {
assert!(align_of::<JSXExpression>() == 8usize);

assert!(size_of::<JSXEmptyExpression>() == 8usize);
assert!(align_of::<JSXEmptyExpression>() == 4usize);
assert!(align_of::<JSXEmptyExpression>() == 8usize);
assert!(offset_of!(JSXEmptyExpression, span) == 0usize);

assert!(size_of::<JSXAttributeItem>() == 16usize);
Expand Down Expand Up @@ -1385,7 +1385,7 @@ const _: () = {
assert!(align_of::<CommentPosition>() == 1usize);

assert!(size_of::<Comment>() == 16usize);
assert!(align_of::<Comment>() == 4usize);
assert!(align_of::<Comment>() == 8usize);
assert!(offset_of!(Comment, span) == 0usize);
assert!(offset_of!(Comment, attached_to) == 8usize);
assert!(offset_of!(Comment, kind) == 12usize);
Expand Down Expand Up @@ -1415,7 +1415,7 @@ const _: () = {
assert!(align_of::<UpdateOperator>() == 1usize);

assert!(size_of::<Span>() == 8usize);
assert!(align_of::<Span>() == 4usize);
assert!(align_of::<Span>() == 8usize);
assert!(offset_of!(Span, start) == 0usize);
assert!(offset_of!(Span, end) == 4usize);

Expand Down Expand Up @@ -1449,8 +1449,8 @@ const _: () = {
assert!(size_of::<Term>() == 16usize);
assert!(align_of::<Term>() == 8usize);

assert!(size_of::<BoundaryAssertion>() == 12usize);
assert!(align_of::<BoundaryAssertion>() == 4usize);
assert!(size_of::<BoundaryAssertion>() == 16usize);
assert!(align_of::<BoundaryAssertion>() == 8usize);
assert!(offset_of!(BoundaryAssertion, span) == 0usize);
assert!(offset_of!(BoundaryAssertion, kind) == 8usize);

Expand All @@ -1475,16 +1475,16 @@ const _: () = {
assert!(offset_of!(Quantifier, body) == 40usize);

assert!(size_of::<Character>() == 16usize);
assert!(align_of::<Character>() == 4usize);
assert!(align_of::<Character>() == 8usize);
assert!(offset_of!(Character, span) == 0usize);
assert!(offset_of!(Character, kind) == 8usize);
assert!(offset_of!(Character, value) == 12usize);

assert!(size_of::<CharacterKind>() == 1usize);
assert!(align_of::<CharacterKind>() == 1usize);

assert!(size_of::<CharacterClassEscape>() == 12usize);
assert!(align_of::<CharacterClassEscape>() == 4usize);
assert!(size_of::<CharacterClassEscape>() == 16usize);
assert!(align_of::<CharacterClassEscape>() == 8usize);
assert!(offset_of!(CharacterClassEscape, span) == 0usize);
assert!(offset_of!(CharacterClassEscape, kind) == 8usize);

Expand All @@ -1500,7 +1500,7 @@ const _: () = {
assert!(offset_of!(UnicodePropertyEscape, value) == 32usize);

assert!(size_of::<Dot>() == 8usize);
assert!(align_of::<Dot>() == 4usize);
assert!(align_of::<Dot>() == 8usize);
assert!(offset_of!(Dot, span) == 0usize);

assert!(size_of::<CharacterClass>() == 48usize);
Expand All @@ -1518,7 +1518,7 @@ const _: () = {
assert!(align_of::<CharacterClassContents>() == 8usize);

assert!(size_of::<CharacterClassRange>() == 40usize);
assert!(align_of::<CharacterClassRange>() == 4usize);
assert!(align_of::<CharacterClassRange>() == 8usize);
assert!(offset_of!(CharacterClassRange, span) == 0usize);
assert!(offset_of!(CharacterClassRange, min) == 8usize);
assert!(offset_of!(CharacterClassRange, max) == 24usize);
Expand Down Expand Up @@ -1548,7 +1548,7 @@ const _: () = {
assert!(offset_of!(IgnoreGroup, body) == 24usize);

assert!(size_of::<Modifiers>() == 16usize);
assert!(align_of::<Modifiers>() == 4usize);
assert!(align_of::<Modifiers>() == 8usize);
assert!(offset_of!(Modifiers, span) == 0usize);
assert!(offset_of!(Modifiers, enabling) == 8usize);
assert!(offset_of!(Modifiers, disabling) == 11usize);
Expand All @@ -1559,8 +1559,8 @@ const _: () = {
assert!(offset_of!(Modifier, multiline) == 1usize);
assert!(offset_of!(Modifier, sticky) == 2usize);

assert!(size_of::<IndexedReference>() == 12usize);
assert!(align_of::<IndexedReference>() == 4usize);
assert!(size_of::<IndexedReference>() == 16usize);
assert!(align_of::<IndexedReference>() == 8usize);
assert!(offset_of!(IndexedReference, span) == 0usize);
assert!(offset_of!(IndexedReference, index) == 8usize);

Expand Down
80 changes: 72 additions & 8 deletions crates/oxc_span/src/span/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::ops::{Index, IndexMut, Range};
use std::{
fmt::{self, Debug},
hash::{Hash, Hasher},
ops::{Index, IndexMut, Range},
};

use miette::{LabeledSpan, SourceOffset, SourceSpan};

Expand All @@ -9,6 +13,18 @@ pub use types::Span;
/// An Empty span useful for creating AST nodes.
pub const SPAN: Span = Span::new(0, 0);

/// Zero-sized type which has pointer alignment (8 on 64-bit, 4 on 32-bit).
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
struct PointerAlign([usize; 0]);

impl PointerAlign {
#[inline]
const fn new() -> Self {
Self([])
}
}

impl Span {
/// Create a new [`Span`] from a start and end position.
///
Expand All @@ -19,7 +35,7 @@ impl Span {
///
#[inline]
pub const fn new(start: u32, end: u32) -> Self {
Self { start, end }
Self { start, end, _align: PointerAlign::new() }
}

/// Create a new empty [`Span`] that starts and ends at an offset position.
Expand All @@ -34,7 +50,7 @@ impl Span {
/// assert_eq!(fifth, Span::new(5, 5));
/// ```
pub fn empty(at: u32) -> Self {
Self { start: at, end: at }
Self::new(at, at)
}

/// Create a new [`Span`] starting at `start` and covering `size` bytes.
Expand Down Expand Up @@ -362,6 +378,23 @@ impl From<Span> for LabeledSpan {
}
}

// Skip hashing `_align` field
impl Hash for Span {
#[inline] // We exclusively use `FxHasher`, which produces small output hashing `u32`s
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.start.hash(hasher);
self.end.hash(hasher);
}
}

// Skip `_align` field in `Debug` output
#[expect(clippy::missing_fields_in_debug)]
impl Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Span").field("start", &self.start).field("end", &self.end).finish()
}
}

/// Get the span for an AST node
pub trait GetSpan {
/// Get the [`Span`] for an AST node
Expand Down Expand Up @@ -413,13 +446,29 @@ mod test {
}

#[test]
#[expect(clippy::items_after_statements)]
fn test_hash() {
use std::hash::{DefaultHasher, Hash, Hasher};
let mut first = DefaultHasher::new();
let mut second = DefaultHasher::new();
Span::new(0, 5).hash(&mut first);
Span::new(0, 5).hash(&mut second);
assert_eq!(first.finish(), second.finish());
fn hash<T: Hash>(value: T) -> u64 {
let mut hasher = DefaultHasher::new();
value.hash(&mut hasher);
hasher.finish()
}

let first_hash = hash(Span::new(0, 5));
let second_hash = hash(Span::new(0, 5));
assert_eq!(first_hash, second_hash);

// Check `_align` field does not alter hash
#[derive(Hash)]
#[repr(C)]
struct PlainSpan {
start: u32,
end: u32,
}

let plain_hash = hash(PlainSpan { start: 0, end: 5 });
assert_eq!(plain_hash, first_hash);
}

#[test]
Expand Down Expand Up @@ -481,3 +530,18 @@ mod test {
let _ = span.shrink(5);
}
}

#[cfg(test)]
mod size_asserts {
use std::mem::{align_of, size_of};

use super::Span;

const _: () = assert!(size_of::<Span>() == 8);

#[cfg(target_pointer_width = "64")]
const _: () = assert!(align_of::<Span>() == 8);

#[cfg(not(target_pointer_width = "64"))]
const _: () = assert!(align_of::<Span>() == 4);
}
Loading
Loading