@@ -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