@@ -665,46 +665,73 @@ impl<'a> AstValidator<'a> {
665
665
/// - Non-const
666
666
/// - Either foreign, or free and `unsafe extern "C"` semantically
667
667
fn check_c_variadic_type ( & self , fk : FnKind < ' a > ) {
668
- let variadic_spans: Vec < _ > = fk
669
- . decl ( )
670
- . inputs
671
- . iter ( )
672
- . filter ( |arg| matches ! ( arg. ty. kind, TyKind :: CVarArgs ) )
673
- . map ( |arg| arg. span )
674
- . collect ( ) ;
668
+ let variadic_params: Vec < _ > =
669
+ fk. decl ( ) . inputs . iter ( ) . filter ( |arg| matches ! ( arg. ty. kind, TyKind :: CVarArgs ) ) . collect ( ) ;
675
670
676
- if variadic_spans. is_empty ( ) {
671
+ // The parser already rejects `...` if it's not the final argument, but we still want to
672
+ // emit the errors below, so we only consider the final `...` here.
673
+ let Some ( variadic_param) = variadic_params. last ( ) else {
677
674
return ;
678
- }
675
+ } ;
679
676
680
- if let Some ( header) = fk. header ( )
681
- && let Const :: Yes ( const_span) = header. constness
682
- {
683
- let mut spans = variadic_spans. clone ( ) ;
684
- spans. push ( const_span) ;
677
+ let FnKind :: Fn ( fn_ctxt, _, Fn { sig, .. } ) = fk else {
678
+ // Unreachable because the parser already rejects `...` in closures.
679
+ unreachable ! ( "C variable argument list cannot be used in closures" )
680
+ } ;
681
+
682
+ // C-variadics are not yet implemented in const evaluation.
683
+ if let Const :: Yes ( const_span) = sig. header . constness {
685
684
self . dcx ( ) . emit_err ( errors:: ConstAndCVariadic {
686
- spans ,
685
+ span : const_span . to ( variadic_param . span ) ,
687
686
const_span,
688
- variadic_spans : variadic_spans . clone ( ) ,
687
+ variadic_span : variadic_param . span ,
689
688
} ) ;
690
689
}
691
690
692
- match ( fk. ctxt ( ) , fk. header ( ) ) {
693
- ( Some ( FnCtxt :: Foreign ) , _) => return ,
694
- ( Some ( FnCtxt :: Free ) , Some ( header) ) => match header. ext {
695
- Extern :: Explicit ( StrLit { symbol_unescaped : sym:: C , .. } , _)
696
- | Extern :: Explicit ( StrLit { symbol_unescaped : sym:: C_dash_unwind , .. } , _)
697
- | Extern :: Implicit ( _)
698
- if matches ! ( header. safety, Safety :: Unsafe ( _) ) =>
699
- {
700
- return ;
701
- }
702
- _ => { }
703
- } ,
704
- _ => { }
705
- } ;
691
+ if let Some ( coroutine_kind) = sig. header . coroutine_kind {
692
+ self . dcx ( ) . emit_err ( errors:: CoroutineAndCVariadic {
693
+ span : coroutine_kind. span ( ) . to ( variadic_param. span ) ,
694
+ coroutine_kind : coroutine_kind. as_str ( ) ,
695
+ coroutine_span : coroutine_kind. span ( ) ,
696
+ variadic_span : variadic_param. span ,
697
+ } ) ;
698
+ }
706
699
707
- self . dcx ( ) . emit_err ( errors:: BadCVariadic { span : variadic_spans } ) ;
700
+ match fn_ctxt {
701
+ FnCtxt :: Free => {
702
+ match sig. header . ext {
703
+ Extern :: Implicit ( _) => { /* defaults to "C" */ }
704
+ Extern :: Explicit ( StrLit { symbol_unescaped, .. } , _) => {
705
+ if !matches ! ( symbol_unescaped, sym:: C | sym:: C_dash_unwind ) {
706
+ self . dcx ( ) . emit_err ( errors:: CVariadicBadExtern {
707
+ span : variadic_param. span ,
708
+ abi : symbol_unescaped,
709
+ extern_span : sig. extern_span ( ) ,
710
+ } ) ;
711
+ }
712
+ }
713
+ Extern :: None => {
714
+ self . dcx ( )
715
+ . emit_err ( errors:: CVariadicNoExtern { span : variadic_param. span } ) ;
716
+ }
717
+ } ;
718
+
719
+ if !matches ! ( sig. header. safety, Safety :: Unsafe ( _) ) {
720
+ self . dcx ( ) . emit_err ( errors:: CVariadicMustBeUnsafe {
721
+ span : variadic_param. span ,
722
+ unsafe_span : sig. safety_span ( ) ,
723
+ } ) ;
724
+ }
725
+ }
726
+ FnCtxt :: Assoc ( _) => {
727
+ // For now, C variable argument lists are unsupported in associated functions.
728
+ self . dcx ( )
729
+ . emit_err ( errors:: CVariadicAssociatedFunction { span : variadic_param. span } ) ;
730
+ }
731
+ FnCtxt :: Foreign => {
732
+ // Whether the ABI supports C variable argument lists is checked later.
733
+ }
734
+ }
708
735
}
709
736
710
737
fn check_item_named ( & self , ident : Ident , kind : & str ) {
0 commit comments