Skip to content

Commit 5e4e3d7

Browse files
committed
Ensure asm noreturn works with labels
1 parent 5e4fd6b commit 5e4e3d7

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

+16-6
Original file line numberDiff line numberDiff line change
@@ -3243,6 +3243,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32433243
}
32443244

32453245
fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
3246+
let mut diverge = asm.options.contains(ast::InlineAsmOptions::NORETURN);
3247+
32463248
for (op, _op_sp) in asm.operands {
32473249
match op {
32483250
hir::InlineAsmOperand::In { expr, .. } => {
@@ -3265,15 +3267,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32653267
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
32663268
hir::InlineAsmOperand::SymStatic { .. } => {}
32673269
hir::InlineAsmOperand::Label { block } => {
3268-
self.check_block_no_value(block);
3270+
let previous_diverges = self.diverges.get();
3271+
3272+
// The label blocks should have unit return value or diverge.
3273+
let ty =
3274+
self.check_block_with_expected(block, ExpectHasType(self.tcx.types.unit));
3275+
if !ty.is_never() {
3276+
self.demand_suptype(block.span, self.tcx.types.unit, ty);
3277+
diverge = false;
3278+
}
3279+
3280+
// We need this to avoid false unreachable warning when a label diverges.
3281+
self.diverges.set(previous_diverges);
32693282
}
32703283
}
32713284
}
3272-
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
3273-
self.tcx.types.never
3274-
} else {
3275-
Ty::new_unit(self.tcx)
3276-
}
3285+
3286+
if diverge { self.tcx.types.never } else { self.tcx.types.unit }
32773287
}
32783288

32793289
fn check_offset_of(

0 commit comments

Comments
 (0)