mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	Merge pull request #20210 from ChayimFriedman2/naked-asm-safe
fix: Inline asm fixes
This commit is contained in:
		
						commit
						e9968fc555
					
				
					 28 changed files with 303 additions and 84 deletions
				
			
		|  | @ -10,7 +10,7 @@ use tt::TextRange; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     expr_store::lower::{ExprCollector, FxIndexSet}, |     expr_store::lower::{ExprCollector, FxIndexSet}, | ||||||
|     hir::{AsmOperand, AsmOptions, Expr, ExprId, InlineAsm, InlineAsmRegOrRegClass}, |     hir::{AsmOperand, AsmOptions, Expr, ExprId, InlineAsm, InlineAsmKind, InlineAsmRegOrRegClass}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| impl ExprCollector<'_> { | impl ExprCollector<'_> { | ||||||
|  | @ -269,8 +269,17 @@ impl ExprCollector<'_> { | ||||||
|                     } |                     } | ||||||
|                 }) |                 }) | ||||||
|         }; |         }; | ||||||
|  | 
 | ||||||
|  |         let kind = if asm.global_asm_token().is_some() { | ||||||
|  |             InlineAsmKind::GlobalAsm | ||||||
|  |         } else if asm.naked_asm_token().is_some() { | ||||||
|  |             InlineAsmKind::NakedAsm | ||||||
|  |         } else { | ||||||
|  |             InlineAsmKind::Asm | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|         let idx = self.alloc_expr( |         let idx = self.alloc_expr( | ||||||
|             Expr::InlineAsm(InlineAsm { operands: operands.into_boxed_slice(), options }), |             Expr::InlineAsm(InlineAsm { operands: operands.into_boxed_slice(), options, kind }), | ||||||
|             syntax_ptr, |             syntax_ptr, | ||||||
|         ); |         ); | ||||||
|         self.source_map |         self.source_map | ||||||
|  |  | ||||||
|  | @ -332,6 +332,17 @@ pub struct OffsetOf { | ||||||
| pub struct InlineAsm { | pub struct InlineAsm { | ||||||
|     pub operands: Box<[(Option<Name>, AsmOperand)]>, |     pub operands: Box<[(Option<Name>, AsmOperand)]>, | ||||||
|     pub options: AsmOptions, |     pub options: AsmOptions, | ||||||
|  |     pub kind: InlineAsmKind, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||||
|  | pub enum InlineAsmKind { | ||||||
|  |     /// `asm!()`.
 | ||||||
|  |     Asm, | ||||||
|  |     /// `global_asm!()`.
 | ||||||
|  |     GlobalAsm, | ||||||
|  |     /// `naked_asm!()`.
 | ||||||
|  |     NakedAsm, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Copy, PartialEq, Eq, Hash)] | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | ||||||
|  |  | ||||||
|  | @ -143,6 +143,8 @@ impl<'a> Ctx<'a> { | ||||||
|             ast::Item::MacroRules(ast) => self.lower_macro_rules(ast)?.into(), |             ast::Item::MacroRules(ast) => self.lower_macro_rules(ast)?.into(), | ||||||
|             ast::Item::MacroDef(ast) => self.lower_macro_def(ast)?.into(), |             ast::Item::MacroDef(ast) => self.lower_macro_def(ast)?.into(), | ||||||
|             ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(), |             ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(), | ||||||
|  |             // FIXME: Handle `global_asm!()`.
 | ||||||
|  |             ast::Item::AsmExpr(_) => return None, | ||||||
|         }; |         }; | ||||||
|         let attrs = RawAttrs::new(self.db, item, self.span_map()); |         let attrs = RawAttrs::new(self.db, item, self.span_map()); | ||||||
|         self.add_attrs(mod_item.ast_id(), attrs); |         self.add_attrs(mod_item.ast_id(), attrs); | ||||||
|  |  | ||||||
|  | @ -35,10 +35,10 @@ use a::{c, d::{e}}; | ||||||
|             #![no_std] |             #![no_std] | ||||||
|             #![doc = " another file comment"] |             #![doc = " another file comment"] | ||||||
| 
 | 
 | ||||||
|             // AstId: ExternCrate[5A82, 0]
 |             // AstId: ExternCrate[070B, 0]
 | ||||||
|             pub(self) extern crate self as renamed; |             pub(self) extern crate self as renamed; | ||||||
| 
 | 
 | ||||||
|             // AstId: ExternCrate[7E1C, 0]
 |             // AstId: ExternCrate[1EA5, 0]
 | ||||||
|             pub(in super) extern crate bli; |             pub(in super) extern crate bli; | ||||||
| 
 | 
 | ||||||
|             // AstId: Use[0000, 0]
 |             // AstId: Use[0000, 0]
 | ||||||
|  | @ -78,15 +78,15 @@ extern "C" { | ||||||
|             // AstId: ExternBlock[0000, 0]
 |             // AstId: ExternBlock[0000, 0]
 | ||||||
|             extern { |             extern { | ||||||
|                 #[on_extern_type] |                 #[on_extern_type] | ||||||
|                 // AstId: TypeAlias[9FDF, 0]
 |                 // AstId: TypeAlias[A09C, 0]
 | ||||||
|                 pub(self) type ExType; |                 pub(self) type ExType; | ||||||
| 
 | 
 | ||||||
|                 #[on_extern_static] |                 #[on_extern_static] | ||||||
|                 // AstId: Static[43C1, 0]
 |                 // AstId: Static[D85E, 0]
 | ||||||
|                 pub(self) static EX_STATIC = _; |                 pub(self) static EX_STATIC = _; | ||||||
| 
 | 
 | ||||||
|                 #[on_extern_fn] |                 #[on_extern_fn] | ||||||
|                 // AstId: Fn[452D, 0]
 |                 // AstId: Fn[B240, 0]
 | ||||||
|                 pub(self) fn ex_fn; |                 pub(self) fn ex_fn; | ||||||
|             } |             } | ||||||
|         "#]],
 |         "#]],
 | ||||||
|  | @ -124,20 +124,20 @@ enum E { | ||||||
| } | } | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             // AstId: Struct[DFF3, 0]
 |             // AstId: Struct[ED35, 0]
 | ||||||
|             pub(self) struct Unit; |             pub(self) struct Unit; | ||||||
| 
 | 
 | ||||||
|             #[derive(Debug)] |             #[derive(Debug)] | ||||||
|             // AstId: Struct[C7A1, 0]
 |             // AstId: Struct[A47C, 0]
 | ||||||
|             pub(self) struct Struct { ... } |             pub(self) struct Struct { ... } | ||||||
| 
 | 
 | ||||||
|             // AstId: Struct[DAC2, 0]
 |             // AstId: Struct[C8C9, 0]
 | ||||||
|             pub(self) struct Tuple(...); |             pub(self) struct Tuple(...); | ||||||
| 
 | 
 | ||||||
|             // AstId: Union[2DBB, 0]
 |             // AstId: Union[2797, 0]
 | ||||||
|             pub(self) union Ize { ... } |             pub(self) union Ize { ... } | ||||||
| 
 | 
 | ||||||
|             // AstId: Enum[7FF8, 0]
 |             // AstId: Enum[7D23, 0]
 | ||||||
|             pub(self) enum E { ... } |             pub(self) enum E { ... } | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -162,18 +162,18 @@ trait Tr: SuperTrait + 'lifetime { | ||||||
| } | } | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             // AstId: Static[B393, 0]
 |             // AstId: Static[F7C1, 0]
 | ||||||
