@@ -139,6 +139,7 @@ impl ExprVisitor<'tcx> {
139139 reg : InlineAsmRegOrRegClass ,
140140 expr : & hir:: Expr < ' tcx > ,
141141 template : & [ InlineAsmTemplatePiece ] ,
142+ is_input : bool ,
142143 tied_input : Option < ( & hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
143144 ) -> Option < InlineAsmType > {
144145 // Check the type against the allowed types for inline asm.
@@ -150,7 +151,9 @@ impl ExprVisitor<'tcx> {
150151 _ => unreachable ! ( ) ,
151152 } ;
152153 let asm_ty = match * ty. kind ( ) {
153- ty:: Never | ty:: Error ( _) => return None ,
154+ // `!` is allowed for input but not for output (issue #87802)
155+ ty:: Never if is_input => return None ,
156+ ty:: Error ( _) => return None ,
154157 ty:: Int ( IntTy :: I8 ) | ty:: Uint ( UintTy :: U8 ) => Some ( InlineAsmType :: I8 ) ,
155158 ty:: Int ( IntTy :: I16 ) | ty:: Uint ( UintTy :: U16 ) => Some ( InlineAsmType :: I16 ) ,
156159 ty:: Int ( IntTy :: I32 ) | ty:: Uint ( UintTy :: U32 ) => Some ( InlineAsmType :: I32 ) ,
@@ -350,24 +353,26 @@ impl ExprVisitor<'tcx> {
350353 for ( idx, ( op, _) ) in asm. operands . iter ( ) . enumerate ( ) {
351354 match * op {
352355 hir:: InlineAsmOperand :: In { reg, ref expr } => {
353- self . check_asm_operand_type ( idx, reg, expr, asm. template , None ) ;
356+ self . check_asm_operand_type ( idx, reg, expr, asm. template , true , None ) ;
354357 }
355358 hir:: InlineAsmOperand :: Out { reg, late : _, ref expr } => {
356359 if let Some ( expr) = expr {
357- self . check_asm_operand_type ( idx, reg, expr, asm. template , None ) ;
360+ self . check_asm_operand_type ( idx, reg, expr, asm. template , false , None ) ;
358361 }
359362 }
360363 hir:: InlineAsmOperand :: InOut { reg, late : _, ref expr } => {
361- self . check_asm_operand_type ( idx, reg, expr, asm. template , None ) ;
364+ self . check_asm_operand_type ( idx, reg, expr, asm. template , false , None ) ;
362365 }
363366 hir:: InlineAsmOperand :: SplitInOut { reg, late : _, ref in_expr, ref out_expr } => {
364- let in_ty = self . check_asm_operand_type ( idx, reg, in_expr, asm. template , None ) ;
367+ let in_ty =
368+ self . check_asm_operand_type ( idx, reg, in_expr, asm. template , true , None ) ;
365369 if let Some ( out_expr) = out_expr {
366370 self . check_asm_operand_type (
367371 idx,
368372 reg,
369373 out_expr,
370374 asm. template ,
375+ false ,
371376 Some ( ( in_expr, in_ty) ) ,
372377 ) ;
373378 }
0 commit comments