Skip to content

Commit 83e4951

Browse files
committed
Ensure asm noreturn works with labels
1 parent e528fd1 commit 83e4951

File tree

1 file changed

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

1 file changed

+19
-6
lines changed

compiler/rustc_hir_typeck/src/expr.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -3222,6 +3222,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32223222
}
32233223

32243224
fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
3225+
let ret_ty = if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
3226+
self.tcx.types.never
3227+
} else {
3228+
Ty::new_unit(self.tcx)
3229+
};
3230+
32253231
for (op, _op_sp) in asm.operands {
32263232
match op {
32273233
hir::InlineAsmOperand::In { expr, .. } => {
@@ -3244,15 +3250,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32443250
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
32453251
hir::InlineAsmOperand::SymStatic { .. } => {}
32463252
hir::InlineAsmOperand::Label { block } => {
3247-
self.check_block_no_value(block);
3253+
let diverges = self.diverges.get();
3254+
3255+
// The label blocks should have unit return value, expect when the assembly
3256+
// itself is noreturn, in which case the label blocks also become noreturn.
3257+
let ty = self.check_block_with_expected(block, ExpectHasType(ret_ty));
3258+
if !ty.is_never() {
3259+
self.demand_suptype(block.span, ret_ty, ty);
3260+
}
3261+
3262+
// We need this to avoid false unreachable warning when a label diverges.
3263+
self.diverges.set(diverges);
32483264
}
32493265
}
32503266
}
3251-
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
3252-
self.tcx.types.never
3253-
} else {
3254-
Ty::new_unit(self.tcx)
3255-
}
3267+
3268+
ret_ty
32563269
}
32573270

32583271
fn check_offset_of(

0 commit comments

Comments
 (0)