mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 05:13:35 +00:00 
			
		
		
		
	feat: parse unsafe record fields
				
					
				
			This commit is contained in:
		
							parent
							
								
									d3aeddfb77
								
							
						
					
					
						commit
						452e2ca031
					
				
					 9 changed files with 39 additions and 9 deletions
				
			
		| 
						 | 
					@ -171,6 +171,7 @@ pub struct FieldData {
 | 
				
			||||||
    pub name: Name,
 | 
					    pub name: Name,
 | 
				
			||||||
    pub type_ref: TypeRefId,
 | 
					    pub type_ref: TypeRefId,
 | 
				
			||||||
    pub visibility: RawVisibility,
 | 
					    pub visibility: RawVisibility,
 | 
				
			||||||
 | 
					    pub is_unsafe: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn repr_from_value(
 | 
					fn repr_from_value(
 | 
				
			||||||
| 
						 | 
					@ -329,14 +330,14 @@ impl EnumVariantData {
 | 
				
			||||||
impl VariantData {
 | 
					impl VariantData {
 | 
				
			||||||
    pub fn fields(&self) -> &Arena<FieldData> {
 | 
					    pub fn fields(&self) -> &Arena<FieldData> {
 | 
				
			||||||
        const EMPTY: &Arena<FieldData> = &Arena::new();
 | 
					        const EMPTY: &Arena<FieldData> = &Arena::new();
 | 
				
			||||||
        match &self {
 | 
					        match self {
 | 
				
			||||||
            VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => fields,
 | 
					            VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => fields,
 | 
				
			||||||
            _ => EMPTY,
 | 
					            _ => EMPTY,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn types_map(&self) -> &TypesMap {
 | 
					    pub fn types_map(&self) -> &TypesMap {
 | 
				
			||||||
        match &self {
 | 
					        match self {
 | 
				
			||||||
            VariantData::Record { types_map, .. } | VariantData::Tuple { types_map, .. } => {
 | 
					            VariantData::Record { types_map, .. } | VariantData::Tuple { types_map, .. } => {
 | 
				
			||||||
                types_map
 | 
					                types_map
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -405,5 +406,6 @@ fn lower_field(
 | 
				
			||||||
        name: field.name.clone(),
 | 
					        name: field.name.clone(),
 | 
				
			||||||
        type_ref: field.type_ref,
 | 
					        type_ref: field.type_ref,
 | 
				
			||||||
        visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
 | 
					        visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
 | 
				
			||||||
 | 
					        is_unsafe: field.is_unsafe,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1032,6 +1032,7 @@ pub struct Field {
 | 
				
			||||||
    pub name: Name,
 | 
					    pub name: Name,
 | 
				
			||||||
    pub type_ref: TypeRefId,
 | 
					    pub type_ref: TypeRefId,
 | 
				
			||||||
    pub visibility: RawVisibilityId,
 | 
					    pub visibility: RawVisibilityId,
 | 
				
			||||||
 | 
					    pub is_unsafe: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Eq, PartialEq)]
 | 
					#[derive(Debug, Clone, Eq, PartialEq)]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,7 +320,7 @@ impl<'a> Ctx<'a> {
 | 
				
			||||||
        let visibility = self.lower_visibility(field);
 | 
					        let visibility = self.lower_visibility(field);
 | 
				
			||||||
        let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty());
 | 
					        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(
 | 
					    fn lower_tuple_field(
 | 
				
			||||||
| 
						 | 
					@ -332,7 +332,7 @@ impl<'a> Ctx<'a> {
 | 
				
			||||||
        let name = Name::new_tuple_field(idx);
 | 
					        let name = Name::new_tuple_field(idx);
 | 
				
			||||||
        let visibility = self.lower_visibility(field);
 | 
					        let visibility = self.lower_visibility(field);
 | 
				
			||||||
        let type_ref = TypeRef::from_ast_opt(body_ctx, field.ty());
 | 
					        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>> {
 | 
					    fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,12 +135,17 @@ impl Printer<'_> {
 | 
				
			||||||
                self.whitespace();
 | 
					                self.whitespace();
 | 
				
			||||||
                w!(self, "{{");
 | 
					                w!(self, "{{");
 | 
				
			||||||
                self.indented(|this| {
 | 
					                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(
 | 
					                        this.print_attrs_of(
 | 
				
			||||||
                            AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
 | 
					                            AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
 | 
				
			||||||
                            "\n",
 | 
					                            "\n",
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                        this.print_visibility(*visibility);
 | 
					                        this.print_visibility(*visibility);
 | 
				
			||||||
 | 
					                        if *is_unsafe {
 | 
				
			||||||
 | 
					                            w!(this, "unsafe ");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        w!(this, "{}: ", name.display(self.db.upcast(), edition));
 | 
					                        w!(this, "{}: ", name.display(self.db.upcast(), edition));
 | 
				
			||||||
                        this.print_type_ref(*type_ref, map);
 | 
					                        this.print_type_ref(*type_ref, map);
 | 
				
			||||||
                        wln!(this, ",");
 | 
					                        wln!(this, ",");
 | 
				
			||||||
| 
						 | 
					@ -151,12 +156,17 @@ impl Printer<'_> {
 | 
				
			||||||
            FieldsShape::Tuple => {
 | 
					            FieldsShape::Tuple => {
 | 
				
			||||||
                w!(self, "(");
 | 
					                w!(self, "(");
 | 
				
			||||||
                self.indented(|this| {
 | 
					                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(
 | 
					                        this.print_attrs_of(
 | 
				
			||||||
                            AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
 | 
					                            AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
 | 
				
			||||||
                            "\n",
 | 
					                            "\n",
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                        this.print_visibility(*visibility);
 | 
					                        this.print_visibility(*visibility);
 | 
				
			||||||
 | 
					                        if *is_unsafe {
 | 
				
			||||||
 | 
					                            w!(this, "unsafe ");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        w!(this, "{}: ", name.display(self.db.upcast(), edition));
 | 
					                        w!(this, "{}: ", name.display(self.db.upcast(), edition));
 | 
				
			||||||
                        this.print_type_ref(*type_ref, map);
 | 
					                        this.print_type_ref(*type_ref, map);
 | 
				
			||||||
                        wln!(this, ",");
 | 
					                        wln!(this, ",");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,7 +107,7 @@ pub(crate) fn variant_list(p: &mut Parser<'_>) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// test record_field_list
 | 
					// 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<'_>) {
 | 
					pub(crate) fn record_field_list(p: &mut Parser<'_>) {
 | 
				
			||||||
    assert!(p.at(T!['{']));
 | 
					    assert!(p.at(T!['{']));
 | 
				
			||||||
    let m = p.start();
 | 
					    let m = p.start();
 | 
				
			||||||
| 
						 | 
					@ -131,6 +131,7 @@ pub(crate) fn record_field_list(p: &mut Parser<'_>) {
 | 
				
			||||||
        // struct S { #[attr] f: f32 }
 | 
					        // struct S { #[attr] f: f32 }
 | 
				
			||||||
        attributes::outer_attrs(p);
 | 
					        attributes::outer_attrs(p);
 | 
				
			||||||
        opt_visibility(p, false);
 | 
					        opt_visibility(p, false);
 | 
				
			||||||
 | 
					        p.eat(T![unsafe]);
 | 
				
			||||||
        if p.at(IDENT) {
 | 
					        if p.at(IDENT) {
 | 
				
			||||||
            name(p);
 | 
					            name(p);
 | 
				
			||||||
            p.expect(T![:]);
 | 
					            p.expect(T![:]);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,20 @@ SOURCE_FILE
 | 
				
			||||||
            PATH_SEGMENT
 | 
					            PATH_SEGMENT
 | 
				
			||||||
              NAME_REF
 | 
					              NAME_REF
 | 
				
			||||||
                IDENT "f32"
 | 
					                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 " "
 | 
					      WHITESPACE " "
 | 
				
			||||||
      R_CURLY "}"
 | 
					      R_CURLY "}"
 | 
				
			||||||
  WHITESPACE "\n"
 | 
					  WHITESPACE "\n"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
struct S { a: i32, b: f32 }
 | 
					struct S { a: i32, b: f32, unsafe c: u8 }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -240,7 +240,7 @@ RecordFieldList =
 | 
				
			||||||
 '{' fields:(RecordField (',' RecordField)* ','?)? '}'
 | 
					 '{' fields:(RecordField (',' RecordField)* ','?)? '}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RecordField =
 | 
					RecordField =
 | 
				
			||||||
  Attr* Visibility?
 | 
					  Attr* Visibility? 'unsafe'?
 | 
				
			||||||
  Name ':' Type ('=' Expr)?
 | 
					  Name ':' Type ('=' Expr)?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TupleFieldList =
 | 
					TupleFieldList =
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1337,6 +1337,8 @@ impl RecordField {
 | 
				
			||||||
    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 | 
					    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 | 
				
			||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 | 
					    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 struct RecordFieldList {
 | 
				
			||||||
    pub(crate) syntax: SyntaxNode,
 | 
					    pub(crate) syntax: SyntaxNode,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue