Ensure asm noreturn works with labels

This commit is contained in:
Gary Guo 2023-12-26 04:44:01 +00:00
parent 5e4fd6bc23
commit 5e4e3d790b

View File

@ -3243,6 +3243,8 @@ fn check_expr_asm_operand(&self, expr: &'tcx hir::Expr<'tcx>, is_input: bool) {
}
fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
let mut diverge = asm.options.contains(ast::InlineAsmOptions::NORETURN);
for (op, _op_sp) in asm.operands {
match op {
hir::InlineAsmOperand::In { expr, .. } => {
@ -3265,15 +3267,23 @@ fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
hir::InlineAsmOperand::SymStatic { .. } => {}
hir::InlineAsmOperand::Label { block } => {
self.check_block_no_value(block);
let previous_diverges = self.diverges.get();
// The label blocks should have unit return value or diverge.
let ty =
self.check_block_with_expected(block, ExpectHasType(self.tcx.types.unit));
if !ty.is_never() {
self.demand_suptype(block.span, self.tcx.types.unit, ty);
diverge = false;
}
// We need this to avoid false unreachable warning when a label diverges.
self.diverges.set(previous_diverges);
}
}
}
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
self.tcx.types.never
} else {
Ty::new_unit(self.tcx)
}
if diverge { self.tcx.types.never } else { self.tcx.types.unit }
}
fn check_offset_of(