fix: Don't report typed hole error in asm! out ops

This commit is contained in:
Lukas Wirth 2024-09-12 08:16:49 +02:00
parent 77e1969c15
commit 6daa6d59f3
2 changed files with 70 additions and 29 deletions

View file

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

View file

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