Change:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --<!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Somewhere during compilation of this code, LLVM's ). Because of that, rustccodegenllvm::asm::inlineasmcall , and the parent function then .
I a statement to log the function type and constraints string passed to LLVM:
claim

Discussion:
reg: InlineAsmRegOrRegClass, expr: &hir::Expr<'tcx>, template: &[InlineAsmTemplatePiece], <ins> is_input: bool, </ins> tied_input: Option<(&hir::Expr<'tcx>, Option<InlineAsmType>)>, ) -> Option<InlineAsmType> { // Check the type against the allowed types for inline asm.

_ => unreachable!(), }; let asm_ty = match *ty.kind() { <del> ty::Never | ty::Error(_) => return None, </del> <ins> // `!` is allowed for input but not for output (issue #87802) ty::Never if is_input => return None, ty::Error(_) => return None, </ins> ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8), ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16), ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),

for (idx, (op, _)) in asm.operands.iter().enumerate() { match *op { hir::InlineAsmOperand::In { reg, ref expr } => { <del> self.check_asm_operand_type(idx, reg, expr, asm.template, None); </del> <ins> self.check_asm_operand_type(idx, reg, expr, asm.template, true, None); </ins> } hir::InlineAsmOperand::Out { reg, late: _, ref expr } => { if let Some(expr) = expr { <del> self.check_asm_operand_type(idx, reg, expr, asm.template, None); </del> <ins> self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); </ins> } } hir::InlineAsmOperand::InOut { reg, late: _, ref expr } => { <del> self.check_asm_operand_type(idx, reg, expr, asm.template, None); </del> <ins> self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); </ins> } hir::InlineAsmOperand::SplitInOut { reg, late: _, ref in_expr, ref out_expr } => { <del> let in_ty = self.check_asm_operand_type(idx, reg, in_expr, asm.template, None); </del> <ins> let in_ty = self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None); </ins> if let Some(out_expr) = out_expr { self.check_asm_operand_type( idx, reg, out_expr, asm.template, <ins> false, </ins> Some((in_expr, in_ty)), ); }

<ins> // only-x86_64 // Make sure rustc doesn't ICE on asm! when output type is !. #![feature(asm)] fn hmm() -> ! { let x; unsafe { asm!("/* {0} */", out(reg) x); //~^ ERROR cannot use value of type `!` for inline assembly } x } fn main() { hmm(); } </ins>

<ins> error: cannot use value of type `!` for inline assembly --> $DIR/issue-87802.rs:9:36 | LL |         asm!("/* {0} */", out(reg) x); |                                    ^ | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: aborting due to previous error </ins>