Skip to content

Commit 234fe9d

Browse files
committed
Ensure asm noreturn works with labels
1 parent f9faa72 commit 234fe9d

File tree

1 file changed

+16
-6
lines changed
  • compiler/rustc_hir_typeck/src

1 file changed

+16
-6
lines changed

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3222,6 +3222,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32223222
}
32233223

32243224
fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
3225+
let mut diverge = asm.options.contains(ast::InlineAsmOptions::NORETURN);
3226+
32253227
for (op, _op_sp) in asm.operands {
32263228
match op {
32273229
hir::InlineAsmOperand::In { expr, .. } => {
@@ -3244,15 +3246,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32443246
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
32453247
hir::InlineAsmOperand::SymStatic { .. } => {}
32463248
hir::InlineAsmOperand::Label { block } => {
3247-
self.check_block_no_value(block);
3249+
let previous_diverges = self.diverges.get();
3250+
3251+
// The label blocks should have unit return value or diverge.
3252+
let ty =
3253+
self.check_block_with_expected(block, ExpectHasType(self.tcx.types.unit));
3254+
if !ty.is_never() {
3255+
self.demand_suptype(block.span, self.tcx.types.unit, ty);
3256+
diverge = false;
3257+
}
3258+
3259+
// We need this to avoid false unreachable warning when a label diverges.
3260+
self.diverges.set(previous_diverges);
32483261
}
32493262
}
32503263
}
3251-
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
3252-
self.tcx.types.never
3253-
} else {
3254-
Ty::new_unit(self.tcx)
3255-
}
3264+
3265+
if diverge { self.tcx.types.never } else { self.tcx.types.unit }
32563266
}
32573267

32583268
fn check_offset_of(

0 commit comments

Comments
 (0)