feat: parse unsafe record fields

This commit is contained in:
Lukas Wirth 2025-03-18 07:11:34 +01:00
parent d3aeddfb77
commit 452e2ca031
9 changed files with 39 additions and 9 deletions

View File

@ -171,6 +171,7 @@ pub struct FieldData {
pub name: Name,
pub type_ref: TypeRefId,
pub visibility: RawVisibility,
pub is_unsafe: bool,
}
fn repr_from_value(
@ -329,14 +330,14 @@ impl EnumVariantData {
impl VariantData {
pub fn fields(&self) -> &Arena<FieldData> {
const EMPTY: &Arena<FieldData> = &Arena::new();
match &self {
match self {
VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => fields,
_ => EMPTY,
}
}
pub fn types_map(&self) -> &TypesMap {
match &self {
match self {
VariantData::Record { types_map, .. } | VariantData::Tuple { types_map, .. } => {
types_map
}
@ -405,5 +406,6 @@ fn lower_field(
name: field.name.clone(),
type_ref: field.type_ref,
visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
is_unsafe: field.is_unsafe,
}
}

View File

@ -1032,6 +1032,7 @@ pub struct Field {
pub name: Name,
pub type_ref: TypeRefId,
pub visibility: RawVisibilityId,
pub is_unsafe: bool,
}
#[derive(Debug, Clone, Eq, PartialEq)]

View File

@ -320,7 +320,7 @@ impl<'a> Ctx<'a> {
let visibility = self.lower_visibility(field);
let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty());
Field { name, type_ref, visibility }
Field { name, type_ref, visibility, is_unsafe: field.unsafe_token().is_some() }
}
fn lower_tuple_field(
@ -332,7 +332,7 @@ impl<'a> Ctx<'a> {
let name = Name::new_tuple_field(idx);
let visibility = self.lower_visibility(field);
let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty());
Field { name, type_ref, visibility }
Field { name, type_ref, visibility, is_unsafe: false }
}
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {

View File

@ -135,12 +135,17 @@ impl Printer<'_> {
self.whitespace();
w!(self, "{{");
self.indented(|this| {
for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
for (idx, Field { name, type_ref, visibility, is_unsafe }) in
fields.iter().enumerate()
{
this.print_attrs_of(
AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
"\n",
);
this.print_visibility(*visibility);
if *is_unsafe {
w!(this, "unsafe ");
}
w!(this, "{}: ", name.display(self.db.upcast(), edition));
this.print_type_ref(*type_ref, map);
wln!(this, ",");
@ -151,12 +156,17 @@ impl Printer<'_> {
FieldsShape::Tuple => {
w!(self, "(");
self.indented(|this| {
for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
for (idx, Field { name, type_ref, visibility, is_unsafe }) in
fields.iter().enumerate()
{
this.print_attrs_of(
AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
"\n",
);
this.print_visibility(*visibility);
if *is_unsafe {
w!(this, "unsafe ");
}
w!(this, "{}: ", name.display(self.db.upcast(), edition));
this.print_type_ref(*type_ref, map);
wln!(this, ",");

View File

@ -107,7 +107,7 @@ pub(crate) fn variant_list(p: &mut Parser<'_>) {
}
// test record_field_list
// struct S { a: i32, b: f32 }
// struct S { a: i32, b: f32, unsafe c: u8 }
pub(crate) fn record_field_list(p: &mut Parser<'_>) {
assert!(p.at(T!['{']));
let m = p.start();
@ -131,6 +131,7 @@ pub(crate) fn record_field_list(p: &mut Parser<'_>) {
// struct S { #[attr] f: f32 }
attributes::outer_attrs(p);
opt_visibility(p, false);
p.eat(T![unsafe]);
if p.at(IDENT) {
name(p);
p.expect(T![:]);

View File

@ -30,6 +30,20 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "f32"
COMMA ","
WHITESPACE " "
RECORD_FIELD
UNSAFE_KW "unsafe"
WHITESPACE " "
NAME
IDENT "c"
COLON ":"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "u8"
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n"

View File

@ -1 +1 @@
struct S { a: i32, b: f32 }
struct S { a: i32, b: f32, unsafe c: u8 }

View File

@ -240,7 +240,7 @@ RecordFieldList =
'{' fields:(RecordField (',' RecordField)* ','?)? '}'
RecordField =
Attr* Visibility?
Attr* Visibility? 'unsafe'?
Name ':' Type ('=' Expr)?
TupleFieldList =

View File

@ -1337,6 +1337,8 @@ impl RecordField {
pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
#[inline]
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
#[inline]
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
}
pub struct RecordFieldList {
pub(crate) syntax: SyntaxNode,