Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imported variadic functions passed to procedural macros incorrectly #58853

Closed
alexcrichton opened this issue Mar 1, 2019 · 5 comments
Closed
Labels
regression-from-stable-to-nightly Performance or correctness regression from stable to nightly.

Comments

@alexcrichton
Copy link
Member

alexcrichton commented Mar 1, 2019

In the most recent nightly (I think #57760 was likely the cause), some input to a macro like this:

#[foo]              
extern "C" {                 
    pub fn foo3(x: i32, ...);
}                            

will actually pass the following as input to the macro:

extern "C" {                      
    pub fn foo3(x: i32, ..., ...);
}                                 

which then fails to parse in libraries like syn!

@alexcrichton alexcrichton added the regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. label Mar 1, 2019
alexcrichton added a commit to rustwasm/wasm-bindgen that referenced this issue Mar 1, 2019
@dlrobertson
Copy link
Contributor

@alexcrichton I'll start looking into this ASAP

@dlrobertson
Copy link
Contributor

dlrobertson commented Mar 1, 2019

FWIW the cause of the extra ... is because we have to "spoof" the VaList in C-variadic functions, so instead of merely setting the variadic member of the FnDecl and FnSig we add an argument of the type CVarArgs to the signature (which when printed is ...). So I'm betting I missed a chunk of code that tacks on a , ... when variadic is set.

@dlrobertson
Copy link
Contributor

dlrobertson commented Mar 1, 2019

@alexcrichton

which then fails to parse in libraries like syn!

When adding the following to syns dev/main.rs

extern "C" {
    pub fn foo(x: i32, ...);
}

I get the following

File {
    shebang: None,
    attrs: [],
    items: [
        ForeignMod(
            ItemForeignMod {
                attrs: [],
                abi: Abi {
                    extern_token: Extern,
                    name: Some(
                        LitStr {
                            token: Literal { lit: Str_(C), suffix: None, span: Span { lo: BytePos(101), hi: BytePos(104), ctxt: #0 } }
                        }
                    )
                },
                brace_token: Brace,
                items: [
                    Fn(
                        ForeignItemFn {
                            attrs: [],
                            vis: Public(
                                VisPublic {
                                    pub_token: Pub
                                }
                            ),
                            ident: Ident {
                                ident: "foo3",
                                span: #0 bytes(122..126)
                            },
                            decl: FnDecl {
                                fn_token: Fn,
                                generics: Generics {
                                    lt_token: None,
                                    params: [],
                                    gt_token: None,
                                    where_clause: None
                                },
                                paren_token: Paren,
                                inputs: [
                                    Captured(
                                        ArgCaptured {
                                            pat: Ident(
                                                PatIdent {
                                                    by_ref: None,
                                                    mutability: None,
                                                    ident: Ident {
                                                        ident: "x",
                                                        span: #0 bytes(127..128)
                                                    },
                                                    subpat: None
                                                }
                                            ),
                                            colon_token: Colon,
                                            ty: Path(
                                                TypePath {
                                                    qself: None,
                                                    path: Path {
                                                        leading_colon: None,
                                                        segments: [
                                                            PathSegment {
                                                                ident: Ident {
                                                                    ident: "i32",
                                                                    span: #0 bytes(130..133)
                                                                },
                                                                arguments: None
                                                            }
                                                        ]
                                                    }
                                                }
                                            )
                                        }
                                    ),
                                    Comma
                                ],
                                variadic: Some(
                                    Dot3
                                ),
                                output: Default
                            },
                            semi_token: Semi
                        }
                    )
                ]
            }
        )
    ]
}

Which looks correct. Am I missing something?

@alexcrichton
Copy link
Member Author

@dlrobertson oh I think you may be triggering syn's string parsing code, to see this in action you can use this gist, where after cloning and executing cargo build you'll see:

$ cargo +nightly build
   Compiling foo v0.1.0 (/home/alex/code/foo)
attr:
input: extern "C" {
    fn foo(x: i32, ..., ...);
}
warning: foreign function is never used: `foo`
 --> main.rs:3:5
  |
3 |     fn foo(x: i32, ...);
  |     ^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(dead_code)] on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.21s

@dlrobertson
Copy link
Contributor

@alexcrichton Thanks for the example! I'm pretty sure the offending code is src/libsyntax/print/pprust.rs:2817-2819. My PR should have cut that chunk.

Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Mar 2, 2019
Fix C-variadic function printing

There is no longer a need to append the string `", ..."` to a functions
args as `...` is parsed as an argument and will appear in the functions
arguments.

r? @alexreg
cc @alexcrichton
Fixes: rust-lang#58853
kennytm added a commit to kennytm/rust that referenced this issue Mar 3, 2019
Fix C-variadic function printing

There is no longer a need to append the string `", ..."` to a functions
args as `...` is parsed as an argument and will appear in the functions
arguments.

Fixes: rust-lang#58853
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
regression-from-stable-to-nightly Performance or correctness regression from stable to nightly.
Projects
None yet
Development

No branches or pull requests

2 participants