From 95c04c450388dbf859d87f3e07e71784ff42c4c6 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 9 Jul 2025 18:55:27 +0300 Subject: [PATCH] Make `global_asm!()` work Because apparently, we were not accepting inline asm in item position, completely breaking it. --- crates/hir-def/src/item_tree/lower.rs | 2 ++ .../macro_expansion_tests/builtin_fn_macro.rs | 12 ++++-------- crates/hir-def/src/resolver.rs | 11 ----------- crates/hir/src/source_analyzer.rs | 8 +++++--- crates/parser/src/grammar/expressions.rs | 2 +- crates/parser/src/grammar/expressions/atom.rs | 2 +- crates/parser/src/grammar/items.rs | 13 +++++++++++++ crates/parser/test_data/generated/runner.rs | 2 ++ .../test_data/parser/inline/ok/asm_kinds.rast | 19 +++++++++---------- .../parser/inline/ok/global_asm.rast | 10 ++++++++++ .../test_data/parser/inline/ok/global_asm.rs | 1 + crates/syntax/rust.ungram | 1 + crates/syntax/src/ast/generated/nodes.rs | 11 +++++++++-- 13 files changed, 58 insertions(+), 36 deletions(-) create mode 100644 crates/parser/test_data/parser/inline/ok/global_asm.rast create mode 100644 crates/parser/test_data/parser/inline/ok/global_asm.rs diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index f327366715..5ab61c8939 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -143,6 +143,8 @@ impl<'a> Ctx<'a> { ast::Item::MacroRules(ast) => self.lower_macro_rules(ast)?.into(), ast::Item::MacroDef(ast) => self.lower_macro_def(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()); self.add_attrs(mod_item.ast_id(), attrs); diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index a48a6be4d8..1c3af47d52 100644 --- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -33,10 +33,9 @@ macro_rules! global_asm {() => {}} #[rustc_builtin_macro] macro_rules! naked_asm {() => {}} -// FIXME: This creates an error -// global_asm! { -// "" -// } +global_asm! { + "" +} #[unsafe(naked)] extern "C" fn foo() { @@ -64,10 +63,7 @@ macro_rules! global_asm {() => {}} #[rustc_builtin_macro] macro_rules! naked_asm {() => {}} -// FIXME: This creates an error -// global_asm! { -// "" -// } +builtin #global_asm ("") #[unsafe(naked)] extern "C" fn foo() { diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 6f321980af..316ad5dae6 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -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( db: &dyn DefDatabase, owner: DefWithBodyId, diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index cbd472f87a..536d3851e4 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1441,9 +1441,11 @@ fn scope_for( ) -> Option { node.ancestors_with_macros(db) .take_while(|it| { - !ast::Item::can_cast(it.kind()) - || ast::MacroCall::can_cast(it.kind()) - || ast::Use::can_cast(it.kind()) + let kind = it.kind(); + !ast::Item::can_cast(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| source_map.node_expr(it.as_ref())?.as_expr()) diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index 0ac25da329..2b4151e3b7 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs @@ -4,7 +4,7 @@ use crate::grammar::attributes::ATTRIBUTE_FIRST; 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}; #[derive(PartialEq, Eq)] diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index b81a026173..a01021a9f7 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs @@ -328,7 +328,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option { // tmp = out(reg) _, // ); // } -fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { +pub(crate) fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { p.expect(T!['(']); if expr(p).is_none() { p.err_and_bump("expected asm template"); diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs index b9f4866574..8e551b0b96 100644 --- a/crates/parser/src/grammar/items.rs +++ b/crates/parser/src/grammar/items.rs @@ -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![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), }; Ok(()) diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs index 8053d0b22d..cef7b0ee23 100644 --- a/crates/parser/test_data/generated/runner.rs +++ b/crates/parser/test_data/generated/runner.rs @@ -300,6 +300,8 @@ mod ok { run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_list.rs"); } #[test] + fn global_asm() { run_and_expect_no_errors("test_data/parser/inline/ok/global_asm.rs"); } + #[test] fn half_open_range_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/half_open_range_pat.rs"); } diff --git a/crates/parser/test_data/parser/inline/ok/asm_kinds.rast b/crates/parser/test_data/parser/inline/ok/asm_kinds.rast index fbf95d15f2..c337d89aa5 100644 --- a/crates/parser/test_data/parser/inline/ok/asm_kinds.rast +++ b/crates/parser/test_data/parser/inline/ok/asm_kinds.rast @@ -23,16 +23,15 @@ SOURCE_FILE R_PAREN ")" SEMICOLON ";" WHITESPACE "\n " - EXPR_STMT - ASM_EXPR - BUILTIN_KW "builtin" - POUND "#" - GLOBAL_ASM_KW "global_asm" - L_PAREN "(" - LITERAL - STRING "\"\"" - R_PAREN ")" - SEMICOLON ";" + ASM_EXPR + BUILTIN_KW "builtin" + POUND "#" + GLOBAL_ASM_KW "global_asm" + L_PAREN "(" + LITERAL + STRING "\"\"" + R_PAREN ")" + SEMICOLON ";" WHITESPACE "\n " EXPR_STMT ASM_EXPR diff --git a/crates/parser/test_data/parser/inline/ok/global_asm.rast b/crates/parser/test_data/parser/inline/ok/global_asm.rast new file mode 100644 index 0000000000..5337c56be1 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/global_asm.rast @@ -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" diff --git a/crates/parser/test_data/parser/inline/ok/global_asm.rs b/crates/parser/test_data/parser/inline/ok/global_asm.rs new file mode 100644 index 0000000000..967ce1f5fd --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/global_asm.rs @@ -0,0 +1 @@ +builtin#global_asm("") diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 88ecbb0ef0..4cbc88cfb5 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -158,6 +158,7 @@ Item = | TypeAlias | Union | Use +| AsmExpr MacroRules = Attr* Visibility? diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index e1e331d653..2b86246542 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -2095,6 +2095,7 @@ impl ast::HasAttrs for GenericParam {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Item { + AsmExpr(AsmExpr), Const(Const), Enum(Enum), ExternBlock(ExternBlock), @@ -2114,7 +2115,6 @@ pub enum Item { Use(Use), } impl ast::HasAttrs for Item {} -impl ast::HasDocComments for Item {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Pat { @@ -8417,6 +8417,10 @@ impl AstNode for GenericParam { } } } +impl From for Item { + #[inline] + fn from(node: AsmExpr) -> Item { Item::AsmExpr(node) } +} impl From for Item { #[inline] fn from(node: Const) -> Item { Item::Const(node) } @@ -8490,7 +8494,8 @@ impl AstNode for Item { fn can_cast(kind: SyntaxKind) -> bool { matches!( kind, - CONST + ASM_EXPR + | CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE @@ -8512,6 +8517,7 @@ impl AstNode for Item { #[inline] fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { + ASM_EXPR => Item::AsmExpr(AsmExpr { syntax }), CONST => Item::Const(Const { syntax }), ENUM => Item::Enum(Enum { syntax }), EXTERN_BLOCK => Item::ExternBlock(ExternBlock { syntax }), @@ -8536,6 +8542,7 @@ impl AstNode for Item { #[inline] fn syntax(&self) -> &SyntaxNode { match self { + Item::AsmExpr(it) => &it.syntax, Item::Const(it) => &it.syntax, Item::Enum(it) => &it.syntax, Item::ExternBlock(it) => &it.syntax,