diff --git a/crates/hir-def/src/body/lower/asm.rs b/crates/hir-def/src/body/lower/asm.rs index 448bc2f033..4213370ac1 100644 --- a/crates/hir-def/src/body/lower/asm.rs +++ b/crates/hir-def/src/body/lower/asm.rs @@ -87,45 +87,64 @@ impl ExprCollector<'_> { ); AsmOperand::In { reg, expr } } else if dir_spec.out_token().is_some() { - let expr = self.collect_expr_opt( - op.asm_operand_expr().and_then(|it| it.in_expr()), - ); - AsmOperand::Out { reg, expr: Some(expr), late: false } + let expr = op + .asm_operand_expr() + .and_then(|it| it.in_expr()) + .filter(|it| !matches!(it, ast::Expr::UnderscoreExpr(_))) + .map(|expr| self.collect_expr(expr)); + AsmOperand::Out { reg, expr, late: false } } else if dir_spec.lateout_token().is_some() { - let expr = self.collect_expr_opt( - op.asm_operand_expr().and_then(|it| it.in_expr()), - ); - AsmOperand::Out { reg, expr: Some(expr), late: true } + let expr = op + .asm_operand_expr() + .and_then(|it| it.in_expr()) + .filter(|it| !matches!(it, ast::Expr::UnderscoreExpr(_))) + .map(|expr| self.collect_expr(expr)); + + AsmOperand::Out { reg, expr, late: true } } else if dir_spec.inout_token().is_some() { let Some(op_expr) = op.asm_operand_expr() else { continue }; let in_expr = self.collect_expr_opt(op_expr.in_expr()); - let out_expr = - op_expr.out_expr().map(|it| self.collect_expr(it)); - match out_expr { - Some(out_expr) => AsmOperand::SplitInOut { - reg, - in_expr, - out_expr: Some(out_expr), - late: false, - }, - None => { + match op_expr.fat_arrow_token().is_some() { + true => { + let out_expr = op_expr + .out_expr() + .filter(|it| { + !matches!(it, ast::Expr::UnderscoreExpr(_)) + }) + .map(|expr| self.collect_expr(expr)); + + AsmOperand::SplitInOut { + reg, + in_expr, + out_expr, + late: false, + } + } + false => { AsmOperand::InOut { reg, expr: in_expr, late: false } } } } else if dir_spec.inlateout_token().is_some() { let Some(op_expr) = op.asm_operand_expr() else { continue }; let in_expr = self.collect_expr_opt(op_expr.in_expr()); - let out_expr = - op_expr.out_expr().map(|it| self.collect_expr(it)); - match out_expr { - Some(out_expr) => AsmOperand::SplitInOut { - reg, - in_expr, - out_expr: Some(out_expr), - late: false, - }, - None => { - AsmOperand::InOut { reg, expr: in_expr, late: false } + match op_expr.fat_arrow_token().is_some() { + true => { + let out_expr = op_expr + .out_expr() + .filter(|it| { + !matches!(it, ast::Expr::UnderscoreExpr(_)) + }) + .map(|expr| self.collect_expr(expr)); + + AsmOperand::SplitInOut { + reg, + in_expr, + out_expr, + late: true, + } + } + false => { + AsmOperand::InOut { reg, expr: in_expr, late: true } } } } else { diff --git a/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs index b5c242e1e9..6994a7ed14 100644 --- a/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -402,4 +402,26 @@ fn f() { ], ); } + + #[test] + fn underscore_in_asm() { + check_diagnostics( + r#" +//- minicore: asm +fn rdtscp() -> u64 { + let hi: u64; + let lo: u64; + unsafe { + core::arch::asm!( + "rdtscp", + out("rdx") hi, + out("rax") lo, + out("rcx") _, + options(nomem, nostack, preserves_flags) + ); + } + (hi << 32) | lo +}"#, + ); + } }