about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-09-12 08:16:49 +0200
committerLukas Wirth <lukastw97@gmail.com>2024-09-12 08:16:49 +0200
commit4361c1ba6789f59d6ec2156fb9e052fb5f6dd054 (patch)
tree11fa38ab8f64a60ada86bc304e066e11e79ec2db
parent91e9cd302127763e4341d204fc6ec10adcce9adb (diff)
downloadrust-4361c1ba6789f59d6ec2156fb9e052fb5f6dd054.tar.gz
rust-4361c1ba6789f59d6ec2156fb9e052fb5f6dd054.zip
fix: Don't report typed hole error in asm! out ops
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs77
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs22
2 files changed, 70 insertions, 29 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs
index 448bc2f033f..4213370ac19 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
index b5c242e1e9f..6994a7ed146 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/src/tools/rust-analyzer/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
+}"#,
+        );
+    }
 }