Ensure asm noreturn works with labels
This commit is contained in:
parent
5e4fd6bc23
commit
5e4e3d790b
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user