Make global_asm!() work

Because apparently, we were not accepting inline asm in item position, completely breaking it.
This commit is contained in:
Chayim Refael Friedman 2025-07-09 18:55:27 +03:00
parent bd8087e86e
commit 95c04c4503
13 changed files with 58 additions and 36 deletions

View File

@ -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);

View File

@ -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() {

View File

@ -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,

View File

@ -1441,9 +1441,11 @@ fn scope_for(
) -> Option<ScopeId> {
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())

View File

@ -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)]

View File

@ -328,7 +328,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
// 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.expect(T!['(']);
if expr(p).is_none() {
p.err_and_bump("expected asm template");

View File

@ -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(())

View File

@ -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");
}

View File

@ -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

View 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"

View File

@ -0,0 +1 @@
builtin#global_asm("")

View File

@ -158,6 +158,7 @@ Item =
| TypeAlias
| Union
| Use
| AsmExpr
MacroRules =
Attr* Visibility?

View File

@ -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<AsmExpr> for Item {
#[inline]
fn from(node: AsmExpr) -> Item { Item::AsmExpr(node) }
}
impl From<Const> 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<Self> {
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,