@@ -628,46 +628,73 @@ impl<'a> AstValidator<'a> {
628
628
/// - Non-const
629
629
/// - Either foreign, or free and `unsafe extern "C"` semantically
630
630
fn check_c_variadic_type ( & self , fk : FnKind < ' a > ) {
631
- let variadic_spans: Vec < _ > = fk
632
- . decl ( )
633
- . inputs
634
- . iter ( )
635
- . filter ( |arg| matches ! ( arg. ty. kind, TyKind :: CVarArgs ) )
636
- . map ( |arg| arg. span )
637
- . collect ( ) ;
631
+ let variadic_params: Vec < _ > =
632
+ fk. decl ( ) . inputs . iter ( ) . filter ( |arg| matches ! ( arg. ty. kind, TyKind :: CVarArgs ) ) . collect ( ) ;
638
633
639
- if variadic_spans. is_empty ( ) {
634
+ // The parser already rejects `...` if it's not the final argument, but we still want to
635
+ // emit the errors below, so we only consider the final `...` here.
636
+ let Some ( variadic_param) = variadic_params. last ( ) else {
640
637
return ;
641
- }
638
+ } ;
642
639
643
- if let Some ( header) = fk. header ( )
644
- && let Const :: Yes ( const_span) = header. constness
645
- {
646
- let mut spans = variadic_spans. clone ( ) ;
647
- spans. push ( const_span) ;
640
+ let FnKind :: Fn ( fn_ctxt, _, Fn { sig, .. } ) = fk else {
641
+ // Unreachable because the parser already rejects `...` in closures.
642
+ unreachable ! ( "C variable argument list cannot be used in closures" )
643
+ } ;
644
+
645
+ // C-variadics are not yet implemented in const evaluation.
646
+ if let Const :: Yes ( const_span) = sig. header . constness {
648
647
self . dcx ( ) . emit_err ( errors:: ConstAndCVariadic {
649
- spans ,
648
+ span : const_span . to ( variadic_param . span ) ,
650
649
const_span,
651
- variadic_spans : variadic_spans . clone ( ) ,
650
+ variadic_span : variadic_param . span ,
652
651
} ) ;
653
652
}
654
653
655
- match ( fk. ctxt ( ) , fk. header ( ) ) {
656
- ( Some ( FnCtxt :: Foreign ) , _) => return ,
657
- ( Some ( FnCtxt :: Free ) , Some ( header) ) => match header. ext {
658
- Extern :: Explicit ( StrLit { symbol_unescaped : sym:: C , .. } , _)
659
- | Extern :: Explicit ( StrLit { symbol_unescaped : sym:: C_dash_unwind , .. } , _)
660
- | Extern :: Implicit ( _)
661
- if matches ! ( header. safety, Safety :: Unsafe ( _) ) =>
662
- {
663
- return ;
664
- }
665
- _ => { }
666
- } ,
667
- _ => { }
668
- } ;
654
+ if let Some ( coroutine_kind) = sig. header . coroutine_kind {
655
+ self . dcx ( ) . emit_err ( errors:: CoroutineAndCVariadic {
656
+ span : coroutine_kind. span ( ) . to ( variadic_param. span ) ,
657
+ coroutine_kind : coroutine_kind. as_str ( ) ,
658
+ coroutine_span : coroutine_kind. span ( ) ,
659
+ variadic_span : variadic_param. span ,
660
+ } ) ;
661
+ }
669
662
670
- self . dcx ( ) . emit_err ( errors:: BadCVariadic { span : variadic_spans } ) ;
663
+ match fn_ctxt {
664
+ FnCtxt :: Free => {
665
+ match sig. header . ext {
666
+ Extern :: Implicit ( _) => { /* defaults to "C" */ }
667
+ Extern :: Explicit ( StrLit { symbol_unescaped, .. } , _) => {
668
+ if !matches ! ( symbol_unescaped, sym:: C | sym:: C_dash_unwind ) {
669
+ self . dcx ( ) . emit_err ( errors:: CVariadicBadExtern {
670
+ span : variadic_param. span ,
671
+ abi : symbol_unescaped,
672
+ extern_span : sig. extern_span ( ) ,
673
+ } ) ;
674
+ }
675
+ }
676
+ Extern :: None => {
677
+ self . dcx ( )
678
+ . emit_err ( errors:: CVariadicNoExtern { span : variadic_param. span } ) ;
679
+ }
680
+ } ;
681
+
682
+ if !matches ! ( sig. header. safety, Safety :: Unsafe ( _) ) {
683
+ self . dcx ( ) . emit_err ( errors:: CVariadicMustBeUnsafe {
684
+ span : variadic_param. span ,
685
+ unsafe_span : sig. safety_span ( ) ,
686
+ } ) ;
687
+ }
688
+ }
689
+ FnCtxt :: Assoc ( _) => {
690
+ // For now, C variable argument lists are unsupported in associated functions.
691
+ self . dcx ( )
692
+ . emit_err ( errors:: CVariadicAssociatedFunction { span : variadic_param. span } ) ;
693
+ }
694
+ FnCtxt :: Foreign => {
695
+ // Whether the ABI supports C variable argument lists is checked later.
696
+ }
697
+ }
671
698
}
672
699
673
700
fn check_item_named ( & self , ident : Ident , kind : & str ) {
0 commit comments