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

Support defining C compatible variadic functions #57760

Merged
merged 7 commits into from
Feb 28, 2019

Conversation

dlrobertson
Copy link
Contributor

@dlrobertson dlrobertson commented Jan 19, 2019

Summary

Add support for defining C compatible variadic functions in unsafe rust with
extern "C" according to RFC 2137.

Details

Parsing

When parsing a user defined function that is unsafe and extern "C" allow
variadic signatures and inject a "spoofed" VaList in the new functions
signature. This allows the user to interact with the variadic arguments via a
VaList instead of manually using va_start and va_end (See RFC 2137 for
details).

Codegen

When running codegen for a variadic function, remove the "spoofed" VaList
from the function signature and inject va_start when the arg local
references are created for the function and va_end on return.

TODO

  • Get feedback on injecting va_start/va_end in MIR vs codegen
  • Properly inject va_end - It seems like it should be possible to inject
    va_end on the TerminatorKind::Return. I just need to figure out how
    to get the LocalRef here.
  • Properly call Rust defined C variadic functions in Rust - The spoofed
    VaList causes problems here.

Related to: #44930

r? @ghost

@dlrobertson
Copy link
Contributor Author

@eddyb @rkruppe @nagisa Thoughts on the codegen would be appreciated.

@joshtriplett Feedback on the API would be appreciated.

@alexreg @oli-obk Thoughts on how I'm currently navigating through MIR would be appreciated.

@rust-highfive

This comment has been minimized.

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:1489bbdc:start=1547926888389172565,finish=1547926961327027666,duration=72937855101
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export IMAGE=x86_64-gnu-llvm-6.0
---
[00:27:26] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" "" "--manifest-path" "/checkout/src/rustc/Cargo.toml" "--message-format" "json"
[00:27:26] expected success, got: exit code: 101
[00:27:26] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap build
[00:27:26] Build completed unsuccessfully in 0:24:01
[00:27:26] Makefile:18: recipe for target 'all' failed
[00:27:26] make: *** [all] Error 1
The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:09b0ef1a
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
Sat Jan 19 20:10:16 UTC 2019
---
travis_time:end:02b9d40c:start=1547928617182321181,finish=1547928617187088232,duration=4767051
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:0766965c
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:29c21bf8
travis_time:start:29c21bf8
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:1d95ab08
$ dmesg | grep -i kill

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

Copy link
Contributor

@alexreg alexreg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this! :-D I think you've essentially taken a sound approach to implementing this feature, though others who are probably more qualified than me will hopefully confirm that. See my suggestions about the codegen from MIR, but otherwise my comments are just nits (really minor things). Feel free to ping me again for a final review, once you've ironed out everything and added more tests. (A brief chapter in the Unstable Book would be nice too.)

src/librustc_codegen_llvm/abi.rs Outdated Show resolved Hide resolved
src/librustc_codegen_llvm/intrinsic.rs Outdated Show resolved Hide resolved
src/librustc_codegen_ssa/mir/block.rs Outdated Show resolved Hide resolved
src/librustc_codegen_ssa/mir/mod.rs Show resolved Hide resolved
src/librustc_target/abi/call/mod.rs Outdated Show resolved Hide resolved
src/libsyntax/parse/parser.rs Outdated Show resolved Hide resolved
src/libsyntax/parse/parser.rs Outdated Show resolved Hide resolved
src/librustc_codegen_ssa/mir/block.rs Outdated Show resolved Hide resolved
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:08968303:start=1548029321522347013,finish=1548029323711145019,duration=2188798006
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export IMAGE=x86_64-gnu-llvm-6.0
---
[00:28:13] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" "" "--manifest-path" "/checkout/src/rustc/Cargo.toml" "--message-format" "json"
[00:28:13] expected success, got: exit code: 101
[00:28:13] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap build
[00:28:13] Build completed unsuccessfully in 0:24:12
[00:28:13] make: *** [all] Error 1
[00:28:13] Makefile:18: recipe for target 'all' failed
The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:104cba2e
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
Mon Jan 21 00:37:06 UTC 2019
---
travis_time:end:091e171c:start=1548031027559960097,finish=1548031027564453221,duration=4493124
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:093cff76
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:18b423c2
travis_time:start:18b423c2
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:13c5bc48
$ dmesg | grep -i kill

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@parched
Copy link
Contributor

parched commented Jan 21, 2019

I noticed some typos I was going to push before I saw this PR, you might just want to take them into this PR instead master...parched:va-args

@dlrobertson
Copy link
Contributor Author

@parched 👍 good catch! I'll merge it in.

@dlrobertson
Copy link
Contributor Author

dlrobertson commented Jan 21, 2019

@parched now that I think about it that will likely solve a aarch64 issue I saw previously, so it might be worth merging as a standalone PR.

@dlrobertson dlrobertson force-pushed the varargs1 branch 2 times, most recently from 9dca909 to 0322ede Compare January 21, 2019 14:51
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:056ec274:start=1548082385573536438,finish=1548082463270471160,duration=77696934722
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export IMAGE=x86_64-gnu-llvm-6.0
---
[00:29:11] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" "" "--manifest-path" "/checkout/src/rustc/Cargo.toml" "--message-format" "json"
[00:29:11] expected success, got: exit code: 101
[00:29:11] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap build
[00:29:11] Build completed unsuccessfully in 0:25:17
[00:29:11] make: *** [all] Error 1
[00:29:11] Makefile:18: recipe for target 'all' failed
The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:065d019a
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
Mon Jan 21 15:23:44 UTC 2019
---
travis_time:end:0ca80c81:start=1548084225293447735,finish=1548084225298890247,duration=5442512
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:0ced8ccf
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:0819f37a
travis_time:start:0819f37a
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:0447d9a4
$ dmesg | grep -i kill

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@dlrobertson
Copy link
Contributor Author

Currently this PR causes an issue with std::process::Command when we try to launch a process. I think it is related to the issue this PR currently creates when calling a C variadic function from Rust.

@dlrobertson
Copy link
Contributor Author

dlrobertson commented Jan 28, 2019

