mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 20:09:01 +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 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, | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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)] | ||||
|  |  | |||
|  | @ -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>> { | ||||
|  |  | |||
|  | @ -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, ","); | ||||
|  |  | |||
|  | @ -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![:]); | ||||
|  |  | |||
|  | @ -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" | ||||
|  |  | |||
|  | @ -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)* ','?)? '}' | ||||
| 
 | ||||
| RecordField = | ||||
|   Attr* Visibility? | ||||
|   Attr* Visibility? 'unsafe'? | ||||
|   Name ':' Type ('=' Expr)? | ||||
| 
 | ||||
| TupleFieldList = | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth