diff --git a/crates/oxc_span/src/generated/assert_layouts.rs b/crates/oxc_span/src/generated/assert_layouts.rs index 0b7e12f99e74d..f0a278de5c6db 100644 --- a/crates/oxc_span/src/generated/assert_layouts.rs +++ b/crates/oxc_span/src/generated/assert_layouts.rs @@ -16,6 +16,9 @@ const _: () = { assert!(size_of::() == 3); assert!(align_of::() == 1); + assert!(offset_of!(SourceType, language) == 0); + assert!(offset_of!(SourceType, module_kind) == 1); + assert!(offset_of!(SourceType, variant) == 2); assert!(size_of::() == 1); assert!(align_of::() == 1); @@ -36,6 +39,9 @@ const _: () = { assert!(size_of::() == 3); assert!(align_of::() == 1); + assert!(offset_of!(SourceType, language) == 0); + assert!(offset_of!(SourceType, module_kind) == 1); + assert!(offset_of!(SourceType, variant) == 2); assert!(size_of::() == 1); assert!(align_of::() == 1); diff --git a/tasks/ast_tools/src/generators/assert_layouts.rs b/tasks/ast_tools/src/generators/assert_layouts.rs index 321ea69a05605..8b93273237425 100644 --- a/tasks/ast_tools/src/generators/assert_layouts.rs +++ b/tasks/ast_tools/src/generators/assert_layouts.rs @@ -444,9 +444,9 @@ fn generate_layout_assertions_for_struct<'s>( let size_align_assertions = generate_size_align_assertions(layout, struct_ident); let offset_asserts = struct_def.fields.iter().filter_map(|field| { - if field.visibility != Visibility::Public { - // Cannot create assertions for fields which are not public, as assertions - // are generated in `oxc_ast` crate, and those types are in other crates + if struct_def.is_foreign || field.visibility == Visibility::Private { + // Cannot create assertions for private fields (cant access them) + // or foreign types (we don't know what fields they have) return None; } diff --git a/tasks/ast_tools/src/parse/load.rs b/tasks/ast_tools/src/parse/load.rs index 0a95da709e4eb..c9fdd4823a0a0 100644 --- a/tasks/ast_tools/src/parse/load.rs +++ b/tasks/ast_tools/src/parse/load.rs @@ -64,13 +64,13 @@ pub fn load_file( } fn parse_struct(item: ItemStruct, file_id: FileId) -> Option<(StructSkeleton, /* is_meta */ bool)> { - let (name, is_meta) = get_type_name(&item.attrs, &item.ident)?; - Some((StructSkeleton { name, file_id, item }, is_meta)) + let (name, is_foreign, is_meta) = get_type_name(&item.attrs, &item.ident)?; + Some((StructSkeleton { name, is_foreign, file_id, item }, is_meta)) } fn parse_enum(item: ItemEnum, file_id: FileId) -> Option<(EnumSkeleton, /* is_meta */ bool)> { - let (name, is_meta) = get_type_name(&item.attrs, &item.ident)?; - Some((EnumSkeleton { name, file_id, item, inherits: vec![] }, is_meta)) + let (name, is_foreign, is_meta) = get_type_name(&item.attrs, &item.ident)?; + Some((EnumSkeleton { name, is_foreign, file_id, item, inherits: vec![] }, is_meta)) } fn parse_macro(item: &ItemMacro, file_id: FileId) -> Option { @@ -96,7 +96,7 @@ fn parse_macro(item: &ItemMacro, file_id: FileId) -> Option { let where_clause = input.parse::>()?; assert!(where_clause.is_none(), "Types with `where` clauses are not supported"); - let Some((name, false)) = get_type_name(&attrs, &ident) else { + let Some((name, false, false)) = get_type_name(&attrs, &ident) else { panic!("Enum in `inherit_variants!` macro must have `#[ast]` attr: {ident}"); }; @@ -126,7 +126,7 @@ fn parse_macro(item: &ItemMacro, file_id: FileId) -> Option { } let item = ItemEnum { attrs, vis, enum_token, ident, generics, brace_token, variants }; - Ok(EnumSkeleton { name, file_id, item, inherits }) + Ok(EnumSkeleton { name, is_foreign: false, file_id, item, inherits }) }) .expect("Failed to parse contents of `inherit_variants!` macro"); @@ -147,7 +147,7 @@ fn parse_macro(item: &ItemMacro, file_id: FileId) -> Option { fn get_type_name( attrs: &[Attribute], ident: &Ident, -) -> Option<(/* type name */ String, /* is_meta */ bool)> { +) -> Option<(/* type name */ String, /* is_foreign */ bool, /* is_meta */ bool)> { let mut has_ast_attr = false; let mut has_meta_attr = false; let mut foreign_name = None; @@ -178,9 +178,13 @@ fn get_type_name( !has_ast_attr, "Type cannot be tagged with both `#[ast]` and `#[ast_meta]`: `{ident}`" ); - Some((ident_name(ident), true)) + Some((ident_name(ident), false, true)) } else if has_ast_attr { - Some((foreign_name.unwrap_or_else(|| ident_name(ident)), false)) + if let Some(foreign_name) = foreign_name { + Some((foreign_name, true, false)) + } else { + Some((ident_name(ident), false, false)) + } } else { None } diff --git a/tasks/ast_tools/src/parse/parse.rs b/tasks/ast_tools/src/parse/parse.rs index f2890d0bf3db9..56ad7c0b0e8cf 100644 --- a/tasks/ast_tools/src/parse/parse.rs +++ b/tasks/ast_tools/src/parse/parse.rs @@ -204,7 +204,7 @@ impl<'c> Parser<'c> { /// Parse [`StructSkeleton`] to yield a [`TypeDef`]. fn parse_struct(&mut self, type_id: TypeId, skeleton: StructSkeleton) -> TypeDef { - let StructSkeleton { name, item, file_id } = skeleton; + let StructSkeleton { name, item, is_foreign, file_id } = skeleton; let has_lifetime = check_generics(&item.generics, &name); let fields = self.parse_fields(&item.fields); let (generated_derives, plural_name) = @@ -214,6 +214,7 @@ impl<'c> Parser<'c> { name, plural_name, has_lifetime, + is_foreign, file_id, generated_derives, fields, @@ -277,7 +278,7 @@ impl<'c> Parser<'c> { /// Parse [`EnumSkeleton`] to yield a [`TypeDef`]. fn parse_enum(&mut self, type_id: TypeId, skeleton: EnumSkeleton) -> TypeDef { - let EnumSkeleton { name, item, inherits, file_id } = skeleton; + let EnumSkeleton { name, item, inherits, is_foreign, file_id } = skeleton; let has_lifetime = check_generics(&item.generics, &name); let variants = item.variants.iter().map(|variant| self.parse_variant(variant)).collect(); let inherits = inherits.into_iter().map(|name| self.type_id(&name)).collect(); @@ -288,6 +289,7 @@ impl<'c> Parser<'c> { name, plural_name, has_lifetime, + is_foreign, file_id, generated_derives, variants, diff --git a/tasks/ast_tools/src/parse/skeleton.rs b/tasks/ast_tools/src/parse/skeleton.rs index 5379f7ac64dee..9a3eb9aa89917 100644 --- a/tasks/ast_tools/src/parse/skeleton.rs +++ b/tasks/ast_tools/src/parse/skeleton.rs @@ -18,6 +18,7 @@ pub enum Skeleton { #[derive(Debug)] pub struct StructSkeleton { pub name: String, + pub is_foreign: bool, pub file_id: FileId, pub item: ItemStruct, } @@ -25,6 +26,7 @@ pub struct StructSkeleton { #[derive(Debug)] pub struct EnumSkeleton { pub name: String, + pub is_foreign: bool, pub file_id: FileId, pub item: ItemEnum, pub inherits: Vec, diff --git a/tasks/ast_tools/src/schema/defs/enum.rs b/tasks/ast_tools/src/schema/defs/enum.rs index c1beb864c3611..48d72264e89aa 100644 --- a/tasks/ast_tools/src/schema/defs/enum.rs +++ b/tasks/ast_tools/src/schema/defs/enum.rs @@ -29,6 +29,8 @@ pub struct EnumDef { pub name: String, pub plural_name: Option, pub has_lifetime: bool, + #[expect(unused)] + pub is_foreign: bool, pub file_id: FileId, pub generated_derives: Derives, pub variants: Vec, @@ -51,6 +53,7 @@ impl EnumDef { name: String, plural_name: Option, has_lifetime: bool, + is_foreign: bool, file_id: FileId, generated_derives: Derives, variants: Vec, @@ -61,6 +64,7 @@ impl EnumDef { name, plural_name, has_lifetime, + is_foreign, file_id, generated_derives, variants, diff --git a/tasks/ast_tools/src/schema/defs/struct.rs b/tasks/ast_tools/src/schema/defs/struct.rs index 31dc5ee63eb99..74bf91cd8a58f 100644 --- a/tasks/ast_tools/src/schema/defs/struct.rs +++ b/tasks/ast_tools/src/schema/defs/struct.rs @@ -27,6 +27,7 @@ pub struct StructDef { pub name: String, pub plural_name: Option, pub has_lifetime: bool, + pub is_foreign: bool, pub file_id: FileId, pub generated_derives: Derives, pub fields: Vec, @@ -42,11 +43,13 @@ pub struct StructDef { impl StructDef { /// Create new [`StructDef`]. + #[expect(clippy::too_many_arguments)] pub fn new( id: TypeId, name: String, plural_name: Option, has_lifetime: bool, + is_foreign: bool, file_id: FileId, generated_derives: Derives, fields: Vec, @@ -56,6 +59,7 @@ impl StructDef { name, plural_name, has_lifetime, + is_foreign, file_id, generated_derives, fields,