Skip to content

Commit 7d4d872

Browse files
committed
Ensure asm noreturn works with labels
1 parent f367ceb commit 7d4d872

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
@@ -3211,6 +3211,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32113211
}
32123212

32133213
fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
3214+
let ret_ty = if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
3215+
self.tcx.types.never
3216+
} else {
3217+
Ty::new_unit(self.tcx)
3218+
};
3219+
32143220
for (op, _op_sp) in asm.operands {
32153221
match op {
32163222
hir::InlineAsmOperand::In { expr, .. } => {
@@ -3233,15 +3239,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32333239
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
32343240
hir::InlineAsmOperand::SymStatic { .. } => {}
32353241
hir::InlineAsmOperand::Label { block } => {
3236-
self.check_block_no_value(block);
3242+
let diverges = self.diverges.get();
3243+
3244+
// The label blocks should have unit return value, expect when the assembly
3245+
// itself is noreturn, in which case the label blocks also become noreturn.
3246+
let ty = self.check_block_with_expected(block, ExpectHasType(ret_ty));
3247+
if !ty.is_never() {
3248+
self.demand_suptype(block.span, ret_ty, ty);
3249+
}
3250+
3251+
// We need this to avoid false unreachable warning when a label diverges.
3252+
self.diverges.set(diverges);
32373253
}
32383254
}
32393255
}
3240-
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
3241-
self.tcx.types.never
3242-
} else {
3243-
Ty::new_unit(self.tcx)
3244-
}
3256+
3257+
ret_ty
32453258
}
32463259

32473260
fn check_offset_of(

0 commit comments

Comments
 (0)