Figured out what is causing the issue with std::process::Command and compiling libc. It is indeed the same problem that occurs when calling C variadic functions from Rust. For example:

When running the following using rustc from this PR.

let fmt_str = CString::new("%d%d\n").unwrap();
printf(fmt_str.as_ptr(), 0, 42);

We currently emit the following LLVM IR:

%11 = invoke i32 (i8*, ...) @printf(i8* %10, i32 42)

When we should emit the following LLVM IR:

%11 = invoke i32 (i8*, ...) @printf(i8* %10, i32 0, i32 42)

So clearly at some point when attempting to remove the "spoofed" VaList we're removing arguments supplied by the user (0 in the case of the above code).

@TimNN TimNN added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 29, 2019
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:136821c9:start=1549035837442556456,finish=1549035971023309935,duration=133580753479
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export IMAGE=x86_64-gnu-llvm-6.0
---
[01:00:07] .................................................................................................... 1000/5358
[01:00:11] iiiii............................................................................................... 1100/5358
[01:00:13] .................................................................................................... 1200/5358
[01:00:16] .................................................................................................... 1300/5358
[01:00:18] ....................................F............................................................... 1400/5358
[01:00:23] ..........................................................................................i......... 1600/5358
[01:00:26] .................................................................i.................................. 1700/5358
[01:00:30] .................................................................................................... 1800/5358
[01:00:30] .................................................................................................... 1800/5358
[01:00:34] ....................................................................F............................... 1900/5358
[01:00:40] .....................i.............................................................................. 2100/5358
[01:00:44] .................................................................................................... 2200/5358
[01:00:48] .................................................................................................... 2300/5358
[01:00:52] .................................................................................................... 2400/5358
---
[01:01:39] ................................................................................ii.................. 3700/5358
[01:01:42] ..................................................................................................i. 3800/5358
[01:01:43] .................................................................................................... 3900/5358
[01:01:45] .......................................................i............................................ 4000/5358
[01:01:48] .........F...............................................FF......................................... 4100/5358
[01:02:02] .................................................................................................... 4300/5358
[01:02:05] .................................................................................................... 4400/5358
[01:02:09] .................................................................................................... 4500/5358
[01:02:13] .........i.......................................................................................... 4600/5358
[01:02:13] .........i.......................................................................................... 4600/5358
[01:02:18] .................................................................................................... 4700/5358
[01:02:21] .................................................................................................... 4800/5358
[01:02:25] .................................................................................................... 4900/5358
[01:02:29] .................................................................................................... 5000/5358
[01:02:32] .................................................................................................... 5100/5358
[01:02:35] .................................................................................................... 5200/5358
[01:02:38] ................................................................F................................i.. 5300/5358
[01:02:39] failures:
[01:02:39] 
[01:02:39] ---- [ui] ui/error-codes/E0617.rs stdout ----
[01:02:39] diff of stderr:
[01:02:39] diff of stderr:
[01:02:39] 
[01:02:39] 28 LL |         printf(::std::ptr::null(), 0u16);
[01:02:39] 29    |                                    ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint`
[01:02:39] 30 
[01:02:39] - error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function
[01:02:39] + error[E0617]: can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...) {printf}` to variadic function
[01:02:39] 32   --> $DIR/E0617.rs:24:36
[01:02:39] 34 LL |         printf(::std::ptr::null(), printf);
[01:02:39] 
[01:02:39] 35    |                                    ^^^^^^
[01:02:39] 35    |                                    ^^^^^^
[01:02:39] - help: cast the value to `unsafe extern "C" fn(*const i8, ...)`
[01:02:39] + help: cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...)`
[01:02:39] 37    |
[01:02:39] - LL |         printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...));
[01:02:39] -    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[01:02:39] + LL |         printf(::std::ptr::null(), printf as for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...));
[01:02:39] 40 
[01:02:39] 41 error: aborting due to 6 previous errors
[01:02:39] 42 
[01:02:39] 
[01:02:39] 
[01:02:39] 
[01:02:39] The actual stderr differed from the expected stderr.
[01:02:39] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/error-codes/E0617/E0617.stderr
[01:02:39] To update references, rerun the tests and pass the `--bless` flag
[01:02:39] To only update this specific test, also pass `--test-args error-codes/E0617.rs`
[01:02:39] error: 1 errors occurred comparing output.
[01:02:39] status: exit code: 1
[01:02:39] status: exit code: 1
[01:02:39] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/error-codes/E0617.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/error-codes/E0617/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/error-codes/E0617/auxiliary" "-A" "unused"
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] stderr:
[01:02:39] stderr:
[01:02:39] ------------------------------------------
[01:02:39] {"message":"can't pass `f32` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":133,"byte_end":137,"line_start":9,"line_end":9,"column_start":36,"column_end":40,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0f32);","highlight_start":36,"highlight_end":40}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_double`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":133,"byte_end":137,"line_start":9,"line_end":9,"column_start":36,"column_end":40,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0f32);","highlight_start":36,"highlight_end":40}],"label":null,"suggested_replacement":"0f32 as c_double","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `f32` to variadic function\n  --> /checkout/src/test/ui/error-codes/E0617.rs:9:36\n   |\nLL |         printf(::std::ptr::null(), 0f32);\n   |                                    ^^^^ help: cast the value to `c_double`: `0f32 as c_double`\n\n"}
[01:02:39] {"message":"can't pass `i8` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":279,"byte_end":282,"line_start":12,"line_end":12,"column_start":36,"column_end":39,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0i8);","highlight_start":36,"highlight_end":39}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_int`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":279,"byte_end":282,"line_start":12,"line_end":12,"column_start":36,"column_end":39,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0i8);","highlight_start":36,"highlight_end":39}],"label":null,"suggested_replacement":"0i8 as c_int","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `i8` to variadic function\n  --> /checkout/src/test/ui/error-codes/E0617.rs:12:36\n   |\nLL |         printf(::std::ptr::null(), 0i8);\n   |                                    ^^^ help: cast the value to `c_int`: `0i8 as c_int`\n\n"}
[01:02:39] {"message":"can't pass `i16` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":420,"byte_end":424,"line_start":15,"line_end":15,"column_start":36,"column_end":40,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0i16);","highlight_start":36,"highlight_end":40}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_int`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":420,"byte_end":424,"line_start":15,"line_end":15,"column_start":36,"column_end":40,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0i16);","highlight_start":36,"highlight_end":40}],"label":null,"suggested_replacement":"0i16 as c_int","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `i16` to variadic function\n  --> /checkout/src/test/ui/error-codes/E0617.rs:15:36\n   |\nLL |         printf(::std::ptr::null(), 0i16);\n   |                                    ^^^^ help: cast the value to `c_int`: `0i16 as c_int`\n\n"}
[01:02:39] {"message":"can't pass `u8` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":563,"byte_end":566,"line_start":18,"line_end":18,"column_start":36,"column_end":39,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0u8);","highlight_start":36,"highlight_end":39}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_uint`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":563,"byte_end":566,"line_start":18,"line_end":18,"column_start":36,"column_end":39,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0u8);","highlight_start":36,"highlight_end":39}],"label":null,"suggested_replacement":"0u8 as c_uint","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `u8` to variadic function\n  --> /checkout/src/test/ui/error-codes/E0617.rs:18:36\n   |\nLL |         printf(::std::ptr::null(), 0u8);\n   |                                    ^^^ help: cast the value to `c_uint`: `0u8 as c_uint`\n\n"}
[01:02:39] {"message":"can't pass `u16` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":705,"byte_end":709,"line_start":21,"line_end":21,"column_start":36,"column_end":40,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0u16);","highlight_start":36,"highlight_end":40}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_uint`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":705,"byte_end":709,"line_start":21,"line_end":21,"column_start":36,"column_end":40,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), 0u16);","highlight_start":36,"highlight_end":40}],"label":null,"suggested_replacement":"0u16 as c_uint","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `u16` to variadic function\n  --> /checkout/src/test/ui/error-codes/E0617.rs:21:36\n   |\nLL |         printf(::std::ptr::null(), 0u16);\n   |                                    ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint`\n\n"}
[01:02:39] {"message":"can't pass `for<'r> unsafe extern \"C\" fn(*const i8, std::ffi::VaList<'r>, ...) {printf}` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":849,"byte_end":855,"line_start":24,"line_end":24,"column_start":36,"column_end":42,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), printf);","highlight_start":36,"highlight_end":42}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `for<'r> unsafe extern \"C\" fn(*const i8, std::ffi::VaList<'r>, ...)`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/error-codes/E0617.rs","byte_start":849,"byte_end":855,"line_start":24,"line_end":24,"column_start":36,"column_end":42,"is_primary":true,"text":[{"text":"        printf(::std::ptr::null(), printf);","highlight_start":36,"highlight_end":42}],"label":null,"suggested_replacement":"printf as for<'r> unsafe extern \"C\" fn(*const i8, std::ffi::VaList<'r>, ...)","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `for<'r> unsafe extern \"C\" fn(*const i8, std::ffi::VaList<'r>, ...) {printf}` to variadic function\n  --> /checkout/src/test/ui/error-codes/E0617.rs:24:36\n   |\nLL |         printf(::std::ptr::null(), printf);\n   |                                    ^^^^^^\nhelp: cast the value to `for<'r> unsafe extern \"C\" fn(*const i8, std::ffi::VaList<'r>, ...)`\n   |\nLL |         printf(::std::ptr::null(), printf as for<'r> unsafe extern \"C\" fn(*const i8, std::ffi::VaList<'r>, ...));\n   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n"}
[01:02:39] {"message":"For more information about this error, try `rustc --explain E0617`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0617`.\n"}
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] 
[01:02:39] thread '[ui] ui/error-codes/E0617.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
[01:02:39] 
[01:02:39] ---- [ui] ui/invalid/invalid-variadic-function.rs stdout ----
[01:02:39] diff of stderr:
[01:02:39] 
[01:02:39] - error: only foreign functions are allowed to be variadic
[01:02:39] + error: expected argument name, found `...`
[01:02:39] 3    |
[01:02:39] 3    |
[01:02:39] 4 LL | extern "C" fn foo(x: u8, ...);
[01:02:39] -    |                          ^^^
[01:02:39] +    |                          ^^^ expected argument name
[01:02:39] 6 
[01:02:39] 6 
[01:02:39] 7 error: expected one of `->`, `where`, or `{`, found `;`
[01:02:39] 
[01:02:39] 
[01:02:39] The actual stderr differed from the expected stderr.
[01:02:39] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/invalid/invalid-variadic-function/invalid-variadic-function.stderr
[01:02:39] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/invalid/invalid-variadic-function/invalid-variadic-function.stderr
[01:02:39] To update references, rerun the tests and pass the `--bless` flag
[01:02:39] To only update this specific test, also pass `--test-args invalid/invalid-variadic-function.rs`
[01:02:39] error: 1 errors occurred comparing output.
[01:02:39] status: exit code: 1
[01:02:39] status: exit code: 1
[01:02:39] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/invalid/invalid-variadic-function.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/invalid/invalid-variadic-function/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/invalid/invalid-variadic-function/auxiliary" "-A" "unused"
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] stderr:
[01:02:39] stderr:
[01:02:39] ------------------------------------------
[01:02:39] {"message":"expected argument name, found `...`","code":null,"level":"error","spans":[{"file_name":"/checkout/src/test/ui/invalid/invalid-variadic-function.rs","byte_start":25,"byte_end":28,"line_start":1,"line_end":1,"column_start":26,"column_end":29,"is_primary":true,"text":[{"text":"extern \"C\" fn foo(x: u8, ...);","highlight_start":26,"highlight_end":29}],"label":"expected argument name","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: expected argument name, found `...`\n  --> /checkout/src/test/ui/invalid/invalid-variadic-function.rs:1:26\n   |\nLL | extern \"C\" fn foo(x: u8, ...);\n   |                          ^^^ expected argument name\n\n"}
[01:02:39] {"message":"expected one of `->`, `where`, or `{`, found `;`","code":null,"level":"error","spans":[{"file_name":"/checkout/src/test/ui/invalid/invalid-variadic-function.rs","byte_start":29,"byte_end":30,"line_start":1,"line_end":1,"column_start":30,"column_end":31,"is_primary":true,"text":[{"text":"extern \"C\" fn foo(x: u8, ...);","highlight_start":30,"highlight_end":31}],"label":"expected one of `->`, `where`, or `{` here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: expected one of `->`, `where`, or `{`, found `;`\n  --> /checkout/src/test/ui/invalid/invalid-variadic-function.rs:1:30\n   |\nLL | extern \"C\" fn foo(x: u8, ...);\n   |                              ^ expected one of `->`, `where`, or `{` here\n\n"}
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] thread '[ui] ui/invalid/invalid-variadic-function.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] thread '[ui] ui/invalid/invalid-variadic-function.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] 
[01:02:39] ---- [ui] ui/parser/recover-enum2.rs stdout ----
[01:02:39] diff of stderr:
[01:02:39] 
[01:02:39] 10 LL |             Nope(i32 {}) //~ ERROR: found `{`
[01:02:39] 11    |                      ^ expected one of 7 possible tokens here
[01:02:39] 12 
[01:02:39] - error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `::`, `<`, `?`, `[`, `_`, `crate`, `dyn`, `extern`, `fn`, `for`, `impl`, `pub`, `unsafe`, `}`, or lifetime, found `{`
[01:02:39] + error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `...`, `::`, `<`, `?`, `[`, `_`, `crate`, `dyn`, `extern`, `fn`, `for`, `impl`, `pub`, `unsafe`, `}`, or lifetime, found `{`
[01:02:39] 15    |
[01:02:39] 15    |
[01:02:39] 16 LL |             Nope(i32 {}) //~ ERROR: found `{`
[01:02:39] -    |                      ^ expected one of 23 possible tokens here
[01:02:39] +    |                      ^ expected one of 24 possible tokens here
[01:02:39] 18 
[01:02:39] 19 error: expected expression, found reserved identifier `_`
[01:02:39] 19 error: expected expression, found reserved identifier `_`
[01:02:39] 20   --> $DIR/recover-enum2.rs:32:22
[01:02:39] 
[01:02:39] 
[01:02:39] The actual stderr differed from the expected stderr.
[01:02:39] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/recover-enum2/recover-enum2.stderr
[01:02:39] To update references, rerun the tests and pass the `--bless` flag
[01:02:39] To only update this specific test, also pass `--test-args parser/recover-enum2.rs`
[01:02:39] error: 1 errors occurred comparing output.
[01:02:39] status: exit code: 1
[01:02:39] status: exit code: 1
[01:02:39] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/parser/recover-enum2.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/recover-enum2/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "continue-parse-after-error" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/recover-enum2/auxiliary" "-A" "unused"
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] stderr:
[01:02:39] stderr:
[01:02:39] ------------------------------------------
[01:02:39] {"message":"expected type, found `{`","code":null,"level":"error","spans":[{"file_name":"/checkout/src/test/ui/parser/recover-enum2.rs","byte_start":145,"byte_end":146,"line_start":8,"line_end":8,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":"            abc: {}, //~ ERROR: expected type, found `{`","highlight_start":18,"highlight_end":19}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: expected type, found `{`\n  --> /checkout/src/test/ui/parser/recover-enum2.rs:8:18\n   |\nLL |             abc: {}, //~ ERROR: expected type, found `{`\n   |                  ^\n\n"}
[01:02:39] {"message":"expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{`","code":null,"level":"error","spans":[{"file_name":"/checkout/src/test/ui/parser/recover-enum2.rs","byte_start":421,"byte_end":422,"line_start":27,"line_end":27,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"            Nope(i32 {}) //~ ERROR: found `{`","highlight_start":22,"highlight_end":23}],"label":"expected one of 7 possible tokens here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{`\n  --> /checkout/src/test/ui/parser/recover-enum2.rs:27:22\n   |\nLL |             Nope(i32 {}) //~ ERROR: found `{`\n   |                      ^ expected one of 7 possible tokens here\n\n"}
[01:02:39] {"message":"expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `...`, `::`, `<`, `?`, `[`, `_`, `crate`, `dyn`, `extern`, `fn`, `for`, `impl`, `pub`, `unsafe`, `}`, or lifetime, found `{`","code":null,"level":"error","spans":[{"file_name":"/checkout/src/test/ui/parser/recover-enum2.rs","byte_start":421,"byte_end":422,"line_start":27,"line_end":27,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"            Nope(i32 {}) //~ ERROR: found `{`","highlight_start":22,"highlight_end":23}],"label":"expected one of 24 possible tokens here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `...`, `::`, `<`, `?`, `[`, `_`, `crate`, `dyn`, `extern`, `fn`, `for`, `impl`, `pub`, `unsafe`, `}`, or lifetime, found `{`\n  --> /checkout/src/test/ui/parser/recover-enum2.rs:27:22\n   |\nLL |             Nope(i32 {}) //~ ERROR: found `{`\n   |                      ^ expected one of 24 possible tokens here\n\n"}
[01:02:39] {"message":"expected expression, found reserved identifier `_`","code":null,"level":"error","spans":[{"file_name":"/checkout/src/test/ui/parser/recover-enum2.rs","byte_start":557,"byte_end":558,"line_start":32,"line_end":32,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`","highlight_start":22,"highlight_end":23}],"label":"expected expression","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: expected expression, found reserved identifier `_`\n  --> /checkout/src/test/ui/parser/recover-enum2.rs:32:22\n   |\nLL |     let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`\n   |                      ^ expected expression\n\n"}
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] thread '[ui] ui/parser/recover-enum2.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] thread '[ui] ui/parser/recover-enum2.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] 
[01:02:39] ---- [ui] ui/parser/variadic-ffi-3.rs stdout ----
[01:02:39] diff of stderr:
[01:02:39] 
[01:02:39] - error: only foreign functions are allowed to be variadic
[01:02:39] + error: expected argument name, found `...`
[01:02:39] 3    |
[01:02:39] 3    |
[01:02:39] 4 LL | fn foo(x: isize, ...) {
[01:02:39] -    |                  ^^^
[01:02:39] +    |                  ^^^ expected argument name
[01:02:39] 6 
[01:02:39] 7 error: aborting due to previous error
[01:02:39] 7 error: aborting due to previous error
[01:02:39] 8 
[01:02:39] 
[01:02:39] 
[01:02:39] The actual stderr differed from the expected stderr.
[01:02:39] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/variadic-ffi-3/variadic-ffi-3.stderr
[01:02:39] To update references, rerun the tests and pass the `--bless` flag
[01:02:39] To only update this specific test, also pass `--test-args parser/variadic-ffi-3.rs`
[01:02:39] error: 1 errors occurred comparing output.
[01:02:39] status: exit code: 1
[01:02:39] status: exit code: 1
[01:02:39] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/parser/variadic-ffi-3.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/variadic-ffi-3/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/variadic-ffi-3/auxiliary" "-A" "unused"
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] stderr:
[01:02:39] stderr:
[01:02:39] ------------------------------------------
[01:02:39] {"message":"expected argument name, found `...`","code":null,"level":"error","spans":[{"file_name":"/checkout/src/test/ui/parser/variadic-ffi-3.rs","byte_start":17,"byte_end":20,"line_start":1,"line_end":1,"column_start":18,"column_end":21,"is_primary":true,"text":[{"text":"fn foo(x: isize, ...) {","highlight_start":18,"highlight_end":21}],"label":"expected argument name","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: expected argument name, found `...`\n  --> /checkout/src/test/ui/parser/variadic-ffi-3.rs:1:18\n   |\nLL | fn foo(x: isize, ...) {\n   |                  ^^^ expected argument name\n\n"}
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] thread '[ui] ui/parser/variadic-ffi-3.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] thread '[ui] ui/parser/variadic-ffi-3.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] 
[01:02:39] ---- [ui] ui/parser/variadic-ffi-4.rs stdout ----
[01:02:39] diff of stderr:
[01:02:39] 
[01:02:39] - error: only foreign functions are allowed to be variadic
[01:02:39] + error: expected argument name, found `...`
[01:02:39] 3    |
[01:02:39] 3    |
[01:02:39] 4 LL | extern "C" fn foo(x: isize, ...) {
[01:02:39] -    |                             ^^^
[01:02:39] +    |                             ^^^ expected argument name
[01:02:39] 6 
[01:02:39] 7 error: aborting due to previous error
[01:02:39] 7 error: aborting due to previous error
[01:02:39] 8 
[01:02:39] 
[01:02:39] 
[01:02:39] The actual stderr differed from the expected stderr.
[01:02:39] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/variadic-ffi-4/variadic-ffi-4.stderr
[01:02:39] To update references, rerun the tests and pass the `--bless` flag
[01:02:39] To only update this specific test, also pass `--test-args parser/variadic-ffi-4.rs`
[01:02:39] error: 1 errors occurred comparing output.
[01:02:39] status: exit code: 1
[01:02:39] status: exit code: 1
[01:02:39] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/parser/variadic-ffi-4.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/variadic-ffi-4/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/variadic-ffi-4/auxiliary" "-A" "unused"
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] stderr:
[01:02:39] stderr:
[01:02:39] ------------------------------------------
[01:02:39] {"message":"expected argument name, found `...`","code":null,"level":"error","spans":[{"file_name":"/checkout/src/test/ui/parser/variadic-ffi-4.rs","byte_start":28,"byte_end":31,"line_start":1,"line_end":1,"column_start":29,"column_end":32,"is_primary":true,"text":[{"text":"extern \"C\" fn foo(x: isize, ...) {","highlight_start":29,"highlight_end":32}],"label":"expected argument name","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: expected argument name, found `...`\n  --> /checkout/src/test/ui/parser/variadic-ffi-4.rs:1:29\n   |\nLL | extern \"C\" fn foo(x: isize, ...) {\n   |                             ^^^ expected argument name\n\n"}
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] thread '[ui] ui/parser/variadic-ffi-4.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] thread '[ui] ui/parser/variadic-ffi-4.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
[01:02:39] 
[01:02:39] ---- [ui] ui/variadic/variadic-ffi-3.rs stdout ----
[01:02:39] diff of stderr:
[01:02:39] 
[01:02:39] 23    |                                                        ^^^ expected non-variadic fn, found variadic function
[01:02:39] 24    |
[01:02:39] 25    = note: expected type `unsafe extern "C" fn(isize, u8)`
[01:02:39] -               found type `unsafe extern "C" fn(isize, u8, ...) {foo}`
[01:02:39] +               found type `for<'r> unsafe extern "C" fn(isize, u8, std::ffi::VaList<'r>, ...) {foo}`
[01:02:39] 28 error[E0308]: mismatched types
[01:02:39] 29   --> $DIR/variadic-ffi-3.rs:19:54
[01:02:39] 
[01:02:39] 
[01:02:39] 31 LL |         let y: extern "C" fn(f: isize, x: u8, ...) = bar;
[01:02:39] 32    |                                                      ^^^ expected variadic fn, found non-variadic function
[01:02:39] 33    |
[01:02:39] -    = note: expected type `extern "C" fn(isize, u8, ...)`
[01:02:39] +    = note: expected type `for<'r> extern "C" fn(isize, u8, std::ffi::VaList<'r>, ...)`
[01:02:39] 35               found type `extern "C" fn(isize, u8) {bar}`
[01:02:39] 36 
[01:02:39] 37 error[E0617]: can't pass `f32` to variadic function
[01:02:39] 
[01:02:39] The actual stderr differed from the expected stderr.
[01:02:39] The actual stderr differed from the expected stderr.
[01:02:39] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/variadic/variadic-ffi-3/variadic-ffi-3.stderr
[01:02:39] To update references, rerun the tests and pass the `--bless` flag
[01:02:39] To only update this specific test, also pass `--test-args variadic/variadic-ffi-3.rs`
[01:02:39] error: 1 errors occurred comparing output.
[01:02:39] status: exit code: 1
[01:02:39] status: exit code: 1
[01:02:39] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/variadic/variadic-ffi-3.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/variadic/variadic-ffi-3/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/variadic/variadic-ffi-3/auxiliary" "-A" "unused"
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] stderr:
[01:02:39] stderr:
[01:02:39] ------------------------------------------
[01:02:39] {"message":"this function takes at least 2 parameters but 0 parameters were supplied","code":{"code":"E0060","explanation":"\nExternal C functions are allowed to be variadic. However, a variadic function\ntakes a minimum number of arguments. For example, consider C's variadic `printf`\nfunction:\n\n```\nuse std::os::raw::{c_char, c_int};\n\nextern \"C\" {\n    fn printf(_: *const c_char, ...) -> c_int;\n}\n```\n\nUsing this declaration, it must be called with at least one argument, so\nsimply calling `printf()` is invalid. But the following uses are allowed:\n\n```\n# #![feature(static_nobundle)]\n# use std::os::raw::{c_char, c_int};\n# #[cfg_attr(all(windows, target_env = \"msvc\"),\n#            link(name = \"legacy_stdio_definitions\", kind = \"static-nobundle\"))]\n# extern \"C\" { fn printf(_: *const c_char, ...) -> c_int; }\n# fn main() {\nunsafe {\n    use std::ffi::CString;\n\n    let fmt = CString::new(\"test\\n\").unwrap();\n    printf(fmt.as_ptr());\n\n    let fmt = CString::new(\"number = %d\\n\").unwrap();\n    printf(fmt.as_ptr(), 3);\n\n    let fmt = CString::new(\"%d, %d\\n\").unwrap();\n    printf(fmt.as_ptr(), 10, 5);\n}\n# }\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":13,"byte_end":42,"line_start":2,"line_end":2,"column_start":5,"column_end":34,"is_primary":false,"text":[{"text":"    fn foo(f: isize, x: u8, ...);","highlight_start":5,"highlight_end":34}],"label":"defined here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":162,"byte_end":167,"line_start":11,"line_end":11,"column_start":9,"column_end":14,"is_primary":true,"text":[{"text":"        foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied","highlight_start":9,"highlight_end":14}],"label":"expected at least 2 parameters","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0060]: this function takes at least 2 parameters but 0 parameters were supplied\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:11:9\n   |\nLL |     fn foo(f: isize, x: u8, ...);\n   |     ----------------------------- defined here\n...\nLL |         foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied\n   |         ^^^^^ expected at least 2 parameters\n\n"}
[01:02:39] {"message":"this function takes at least 2 parameters but 1 parameter was supplied","code":{"code":"E0060","explanation":"\nExternal C functions are allowed to be variadic. However, a variadic function\ntakes a minimum number of arguments. For example, consider C's variadic `printf`\nfunction:\n\n```\nuse std::os::raw::{c_char, c_int};\n\nextern \"C\" {\n    fn printf(_: *const c_char, ...) -> c_int;\n}\n```\n\nUsing this declaration, it must be called with at least one argument, so\nsimply calling `printf()` is invalid. But the following uses are allowed:\n\n```\n# #![feature(static_nobundle)]\n# use std::os::raw::{c_char, c_int};\n# #[cfg_attr(all(windows, target_env = \"msvc\"),\n#            link(name = \"legacy_stdio_definitions\", kind = \"static-nobundle\"))]\n# extern \"C\" { fn printf(_: *const c_char, ...) -> c_int; }\n# fn main() {\nunsafe {\n    use std::ffi::CString;\n\n    let fmt = CString::new(\"test\\n\").unwrap();\n    printf(fmt.as_ptr());\n\n    let fmt = CString::new(\"number = %d\\n\").unwrap();\n    printf(fmt.as_ptr(), 3);\n\n    let fmt = CString::new(\"%d, %d\\n\").unwrap();\n    printf(fmt.as_ptr(), 10, 5);\n}\n# }\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":13,"byte_end":42,"line_start":2,"line_end":2,"column_start":5,"column_end":34,"is_primary":false,"text":[{"text":"    fn foo(f: isize, x: u8, ...);","highlight_start":5,"highlight_end":34}],"label":"defined here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":261,"byte_end":267,"line_start":12,"line_end":12,"column_start":9,"column_end":15,"is_primary":true,"text":[{"text":"        foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied","highlight_start":9,"highlight_end":15}],"label":"expected at least 2 parameters","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0060]: this function takes at least 2 parameters but 1 parameter was supplied\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:12:9\n   |\nLL |     fn foo(f: isize, x: u8, ...);\n   |     ----------------------------- defined here\n...\nLL |         foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied\n   |         ^^^^^^ expected at least 2 parameters\n\n"}
[01:02:39] {"message":"mismatched types","code":{"code":"E0308","explanation":"\nThis error occurs when the compiler was unable to infer the concrete type of a\nvariable. It can occur for several cases, the most common of which is a\nmismatch in the expected type that the compiler inferred for a variable's\ninitializing expression, and the actual type explicitly assigned to the\nvariable.\n\nFor example:\n\n```compile_fail,E0308\nlet x: i32 = \"I am not a number!\";\n//     ~~~   ~~~~~~~~~~~~~~~~~~~~\n//      |             |\n//      |    initializing expression;\n//      |    compiler infers type `&str`\n//      |\n//    type `i32` assigned to variable `x`\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":407,"byte_end":410,"line_start":14,"line_end":14,"column_start":56,"column_end":59,"is_primary":true,"text":[{"text":"        let x: unsafe extern \"C\" fn(f: isize, x: u8) = foo;","highlight_start":56,"highlight_end":59}],"label":"expected non-variadic fn, found variadic function","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `unsafe extern \"C\" fn(isize, u8)`\n   found type `for<'r> unsafe extern \"C\" fn(isize, u8, std::ffi::VaList<'r>, ...) {foo}`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0308]: mismatched types\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:14:56\n   |\nLL |         let x: unsafe extern \"C\" fn(f: isize, x: u8) = foo;\n   |                                                        ^^^ expected non-variadic fn, found variadic function\n   |\n   = note: expected type `unsafe extern \"C\" fn(isize, u8)`\n              found type `for<'r> unsafe extern \"C\" fn(isize, u8, std::ffi::VaList<'r>, ...) {foo}`\n\n"}
[01:02:39] {"message":"mismatched types","code":{"code":"E0308","explanation":"\nThis error occurs when the compiler was unable to infer the concrete type of a\nvariable. It can occur for several cases, the most common of which is a\nmismatch in the expected type that the compiler inferred for a variable's\ninitializing expression, and the actual type explicitly assigned to the\nvariable.\n\nFor example:\n\n```compile_fail,E0308\nlet x: i32 = \"I am not a number!\";\n//     ~~~   ~~~~~~~~~~~~~~~~~~~~\n//      |             |\n//      |    initializing expression;\n//      |    compiler infers type `&str`\n//      |\n//    type `i32` assigned to variable `x`\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":633,"byte_end":636,"line_start":19,"line_end":19,"column_start":54,"column_end":57,"is_primary":true,"text":[{"text":"        let y: extern \"C\" fn(f: isize, x: u8, ...) = bar;","highlight_start":54,"highlight_end":57}],"label":"expected variadic fn, found non-variadic function","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `for<'r> extern \"C\" fn(isize, u8, std::ffi::VaList<'r>, ...)`\n   found type `extern \"C\" fn(isize, u8) {bar}`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0308]: mismatched types\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:19:54\n   |\nLL |         let y: extern \"C\" fn(f: isize, x: u8, ...) = bar;\n   |                                                      ^^^ expected variadic fn, found non-variadic function\n   |\n   = note: expected type `for<'r> extern \"C\" fn(isize, u8, std::ffi::VaList<'r>, ...)`\n              found type `extern \"C\" fn(isize, u8) {bar}`\n\n"}
[01:02:39] {"message":"can't pass `f32` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":810,"byte_end":814,"line_start":24,"line_end":24,"column_start":19,"column_end":23,"is_primary":true,"text":[{"text":"        foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function","highlight_start":19,"highlight_end":23}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_double`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":810,"byte_end":814,"line_start":24,"line_end":24,"column_start":19,"column_end":23,"is_primary":true,"text":[{"text":"        foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function","highlight_start":19,"highlight_end":23}],"label":null,"suggested_replacement":"3f32 as c_double","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `f32` to variadic function\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:24:19\n   |\nLL |         foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function\n   |                   ^^^^ help: cast the value to `c_double`: `3f32 as c_double`\n\n"}
[01:02:39] {"message":"can't pass `bool` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":883,"byte_end":887,"line_start":25,"line_end":25,"column_start":19,"column_end":23,"is_primary":true,"text":[{"text":"        foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function","highlight_start":19,"highlight_end":23}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_int`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":883,"byte_end":887,"line_start":25,"line_end":25,"column_start":19,"column_end":23,"is_primary":true,"text":[{"text":"        foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function","highlight_start":19,"highlight_end":23}],"label":null,"suggested_replacement":"true as c_int","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `bool` to variadic function\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:25:19\n   |\nLL |         foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function\n   |                   ^^^^ help: cast the value to `c_int`: `true as c_int`\n\n"}
[01:02:39] {"message":"can't pass `i8` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":957,"byte_end":960,"line_start":26,"line_end":26,"column_start":19,"column_end":22,"is_primary":true,"text":[{"text":"        foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function","highlight_start":19,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_int`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":957,"byte_end":960,"line_start":26,"line_end":26,"column_start":19,"column_end":22,"is_primary":true,"text":[{"text":"        foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function","highlight_start":19,"highlight_end":22}],"label":null,"suggested_replacement":"1i8 as c_int","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `i8` to variadic function\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:26:19\n   |\nLL |         foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function\n   |                   ^^^ help: cast the value to `c_int`: `1i8 as c_int`\n\n"}
[01:02:39] {"message":"can't pass `u8` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":1028,"byte_end":1031,"line_start":27,"line_end":27,"column_start":19,"column_end":22,"is_primary":true,"text":[{"text":"        foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function","highlight_start":19,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_uint`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":1028,"byte_end":1031,"line_start":27,"line_end":27,"column_start":19,"column_end":22,"is_primary":true,"text":[{"text":"        foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function","highlight_start":19,"highlight_end":22}],"label":null,"suggested_replacement":"1u8 as c_uint","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `u8` to variadic function\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:27:19\n   |\nLL |         foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function\n   |                   ^^^ help: cast the value to `c_uint`: `1u8 as c_uint`\n\n"}
[01:02:39] {"message":"can't pass `i16` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":1099,"byte_end":1103,"line_start":28,"line_end":28,"column_start":19,"column_end":23,"is_primary":true,"text":[{"text":"        foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function","highlight_start":19,"highlight_end":23}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_int`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":1099,"byte_end":1103,"line_start":28,"line_end":28,"column_start":19,"column_end":23,"is_primary":true,"text":[{"text":"        foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function","highlight_start":19,"highlight_end":23}],"label":null,"suggested_replacement":"1i16 as c_int","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `i16` to variadic function\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:28:19\n   |\nLL |         foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function\n   |                   ^^^^ help: cast the value to `c_int`: `1i16 as c_int`\n\n"}
[01:02:39] {"message":"can't pass `u16` to variadic function","code":{"code":"E0617","explanation":"\nAttempted to pass an invalid type of variable into a variadic function.\n\nErroneous code example:\n\n```compile_fail,E0617\nextern {\n    fn printf(c: *const i8, ...);\n}\n\nunsafe {\n    printf(::std::ptr::null(), 0f32);\n    // error: can't pass an `f32` to variadic function, cast to `c_double`\n}\n```\n\nCertain Rust types must be cast before passing them to a variadic function,\nbecause of arcane ABI rules dictated by the C standard. To fix the error,\ncast the value to the type specified by the error message (which you may need\nto import from `std::os::raw`).\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":1172,"byte_end":1176,"line_start":29,"line_end":29,"column_start":19,"column_end":23,"is_primary":true,"text":[{"text":"        foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function","highlight_start":19,"highlight_end":23}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"cast the value to `c_uint`","code":null,"level":"help","spans":[{"file_name":"/checkout/src/test/ui/variadic/variadic-ffi-3.rs","byte_start":1172,"byte_end":1176,"line_start":29,"line_end":29,"column_start":19,"column_end":23,"is_primary":true,"text":[{"text":"        foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function","highlight_start":19,"highlight_end":23}],"label":null,"suggested_replacement":"1u16 as c_uint","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error[E0617]: can't pass `u16` to variadic function\n  --> /checkout/src/test/ui/variadic/variadic-ffi-3.rs:29:19\n   |\nLL |         foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function\n   |                   ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint`\n\n"}
[01:02:39] {"message":"aborting due to 10 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 10 previous errors\n\n"}
[01:02:39] {"message":"Some errors occurred: E0060, E0308, E0617.","code":null,"level":"","spans":[],"children":[],"rendered":"Some errors occurred: E0060, E0308, E0617.\n"}
[01:02:39] 
[01:02:39] ------------------------------------------
[01:02:39] 
[01:02:39] thread '[ui] ui/variadic/variadic-ffi-3.rs' panicked at 'explicit panic', src/tools/compiletest/src/runtest.rs:3295:9
---
[01:02:39] 
[01:02:39] thread 'main' panicked at 'Some tests failed', src/tools/compiletest/src/main.rs:502:22
[01:02:39] 
[01:02:39] 
[01:02:39] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-6.0/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "6.0.0\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--llvm-cxxflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[01:02:39] 
[01:02:39] 
[01:02:39] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:02:39] Build completed unsuccessfully in 0:04:05
[01:02:39] Build completed unsuccessfully in 0:04:05
[01:02:39] make: *** [check] Error 1
[01:02:39] Makefile:48: recipe for target 'check' failed
The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:06838e6d
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
Fri Feb  1 16:48:59 UTC 2019
---
travis_time:end:1325f658:start=1549039740978872858,finish=1549039740983833554,duration=4960696
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:18884dd0
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!check

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

src/librustc_codegen_llvm/abi.rs Outdated Show resolved Hide resolved
@rust-highfive

This comment has been minimized.

@dlrobertson dlrobertson force-pushed the varargs1 branch 2 times, most recently from 36e5d87 to 285ec4e Compare February 2, 2019 02:59
@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 27, 2019
@bors
Copy link
Contributor

bors commented Feb 28, 2019

⌛ Testing commit f7dd438 with merge 35046f85f921a5daadfcd7be66cd82ea27352f2b...

@Mark-Simulacrum
Copy link
Member

@bors retry - prioritize stable backport

@bors
Copy link
Contributor

bors commented Feb 28, 2019

⌛ Testing commit f7dd438 with merge 1999a22...

bors added a commit that referenced this pull request Feb 28, 2019
Support defining C compatible variadic functions

## Summary

Add support for defining C compatible variadic functions in unsafe rust with
`extern "C"` according to [RFC 2137].

## Details

### Parsing
When parsing a user defined function that is `unsafe` and `extern "C"` allow
variadic signatures and inject a "spoofed" `VaList` in the new functions
signature. This allows the user to interact with the variadic arguments via a
`VaList` instead of manually using `va_start` and `va_end` (See [RFC 2137] for
details).

### Codegen

When running codegen for a variadic function, remove the "spoofed" `VaList`
from the function signature and inject `va_start` when the arg local
references are created for the function and `va_end` on return.

## TODO

 - [x] Get feedback on injecting `va_start/va_end` in MIR vs codegen
 - [x] Properly inject `va_end` - It seems like it should be possible to inject
       `va_end` on the `TerminatorKind::Return`. I just need to figure out how
       to get the `LocalRef` here.
 - [x] Properly call Rust defined C variadic functions in Rust - The spoofed
       `VaList` causes problems here.

Related to: #44930

r? @ghost

[RFC 2137]: https://github.com/rust-lang/rfcs/blob/master/text/2137-variadic.md
@bors
Copy link
Contributor

bors commented Feb 28, 2019

☀️ Test successful - checks-travis, status-appveyor
Approved by: alexreg
Pushing 1999a22 to master...

@alexcrichton
Copy link
Member

@dlrobertson I think this may have regressed macros and variadic functions slightly, I've got a test that looks like:

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

but the input to the macro #[foo] looks like:

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

Do you think this may have accidentally broken the pretty printer for variadic functions?

@alexcrichton
Copy link
Member

(I've opened up #58853 to track regardless)

@dlrobertson
Copy link
Contributor Author

Do you think this may have accidentally broken the pretty printer for variadic functions?

It is very likely.

(I've opened up #58853 to track regardless)

Thanks!

@thedataking
Copy link

@dlrobertson I appreciate your hard work on this feature. I think hitting an issue in release mode on the latest nightly (rustc 1.35.0-nightly (f22dca0a1 2019-03-05)). The unoptimized build of the following works as you'd expect whereas the optimized binary segfaults:

#![feature(c_variadic)]

extern "C" {
    #[no_mangle]
    fn vprintf(_: *const libc::c_char, _: ...) -> libc::c_int;
}

#[no_mangle]
unsafe extern "C" fn variadic(fmt: *const libc::c_char, a: ...)
 -> libc::c_int {
    vprintf(fmt, a)
}

fn main() {
    let fmt = std::ffi::CString::new("test %d %d %d\n").expect("new failed");
    unsafe {
        variadic(fmt.as_ptr(), 1, 2, 3);
    }
}

Advance apologies if I'm doing something that isn't expected to work.

@varkor
Copy link
Member

varkor commented Mar 7, 2019

@thedataking: Can you open this example up as a new issue, so we don't lose track of it here?

@dlrobertson
Copy link
Contributor Author

@thedataking Thanks for the catch. A issue would definitely be appreciated.

@thedataking
Copy link

@dlrobertson @varkor I opened up #58980 to track this issue. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-c_variadic `#![feature(c_variadic)]` merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.