|             pub static ST = _; |             pub static ST = _; | ||||||
| 
 | 
 | ||||||
|             // AstId: Const[B309, 0]
 |             // AstId: Const[84BB, 0]
 | ||||||
|             pub(self) const _ = _; |             pub(self) const _ = _; | ||||||
| 
 | 
 | ||||||
|             #[attr] |             #[attr] | ||||||
|             #[inner_attr_in_fn] |             #[inner_attr_in_fn] | ||||||
|             // AstId: Fn[75E3, 0]
 |             // AstId: Fn[BE8F, 0]
 | ||||||
|             pub(self) fn f; |             pub(self) fn f; | ||||||
| 
 | 
 | ||||||
|             // AstId: Trait[2998, 0]
 |             // AstId: Trait[9320, 0]
 | ||||||
|             pub(self) trait Tr { ... } |             pub(self) trait Tr { ... } | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -197,16 +197,16 @@ mod outline; | ||||||
|         expect![[r##" |         expect![[r##" | ||||||
|             #[doc = " outer"] |             #[doc = " outer"] | ||||||
|             #[doc = " inner"] |             #[doc = " inner"] | ||||||
|             // AstId: Module[CF93, 0]
 |             // AstId: Module[03AE, 0]
 | ||||||
|             pub(self) mod inline { |             pub(self) mod inline { | ||||||
|                 // AstId: Use[0000, 0]
 |                 // AstId: Use[0000, 0]
 | ||||||
|                 pub(self) use super::*; |                 pub(self) use super::*; | ||||||
| 
 | 
 | ||||||
|                 // AstId: Fn[1B26, 0]
 |                 // AstId: Fn[2A78, 0]
 | ||||||
|                 pub(self) fn fn_in_module; |                 pub(self) fn fn_in_module; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // AstId: Module[8994, 0]
 |             // AstId: Module[C08B, 0]
 | ||||||
|             pub(self) mod outline; |             pub(self) mod outline; | ||||||
|         "##]],
 |         "##]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -225,13 +225,13 @@ pub macro m2() {} | ||||||
| m!(); | m!(); | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             // AstId: MacroRules[88CE, 0]
 |             // AstId: MacroRules[7E68, 0]
 | ||||||
|             macro_rules! m { ... } |             macro_rules! m { ... } | ||||||
| 
 | 
 | ||||||
|             // AstId: MacroDef[DC34, 0]
 |             // AstId: MacroDef[1C1E, 0]
 | ||||||
|             pub macro m2 { ... } |             pub macro m2 { ... } | ||||||
| 
 | 
 | ||||||
|             // AstId: MacroCall[612F, 0], SyntaxContextId: ROOT2024, ExpandTo: Items
 |             // AstId: MacroCall[7E68, 0], SyntaxContextId: ROOT2024, ExpandTo: Items
 | ||||||
|             m!(...); |             m!(...); | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -244,7 +244,7 @@ fn pub_self() { | ||||||
| pub(self) struct S; | pub(self) struct S; | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             // AstId: Struct[42E2, 0]
 |             // AstId: Struct[5024, 0]
 | ||||||
|             pub(self) struct S; |             pub(self) struct S; | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  | @ -28,6 +28,19 @@ fn test_asm_expand() { | ||||||
|         r#" |         r#" | ||||||
| #[rustc_builtin_macro] | #[rustc_builtin_macro] | ||||||
| macro_rules! asm {() => {}} | macro_rules! asm {() => {}} | ||||||
|  | #[rustc_builtin_macro] | ||||||
|  | macro_rules! global_asm {() => {}} | ||||||
|  | #[rustc_builtin_macro] | ||||||
|  | macro_rules! naked_asm {() => {}} | ||||||
|  | 
 | ||||||
|  | global_asm! { | ||||||
|  |     "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[unsafe(naked)] | ||||||
|  | extern "C" fn foo() { | ||||||
|  |     naked_asm!(""); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
|     let i: u64 = 3; |     let i: u64 = 3; | ||||||
|  | @ -45,6 +58,17 @@ fn main() { | ||||||
|         expect![[r##" |         expect![[r##" | ||||||
| #[rustc_builtin_macro] | #[rustc_builtin_macro] | ||||||
| macro_rules! asm {() => {}} | macro_rules! asm {() => {}} | ||||||
|  | #[rustc_builtin_macro] | ||||||
|  | macro_rules! global_asm {() => {}} | ||||||
|  | #[rustc_builtin_macro] | ||||||
|  | macro_rules! naked_asm {() => {}} | ||||||
|  | 
 | ||||||
|  | builtin #global_asm ("") | ||||||
|  | 
 | ||||||
|  | #[unsafe(naked)] | ||||||
|  | extern "C" fn foo() { | ||||||
|  |     builtin #naked_asm (""); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
|     let i: u64 = 3; |     let i: u64 = 3; | ||||||
|  |  | ||||||
|  | @ -35,9 +35,9 @@ macro_rules! f { | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct#0:MacroRules[8C8E, 0]@58..64#14336# MyTraitMap2#0:MacroCall[D499, 0]@31..42#ROOT2024# {#0:MacroRules[8C8E, 0]@72..73#14336# | struct#0:MacroRules[BE8F, 0]@58..64#14336# MyTraitMap2#0:MacroCall[BE8F, 0]@31..42#ROOT2024# {#0:MacroRules[BE8F, 0]@72..73#14336# | ||||||
|     map#0:MacroRules[8C8E, 0]@86..89#14336#:#0:MacroRules[8C8E, 0]@89..90#14336# #0:MacroRules[8C8E, 0]@89..90#14336#::#0:MacroRules[8C8E, 0]@91..93#14336#std#0:MacroRules[8C8E, 0]@93..96#14336#::#0:MacroRules[8C8E, 0]@96..98#14336#collections#0:MacroRules[8C8E, 0]@98..109#14336#::#0:MacroRules[8C8E, 0]@109..111#14336#HashSet#0:MacroRules[8C8E, 0]@111..118#14336#<#0:MacroRules[8C8E, 0]@118..119#14336#(#0:MacroRules[8C8E, 0]@119..120#14336#)#0:MacroRules[8C8E, 0]@120..121#14336#>#0:MacroRules[8C8E, 0]@121..122#14336#,#0:MacroRules[8C8E, 0]@122..123#14336# |     map#0:MacroRules[BE8F, 0]@86..89#14336#:#0:MacroRules[BE8F, 0]@89..90#14336# #0:MacroRules[BE8F, 0]@89..90#14336#::#0:MacroRules[BE8F, 0]@91..93#14336#std#0:MacroRules[BE8F, 0]@93..96#14336#::#0:MacroRules[BE8F, 0]@96..98#14336#collections#0:MacroRules[BE8F, 0]@98..109#14336#::#0:MacroRules[BE8F, 0]@109..111#14336#HashSet#0:MacroRules[BE8F, 0]@111..118#14336#<#0:MacroRules[BE8F, 0]@118..119#14336#(#0:MacroRules[BE8F, 0]@119..120#14336#)#0:MacroRules[BE8F, 0]@120..121#14336#>#0:MacroRules[BE8F, 0]@121..122#14336#,#0:MacroRules[BE8F, 0]@122..123#14336# | ||||||
| }#0:MacroRules[8C8E, 0]@132..133#14336# | }#0:MacroRules[BE8F, 0]@132..133#14336# | ||||||
| "#]],
 | "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  | @ -75,12 +75,12 @@ macro_rules! f { | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn#0:MacroCall[D499, 0]@30..32#ROOT2024# main#0:MacroCall[D499, 0]@33..37#ROOT2024#(#0:MacroCall[D499, 0]@37..38#ROOT2024#)#0:MacroCall[D499, 0]@38..39#ROOT2024# {#0:MacroCall[D499, 0]@40..41#ROOT2024# | fn#0:MacroCall[BE8F, 0]@30..32#ROOT2024# main#0:MacroCall[BE8F, 0]@33..37#ROOT2024#(#0:MacroCall[BE8F, 0]@37..38#ROOT2024#)#0:MacroCall[BE8F, 0]@38..39#ROOT2024# {#0:MacroCall[BE8F, 0]@40..41#ROOT2024# | ||||||
|     1#0:MacroCall[D499, 0]@50..51#ROOT2024#;#0:MacroCall[D499, 0]@51..52#ROOT2024# |     1#0:MacroCall[BE8F, 0]@50..51#ROOT2024#;#0:MacroCall[BE8F, 0]@51..52#ROOT2024# | ||||||
|     1.0#0:MacroCall[D499, 0]@61..64#ROOT2024#;#0:MacroCall[D499, 0]@64..65#ROOT2024# |     1.0#0:MacroCall[BE8F, 0]@61..64#ROOT2024#;#0:MacroCall[BE8F, 0]@64..65#ROOT2024# | ||||||
|     (#0:MacroCall[D499, 0]@74..75#ROOT2024#(#0:MacroCall[D499, 0]@75..76#ROOT2024#1#0:MacroCall[D499, 0]@76..77#ROOT2024#,#0:MacroCall[D499, 0]@77..78#ROOT2024# )#0:MacroCall[D499, 0]@78..79#ROOT2024#,#0:MacroCall[D499, 0]@79..80#ROOT2024# )#0:MacroCall[D499, 0]@80..81#ROOT2024#.#0:MacroCall[D499, 0]@81..82#ROOT2024#0#0:MacroCall[D499, 0]@82..85#ROOT2024#.#0:MacroCall[D499, 0]@82..85#ROOT2024#0#0:MacroCall[D499, 0]@82..85#ROOT2024#;#0:MacroCall[D499, 0]@85..86#ROOT2024# |     (#0:MacroCall[BE8F, 0]@74..75#ROOT2024#(#0:MacroCall[BE8F, 0]@75..76#ROOT2024#1#0:MacroCall[BE8F, 0]@76..77#ROOT2024#,#0:MacroCall[BE8F, 0]@77..78#ROOT2024# )#0:MacroCall[BE8F, 0]@78..79#ROOT2024#,#0:MacroCall[BE8F, 0]@79..80#ROOT2024# )#0:MacroCall[BE8F, 0]@80..81#ROOT2024#.#0:MacroCall[BE8F, 0]@81..82#ROOT2024#0#0:MacroCall[BE8F, 0]@82..85#ROOT2024#.#0:MacroCall[BE8F, 0]@82..85#ROOT2024#0#0:MacroCall[BE8F, 0]@82..85#ROOT2024#;#0:MacroCall[BE8F, 0]@85..86#ROOT2024# | ||||||
|     let#0:MacroCall[D499, 0]@95..98#ROOT2024# x#0:MacroCall[D499, 0]@99..100#ROOT2024# =#0:MacroCall[D499, 0]@101..102#ROOT2024# 1#0:MacroCall[D499, 0]@103..104#ROOT2024#;#0:MacroCall[D499, 0]@104..105#ROOT2024# |     let#0:MacroCall[BE8F, 0]@95..98#ROOT2024# x#0:MacroCall[BE8F, 0]@99..100#ROOT2024# =#0:MacroCall[BE8F, 0]@101..102#ROOT2024# 1#0:MacroCall[BE8F, 0]@103..104#ROOT2024#;#0:MacroCall[BE8F, 0]@104..105#ROOT2024# | ||||||
| }#0:MacroCall[D499, 0]@110..111#ROOT2024# | }#0:MacroCall[BE8F, 0]@110..111#ROOT2024# | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| "#]],
 | "#]],
 | ||||||
|  | @ -171,7 +171,7 @@ fn main(foo: ()) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn main(foo: ()) { |     fn main(foo: ()) { | ||||||
|         /* error: unresolved macro unresolved */"helloworld!"#0:Fn[B9C7, 0]@236..321#ROOT2024#; |         /* error: unresolved macro unresolved */"helloworld!"#0:Fn[15AE, 0]@236..321#ROOT2024#; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -197,7 +197,7 @@ macro_rules! mk_struct { | ||||||
| #[macro_use] | #[macro_use] | ||||||
| mod foo; | mod foo; | ||||||
| 
 | 
 | ||||||
| struct#1:MacroRules[E572, 0]@59..65#14336# Foo#0:MacroCall[BDD3, 0]@32..35#ROOT2024#(#1:MacroRules[E572, 0]@70..71#14336#u32#0:MacroCall[BDD3, 0]@41..44#ROOT2024#)#1:MacroRules[E572, 0]@74..75#14336#;#1:MacroRules[E572, 0]@75..76#14336# | struct#1:MacroRules[DB0C, 0]@59..65#14336# Foo#0:MacroCall[DB0C, 0]@32..35#ROOT2024#(#1:MacroRules[DB0C, 0]@70..71#14336#u32#0:MacroCall[DB0C, 0]@41..44#ROOT2024#)#1:MacroRules[DB0C, 0]@74..75#14336#;#1:MacroRules[DB0C, 0]@75..76#14336# | ||||||
| "#]],
 | "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -181,9 +181,9 @@ fn foo(&self) { | ||||||
|     self.0. 1; |     self.0. 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn#0:Fn[4D85, 0]@45..47#ROOT2024# foo#0:Fn[4D85, 0]@48..51#ROOT2024#(#0:Fn[4D85, 0]@51..52#ROOT2024#�:Fn[4D85, 0]@52..53#ROOT2024#self#0:Fn[4D85, 0]@53..57#ROOT2024# )#0:Fn[4D85, 0]@57..58#ROOT2024# {#0:Fn[4D85, 0]@59..60#ROOT2024# | fn#0:Fn[8A31, 0]@45..47#ROOT2024# foo#0:Fn[8A31, 0]@48..51#ROOT2024#(#0:Fn[8A31, 0]@51..52#ROOT2024#�:Fn[8A31, 0]@52..53#ROOT2024#self#0:Fn[8A31, 0]@53..57#ROOT2024# )#0:Fn[8A31, 0]@57..58#ROOT2024# {#0:Fn[8A31, 0]@59..60#ROOT2024# | ||||||
|     self#0:Fn[4D85, 0]@65..69#ROOT2024# .#0:Fn[4D85, 0]@69..70#ROOT2024#0#0:Fn[4D85, 0]@70..71#ROOT2024#.#0:Fn[4D85, 0]@71..72#ROOT2024#1#0:Fn[4D85, 0]@73..74#ROOT2024#;#0:Fn[4D85, 0]@74..75#ROOT2024# |     self#0:Fn[8A31, 0]@65..69#ROOT2024# .#0:Fn[8A31, 0]@69..70#ROOT2024#0#0:Fn[8A31, 0]@70..71#ROOT2024#.#0:Fn[8A31, 0]@71..72#ROOT2024#1#0:Fn[8A31, 0]@73..74#ROOT2024#;#0:Fn[8A31, 0]@74..75#ROOT2024# | ||||||
| }#0:Fn[4D85, 0]@76..77#ROOT2024#"#]],
 | }#0:Fn[8A31, 0]@76..77#ROOT2024#"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1052,17 +1052,6 @@ impl<'db> Scope<'db> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn resolver_for_expr( |  | ||||||
|     db: &dyn DefDatabase, |  | ||||||
|     owner: DefWithBodyId, |  | ||||||
|     expr_id: ExprId, |  | ||||||
| ) -> Resolver<'_> { |  | ||||||
|     let r = owner.resolver(db); |  | ||||||
|     let scopes = db.expr_scopes(owner); |  | ||||||
|     let scope_id = scopes.scope_for(expr_id); |  | ||||||
|     resolver_for_scope_(db, scopes, scope_id, r, owner) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn resolver_for_scope( | pub fn resolver_for_scope( | ||||||
|     db: &dyn DefDatabase, |     db: &dyn DefDatabase, | ||||||
|     owner: DefWithBodyId, |     owner: DefWithBodyId, | ||||||
|  |  | ||||||
|  | @ -125,8 +125,8 @@ register_builtin! { | ||||||
|     (assert, Assert) => assert_expand, |     (assert, Assert) => assert_expand, | ||||||
|     (stringify, Stringify) => stringify_expand, |     (stringify, Stringify) => stringify_expand, | ||||||
|     (asm, Asm) => asm_expand, |     (asm, Asm) => asm_expand, | ||||||
|     (global_asm, GlobalAsm) => asm_expand, |     (global_asm, GlobalAsm) => global_asm_expand, | ||||||
|     (naked_asm, NakedAsm) => asm_expand, |     (naked_asm, NakedAsm) => naked_asm_expand, | ||||||
|     (cfg, Cfg) => cfg_expand, |     (cfg, Cfg) => cfg_expand, | ||||||
|     (core_panic, CorePanic) => panic_expand, |     (core_panic, CorePanic) => panic_expand, | ||||||
|     (std_panic, StdPanic) => panic_expand, |     (std_panic, StdPanic) => panic_expand, | ||||||
|  | @ -325,6 +325,36 @@ fn asm_expand( | ||||||
|     ExpandResult::ok(expanded) |     ExpandResult::ok(expanded) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn global_asm_expand( | ||||||
|  |     _db: &dyn ExpandDatabase, | ||||||
|  |     _id: MacroCallId, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  |     span: Span, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|  |     let mut tt = tt.clone(); | ||||||
|  |     tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis; | ||||||
|  |     let pound = mk_pound(span); | ||||||
|  |     let expanded = quote! {span => | ||||||
|  |         builtin #pound global_asm #tt | ||||||
|  |     }; | ||||||
|  |     ExpandResult::ok(expanded) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn naked_asm_expand( | ||||||
|  |     _db: &dyn ExpandDatabase, | ||||||
|  |     _id: MacroCallId, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  |     span: Span, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|  |     let mut tt = tt.clone(); | ||||||
|  |     tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis; | ||||||
|  |     let pound = mk_pound(span); | ||||||
|  |     let expanded = quote! {span => | ||||||
|  |         builtin #pound naked_asm #tt | ||||||
|  |     }; | ||||||
|  |     ExpandResult::ok(expanded) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn cfg_expand( | fn cfg_expand( | ||||||
|     db: &dyn ExpandDatabase, |     db: &dyn ExpandDatabase, | ||||||
|     id: MacroCallId, |     id: MacroCallId, | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ use either::Either; | ||||||
| use hir_def::{ | use hir_def::{ | ||||||
|     AdtId, DefWithBodyId, FieldId, FunctionId, VariantId, |     AdtId, DefWithBodyId, FieldId, FunctionId, VariantId, | ||||||
|     expr_store::{Body, path::Path}, |     expr_store::{Body, path::Path}, | ||||||
|     hir::{AsmOperand, Expr, ExprId, ExprOrPatId, Pat, PatId, Statement, UnaryOp}, |     hir::{AsmOperand, Expr, ExprId, ExprOrPatId, InlineAsmKind, Pat, PatId, Statement, UnaryOp}, | ||||||
|     resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs}, |     resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs}, | ||||||
|     signatures::StaticFlags, |     signatures::StaticFlags, | ||||||
|     type_ref::Rawness, |     type_ref::Rawness, | ||||||
|  | @ -315,7 +315,12 @@ impl<'db> UnsafeVisitor<'db> { | ||||||
|                 self.inside_assignment = old_inside_assignment; |                 self.inside_assignment = old_inside_assignment; | ||||||
|             } |             } | ||||||
|             Expr::InlineAsm(asm) => { |             Expr::InlineAsm(asm) => { | ||||||
|                 self.on_unsafe_op(current.into(), UnsafetyReason::InlineAsm); |                 if asm.kind == InlineAsmKind::Asm { | ||||||
|  |                     // `naked_asm!()` requires `unsafe` on the attribute (`#[unsafe(naked)]`),
 | ||||||
|  |                     // and `global_asm!()` doesn't require it at all.
 | ||||||
|  |                     self.on_unsafe_op(current.into(), UnsafetyReason::InlineAsm); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 asm.operands.iter().for_each(|(_, op)| match op { |                 asm.operands.iter().for_each(|(_, op)| match op { | ||||||
|                     AsmOperand::In { expr, .. } |                     AsmOperand::In { expr, .. } | ||||||
|                     | AsmOperand::Out { expr: Some(expr), .. } |                     | AsmOperand::Out { expr: Some(expr), .. } | ||||||
|  |  | ||||||
|  | @ -3222,7 +3222,8 @@ impl Macro { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn is_asm_or_global_asm(&self, db: &dyn HirDatabase) -> bool { |     /// Is this `asm!()`, or a variant of it (e.g. `global_asm!()`)?
 | ||||||
|  |     pub fn is_asm_like(&self, db: &dyn HirDatabase) -> bool { | ||||||
|         match self.id { |         match self.id { | ||||||
|             MacroId::Macro2Id(it) => { |             MacroId::Macro2Id(it) => { | ||||||
|                 matches!(it.lookup(db).expander, MacroExpander::BuiltIn(m) if m.is_asm()) |                 matches!(it.lookup(db).expander, MacroExpander::BuiltIn(m) if m.is_asm()) | ||||||
|  |  | ||||||
|  | @ -1776,7 +1776,7 @@ impl<'db> SemanticsImpl<'db> { | ||||||
| 
 | 
 | ||||||
|     pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool { |     pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool { | ||||||
|         let Some(mac) = self.resolve_macro_call(macro_call) else { return false }; |         let Some(mac) = self.resolve_macro_call(macro_call) else { return false }; | ||||||
|         if mac.is_asm_or_global_asm(self.db) { |         if mac.is_asm_like(self.db) { | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1439,9 +1439,11 @@ fn scope_for( | ||||||
| ) -> Option<ScopeId> { | ) -> Option<ScopeId> { | ||||||
|     node.ancestors_with_macros(db) |     node.ancestors_with_macros(db) | ||||||
|         .take_while(|it| { |         .take_while(|it| { | ||||||
|             !ast::Item::can_cast(it.kind()) |             let kind = it.kind(); | ||||||
|                 || ast::MacroCall::can_cast(it.kind()) |             !ast::Item::can_cast(kind) | ||||||
|                 || ast::Use::can_cast(it.kind()) |                 || ast::MacroCall::can_cast(kind) | ||||||
|  |                 || ast::Use::can_cast(kind) | ||||||
|  |                 || ast::AsmExpr::can_cast(kind) | ||||||
|         }) |         }) | ||||||
|         .filter_map(|it| it.map(ast::Expr::cast).transpose()) |         .filter_map(|it| it.map(ast::Expr::cast).transpose()) | ||||||
|         .filter_map(|it| source_map.node_expr(it.as_ref())?.as_expr()) |         .filter_map(|it| source_map.node_expr(it.as_ref())?.as_expr()) | ||||||
|  |  | ||||||
|  | @ -983,4 +983,19 @@ fn test() { | ||||||
|             "#,
 |             "#,
 | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn naked_asm_is_safe() { | ||||||
|  |         check_diagnostics( | ||||||
|  |             r#" | ||||||
|  | #[rustc_builtin_macro] | ||||||
|  | macro_rules! naked_asm { () => {} } | ||||||
|  | 
 | ||||||
|  | #[unsafe(naked)] | ||||||
|  | extern "C" fn naked() { | ||||||
|  |     naked_asm!(""); | ||||||
|  | } | ||||||
|  |         "#,
 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ use crate::grammar::attributes::ATTRIBUTE_FIRST; | ||||||
| 
 | 
 | ||||||
| use super::*; | use super::*; | ||||||
| 
 | 
 | ||||||
| pub(super) use atom::{EXPR_RECOVERY_SET, LITERAL_FIRST, literal}; | pub(super) use atom::{EXPR_RECOVERY_SET, LITERAL_FIRST, literal, parse_asm_expr}; | ||||||
| pub(crate) use atom::{block_expr, match_arm_list}; | pub(crate) use atom::{block_expr, match_arm_list}; | ||||||
| 
 | 
 | ||||||
| #[derive(PartialEq, Eq)] | #[derive(PartialEq, Eq)] | ||||||
|  |  | ||||||
|  | @ -253,8 +253,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> { | ||||||
|     let m = p.start(); |     let m = p.start(); | ||||||
|     p.bump_remap(T![builtin]); |     p.bump_remap(T![builtin]); | ||||||
|     p.bump(T![#]); |     p.bump(T![#]); | ||||||
|     if p.at_contextual_kw(T![offset_of]) { |     if p.eat_contextual_kw(T![offset_of]) { | ||||||
|         p.bump_remap(T![offset_of]); |  | ||||||
|         p.expect(T!['(']); |         p.expect(T!['(']); | ||||||
|         type_(p); |         type_(p); | ||||||
|         p.expect(T![,]); |         p.expect(T![,]); | ||||||
|  | @ -278,8 +277,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> { | ||||||
|             p.expect(T![')']); |             p.expect(T![')']); | ||||||
|         } |         } | ||||||
|         Some(m.complete(p, OFFSET_OF_EXPR)) |         Some(m.complete(p, OFFSET_OF_EXPR)) | ||||||
|     } else if p.at_contextual_kw(T![format_args]) { |     } else if p.eat_contextual_kw(T![format_args]) { | ||||||
|         p.bump_remap(T![format_args]); |  | ||||||
|         p.expect(T!['(']); |         p.expect(T!['(']); | ||||||
|         expr(p); |         expr(p); | ||||||
|         if p.eat(T![,]) { |         if p.eat(T![,]) { | ||||||
|  | @ -302,7 +300,16 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> { | ||||||
|         } |         } | ||||||
|         p.expect(T![')']); |         p.expect(T![')']); | ||||||
|         Some(m.complete(p, FORMAT_ARGS_EXPR)) |         Some(m.complete(p, FORMAT_ARGS_EXPR)) | ||||||
|     } else if p.at_contextual_kw(T![asm]) { |     } else if p.eat_contextual_kw(T![asm]) | ||||||
|  |         || p.eat_contextual_kw(T![global_asm]) | ||||||
|  |         || p.eat_contextual_kw(T![naked_asm]) | ||||||
|  |     { | ||||||
|  |         // test asm_kinds
 | ||||||
|  |         // fn foo() {
 | ||||||
|  |         //     builtin#asm("");
 | ||||||
|  |         //     builtin#global_asm("");
 | ||||||
|  |         //     builtin#naked_asm("");
 | ||||||
|  |         // }
 | ||||||
|         parse_asm_expr(p, m) |         parse_asm_expr(p, m) | ||||||
|     } else { |     } else { | ||||||
|         m.abandon(p); |         m.abandon(p); | ||||||
|  | @ -321,8 +328,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> { | ||||||
| //         tmp = out(reg) _,
 | //         tmp = out(reg) _,
 | ||||||
| //     );
 | //     );
 | ||||||
| // }
 | // }
 | ||||||
| fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> { | pub(crate) fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> { | ||||||
|     p.bump_remap(T![asm]); |  | ||||||
|     p.expect(T!['(']); |     p.expect(T!['(']); | ||||||
|     if expr(p).is_none() { |     if expr(p).is_none() { | ||||||
|         p.err_and_bump("expected asm template"); |         p.err_and_bump("expected asm template"); | ||||||
|  |  | ||||||
|  | @ -261,6 +261,19 @@ fn opt_item_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), Marke | ||||||
|         T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::konst(p, m), |         T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::konst(p, m), | ||||||
|         T![static] if (la == IDENT || la == T![_] || la == T![mut]) => consts::static_(p, m), |         T![static] if (la == IDENT || la == T![_] || la == T![mut]) => consts::static_(p, m), | ||||||
| 
 | 
 | ||||||
|  |         IDENT | ||||||
|  |             if p.at_contextual_kw(T![builtin]) | ||||||
|  |                 && p.nth_at(1, T![#]) | ||||||
|  |                 && p.nth_at_contextual_kw(2, T![global_asm]) => | ||||||
|  |         { | ||||||
|  |             p.bump_remap(T![builtin]); | ||||||
|  |             p.bump(T![#]); | ||||||
|  |             p.bump_remap(T![global_asm]); | ||||||
|  |             // test global_asm
 | ||||||
|  |             // builtin#global_asm("")
 | ||||||
|  |             expressions::parse_asm_expr(p, m); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         _ => return Err(m), |         _ => return Err(m), | ||||||
|     }; |     }; | ||||||
|     Ok(()) |     Ok(()) | ||||||
|  |  | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -21,6 +21,8 @@ mod ok { | ||||||
|     #[test] |     #[test] | ||||||
|     fn asm_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_expr.rs"); } |     fn asm_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_expr.rs"); } | ||||||
|     #[test] |     #[test] | ||||||
|  |     fn asm_kinds() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_kinds.rs"); } | ||||||
|  |     #[test] | ||||||
|     fn asm_label() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_label.rs"); } |     fn asm_label() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_label.rs"); } | ||||||
|     #[test] |     #[test] | ||||||
|     fn assoc_const_eq() { |     fn assoc_const_eq() { | ||||||
|  | @ -298,6 +300,8 @@ mod ok { | ||||||
|         run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_list.rs"); |         run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_list.rs"); | ||||||
|     } |     } | ||||||
|     #[test] |     #[test] | ||||||
|  |     fn global_asm() { run_and_expect_no_errors("test_data/parser/inline/ok/global_asm.rs"); } | ||||||
|  |     #[test] | ||||||
|     fn half_open_range_pat() { |     fn half_open_range_pat() { | ||||||
|         run_and_expect_no_errors("test_data/parser/inline/ok/half_open_range_pat.rs"); |         run_and_expect_no_errors("test_data/parser/inline/ok/half_open_range_pat.rs"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
							
								
								
									
										48
									
								
								crates/parser/test_data/parser/inline/ok/asm_kinds.rast
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								crates/parser/test_data/parser/inline/ok/asm_kinds.rast
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | SOURCE_FILE | ||||||
|  |   FN | ||||||
|  |     FN_KW "fn" | ||||||
|  |     WHITESPACE " " | ||||||
|  |     NAME | ||||||
|  |       IDENT "foo" | ||||||
|  |     PARAM_LIST | ||||||
|  |       L_PAREN "(" | ||||||
|  |       R_PAREN ")" | ||||||
|  |     WHITESPACE " " | ||||||
|  |     BLOCK_EXPR | ||||||
|  |       STMT_LIST | ||||||
|  |         L_CURLY "{" | ||||||
|  |         WHITESPACE "\n    " | ||||||
|  |         EXPR_STMT | ||||||
|  |           ASM_EXPR | ||||||
|  |             BUILTIN_KW "builtin" | ||||||
|  |             POUND "#" | ||||||
|  |             ASM_KW "asm" | ||||||
|  |             L_PAREN "(" | ||||||
|  |             LITERAL | ||||||
|  |               STRING "\"\"" | ||||||
|  |             R_PAREN ")" | ||||||
|  |           SEMICOLON ";" | ||||||
|  |         WHITESPACE "\n    " | ||||||
|  |         ASM_EXPR | ||||||
|  |           BUILTIN_KW "builtin" | ||||||
|  |           POUND "#" | ||||||
|  |           GLOBAL_ASM_KW "global_asm" | ||||||
|  |           L_PAREN "(" | ||||||
|  |           LITERAL | ||||||
|  |             STRING "\"\"" | ||||||
|  |           R_PAREN ")" | ||||||
|  |         SEMICOLON ";" | ||||||
|  |         WHITESPACE "\n    " | ||||||
|  |         EXPR_STMT | ||||||
|  |           ASM_EXPR | ||||||
|  |             BUILTIN_KW "builtin" | ||||||
|  |             POUND "#" | ||||||
|  |             NAKED_ASM_KW "naked_asm" | ||||||
|  |             L_PAREN "(" | ||||||
|  |             LITERAL | ||||||
|  |               STRING "\"\"" | ||||||
|  |             R_PAREN ")" | ||||||
|  |           SEMICOLON ";" | ||||||
|  |         WHITESPACE "\n" | ||||||
|  |         R_CURLY "}" | ||||||
|  |   WHITESPACE "\n" | ||||||
							
								
								
									
										5
									
								
								crates/parser/test_data/parser/inline/ok/asm_kinds.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								crates/parser/test_data/parser/inline/ok/asm_kinds.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | fn foo() { | ||||||
|  |     builtin#asm(""); | ||||||
|  |     builtin#global_asm(""); | ||||||
|  |     builtin#naked_asm(""); | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								crates/parser/test_data/parser/inline/ok/global_asm.rast
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								crates/parser/test_data/parser/inline/ok/global_asm.rast
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | SOURCE_FILE | ||||||
|  |   ASM_EXPR | ||||||
|  |     BUILTIN_KW "builtin" | ||||||
|  |     POUND "#" | ||||||
|  |     GLOBAL_ASM_KW "global_asm" | ||||||
|  |     L_PAREN "(" | ||||||
|  |     LITERAL | ||||||
|  |       STRING "\"\"" | ||||||
|  |     R_PAREN ")" | ||||||
|  |   WHITESPACE "\n" | ||||||
							
								
								
									
										1
									
								
								crates/parser/test_data/parser/inline/ok/global_asm.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								crates/parser/test_data/parser/inline/ok/global_asm.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | builtin#global_asm("") | ||||||
|  | @ -880,7 +880,8 @@ fn main() {{}} | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn diagnostics_dont_block_typing() { | fn diagnostics_dont_block_typing() { | ||||||
|     if skip_slow_tests() { |     if skip_slow_tests() || std::env::var("CI").is_ok() { | ||||||
|  |         // FIXME: This test is failing too frequently (therefore we disable it on CI).
 | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -92,6 +92,7 @@ impl fmt::Debug for ErasedFileAstId { | ||||||
|             Use, |             Use, | ||||||
|             Impl, |             Impl, | ||||||
|             BlockExpr, |             BlockExpr, | ||||||
|  |             AsmExpr, | ||||||
|             Fixup, |             Fixup, | ||||||
|         ); |         ); | ||||||
|         if f.alternate() { |         if f.alternate() { | ||||||
|  | @ -144,6 +145,10 @@ enum ErasedFileAstIdKind { | ||||||
|     Impl, |     Impl, | ||||||
|     /// Associated with [`BlockExprFileAstId`].
 |     /// Associated with [`BlockExprFileAstId`].
 | ||||||
|     BlockExpr, |     BlockExpr, | ||||||
|  |     // `global_asm!()` is an item, so we need to give it an `AstId`. So we give to all inline asm
 | ||||||
|  |     // because incrementality is not a problem, they will always be the only item in the macro file,
 | ||||||
|  |     // and memory usage also not because they're rare.
 | ||||||
|  |     AsmExpr, | ||||||
|     /// Keep this last.
 |     /// Keep this last.
 | ||||||
|     Root, |     Root, | ||||||
| } | } | ||||||
|  | @ -204,14 +209,17 @@ impl ErasedFileAstId { | ||||||
|             .or_else(|| extern_block_ast_id(node, index_map)) |             .or_else(|| extern_block_ast_id(node, index_map)) | ||||||
|             .or_else(|| use_ast_id(node, index_map)) |             .or_else(|| use_ast_id(node, index_map)) | ||||||
|             .or_else(|| impl_ast_id(node, index_map)) |             .or_else(|| impl_ast_id(node, index_map)) | ||||||
|  |             .or_else(|| asm_expr_ast_id(node, index_map)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn should_alloc(node: &SyntaxNode) -> bool { |     fn should_alloc(node: &SyntaxNode) -> bool { | ||||||
|         should_alloc_has_name(node) |         let kind = node.kind(); | ||||||
|             || should_alloc_assoc_item(node) |         should_alloc_has_name(kind) | ||||||
|             || ast::ExternBlock::can_cast(node.kind()) |             || should_alloc_assoc_item(kind) | ||||||
|             || ast::Use::can_cast(node.kind()) |             || ast::ExternBlock::can_cast(kind) | ||||||
|             || ast::Impl::can_cast(node.kind()) |             || ast::Use::can_cast(kind) | ||||||
|  |             || ast::Impl::can_cast(kind) | ||||||
|  |             || ast::AsmExpr::can_cast(kind) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[inline] |     #[inline] | ||||||
|  | @ -278,7 +286,6 @@ impl<N> FileAstId<N> { | ||||||
| 
 | 
 | ||||||
| #[derive(Hash)] | #[derive(Hash)] | ||||||
| struct ErasedHasNameFileAstId<'a> { | struct ErasedHasNameFileAstId<'a> { | ||||||
|     kind: SyntaxKind, |  | ||||||
|     name: &'a str, |     name: &'a str, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -332,6 +339,19 @@ fn use_ast_id( | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl AstIdNode for ast::AsmExpr {} | ||||||
|  | 
 | ||||||
|  | fn asm_expr_ast_id( | ||||||
|  |     node: &SyntaxNode, | ||||||
|  |     index_map: &mut ErasedAstIdNextIndexMap, | ||||||
|  | ) -> Option<ErasedFileAstId> { | ||||||
|  |     if ast::AsmExpr::can_cast(node.kind()) { | ||||||
|  |         Some(index_map.new_id(ErasedFileAstIdKind::AsmExpr, ())) | ||||||
|  |     } else { | ||||||
|  |         None | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl AstIdNode for ast::Impl {} | impl AstIdNode for ast::Impl {} | ||||||
| 
 | 
 | ||||||
| fn impl_ast_id( | fn impl_ast_id( | ||||||
|  | @ -433,7 +453,6 @@ macro_rules! register_has_name_ast_id { | ||||||
|         )+ |         )+ | ||||||
| 
 | 
 | ||||||
|         fn has_name_ast_id(node: &SyntaxNode, index_map: &mut ErasedAstIdNextIndexMap) -> Option<ErasedFileAstId> { |         fn has_name_ast_id(node: &SyntaxNode, index_map: &mut ErasedAstIdNextIndexMap) -> Option<ErasedFileAstId> { | ||||||
|             let kind = node.kind(); |  | ||||||
|             match_ast! { |             match_ast! { | ||||||
|                 match node { |                 match node { | ||||||
|                     $( |                     $( | ||||||
|  | @ -441,7 +460,6 @@ macro_rules! register_has_name_ast_id { | ||||||
|                             let name = node.$name_method(); |                             let name = node.$name_method(); | ||||||
|                             let name = name.as_ref().map_or("", |it| it.text_non_mutable()); |                             let name = name.as_ref().map_or("", |it| it.text_non_mutable()); | ||||||
|                             let result = ErasedHasNameFileAstId { |                             let result = ErasedHasNameFileAstId { | ||||||
|                                 kind, |  | ||||||
|                                 name, |                                 name, | ||||||
|                             }; |                             }; | ||||||
|                             Some(index_map.new_id(ErasedFileAstIdKind::$ident, result)) |                             Some(index_map.new_id(ErasedFileAstIdKind::$ident, result)) | ||||||
|  | @ -452,8 +470,7 @@ macro_rules! register_has_name_ast_id { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         fn should_alloc_has_name(node: &SyntaxNode) -> bool { |         fn should_alloc_has_name(kind: SyntaxKind) -> bool { | ||||||
|             let kind = node.kind(); |  | ||||||
|             false $( || ast::$ident::can_cast(kind) )* |             false $( || ast::$ident::can_cast(kind) )* | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  | @ -483,7 +500,6 @@ macro_rules! register_assoc_item_ast_id { | ||||||
|             index_map: &mut ErasedAstIdNextIndexMap, |             index_map: &mut ErasedAstIdNextIndexMap, | ||||||
|             parent: Option<&ErasedFileAstId>, |             parent: Option<&ErasedFileAstId>, | ||||||
|         ) -> Option<ErasedFileAstId> { |         ) -> Option<ErasedFileAstId> { | ||||||
|             let kind = node.kind(); |  | ||||||
|             match_ast! { |             match_ast! { | ||||||
|                 match node { |                 match node { | ||||||
|                     $( |                     $( | ||||||
|  | @ -491,7 +507,6 @@ macro_rules! register_assoc_item_ast_id { | ||||||
|                             let name = $name_callback(node); |                             let name = $name_callback(node); | ||||||
|                             let name = name.as_ref().map_or("", |it| it.text_non_mutable()); |                             let name = name.as_ref().map_or("", |it| it.text_non_mutable()); | ||||||
|                             let properties = ErasedHasNameFileAstId { |                             let properties = ErasedHasNameFileAstId { | ||||||
|                                 kind, |  | ||||||
|                                 name, |                                 name, | ||||||
|                             }; |                             }; | ||||||
|                             let result = ErasedAssocItemFileAstId { |                             let result = ErasedAssocItemFileAstId { | ||||||
|  | @ -506,8 +521,7 @@ macro_rules! register_assoc_item_ast_id { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         fn should_alloc_assoc_item(node: &SyntaxNode) -> bool { |         fn should_alloc_assoc_item(kind: SyntaxKind) -> bool { | ||||||
|             let kind = node.kind(); |  | ||||||
|             false $( || ast::$ident::can_cast(kind) )* |             false $( || ast::$ident::can_cast(kind) )* | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -158,6 +158,7 @@ Item = | ||||||
| | TypeAlias | | TypeAlias | ||||||
| | Union | | Union | ||||||
| | Use | | Use | ||||||
|  | | AsmExpr | ||||||
| 
 | 
 | ||||||
| MacroRules = | MacroRules = | ||||||
|   Attr* Visibility? |   Attr* Visibility? | ||||||
|  | @ -409,7 +410,8 @@ OffsetOfExpr = | ||||||
| // global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")" | // global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")" | ||||||
| // format_string := STRING_LITERAL / RAW_STRING_LITERAL | // format_string := STRING_LITERAL / RAW_STRING_LITERAL | ||||||
| AsmExpr = | AsmExpr = | ||||||
|   Attr* 'builtin' '#' 'asm' '(' template:(Expr (',' Expr)*) (AsmPiece (',' AsmPiece)*)? ','? ')' |   Attr* 'builtin' '#' ( 'asm' | 'global_asm' | 'naked_asm' ) | ||||||
|  |   '(' template:(Expr (',' Expr)*) (AsmPiece (',' AsmPiece)*)? ','? ')' | ||||||
| 
 | 
 | ||||||
| // operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" | // operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" | ||||||
| AsmOperandExpr = in_expr:Expr ('=>' out_expr:Expr)? | AsmOperandExpr = in_expr:Expr ('=>' out_expr:Expr)? | ||||||
|  |  | ||||||
|  | @ -118,6 +118,14 @@ impl AsmExpr { | ||||||
|     pub fn asm_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![asm]) } |     pub fn asm_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![asm]) } | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) } |     pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) } | ||||||
|  |     #[inline] | ||||||
|  |     pub fn global_asm_token(&self) -> Option<SyntaxToken> { | ||||||
|  |         support::token(&self.syntax, T![global_asm]) | ||||||
|  |     } | ||||||
|  |     #[inline] | ||||||
|  |     pub fn naked_asm_token(&self) -> Option<SyntaxToken> { | ||||||
|  |         support::token(&self.syntax, T![naked_asm]) | ||||||
|  |     } | ||||||
| } | } | ||||||
| pub struct AsmLabel { | pub struct AsmLabel { | ||||||
|     pub(crate) syntax: SyntaxNode, |     pub(crate) syntax: SyntaxNode, | ||||||
|  | @ -2087,6 +2095,7 @@ impl ast::HasAttrs for GenericParam {} | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, PartialEq, Eq, Hash)] | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||||||
| pub enum Item { | pub enum Item { | ||||||
|  |     AsmExpr(AsmExpr), | ||||||
|     Const(Const), |     Const(Const), | ||||||
|     Enum(Enum), |     Enum(Enum), | ||||||
|     ExternBlock(ExternBlock), |     ExternBlock(ExternBlock), | ||||||
|  | @ -2106,7 +2115,6 @@ pub enum Item { | ||||||
|     Use(Use), |     Use(Use), | ||||||
| } | } | ||||||
| impl ast::HasAttrs for Item {} | impl ast::HasAttrs for Item {} | ||||||
| impl ast::HasDocComments for Item {} |  | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, PartialEq, Eq, Hash)] | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||||||
| pub enum Pat { | pub enum Pat { | ||||||
|  | @ -8409,6 +8417,10 @@ impl AstNode for GenericParam { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | impl From<AsmExpr> for Item { | ||||||
|  |     #[inline] | ||||||
|  |     fn from(node: AsmExpr) -> Item { Item::AsmExpr(node) } | ||||||
|  | } | ||||||
| impl From<Const> for Item { | impl From<Const> for Item { | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn from(node: Const) -> Item { Item::Const(node) } |     fn from(node: Const) -> Item { Item::Const(node) } | ||||||
|  | @ -8482,7 +8494,8 @@ impl AstNode for Item { | ||||||
|     fn can_cast(kind: SyntaxKind) -> bool { |     fn can_cast(kind: SyntaxKind) -> bool { | ||||||
|         matches!( |         matches!( | ||||||
|             kind, |             kind, | ||||||
|             CONST |             ASM_EXPR | ||||||
|  |                 | CONST | ||||||
|                 | ENUM |                 | ENUM | ||||||
|                 | EXTERN_BLOCK |                 | EXTERN_BLOCK | ||||||
|                 | EXTERN_CRATE |                 | EXTERN_CRATE | ||||||
|  | @ -8504,6 +8517,7 @@ impl AstNode for Item { | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn cast(syntax: SyntaxNode) -> Option<Self> { |     fn cast(syntax: SyntaxNode) -> Option<Self> { | ||||||
|         let res = match syntax.kind() { |         let res = match syntax.kind() { | ||||||
|  |             ASM_EXPR => Item::AsmExpr(AsmExpr { syntax }), | ||||||
|             CONST => Item::Const(Const { syntax }), |             CONST => Item::Const(Const { syntax }), | ||||||
|             ENUM => Item::Enum(Enum { syntax }), |             ENUM => Item::Enum(Enum { syntax }), | ||||||
|             EXTERN_BLOCK => Item::ExternBlock(ExternBlock { syntax }), |             EXTERN_BLOCK => Item::ExternBlock(ExternBlock { syntax }), | ||||||
|  | @ -8528,6 +8542,7 @@ impl AstNode for Item { | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn syntax(&self) -> &SyntaxNode { |     fn syntax(&self) -> &SyntaxNode { | ||||||
|         match self { |         match self { | ||||||
|  |             Item::AsmExpr(it) => &it.syntax, | ||||||
|             Item::Const(it) => &it.syntax, |             Item::Const(it) => &it.syntax, | ||||||
|             Item::Enum(it) => &it.syntax, |             Item::Enum(it) => &it.syntax, | ||||||
|             Item::ExternBlock(it) => &it.syntax, |             Item::ExternBlock(it) => &it.syntax, | ||||||
|  |  | ||||||
|  | @ -116,6 +116,8 @@ const CONTEXTUAL_KEYWORDS: &[&str] = | ||||||
| // keywords we use for special macro expansions
 | // keywords we use for special macro expansions
 | ||||||
| const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &[ | const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &[ | ||||||
|     "asm", |     "asm", | ||||||
|  |     "naked_asm", | ||||||
|  |     "global_asm", | ||||||
|     "att_syntax", |     "att_syntax", | ||||||
|     "builtin", |     "builtin", | ||||||
|     "clobber_abi", |     "clobber_abi", | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Shoyu Vanilla (Flint)
						Shoyu Vanilla (Flint)