diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:21:43 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:21:43 +0000 |
commit | 6a7cf9b600ca7f87bf4569b8b7a44be6fb00b740 (patch) | |
tree | 5c229c19807bc789990e1c77c40d790be20f6e2b | |
parent | 2dd71187e2dab671b4fa6c7e1e3e698f6d328cf3 (diff) | |
parent | 266d58b94dad5c2ce34051ad04ab8cd87293cd64 (diff) | |
download | cxx-android14-mainline-networking-release.tar.gz |
Snap for 10447354 from 266d58b94dad5c2ce34051ad04ab8cd87293cd64 to mainline-networking-releaseaml_net_341710020aml_net_341610030aml_net_341510050aml_net_341510000aml_net_341411030aml_net_341311010aml_net_341310020aml_net_341014000aml_net_340913000android14-mainline-networking-release
Change-Id: I945678f450bb8a6566214daa927134854fbbd0d1
202 files changed, 4306 insertions, 1848 deletions
diff --git a/.bazelignore b/.bazelignore index 2f7896d1..c42dab31 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1 +1,2 @@ target/ +tools/buck/buck2/ diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 00000000..5e3ff76a --- /dev/null +++ b/.bazelrc @@ -0,0 +1,2 @@ +build --enable_platform_specific_config +build:linux --@rules_rust//:extra_rustc_flags=-Clink-arg=-fuse-ld=lld diff --git a/.buckconfig b/.buckconfig index 5c6c995a..045974f7 100644 --- a/.buckconfig +++ b/.buckconfig @@ -1,23 +1,17 @@ -[project] - # We use some symlinks in the source tree, but they get eliminated by `cargo - # publish` and `cargo vendor` so this allow_symlinks setting should not be - # required downstream. - allow_symlinks = allow - - # Hide BUCK files under target/package/ from `buck build ...`. Otherwise: - # $ buck build ... - # //target/package/cxx-0.3.0/tests:ffi references non-existing file or directory 'target/package/cxx-0.3.0/tests/ffi/lib.rs' - ignore = target +[repositories] +repo = . +prelude = tools/buck/prelude +toolchains = tools/buck/toolchains +ovr_config = tools/buck/prelude +buck = none +fbcode = none +fbsource = none -[cxx] - cxxflags = -std=c++11 - -[rust] - default_edition = 2018 - rustc_flags = \ - -Clink-arg=-fuse-ld=lld \ - -Crelocation-model=dynamic-no-pic \ - --cap-lints=allow +[project] +# Hide BUCK files under target/package/ from `buck build ...`. Otherwise: +# $ buck build ... +# //target/package/cxx-0.3.0/tests:ffi references non-existing file or directory 'target/package/cxx-0.3.0/tests/ffi/lib.rs' +ignore = target -[defaults.rust_library] - type = check +[parser] +target_platform_detector_spec = target://...->ovr_config//platforms:default diff --git a/.buckversion b/.buckversion deleted file mode 100644 index b25fa3fc..00000000 --- a/.buckversion +++ /dev/null @@ -1 +0,0 @@ -last diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f9f0dca7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +third-party/BUCK linguist-generated diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b82cd99..93feb348 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,9 @@ on: pull_request: schedule: [cron: "40 1 * * *"] +permissions: + contents: read + jobs: test: name: ${{matrix.name || format('Rust {0}', matrix.rust)}} @@ -16,25 +19,23 @@ jobs: - rust: nightly - rust: beta - rust: stable - - rust: 1.48.0 + - rust: 1.60.0 - name: macOS rust: nightly os: macos - - name: Windows (gnu) - rust: nightly-x86_64-pc-windows-gnu - os: windows - name: Windows (msvc) rust: nightly-x86_64-pc-windows-msvc os: windows flags: /EHsc env: CXXFLAGS: ${{matrix.flags}} - RUSTFLAGS: --cfg deny_warnings + RUSTFLAGS: --cfg deny_warnings -Dwarnings + timeout-minutes: 45 steps: - name: Enable symlinks (windows) if: matrix.os == 'windows' run: git config --global core.symlinks true - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} @@ -45,51 +46,61 @@ jobs: # build. The extra coverage is not particularly valuable and we can # still ensure the test is kept passing on the basis of the scheduled # builds. - if: matrix.os && github.event_name != 'schedule' - run: echo "RUSTFLAGS=--cfg skip_ui_tests $RUSTFLAGS" >> $GITHUB_ENV + run: | + echo RUSTFLAGS=$RUSTFLAGS >> $GITHUB_ENV + echo exclude=--exclude cxx-test-suite >> $GITHUB_OUTPUT + env: + RUSTFLAGS: ${{env.RUSTFLAGS}} ${{matrix.os && github.event_name != 'schedule' && '--cfg skip_ui_tests' || ''}} + id: testsuite shell: bash - run: cargo run --manifest-path demo/Cargo.toml - - run: cargo test --workspace --exclude cxx-test-suite + - run: cargo test --workspace ${{steps.testsuite.outputs.exclude}} + - run: cargo check --no-default-features --features alloc + env: + RUSTFLAGS: --cfg compile_error_if_std ${{env.RUSTFLAGS}} + - run: cargo check --no-default-features + env: + RUSTFLAGS: --cfg compile_error_if_alloc --cfg cxx_experimental_no_alloc ${{env.RUSTFLAGS}} buck: name: Buck runs-on: ubuntu-latest if: github.event_name != 'pull_request' + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 - - uses: dtolnay/rust-toolchain@stable - - uses: actions/setup-java@v1 + - uses: actions/checkout@v3 with: - java-version: 11 - java-package: jre - - name: Install Buck - run: | - mkdir bin - wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/a5f0342ae3/buck-a5f0342ae3-java11.pex # dev branch from 2020.10.11 - chmod +x bin/buck - echo bin >> $GITHUB_PATH + submodules: true + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@reindeer + - uses: dtolnay/install@buck2 - name: Install lld run: sudo apt-get install lld - - name: Vendor dependencies - run: | - cp third-party/Cargo.lock . - cargo vendor --versioned-dirs --locked third-party/vendor - - run: buck build :cxx#check --verbose=0 - - run: buck run demo --verbose=0 - - run: buck test ... --verbose=0 + - run: cargo vendor --versioned-dirs --locked + working-directory: third-party + - run: reindeer vendor + working-directory: third-party + - name: Check reindeer-generated BUCK file up to date + run: git diff --exit-code + - run: buck2 run demo + - run: buck2 build ... + - run: buck2 run tests:test bazel: name: Bazel runs-on: ubuntu-latest if: github.event_name != 'pull_request' + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install Bazel run: | - wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/4.0.0/bazel-4.0.0-installer-linux-x86_64.sh + wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/5.1.1/bazel-5.1.1-installer-linux-x86_64.sh chmod +x install.sh ./install.sh --user echo $HOME/bin >> $GITHUB_PATH + - name: Install lld + run: sudo apt-get install lld - run: bazel run demo --verbose_failures --noshow_progress - run: bazel test ... --verbose_failures --noshow_progress @@ -97,8 +108,9 @@ jobs: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@clippy - run: cargo clippy --workspace --tests -- -Dclippy::all @@ -106,9 +118,20 @@ jobs: name: Clang Tidy runs-on: ubuntu-latest if: github.event_name != 'pull_request' + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install clang-tidy run: sudo apt-get install clang-tidy-11 - name: Run clang-tidy run: clang-tidy-11 src/cxx.cc --warnings-as-errors=* + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index d6b0ca6d..09382b79 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -12,8 +12,11 @@ jobs: deploy: name: Deploy runs-on: ubuntu-latest + permissions: + contents: write + timeout-minutes: 30 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get mdBook run: | diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..208a58a9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tools/buck/prelude"] + path = tools/buck/prelude + url = https://github.com/facebookincubator/buck2-prelude diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 00000000..d93f3088 --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1,3 @@ +{ + "ignore_dirs": ["buck-out"] +} @@ -39,6 +39,10 @@ rust_library { crate_name: "cxx", srcs: ["src/lib.rs"], edition: "2018", + features: [ + "alloc", + "std", + ], rustlibs: [ "libanyhow", "libthiserror", @@ -51,9 +55,11 @@ rust_library { ], shared_libs: ["libc++"], host_supported: true, + vendor_available: true, + product_available: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", "com.android.compos", "com.android.virt", ], @@ -61,13 +67,16 @@ rust_library { } cc_library_static { - host_supported: true, name: "libcxxbridge05", + defaults: ["rust_static_cc_lib_defaults"], cflags: ["-DRUST_CXX_NO_EXCEPTIONS"], srcs: ["src/cxx.cc"], + host_supported: true, + vendor_available: true, + product_available: true, apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", "com.android.compos", "com.android.virt", ], @@ -1,6 +1,11 @@ rust_library( name = "cxx", - srcs = glob(["src/**"]), + srcs = glob(["src/**/*.rs"]), + edition = "2018", + features = [ + "alloc", + "std", + ], visibility = ["PUBLIC"], deps = [ ":core", @@ -10,8 +15,12 @@ rust_library( rust_binary( name = "codegen", - srcs = glob(["gen/cmd/src/**"]), + srcs = glob(["gen/cmd/src/**/*.rs"]) + [ + "gen/cmd/src/gen", + "gen/cmd/src/syntax", + ], crate = "cxxbridge", + edition = "2018", visibility = ["PUBLIC"], deps = [ "//third-party:clap", @@ -35,8 +44,9 @@ cxx_library( rust_library( name = "macro", - srcs = glob(["macro/src/**"]), + srcs = glob(["macro/src/**/*.rs"]) + ["macro/src/syntax"], crate = "cxxbridge_macro", + edition = "2018", proc_macro = True, deps = [ "//third-party:proc-macro2", @@ -47,12 +57,16 @@ rust_library( rust_library( name = "build", - srcs = glob(["gen/build/src/**"]), + srcs = glob(["gen/build/src/**/*.rs"]) + [ + "gen/build/src/gen", + "gen/build/src/syntax", + ], + edition = "2018", visibility = ["PUBLIC"], deps = [ "//third-party:cc", "//third-party:codespan-reporting", - "//third-party:lazy_static", + "//third-party:once_cell", "//third-party:proc-macro2", "//third-party:quote", "//third-party:scratch", @@ -62,7 +76,11 @@ rust_library( rust_library( name = "lib", - srcs = glob(["gen/lib/src/**"]), + srcs = glob(["gen/lib/src/**/*.rs"]) + [ + "gen/lib/src/gen", + "gen/lib/src/syntax", + ], + edition = "2018", visibility = ["PUBLIC"], deps = [ "//third-party:cc", @@ -1,9 +1,14 @@ load("@rules_cc//cc:defs.bzl", "cc_library") -load("@rules_rust//rust:rust.bzl", "rust_binary", "rust_library") +load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_proc_macro") rust_library( name = "cxx", srcs = glob(["src/**/*.rs"]), + crate_features = [ + "alloc", + "std", + ], + edition = "2018", proc_macro_deps = [ ":cxxbridge-macro", ], @@ -15,6 +20,7 @@ rust_binary( name = "codegen", srcs = glob(["gen/cmd/src/**/*.rs"]), data = ["gen/cmd/src/gen/include/cxx.h"], + edition = "2018", visibility = ["//visibility:public"], deps = [ "//third-party:clap", @@ -39,10 +45,10 @@ cc_library( hdrs = ["include/cxx.h"], ) -rust_library( +rust_proc_macro( name = "cxxbridge-macro", - srcs = glob(["macro/src/**"]), - crate_type = "proc-macro", + srcs = glob(["macro/src/**/*.rs"]), + edition = "2018", deps = [ "//third-party:proc-macro2", "//third-party:quote", @@ -54,11 +60,12 @@ rust_library( name = "build", srcs = glob(["gen/build/src/**/*.rs"]), data = ["gen/build/src/gen/include/cxx.h"], + edition = "2018", visibility = ["//visibility:public"], deps = [ "//third-party:cc", "//third-party:codespan-reporting", - "//third-party:lazy_static", + "//third-party:once_cell", "//third-party:proc-macro2", "//third-party:quote", "//third-party:scratch", @@ -70,6 +77,7 @@ rust_library( name = "lib", srcs = glob(["gen/lib/src/**/*.rs"]), data = ["gen/lib/src/gen/include/cxx.h"], + edition = "2018", visibility = ["//visibility:public"], deps = [ "//third-party:cc", @@ -1,45 +1,51 @@ [package] name = "cxx" -version = "1.0.54" # remember to update html_root_url +version = "1.0.85" # remember to update html_root_url authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -links = "cxxbridge1" -license = "MIT OR Apache-2.0" +categories = ["development-tools::ffi", "api-bindings", "no-std"] description = "Safe interop between Rust and C++" -repository = "https://github.com/dtolnay/cxx" documentation = "https://docs.rs/cxx" -homepage = "https://cxx.rs" -readme = "README.md" +edition = "2018" exclude = ["/demo", "/gen", "/syntax", "/third-party"] -keywords = ["ffi"] -categories = ["development-tools::ffi", "api-bindings"] +homepage = "https://cxx.rs" +keywords = ["ffi", "c++"] +license = "MIT OR Apache-2.0" +links = "cxxbridge1" +repository = "https://github.com/dtolnay/cxx" +rust-version = "1.48" [features] -default = ["cxxbridge-flags/default"] # c++11 +default = ["std", "cxxbridge-flags/default"] # c++11 "c++14" = ["cxxbridge-flags/c++14"] "c++17" = ["cxxbridge-flags/c++17"] "c++20" = ["cxxbridge-flags/c++20"] +alloc = [] +std = ["alloc"] [dependencies] -cxxbridge-macro = { version = "=1.0.54", path = "macro" } +cxxbridge-macro = { version = "=1.0.85", path = "macro" } link-cplusplus = "1.0" [build-dependencies] cc = "1.0.49" -cxxbridge-flags = { version = "=1.0.54", path = "flags", default-features = false } +cxxbridge-flags = { version = "=1.0.85", path = "flags", default-features = false } [dev-dependencies] -cxx-build = { version = "=1.0.54", path = "gen/build" } +cxx-build = { version = "=1.0.85", path = "gen/build" } cxx-gen = { version = "0.7", path = "gen/lib" } cxx-test-suite = { version = "0", path = "tests/ffi" } rustversion = "1.0" -trybuild = { version = "1.0.33", features = ["diff"] } +trybuild = { version = "1.0.66", features = ["diff"] } + +[lib] +doc-scrape-examples = false [workspace] members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"] [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--cfg", "doc_cfg"] [patch.crates-io] cxx = { path = "." } @@ -3,8 +3,8 @@ CXX — safe FFI between Rust and C++ [<img alt="github" src="https://img.shields.io/badge/github-dtolnay/cxx-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/cxx) [<img alt="crates.io" src="https://img.shields.io/crates/v/cxx.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/cxx) -[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-cxx-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/cxx) -[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/cxx/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/cxx/actions?query=branch%3Amaster) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-cxx-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/cxx) +[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/cxx/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/cxx/actions?query=branch%3Amaster) This library provides a **safe** mechanism for calling C++ code from Rust and Rust code from C++, not subject to the many ways that things can go wrong when @@ -4,20 +4,21 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "rules_rust", - sha256 = "697a6f4f2adbd1b00f792346d6eca4cd45f691be63069c7d7ebf4fcf82a377a8", - strip_prefix = "rules_rust-8bad4c5e4e53d9f6f8d4d5228e26a44d92f37ab2", + sha256 = "617082067629939c0a22f587811a3e822a50a203119a90380e21f5aec3373da9", + strip_prefix = "rules_rust-e07881fa22a5f0d16230d8b23bbff2bf358823b8", urls = [ - # Master branch as of 2021-04-11 - "https://github.com/bazelbuild/rules_rust/archive/8bad4c5e4e53d9f6f8d4d5228e26a44d92f37ab2.tar.gz", + # Main branch as of 2022-04-27 + "https://github.com/bazelbuild/rules_rust/archive/e07881fa22a5f0d16230d8b23bbff2bf358823b8.tar.gz", ], ) -load("@rules_rust//rust:repositories.bzl", "rust_repositories") +load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") -RUST_VERSION = "1.54.0" +RUST_VERSION = "1.65.0" -rust_repositories( - edition = "2018", +rules_rust_dependencies() + +rust_register_toolchains( version = RUST_VERSION, ) @@ -25,6 +26,6 @@ load("//tools/bazel:vendor.bzl", "vendor") vendor( name = "third-party", - lockfile = "//third-party:Cargo.lock", cargo_version = RUST_VERSION, + lockfile = "//third-party:Cargo.lock", ) diff --git a/book/diagram/.gitignore b/book/diagram/.gitignore index 81631c69..27572bd3 100644 --- a/book/diagram/.gitignore +++ b/book/diagram/.gitignore @@ -1,2 +1,7 @@ -/bin -/build +*.aux +*.fdb_latexmk +*.fls +*.log +*.pdf +*.png +*.svg diff --git a/book/diagram/Makefile b/book/diagram/Makefile index 161da349..1723a9b9 100644 --- a/book/diagram/Makefile +++ b/book/diagram/Makefile @@ -1,12 +1,8 @@ -all: overview.svg +overview.svg: overview.pdf + pdf2svg $< $@ -build/bin/svgbob: - cargo install --git https://github.com/ivanceras/svgbob --rev df01674c47350665158ececa476e63f51c58a9c7 --root build +overview.pdf: overview.tex + latexmk $< -%.svg: %.ascii build/bin/svgbob - build/bin/svgbob $< > $@ - -clean: - rm -f *.svg - -.PHONY: all clean +overview.png: overview.svg + svgexport $< $@ 3x diff --git a/book/diagram/overview.ascii b/book/diagram/overview.ascii deleted file mode 100644 index dd1c4b93..00000000 --- a/book/diagram/overview.ascii +++ /dev/null @@ -1,13 +0,0 @@ - .-----------------------------. - | #[cxx::bridge] mod | - | description of boundary | - '--------------+--------------' - | - | - "Macro expansion" | "Code generation" - +---------------+---------------+ - Safe | | - straightforward v v Straightforward - "Rust APIs".----------------. "Hidden C ABI".---------------. "C++ APIs" -Rust <----------->| "Rust bindings"|<~~~~~~~~~~~~~>| "C++ bindings"|<-----------> "C++" -code '----------------' '---------------' code diff --git a/book/diagram/overview.svg b/book/diagram/overview.svg deleted file mode 100644 index e5154668..00000000 --- a/book/diagram/overview.svg +++ /dev/null @@ -1,132 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="696" height="224"> - <style>line, path, circle,rect,polygon { - stroke: black; - stroke-width: 2; - stroke-opacity: 1; - fill-opacity: 1; - stroke-linecap: round; - stroke-linejoin: miter; - } - - text { - fill: black; - } - rect.backdrop{ - stroke: none; - fill: white; - } - .broken{ - stroke-dasharray: 8; - } - .filled{ - fill: black; - } - .bg_filled{ - fill: white; - } - .nofill{ - fill: white; - } - - text { - font-family: monospace; - font-size: 14px; - } - - .end_marked_arrow{ - marker-end: url(#arrow); - } - .start_marked_arrow{ - marker-start: url(#arrow); - } - - .end_marked_diamond{ - marker-end: url(#diamond); - } - .start_marked_diamond{ - marker-start: url(#diamond); - } - - .end_marked_circle{ - marker-end: url(#circle); - } - .start_marked_circle{ - marker-start: url(#circle); - } - - .end_marked_open_circle{ - marker-end: url(#open_circle); - } - .start_marked_open_circle{ - marker-start: url(#open_circle); - } - - .end_marked_big_open_circle{ - marker-end: url(#big_open_circle); - } - .start_marked_big_open_circle{ - marker-start: url(#big_open_circle); - } - - - </style> - <defs> - <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <polygon points="0,0 0,4 4,2 0,0"></polygon> - </marker> - <marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <polygon points="0,2 2,0 4,2 2,4 0,2"></polygon> - </marker> - <marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="2" class="filled"></circle> - </marker> - <marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="2" class="bg_filled"></circle> - </marker> - <marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="3" class="bg_filled"></circle> - </marker> - </defs> - <rect class="backdrop" x="0" y="0" width="696" height="224"></rect> - <rect x="148" y="168" width="136" height="32" class="solid nofill" rx="4"></rect> - <text x="162" y="188" >Rust bindings</text> - <rect x="412" y="168" width="128" height="32" class="solid nofill" rx="4"></rect> - <text x="426" y="188" >C++ bindings</text> - <text x="266" y="28" >#[cxx::bridge]</text> - <text x="394" y="28" >mod</text> - <text x="250" y="44" >description</text> - <text x="346" y="44" >of</text> - <text x="370" y="44" >boundary</text> - <line x1="220" y1="120" x2="220" y2="160" class="solid end_marked_arrow"></line> - <line x1="476" y1="120" x2="476" y2="160" class="solid end_marked_arrow"></line> - <text x="74" y="140" >Safe</text> - <text x="34" y="156" >straightforward</text> - <text x="530" y="156" >Straightforward</text> - <polygon points="48,180 40,184 48,188" class="filled"></polygon> - <line x1="48" y1="184" x2="144" y2="184" class="solid end_marked_arrow"></line> - <polygon points="296,180 288,184 296,188" class="filled"></polygon> - <line x1="296" y1="184" x2="408" y2="184" class="broken end_marked_arrow"></line> - <polygon points="552,180 544,184 552,188" class="filled"></polygon> - <line x1="552" y1="184" x2="648" y2="184" class="solid end_marked_arrow"></line> - <text x="2" y="188" >Rust</text> - <text x="2" y="204" >code</text> - <text x="658" y="204" >code</text> - <text x="202" y="108" >Macro expansion</text> - <text x="370" y="108" >Code generation</text> - <text x="58" y="172" >Rust APIs</text> - <text x="298" y="172" >Hidden C ABI</text> - <text x="562" y="172" >C++ APIs</text> - <text x="658" y="188" >C++</text> - <g> - <path d="M 228,8 A 8,8 0,0,0 220,16" class="nofill"></path> - <line x1="228" y1="8" x2="468" y2="8" class="solid"></line> - <path d="M 468,8 A 8,8 0,0,1 476,16" class="nofill"></path> - <line x1="220" y1="16" x2="220" y2="48" class="solid"></line> - <line x1="476" y1="16" x2="476" y2="48" class="solid"></line> - <path d="M 220,48 A 8,8 0,0,0 228,56" class="nofill"></path> - <line x1="228" y1="56" x2="468" y2="56" class="solid"></line> - <line x1="348" y1="56" x2="348" y2="120" class="solid"></line> - <path d="M 476,48 A 8,8 0,0,1 468,56" class="nofill"></path> - <line x1="220" y1="120" x2="476" y2="120" class="solid"></line> - </g> -</svg> diff --git a/book/diagram/overview.tex b/book/diagram/overview.tex new file mode 100644 index 00000000..a613bb75 --- /dev/null +++ b/book/diagram/overview.tex @@ -0,0 +1,45 @@ +\documentclass{standalone} +\usepackage{makecell} +\usepackage{pgfplots} +\usepackage{sansmath} +\usetikzlibrary{arrows.meta} +\pgfplotsset{compat=1.16} +\begin{document} +\pagecolor{white} +\begin{tikzpicture}[ + x=1cm, + y=-.6cm, + every node/.append style={ + line width=1.5pt, + font=\Large\sansmath\sffamily, + }, + every path/.append style={ + >={Latex[length=10pt,width=8pt]}, + line width=1.5pt, + }, + execute at end node={\vphantom{bg}}, +] +\node[draw, rounded corners=5, inner xsep=30pt, inner ysep=2pt] + (bridge) at (0, .25) {\makecell{\texttt{\#\hspace{-1pt}[}cxx::bridge\texttt{]} mod\\[-4pt]description of boundary}}; +\node[draw, rounded corners, inner xsep=10pt, inner ysep=6pt, text depth=1pt] + (rust-bindings) at (-3.5, 6.5) {Rust bindings}; +\node[draw, rounded corners, inner xsep=10pt, inner ysep=6pt, text depth=1pt] + (cpp-bindings) at (3.5, 6.5) {C\texttt{++} bindings}; +\node[inner xsep=4pt, inner ysep=-0pt] + (rust-code) at (-9, 6.5) {\makecell[r]{\\[-8pt]Rust\\[-4pt]code}}; +\node[inner xsep=4pt, inner ysep=-0pt] + (cpp-code) at (9, 6.5) {\makecell[l]{\\[-8pt]C\texttt{++}\\[-4pt]code}}; +\draw (bridge) -- (0, 4); +\draw[<->] (rust-bindings) |- (0, 4) -| (cpp-bindings); +\draw[<->] (rust-code) -- (rust-bindings); +\draw[<->, dash pattern=on 8pt off 6pt] (rust-bindings) -- (cpp-bindings); +\draw[<->] (cpp-bindings) -- (cpp-code); +\draw (-.75, 4) node[anchor=south east] {Macro expansion}; +\draw (.75, 4) node[anchor=south west] {Code generation}; +\draw (0, 6.5) node[anchor=south, inner ysep=4pt] {Hidden C ABI}; +\draw (-6.75, 6.5) node[anchor=south, inner ysep=1pt] {\makecell{Safe\\[-4pt]straightforward\\[-4pt]Rust APIs}}; +\draw (6.75, 6.5) node[anchor=south, inner ysep=1pt] {\makecell{Straightforward\\[-4pt]C\texttt{++} APIs}}; +\pgfresetboundingbox\path + (-9.5, 0) -- (rust-bindings.south)+(0, .3) -- (9.5, 0) -- (bridge.north); +\end{tikzpicture} +\end{document} diff --git a/book/src/binding/cxxstring.md b/book/src/binding/cxxstring.md index 0b1d7bbd..cfe707f2 100644 --- a/book/src/binding/cxxstring.md +++ b/book/src/binding/cxxstring.md @@ -73,6 +73,7 @@ fn main() { #pragma once #include <map> #include <memory> +#include <string> #include <variant> #include <vector> diff --git a/book/src/binding/string.md b/book/src/binding/string.md index d564e00c..1e482781 100644 --- a/book/src/binding/string.md +++ b/book/src/binding/string.md @@ -18,15 +18,24 @@ public: String(String &&) noexcept; ~String() noexcept; - // Throws std::invalid_argument if not utf-8. + // Throws std::invalid_argument if not UTF-8. String(const std::string &); String(const char *); String(const char *, size_t); - // Throws std::invalid_argument if not utf-16. + // Replaces invalid UTF-8 data with the replacement character (U+FFFD). + static String lossy(const std::string &) noexcept; + static String lossy(const char *) noexcept; + static String lossy(const char *, size_t) noexcept; + + // Throws std::invalid_argument if not UTF-16. String(const char16_t *); String(const char16_t *, size_t); + // Replaces invalid UTF-16 data with the replacement character (U+FFFD). + static String lossy(const char16_t *) noexcept; + static String lossy(const char16_t *, size_t) noexcept; + String &operator=(const String &) noexcept; String &operator=(String &&) noexcept; diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md index 948fa671..4d6587ab 100644 --- a/book/src/binding/vec.md +++ b/book/src/binding/vec.md @@ -47,6 +47,8 @@ public: void push_back(T &&value); template <typename... Args> void emplace_back(Args &&...args); + void truncate(size_t len); + void clear(); class iterator; iterator begin() noexcept; diff --git a/book/src/build/bazel.md b/book/src/build/bazel.md index 8f910550..6a2c82b0 100644 --- a/book/src/build/bazel.md +++ b/book/src/build/bazel.md @@ -70,7 +70,7 @@ def rust_cxx_bridge(name, src, deps = []): # demo/BUILD load("@rules_cc//cc:defs.bzl", "cc_library") -load("@rules_rust//rust:rust.bzl", "rust_binary") +load("@rules_rust//rust:defs.bzl", "rust_binary") load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_binary( diff --git a/book/src/build/cmake.md b/book/src/build/cmake.md index 4b50746c..478552e7 100644 --- a/book/src/build/cmake.md +++ b/book/src/build/cmake.md @@ -29,3 +29,19 @@ what is available in these links, feel free to make a PR adding it to this list. - Tested on Windows 10 with GNU target, and on Linux --- + +- **<https://github.com/geekbrother/cxx-corrosion-cmake>** + + - Improved rusty_cmake CMake file to use modern C++ + - Rich examples of using different primitive types and Rust's Result return to C++ + - MacOS and Linux only + +--- + +- **<https://github.com/paandahl/cpp-with-rust>** + + - Same blobstore example as the official demo, but inverted languages + - Minimal CMake configuration + - Tested on Linux, macOS, and Windows + +--- diff --git a/book/src/cxx.png b/book/src/cxx.png Binary files differindex aeb7ca9b..07118aaf 100644 --- a/book/src/cxx.png +++ b/book/src/cxx.png diff --git a/book/src/index.md b/book/src/index.md index 7b03e7e1..7add044c 100644 --- a/book/src/index.md +++ b/book/src/index.md @@ -1,5 +1,5 @@ <div class="badges"> -<a href="https://github.com/dtolnay/cxx"><img src="https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github" alt="github" height="28" class="badge"></a><a href="https://crates.io/crates/cxx"><img src="https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust" alt="crates-io" height="28" class="badge"></a><a href="https://docs.rs/cxx"><img src="https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" alt="docs-rs" height="28" class="badge"></a> +<a href="https://github.com/dtolnay/cxx"><img src="https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github" alt="github" height="28" class="badge"></a><a href="https://crates.io/crates/cxx"><img src="https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust" alt="crates-io" height="28" class="badge"></a><a href="https://docs.rs/cxx"><img src="https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" alt="docs-rs" height="28" class="badge"></a> </div> # CXX — safe interop between Rust and C++ @@ -11,7 +11,7 @@ boundary effectively within this regime. CXX fills in the low level stuff so that you get a safe binding, preventing the pitfalls of doing a foreign function interface over unsafe C-style signatures. -<div style="height:226px;padding:34px 0 24px"> +<div style="height:190px;width=718px;padding:44px 0 44px"> <object type="image/svg+xml" data="overview.svg"></object> </div> diff --git a/book/src/overview.svg b/book/src/overview.svg index 65905471..df4fcf49 100644 --- a/book/src/overview.svg +++ b/book/src/overview.svg @@ -1,99 +1,444 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="696" height="224"> - <style>line, path, circle,rect,polygon { - stroke: black; - stroke-width: 2; - stroke-opacity: 1; - fill-opacity: 1; - stroke-linecap: round; - stroke-linejoin: miter; - } - - text { - fill: black; - } - rect.backdrop{ - stroke: none; - fill: white; - fill-opacity: 0; - } - .broken{ - stroke-dasharray: 8; - } - .filled{ - fill: black; - } - .bg_filled{ - fill: white; - } - .nofill{ - fill: white; - fill-opacity: 0; - } - - text { - font-family: monospace; - font-size: 14px; - } - </style> - <defs> - <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <polygon points="0,0 0,4 4,2 0,0"></polygon> - </marker> - <marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <polygon points="0,2 2,0 4,2 2,4 0,2"></polygon> - </marker> - <marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="2" class="filled"></circle> - </marker> - <marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="2" class="bg_filled"></circle> - </marker> - <marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="3" class="bg_filled"></circle> - </marker> - </defs> - <rect class="backdrop" x="0" y="0" width="696" height="224"></rect> - <rect x="148" y="168" width="136" height="32" class="solid nofill" rx="4"></rect> - <text x="162" y="188" >Rust bindings</text> - <rect x="412" y="168" width="128" height="32" class="solid nofill" rx="4"></rect> - <text x="426" y="188" >C++ bindings</text> - <text x="272" y="28" >#[cxx::bridge] mod</text> - <text x="250" y="44" >description of boundary</text> - <line x1="220" y1="120" x2="220" y2="160" class="solid"></line> - <polygon points="216,156 224,156 220,164" class="filled"></polygon> - <line x1="476" y1="120" x2="476" y2="160" class="solid"></line> - <polygon points="472,156 480,156 476,164" class="filled"></polygon> - <text x="74" y="140" >Safe</text> - <text x="34" y="156" >straightforward</text> - <text x="530" y="156" >Straightforward</text> - <polygon points="48,180 40,184 48,188" class="filled"></polygon> - <line x1="48" y1="184" x2="144" y2="184" class="solid"></line> - <polygon points="136,180 144,184 136,188" class="filled"></polygon> - <polygon points="296,180 288,184 296,188" class="filled"></polygon> - <line x1="296" y1="184" x2="408" y2="184" class="broken"></line> - <polygon points="400,180 408,184 400,188" class="filled"></polygon> - <polygon points="552,180 544,184 552,188" class="filled"></polygon> - <line x1="552" y1="184" x2="648" y2="184" class="solid"></line> - <polygon points="644,180 652,184 644,188" class="filled"></polygon> - <text x="2" y="188" >Rust</text> - <text x="2" y="204" >code</text> - <text x="658" y="204" >code</text> - <text x="202" y="108" >Macro expansion</text> - <text x="370" y="108" >Code generation</text> - <text x="58" y="172" >Rust APIs</text> - <text x="298" y="172" >Hidden C ABI</text> - <text x="562" y="172" >C++ APIs</text> - <text x="658" y="188" >C++</text> - <g> - <path d="M 228,8 A 8,8 0,0,0 220,16" class="nofill"></path> - <line x1="228" y1="8" x2="468" y2="8" class="solid"></line> - <path d="M 468,8 A 8,8 0,0,1 476,16" class="nofill"></path> - <line x1="220" y1="16" x2="220" y2="48" class="solid"></line> - <line x1="476" y1="16" x2="476" y2="48" class="solid"></line> - <path d="M 220,48 A 8,8 0,0,0 228,56" class="nofill"></path> - <line x1="228" y1="56" x2="468" y2="56" class="solid"></line> - <line x1="348" y1="56" x2="348" y2="120" class="solid"></line> - <path d="M 476,48 A 8,8 0,0,1 468,56" class="nofill"></path> - <line x1="220" y1="120" x2="476" y2="120" class="solid"></line> - </g> +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="541.903pt" height="142.287pt" viewBox="0 0 541.903 142.287" version="1.1"> +<defs> +<g> +<symbol overflow="visible" id="glyph0-0"> +<path style="stroke:none;" d=""/> +</symbol> +<symbol overflow="visible" id="glyph0-1"> +<path style="stroke:none;" d="M 5.140625 -2.359375 L 6.234375 -2.359375 C 6.421875 -2.359375 6.890625 -2.359375 6.890625 -2.828125 C 6.890625 -3.296875 6.4375 -3.296875 6.234375 -3.296875 L 5.265625 -3.296875 L 5.515625 -5.46875 L 6.234375 -5.46875 C 6.421875 -5.46875 6.890625 -5.46875 6.890625 -5.921875 C 6.890625 -6.390625 6.4375 -6.390625 6.234375 -6.390625 L 5.65625 -6.390625 L 5.875 -8.125 C 5.9375 -8.59375 5.6875 -8.765625 5.421875 -8.765625 C 5.015625 -8.765625 4.984375 -8.390625 4.953125 -8.203125 L 4.71875 -6.390625 L 3.171875 -6.390625 L 3.40625 -8.125 C 3.453125 -8.59375 3.203125 -8.765625 2.9375 -8.765625 C 2.53125 -8.765625 2.5 -8.390625 2.46875 -8.203125 L 2.234375 -6.390625 L 1.140625 -6.390625 C 0.953125 -6.390625 0.484375 -6.390625 0.484375 -5.9375 C 0.484375 -5.46875 0.9375 -5.46875 1.140625 -5.46875 L 2.109375 -5.46875 L 1.84375 -3.296875 L 1.140625 -3.296875 C 0.953125 -3.296875 0.484375 -3.296875 0.484375 -2.84375 C 0.484375 -2.359375 0.9375 -2.359375 1.140625 -2.359375 L 1.71875 -2.359375 L 1.484375 -0.640625 C 1.40625 0 1.90625 0 1.953125 0 C 2.359375 0 2.390625 -0.375 2.421875 -0.5625 L 2.65625 -2.359375 L 4.203125 -2.359375 L 3.96875 -0.640625 C 3.890625 0 4.390625 0 4.4375 0 C 4.828125 0 4.875 -0.375 4.90625 -0.5625 Z M 3.046875 -5.46875 L 4.59375 -5.46875 L 4.328125 -3.296875 L 2.78125 -3.296875 Z M 3.046875 -5.46875 "/> +</symbol> +<symbol overflow="visible" id="glyph0-2"> +<path style="stroke:none;" d="M 6.21875 -9.125 C 6.421875 -9.125 6.796875 -9.125 6.796875 -9.53125 C 6.796875 -9.953125 6.421875 -9.953125 6.21875 -9.953125 L 3.734375 -9.953125 C 3.25 -9.953125 3.15625 -9.828125 3.15625 -9.359375 L 3.15625 0.609375 C 3.15625 1.046875 3.234375 1.1875 3.734375 1.1875 L 6.21875 1.1875 C 6.421875 1.1875 6.796875 1.1875 6.796875 0.78125 C 6.796875 0.359375 6.421875 0.359375 6.21875 0.359375 L 4.09375 0.359375 L 4.09375 -9.125 Z M 6.21875 -9.125 "/> +</symbol> +<symbol overflow="visible" id="glyph0-3"> +<path style="stroke:none;" d="M 4.21875 -9.359375 C 4.21875 -9.8125 4.125 -9.953125 3.640625 -9.953125 L 1.140625 -9.953125 C 0.953125 -9.953125 0.578125 -9.953125 0.578125 -9.53125 C 0.578125 -9.125 0.953125 -9.125 1.140625 -9.125 L 3.28125 -9.125 L 3.28125 0.359375 L 1.140625 0.359375 C 0.953125 0.359375 0.578125 0.359375 0.578125 0.78125 C 0.578125 1.1875 0.953125 1.1875 1.140625 1.1875 L 3.640625 1.1875 C 4.109375 1.1875 4.21875 1.0625 4.21875 0.609375 Z M 4.21875 -9.359375 "/> +</symbol> +<symbol overflow="visible" id="glyph0-4"> +<path style="stroke:none;" d="M 4.15625 -3.921875 L 6.203125 -3.921875 C 6.390625 -3.921875 6.84375 -3.921875 6.84375 -4.375 C 6.84375 -4.84375 6.390625 -4.84375 6.203125 -4.84375 L 4.15625 -4.84375 L 4.15625 -6.90625 C 4.15625 -7.078125 4.15625 -7.546875 3.703125 -7.546875 C 3.234375 -7.546875 3.234375 -7.09375 3.234375 -6.90625 L 3.234375 -4.84375 L 1.171875 -4.84375 C 0.984375 -4.84375 0.53125 -4.84375 0.53125 -4.390625 C 0.53125 -3.921875 0.96875 -3.921875 1.171875 -3.921875 L 3.234375 -3.921875 L 3.234375 -1.859375 C 3.234375 -1.671875 3.234375 -1.21875 3.6875 -1.21875 C 4.15625 -1.21875 4.15625 -1.65625 4.15625 -1.859375 Z M 4.15625 -3.921875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-0"> +<path style="stroke:none;" d=""/> +</symbol> +<symbol overflow="visible" id="glyph1-1"> +<path style="stroke:none;" d="M 5.75 -1.546875 C 5.09375 -1.015625 4.359375 -0.75 3.5625 -0.75 C 2.359375 -0.75 1.59375 -1.8125 1.59375 -3.203125 C 1.59375 -4.390625 2.171875 -5.6875 3.59375 -5.6875 C 4.5625 -5.6875 4.96875 -5.46875 5.578125 -5.046875 L 5.75 -5.984375 C 4.921875 -6.46875 4.453125 -6.578125 3.59375 -6.578125 C 1.625 -6.578125 0.5 -4.828125 0.5 -3.203125 C 0.5 -1.359375 1.828125 0.140625 3.546875 0.140625 C 4.25 0.140625 5.046875 -0.03125 5.84375 -0.609375 C 5.84375 -0.640625 5.796875 -1.09375 5.78125 -1.140625 Z M 5.75 -1.546875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-2"> +<path style="stroke:none;" d="M 3.640625 -3.28125 L 6.1875 -6.375 L 4.984375 -6.375 L 3.171875 -4.046875 L 1.296875 -6.375 L 0.078125 -6.375 L 2.6875 -3.28125 L 0 0 L 1.1875 0 L 3.171875 -2.671875 L 5.203125 0 L 6.40625 0 Z M 3.640625 -3.28125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-3"> +<path style="stroke:none;" d="M 2.53125 -6.375 L 1.359375 -6.375 L 1.359375 -5.203125 L 2.53125 -5.203125 Z M 1.359375 -1.15625 L 1.359375 0 L 2.53125 0 L 2.53125 -1.15625 Z M 1.359375 -1.15625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-4"> +<path style="stroke:none;" d="M 2.1875 -9.953125 L 1.125 -9.953125 L 1.125 0 L 2.203125 0 L 2.203125 -0.640625 C 2.875 -0.015625 3.578125 0.140625 4.078125 0.140625 C 5.4375 0.140625 6.6875 -1.25 6.6875 -3.203125 C 6.6875 -4.96875 5.734375 -6.515625 4.40625 -6.515625 C 3.984375 -6.515625 3.0625 -6.421875 2.1875 -5.703125 Z M 2.203125 -4.828125 C 2.46875 -5.234375 2.984375 -5.65625 3.6875 -5.65625 C 4.5625 -5.65625 5.59375 -4.984375 5.59375 -3.203125 C 5.59375 -1.328125 4.421875 -0.71875 3.546875 -0.71875 C 3.140625 -0.71875 2.875 -0.859375 2.609375 -1.0625 C 2.265625 -1.359375 2.203125 -1.625 2.203125 -1.859375 Z M 2.203125 -4.828125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-5"> +<path style="stroke:none;" d="M 2.1875 -3.140625 C 2.1875 -4.59375 3.265625 -5.53125 4.5625 -5.546875 L 4.5625 -6.515625 C 3.25 -6.5 2.5 -5.734375 2.109375 -5.171875 L 2.109375 -6.4375 L 1.125 -6.4375 L 1.125 0 L 2.1875 0 Z M 2.1875 -3.140625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-6"> +<path style="stroke:none;" d="M 2.265625 -9.734375 L 1.03125 -9.734375 L 1.03125 -8.5 L 2.265625 -8.5 Z M 2.1875 -6.375 L 1.125 -6.375 L 1.125 0 L 2.1875 0 Z M 2.1875 -6.375 "/> +</symbol> +<symbol overflow="visible" id="glyph1-7"> +<path style="stroke:none;" d="M 6.0625 -9.953125 L 5 -9.953125 L 5 -5.765625 C 4.34375 -6.3125 3.59375 -6.515625 2.984375 -6.515625 C 1.625 -6.515625 0.5 -5.046875 0.5 -3.1875 C 0.5 -1.328125 1.5625 0.140625 2.921875 0.140625 C 3.453125 0.140625 4.265625 -0.03125 4.984375 -0.734375 L 4.984375 0 L 6.0625 0 Z M 4.984375 -1.6875 C 4.640625 -1.078125 4.125 -0.71875 3.5 -0.71875 C 2.625 -0.71875 1.59375 -1.390625 1.59375 -3.171875 C 1.59375 -5.078125 2.8125 -5.65625 3.640625 -5.65625 C 4.203125 -5.65625 4.65625 -5.359375 4.984375 -4.890625 Z M 4.984375 -1.6875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-8"> +<path style="stroke:none;" d="M 4.890625 -5.65625 C 4.890625 -5.65625 4.921875 -5.625 4.9375 -5.59375 C 5.234375 -5.625 5.546875 -5.671875 6.078125 -5.671875 C 6.125 -5.671875 6.453125 -5.671875 6.8125 -5.640625 L 6.65625 -6.515625 C 6.390625 -6.515625 5.40625 -6.5 4.453125 -6.03125 C 3.984375 -6.4375 3.40625 -6.515625 3.125 -6.515625 C 1.875 -6.515625 0.875 -5.46875 0.875 -4.203125 C 0.875 -3.6875 1.03125 -3.21875 1.34375 -2.78125 C 1.015625 -2.328125 0.9375 -1.890625 0.9375 -1.546875 C 0.9375 -1.015625 1.140625 -0.65625 1.296875 -0.46875 C 0.5625 0 0.390625 0.609375 0.390625 1.015625 C 0.390625 2.0625 1.75 2.9375 3.5 2.9375 C 5.25 2.9375 6.625 2.09375 6.625 1 C 6.625 -1 4.296875 -1 3.71875 -1 L 2.5 -1 C 2.296875 -1 1.671875 -1 1.671875 -1.765625 C 1.671875 -2.078125 1.734375 -2.171875 1.828125 -2.296875 C 2.0625 -2.125 2.53125 -1.875 3.109375 -1.875 C 4.34375 -1.875 5.359375 -2.890625 5.359375 -4.203125 C 5.359375 -4.71875 5.171875 -5.25 4.875 -5.640625 Z M 3.125 -2.671875 C 2.5 -2.671875 1.859375 -3.09375 1.859375 -4.1875 C 1.859375 -5.46875 2.671875 -5.71875 3.109375 -5.71875 C 3.75 -5.71875 4.375 -5.296875 4.375 -4.203125 C 4.375 -2.921875 3.578125 -2.671875 3.125 -2.671875 Z M 3.734375 0.03125 C 4.046875 0.03125 5.625 0.03125 5.625 1.015625 C 5.625 1.671875 4.640625 2.15625 3.515625 2.15625 C 2.390625 2.15625 1.390625 1.703125 1.390625 1 C 1.390625 0.96875 1.390625 0.03125 2.484375 0.03125 Z M 3.734375 0.03125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-9"> +<path style="stroke:none;" d="M 5.84375 -3.234375 C 5.84375 -3.84375 5.78125 -4.71875 5.328125 -5.484375 C 4.734375 -6.46875 3.734375 -6.578125 3.3125 -6.578125 C 1.765625 -6.578125 0.46875 -5.09375 0.46875 -3.234375 C 0.46875 -1.328125 1.84375 0.140625 3.515625 0.140625 C 4.171875 0.140625 4.96875 -0.046875 5.75 -0.609375 C 5.75 -0.671875 5.703125 -1.125 5.703125 -1.140625 C 5.6875 -1.15625 5.671875 -1.484375 5.671875 -1.53125 C 4.8125 -0.8125 3.96875 -0.71875 3.546875 -0.71875 C 2.4375 -0.71875 1.484375 -1.703125 1.46875 -3.234375 Z M 1.546875 -4 C 1.796875 -4.96875 2.46875 -5.71875 3.3125 -5.71875 C 3.765625 -5.71875 4.75 -5.515625 4.984375 -4 Z M 1.546875 -4 "/> +</symbol> +<symbol overflow="visible" id="glyph1-10"> +<path style="stroke:none;" d="M 10 -4.3125 C 10 -5.3125 9.734375 -6.515625 8.0625 -6.515625 C 6.84375 -6.515625 6.171875 -5.671875 5.953125 -5.34375 C 5.6875 -6.25 4.90625 -6.515625 4.15625 -6.515625 C 2.984375 -6.515625 2.359375 -5.75 2.125 -5.453125 L 2.125 -6.4375 L 1.109375 -6.4375 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.515625 2.5625 -5.65625 3.609375 -5.65625 C 4.9375 -5.65625 5 -4.75 5 -4.21875 L 5 0 L 6.09375 0 L 6.09375 -3.578125 C 6.09375 -4.515625 6.46875 -5.65625 7.515625 -5.65625 C 8.828125 -5.65625 8.90625 -4.75 8.90625 -4.21875 L 8.90625 0 L 10 0 Z M 10 -4.3125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-11"> +<path style="stroke:none;" d="M 6.578125 -3.15625 C 6.578125 -5.09375 5.15625 -6.578125 3.515625 -6.578125 C 1.828125 -6.578125 0.4375 -5.0625 0.4375 -3.15625 C 0.4375 -1.28125 1.859375 0.140625 3.5 0.140625 C 5.1875 0.140625 6.578125 -1.3125 6.578125 -3.15625 Z M 3.515625 -0.75 C 2.484375 -0.75 1.515625 -1.609375 1.515625 -3.296875 C 1.515625 -5.03125 2.59375 -5.71875 3.5 -5.71875 C 4.484375 -5.71875 5.5 -4.984375 5.5 -3.296875 C 5.5 -1.53125 4.46875 -0.75 3.515625 -0.75 Z M 3.515625 -0.75 "/> +</symbol> +<symbol overflow="visible" id="glyph1-12"> +<path style="stroke:none;" d="M 4.8125 -6.140625 C 3.90625 -6.5625 3.125 -6.578125 2.796875 -6.578125 C 2.46875 -6.578125 0.46875 -6.578125 0.46875 -4.71875 C 0.46875 -4.09375 0.8125 -3.65625 1.03125 -3.453125 C 1.546875 -3.015625 1.90625 -2.9375 2.75 -2.765625 C 3.234375 -2.671875 4.0625 -2.5 4.0625 -1.734375 C 4.0625 -0.75 2.9375 -0.75 2.734375 -0.75 C 2.171875 -0.75 1.328125 -0.90625 0.5625 -1.46875 L 0.390625 -0.484375 C 0.453125 -0.4375 1.4375 0.140625 2.75 0.140625 C 4.609375 0.140625 5.046875 -0.96875 5.046875 -1.828125 C 5.046875 -2.546875 4.609375 -3.015625 4.546875 -3.078125 C 4.015625 -3.625 3.578125 -3.71875 2.71875 -3.890625 C 2.1875 -3.984375 1.46875 -4.125 1.46875 -4.84375 C 1.46875 -5.734375 2.46875 -5.734375 2.65625 -5.734375 C 3.40625 -5.734375 4.015625 -5.5625 4.640625 -5.203125 Z M 4.8125 -6.140625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-13"> +<path style="stroke:none;" d="M 2.203125 -0.640625 C 2.703125 -0.203125 3.296875 0.140625 4.078125 0.140625 C 5.453125 0.140625 6.6875 -1.25 6.6875 -3.203125 C 6.6875 -4.9375 5.765625 -6.515625 4.4375 -6.515625 C 3.84375 -6.515625 2.921875 -6.328125 2.1875 -5.6875 L 2.1875 -6.375 L 1.125 -6.375 L 1.125 2.78125 L 2.203125 2.78125 Z M 2.203125 -4.8125 C 2.53125 -5.3125 3.078125 -5.625 3.671875 -5.625 C 4.734375 -5.625 5.59375 -4.546875 5.59375 -3.1875 C 5.59375 -1.75 4.609375 -0.71875 3.546875 -0.71875 C 3.140625 -0.71875 2.875 -0.859375 2.609375 -1.0625 C 2.25 -1.375 2.203125 -1.640625 2.203125 -1.859375 Z M 2.203125 -4.8125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-14"> +<path style="stroke:none;" d="M 2.453125 -5.53125 L 4.4375 -5.53125 L 4.4375 -6.375 L 2.453125 -6.375 L 2.453125 -8.1875 L 1.46875 -8.1875 L 1.46875 -6.375 L 0.265625 -6.375 L 0.265625 -5.53125 L 1.4375 -5.53125 L 1.4375 -1.671875 C 1.4375 -0.84375 1.625 0.140625 2.609375 0.140625 C 3.578125 0.140625 4.234375 -0.1875 4.671875 -0.421875 L 4.453125 -1.25 C 3.953125 -0.796875 3.421875 -0.75 3.171875 -0.75 C 2.53125 -0.75 2.453125 -1.421875 2.453125 -1.921875 Z M 2.453125 -5.53125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-15"> +<path style="stroke:none;" d="M 6.078125 -4.3125 C 6.078125 -5.1875 5.890625 -6.515625 4.15625 -6.515625 C 3.359375 -6.515625 2.671875 -6.15625 2.125 -5.46875 L 2.125 -6.4375 L 1.109375 -6.4375 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.453125 2.53125 -5.65625 3.609375 -5.65625 C 4.953125 -5.65625 4.984375 -4.71875 4.984375 -4.21875 L 4.984375 0 L 6.078125 0 Z M 6.078125 -4.3125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-16"> +<path style="stroke:none;" d="M 2.484375 -5.53125 L 4.015625 -5.53125 L 4.015625 -6.375 L 2.453125 -6.375 L 2.453125 -8.09375 C 2.453125 -9.0625 3.265625 -9.234375 3.75 -9.234375 C 4.25 -9.234375 4.6875 -9.078125 4.859375 -9.015625 L 4.859375 -9.953125 C 4.765625 -9.984375 4.28125 -10.09375 3.765625 -10.09375 C 2.390625 -10.09375 1.421875 -9.046875 1.421875 -7.65625 L 1.421875 -6.375 L 0.375 -6.375 L 0.375 -5.53125 L 1.421875 -5.53125 L 1.421875 0 L 2.484375 0 Z M 2.484375 -5.53125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-17"> +<path style="stroke:none;" d="M 6.078125 -6.375 L 4.984375 -6.375 L 4.984375 -2.265625 C 4.984375 -1.171875 4.234375 -0.640625 3.296875 -0.640625 C 2.296875 -0.640625 2.1875 -1.015625 2.1875 -1.65625 L 2.1875 -6.375 L 1.109375 -6.375 L 1.109375 -1.59375 C 1.109375 -0.5625 1.4375 0.140625 2.609375 0.140625 C 3.015625 0.140625 4.140625 0.078125 5.015625 -0.71875 L 5.015625 0 L 6.078125 0 Z M 6.078125 -6.375 "/> +</symbol> +<symbol overflow="visible" id="glyph1-18"> +<path style="stroke:none;" d="M 5.609375 -4.203125 C 5.609375 -5.578125 4.625 -6.578125 3.28125 -6.578125 C 2.421875 -6.578125 1.78125 -6.390625 1.078125 -5.984375 L 1.15625 -5.03125 C 1.796875 -5.5 2.453125 -5.75 3.28125 -5.75 C 3.9375 -5.75 4.515625 -5.21875 4.515625 -4.171875 L 4.515625 -3.578125 C 3.875 -3.5625 3.015625 -3.515625 2.15625 -3.234375 C 1.1875 -2.890625 0.625 -2.359375 0.625 -1.65625 C 0.625 -1.015625 1 0.140625 2.21875 0.140625 C 3.015625 0.140625 4.015625 -0.09375 4.546875 -0.53125 L 4.546875 0 L 5.609375 0 Z M 4.515625 -1.921875 C 4.515625 -1.640625 4.515625 -1.296875 4.046875 -1 C 3.65625 -0.765625 3.171875 -0.71875 2.953125 -0.71875 C 2.1875 -0.71875 1.65625 -1.140625 1.65625 -1.65625 C 1.65625 -2.640625 3.640625 -2.859375 4.515625 -2.859375 Z M 4.515625 -1.921875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-19"> +<path style="stroke:none;" d="M 6.203125 -6.375 L 5.140625 -6.375 C 4.46875 -4.671875 3.375 -1.859375 3.3125 -0.828125 L 3.296875 -0.828125 C 3.234375 -1.671875 2.46875 -3.578125 2.359375 -3.859375 L 1.328125 -6.375 L 0.203125 -6.375 L 2.875 0 L 2.359375 1.3125 C 2.046875 2.015625 1.84375 2.09375 1.578125 2.09375 C 1.375 2.09375 0.921875 2.046875 0.46875 1.875 L 0.5625 2.8125 C 0.640625 2.828125 1.125 2.921875 1.578125 2.921875 C 1.921875 2.921875 2.59375 2.921875 3.21875 1.34375 Z M 6.203125 -6.375 "/> +</symbol> +<symbol overflow="visible" id="glyph1-20"> +<path style="stroke:none;" d="M 5.84375 -4.671875 C 7.40625 -5.125 8.25 -6.203125 8.25 -7.265625 C 8.25 -8.703125 6.71875 -9.953125 4.6875 -9.953125 L 1.3125 -9.953125 L 1.3125 0 L 2.515625 0 L 2.515625 -4.546875 L 4.75 -4.546875 L 7.40625 0 L 8.640625 0 Z M 2.515625 -5.40625 L 2.515625 -9.15625 L 4.53125 -9.15625 C 6.265625 -9.15625 7.109375 -8.234375 7.109375 -7.265625 C 7.109375 -6.390625 6.34375 -5.40625 4.53125 -5.40625 Z M 2.515625 -5.40625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-21"> +<path style="stroke:none;" d="M 8.171875 -1.65625 C 7.296875 -1 6.703125 -0.765625 5.453125 -0.765625 C 3.578125 -0.765625 2.171875 -2.703125 2.171875 -5 C 2.171875 -6.9375 3.328125 -9.21875 5.515625 -9.21875 C 6.453125 -9.21875 7.171875 -8.9375 7.890625 -8.453125 L 8.109375 -9.625 C 7.171875 -9.984375 6.46875 -10.109375 5.484375 -10.109375 C 3.046875 -10.109375 0.953125 -7.953125 0.953125 -4.984375 C 0.953125 -1.84375 3.25 0.125 5.34375 0.125 C 6.78125 0.125 7.09375 0.046875 8.265625 -0.65625 Z M 8.171875 -1.65625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-22"> +<path style="stroke:none;" d="M 3 -9.953125 L 1.359375 -9.953125 L 1.359375 0 L 2.46875 0 L 2.46875 -8.84375 L 2.484375 -8.84375 C 2.6875 -7.875 5 -1.734375 5.546875 -0.296875 L 6.59375 -0.296875 C 7.078125 -1.53125 9.4375 -7.78125 9.703125 -8.859375 L 9.703125 0 L 10.8125 0 L 10.8125 -9.953125 L 9.1875 -9.953125 L 7.546875 -5.53125 C 6.796875 -3.53125 6.234375 -2.015625 6.09375 -1.359375 L 6.078125 -1.359375 C 6.03125 -1.609375 5.859375 -2.140625 5.671875 -2.703125 C 5.40625 -3.46875 5.40625 -3.5 5.171875 -4.09375 Z M 3 -9.953125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-23"> +<path style="stroke:none;" d="M 8.53125 -9.953125 L 7.296875 -9.953125 L 7.296875 -5.609375 L 2.53125 -5.609375 L 2.53125 -9.953125 L 1.296875 -9.953125 L 1.296875 0 L 2.53125 0 L 2.53125 -4.75 L 7.296875 -4.75 L 7.296875 0 L 8.53125 0 Z M 8.53125 -9.953125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-24"> +<path style="stroke:none;" d="M 5.265625 -9.953125 L 4 -9.953125 L 0.390625 0 L 1.453125 0 L 2.5 -2.90625 L 6.546875 -2.90625 L 7.609375 0 L 8.875 0 Z M 4.515625 -8.921875 L 6.234375 -3.71875 L 2.8125 -3.71875 Z M 4.515625 -8.921875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-25"> +<path style="stroke:none;" d="M 1.328125 -9.953125 L 1.328125 0 L 5.03125 0 C 7.0625 0 8.53125 -1.296875 8.53125 -2.703125 C 8.53125 -3.953125 7.28125 -4.984375 5.8125 -5.203125 C 7.484375 -5.671875 8.140625 -6.625 8.140625 -7.453125 C 8.140625 -8.75 6.671875 -9.953125 4.640625 -9.953125 Z M 2.5 -5.609375 L 2.5 -9.15625 L 4.265625 -9.15625 C 5.796875 -9.15625 7.03125 -8.390625 7.03125 -7.4375 C 7.03125 -6.4375 5.796875 -5.609375 4.28125 -5.609375 Z M 2.5 -0.796875 L 2.5 -4.75 L 4.40625 -4.75 C 6.25 -4.75 7.40625 -3.71875 7.40625 -2.71875 C 7.40625 -1.703125 6.234375 -0.796875 4.640625 -0.796875 Z M 2.5 -0.796875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-26"> +<path style="stroke:none;" d="M 2.53125 -9.953125 L 1.296875 -9.953125 L 1.296875 0 L 2.53125 0 Z M 2.53125 -9.953125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-27"> +<path style="stroke:none;" d="M 6.53125 -9.546875 C 5.9375 -9.875 5.21875 -10.25 3.9375 -10.25 C 2.015625 -10.25 0.78125 -8.875 0.78125 -7.4375 C 0.78125 -6.421875 1.390625 -5.765625 1.46875 -5.6875 C 2.171875 -4.984375 2.65625 -4.84375 3.578125 -4.625 C 4.796875 -4.3125 4.984375 -4.265625 5.453125 -3.78125 C 5.6875 -3.53125 5.90625 -3.0625 5.90625 -2.5625 C 5.90625 -1.578125 5.09375 -0.65625 3.859375 -0.65625 C 2.8125 -0.65625 1.6875 -1.078125 0.84375 -1.84375 L 0.625 -0.6875 C 1.9375 0.171875 3.203125 0.296875 3.859375 0.296875 C 5.703125 0.296875 7.015625 -1.125 7.015625 -2.71875 C 7.015625 -3.625 6.5625 -4.3125 6.25 -4.671875 C 5.59375 -5.375 5.0625 -5.515625 4.109375 -5.765625 C 3.125 -6.015625 2.765625 -6.09375 2.453125 -6.390625 C 2.265625 -6.59375 1.875 -6.953125 1.875 -7.609375 C 1.875 -8.484375 2.671875 -9.328125 3.9375 -9.328125 C 5.15625 -9.328125 5.796875 -8.84375 6.3125 -8.390625 Z M 6.53125 -9.546875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-28"> +<path style="stroke:none;" d="M 6.078125 -4.3125 C 6.078125 -5.1875 5.890625 -6.515625 4.15625 -6.515625 C 3.171875 -6.515625 2.515625 -5.953125 2.171875 -5.515625 L 2.171875 -9.953125 L 1.109375 -9.953125 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.453125 2.53125 -5.65625 3.609375 -5.65625 C 4.953125 -5.65625 4.984375 -4.71875 4.984375 -4.21875 L 4.984375 0 L 6.078125 0 Z M 6.078125 -4.3125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-29"> +<path style="stroke:none;" d="M 9.328125 -6.375 L 8.28125 -6.375 L 7.421875 -3.453125 C 7.21875 -2.765625 6.8125 -1.421875 6.75 -0.796875 L 6.734375 -0.796875 C 6.703125 -1.140625 6.46875 -2.109375 6.171875 -3.125 L 5.21875 -6.375 L 4.234375 -6.375 L 3.40625 -3.5625 C 3.15625 -2.671875 2.8125 -1.4375 2.765625 -0.828125 L 2.75 -0.828125 C 2.734375 -1.109375 2.578125 -1.859375 2.3125 -2.828125 L 1.296875 -6.375 L 0.203125 -6.375 L 2.125 0 L 3.234375 0 C 3.765625 -1.8125 4.609375 -4.53125 4.6875 -5.53125 L 4.703125 -5.53125 C 4.734375 -4.953125 5.015625 -3.921875 5.125 -3.578125 L 6.140625 0 L 7.40625 0 Z M 9.328125 -6.375 "/> +</symbol> +<symbol overflow="visible" id="glyph1-30"> +<path style="stroke:none;" d="M 4.8125 -4.140625 C 6.78125 -4.140625 8.140625 -5.5625 8.140625 -7.0625 C 8.140625 -8.578125 6.75 -9.953125 4.8125 -9.953125 L 1.3125 -9.953125 L 1.3125 0 L 2.53125 0 L 2.53125 -4.140625 Z M 4.5 -9.15625 C 6.1875 -9.15625 7.015625 -8.140625 7.015625 -7.078125 C 7.015625 -5.9375 6.140625 -4.984375 4.5 -4.984375 L 2.515625 -4.984375 L 2.515625 -9.15625 Z M 4.5 -9.15625 "/> +</symbol> +</g> +<clipPath id="clip1"> + <path d="M 0 0 L 541.902344 0 L 541.902344 142.285156 L 0 142.285156 Z M 0 0 "/> +</clipPath> +<clipPath id="clip2"> + <path d="M 102 92 L 245 92 L 245 142.285156 L 102 142.285156 Z M 102 92 "/> +</clipPath> +<clipPath id="clip3"> + <path d="M 302 92 L 442 92 L 442 142.285156 L 302 142.285156 Z M 302 92 "/> +</clipPath> +<clipPath id="clip4"> + <path d="M 17 101 L 67 101 L 67 142.285156 L 17 142.285156 Z M 17 101 "/> +</clipPath> +<clipPath id="clip5"> + <path d="M 92 101 L 142 101 L 142 142.285156 L 92 142.285156 Z M 92 101 "/> +</clipPath> +<clipPath id="clip6"> + <path d="M 205 101 L 255 101 L 255 142.285156 L 205 142.285156 Z M 205 101 "/> +</clipPath> +<clipPath id="clip7"> + <path d="M 292 101 L 342 101 L 342 142.285156 L 292 142.285156 Z M 292 101 "/> +</clipPath> +<clipPath id="clip8"> + <path d="M 402 101 L 452 101 L 452 142.285156 L 402 142.285156 Z M 402 101 "/> +</clipPath> +<clipPath id="clip9"> + <path d="M 479 101 L 528 101 L 528 142.285156 L 479 142.285156 Z M 479 101 "/> +</clipPath> +</defs> +<g id="surface1"> +<g clip-path="url(#clip1)" clip-rule="nonzero"> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 142.285156 L 543.933594 142.285156 L 543.933594 -0.535156 L 0 -0.535156 Z M 0 142.285156 "/> +</g> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 93.618469 13.681906 L -93.619813 13.681906 C -96.369813 13.681906 -98.600281 11.451438 -98.600281 8.701438 L -98.600281 -17.204812 C -98.600281 -19.954812 -96.369813 -22.185281 -93.619813 -22.185281 L 93.618469 -22.185281 C 96.368469 -22.185281 98.598937 -19.954812 98.598937 -17.204812 L 98.598937 8.701438 C 98.598937 11.451438 96.368469 13.681906 93.618469 13.681906 Z M 93.618469 13.681906 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-1" x="215.699" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-2" x="222.091667" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-1" x="229.467" y="15.293"/> + <use xlink:href="#glyph1-2" x="235.710466" y="15.293"/> + <use xlink:href="#glyph1-2" x="242.136129" y="15.293"/> + <use xlink:href="#glyph1-3" x="248.561792" y="15.293"/> + <use xlink:href="#glyph1-3" x="252.463959" y="15.293"/> + <use xlink:href="#glyph1-4" x="256.366125" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="263.184874" y="15.293"/> + <use xlink:href="#glyph1-6" x="267.959289" y="15.293"/> + <use xlink:href="#glyph1-7" x="271.263219" y="15.293"/> + <use xlink:href="#glyph1-8" x="278.469315" y="15.293"/> + <use xlink:href="#glyph1-9" x="285.493215" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-3" x="291.733" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-10" x="303.797" y="15.293"/> + <use xlink:href="#glyph1-11" x="314.905263" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="322.31651" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="203.901" y="29.24"/> + <use xlink:href="#glyph1-9" x="211.107096" y="29.24"/> + <use xlink:href="#glyph1-12" x="217.350563" y="29.24"/> + <use xlink:href="#glyph1-1" x="222.734691" y="29.24"/> + <use xlink:href="#glyph1-5" x="228.978158" y="29.24"/> + <use xlink:href="#glyph1-6" x="233.752573" y="29.24"/> + <use xlink:href="#glyph1-13" x="237.056503" y="29.24"/> + <use xlink:href="#glyph1-14" x="244.262599" y="29.24"/> + <use xlink:href="#glyph1-6" x="249.335415" y="29.24"/> + <use xlink:href="#glyph1-11" x="252.639345" y="29.24"/> + <use xlink:href="#glyph1-15" x="259.663245" y="29.24"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-11" x="271.546202" y="29.24"/> + <use xlink:href="#glyph1-16" x="278.570102" y="29.24"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-4" x="287.553692" y="29.24"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-11" x="295.147136" y="29.24"/> + <use xlink:href="#glyph1-17" x="302.171035" y="29.24"/> + <use xlink:href="#glyph1-15" x="309.377132" y="29.24"/> + <use xlink:href="#glyph1-7" x="316.583228" y="29.24"/> + <use xlink:href="#glyph1-18" x="323.789324" y="29.24"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="330.126041" y="29.24"/> + <use xlink:href="#glyph1-19" x="334.900456" y="29.24"/> +</g> +<g clip-path="url(#clip2)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -53.619813 -99.095437 L -144.807313 -99.095437 C -147.006531 -99.095437 -148.791688 -100.880594 -148.791688 -103.079812 L -148.791688 -118.025125 C -148.791688 -120.22825 -147.006531 -122.0095 -144.807313 -122.0095 L -53.619813 -122.0095 C -51.420594 -122.0095 -49.635438 -120.22825 -49.635438 -118.025125 L -49.635438 -103.079812 C -49.635438 -100.880594 -51.420594 -99.095437 -53.619813 -99.095437 Z M -53.619813 -99.095437 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-20" x="133.785" y="129.463"/> + <use xlink:href="#glyph1-17" x="142.825975" y="129.463"/> + <use xlink:href="#glyph1-12" x="150.032072" y="129.463"/> + <use xlink:href="#glyph1-14" x="155.4162" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-4" x="165.165878" y="129.463"/> + <use xlink:href="#glyph1-6" x="172.371974" y="129.463"/> + <use xlink:href="#glyph1-15" x="175.675904" y="129.463"/> + <use xlink:href="#glyph1-7" x="182.882" y="129.463"/> + <use xlink:href="#glyph1-6" x="190.088097" y="129.463"/> + <use xlink:href="#glyph1-15" x="193.392026" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-8" x="200.612469" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-12" x="207.622022" y="129.463"/> +</g> +<g clip-path="url(#clip3)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 143.3255 -99.095437 L 55.102844 -99.095437 C 52.903625 -99.095437 51.118469 -100.880594 51.118469 -103.079812 L 51.118469 -118.025125 C 51.118469 -120.22825 52.903625 -122.0095 55.102844 -122.0095 L 143.3255 -122.0095 C 145.524719 -122.0095 147.309875 -120.22825 147.309875 -118.025125 L 147.309875 -103.079812 C 147.309875 -100.880594 145.524719 -99.095437 143.3255 -99.095437 Z M 143.3255 -99.095437 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="333.693" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-4" x="342.668" y="129.463"/> + <use xlink:href="#glyph0-4" x="350.050555" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-4" x="362.115" y="129.463"/> + <use xlink:href="#glyph1-6" x="369.321096" y="129.463"/> + <use xlink:href="#glyph1-15" x="372.625026" y="129.463"/> + <use xlink:href="#glyph1-7" x="379.831122" y="129.463"/> + <use xlink:href="#glyph1-6" x="387.037219" y="129.463"/> + <use xlink:href="#glyph1-15" x="390.341148" y="129.463"/> + <use xlink:href="#glyph1-8" x="397.547245" y="129.463"/> + <use xlink:href="#glyph1-12" x="404.571144" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-20" x="4.343" y="126.574"/> + <use xlink:href="#glyph1-17" x="13.383975" y="126.574"/> + <use xlink:href="#glyph1-12" x="20.590072" y="126.574"/> + <use xlink:href="#glyph1-14" x="25.9742" y="126.574"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-1" x="3.941" y="140.522"/> + <use xlink:href="#glyph1-11" x="10.184466" y="140.522"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="17.595713" y="140.522"/> + <use xlink:href="#glyph1-9" x="24.801809" y="140.522"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="514.177" y="126.574"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-4" x="523.151" y="126.574"/> + <use xlink:href="#glyph0-4" x="530.533555" y="126.574"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-1" x="514.177" y="140.522"/> + <use xlink:href="#glyph1-11" x="520.420466" y="140.522"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="527.831713" y="140.522"/> + <use xlink:href="#glyph1-9" x="535.037809" y="140.522"/> +</g> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00128125 -22.931375 L 0.00128125 -68.032937 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -99.213563 -89.1345 L -99.213563 -68.032937 L 99.212219 -68.032937 L 99.212219 -89.1345 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317146 0.0002575 C 5.539802 0.207289 2.129646 1.371351 0.00074 2.640882 L 0.00074 -2.640368 C 2.129646 -1.370836 5.539802 -0.206774 6.317146 0.0002575 Z M 6.317146 0.0002575 " transform="matrix(0,1,1,0,173.39818,103.56176)"/> +<path style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317146 -0.00160125 C 5.539802 0.20543 2.129646 1.373399 0.00074 2.639024 L 0.00074 -2.63832 C 2.129646 -1.372695 5.539802 -0.204726 6.317146 -0.00160125 Z M 6.317146 -0.00160125 " transform="matrix(0,1,1,0,371.82582,103.56176)"/> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -227.619813 -110.552469 L -158.752625 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 38.675781 124.980469 C 39.453125 125.1875 42.859375 126.351562 44.992188 127.621094 L 44.992188 122.339844 C 42.859375 123.609375 39.453125 124.777344 38.675781 124.980469 Z M 38.675781 124.980469 "/> +<g clip-path="url(#clip4)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.316149 -0.00123125 C 5.538805 0.2058 2.132555 1.369862 -0.0002575 2.639394 L -0.0002575 -2.641856 C 2.132555 -1.372325 5.538805 -0.204356 6.316149 -0.00123125 Z M 6.316149 -0.00123125 " transform="matrix(-1,0,0,1,44.99193,124.9817)"/> +</g> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 120.171875 124.980469 C 119.398438 124.777344 115.988281 123.609375 113.859375 122.339844 L 113.859375 127.621094 C 115.988281 126.351562 119.398438 125.1875 120.171875 124.980469 Z M 120.171875 124.980469 "/> +<g clip-path="url(#clip5)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.313975 0.00123125 C 5.540537 0.204356 2.130381 1.372325 0.001475 2.641856 L 0.001475 -2.639394 C 2.130381 -1.369862 5.540537 -0.2058 6.313975 0.00123125 Z M 6.313975 0.00123125 " transform="matrix(1,0,0,-1,113.8579,124.9817)"/> +</g> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:7.97021,5.97766;stroke-miterlimit:10;" d="M -39.6745 -110.552469 L 41.157531 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 226.621094 124.980469 C 227.398438 125.1875 230.808594 126.351562 232.9375 127.621094 L 232.9375 122.339844 C 230.808594 123.609375 227.398438 124.777344 226.621094 124.980469 Z M 226.621094 124.980469 "/> +<g clip-path="url(#clip6)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317366 -0.00123125 C 5.540023 0.2058 2.129866 1.369862 0.00096 2.639394 L 0.00096 -2.641856 C 2.129866 -1.372325 5.540023 -0.204356 6.317366 -0.00123125 Z M 6.317366 -0.00123125 " transform="matrix(-1,0,0,1,232.93846,124.9817)"/> +</g> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 320.082031 124.980469 C 319.308594 124.777344 315.898438 123.609375 313.769531 122.339844 L 313.769531 127.621094 C 315.898438 126.351562 319.308594 125.1875 320.082031 124.980469 Z M 320.082031 124.980469 "/> +<g clip-path="url(#clip7)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.313811 0.00123125 C 5.540374 0.204356 2.130217 1.372325 0.00131125 2.641856 L 0.00131125 -2.639394 C 2.130217 -1.369862 5.540374 -0.2058 6.313811 0.00123125 Z M 6.313811 0.00123125 " transform="matrix(1,0,0,-1,313.76822,124.9817)"/> +</g> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.270812 -110.552469 L 227.618469 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 423.566406 124.980469 C 424.34375 125.1875 427.753906 126.351562 429.882812 127.621094 L 429.882812 122.339844 C 427.753906 123.609375 424.34375 124.777344 423.566406 124.980469 Z M 423.566406 124.980469 "/> +<g clip-path="url(#clip8)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317014 -0.00123125 C 5.53967 0.2058 2.129514 1.369862 0.0006075 2.639394 L 0.0006075 -2.641856 C 2.129514 -1.372325 5.53967 -0.204356 6.317014 -0.00123125 Z M 6.317014 -0.00123125 " transform="matrix(-1,0,0,1,429.88342,124.9817)"/> +</g> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 506.546875 124.980469 C 505.773438 124.777344 502.363281 123.609375 500.230469 122.339844 L 500.230469 127.621094 C 502.363281 126.351562 505.773438 125.1875 506.546875 124.980469 Z M 506.546875 124.980469 "/> +<g clip-path="url(#clip9)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.314805 0.00123125 C 5.541367 0.204356 2.131211 1.372325 -0.00160125 2.641856 L -0.00160125 -2.639394 C 2.131211 -1.369862 5.541367 -0.2058 6.314805 0.00123125 Z M 6.314805 0.00123125 " transform="matrix(1,0,0,-1,500.23207,124.9817)"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-22" x="148.925" y="75.603"/> + <use xlink:href="#glyph1-18" x="161.112097" y="75.603"/> + <use xlink:href="#glyph1-1" x="167.836161" y="75.603"/> + <use xlink:href="#glyph1-5" x="174.079627" y="75.603"/> + <use xlink:href="#glyph1-11" x="178.854042" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-9" x="190.554803" y="75.603"/> + <use xlink:href="#glyph1-2" x="196.798269" y="75.603"/> + <use xlink:href="#glyph1-13" x="203.223932" y="75.603"/> + <use xlink:href="#glyph1-18" x="210.430029" y="75.603"/> + <use xlink:href="#glyph1-15" x="217.154093" y="75.603"/> + <use xlink:href="#glyph1-12" x="224.360189" y="75.603"/> + <use xlink:href="#glyph1-6" x="229.744318" y="75.603"/> + <use xlink:href="#glyph1-11" x="233.048248" y="75.603"/> + <use xlink:href="#glyph1-15" x="240.072147" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="297.94" y="75.603"/> + <use xlink:href="#glyph1-11" x="306.914983" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="314.32623" y="75.603"/> + <use xlink:href="#glyph1-9" x="321.532326" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-8" x="332.452653" y="75.603"/> + <use xlink:href="#glyph1-9" x="339.476553" y="75.603"/> + <use xlink:href="#glyph1-15" x="345.720019" y="75.603"/> + <use xlink:href="#glyph1-9" x="352.926115" y="75.603"/> + <use xlink:href="#glyph1-5" x="359.169582" y="75.603"/> + <use xlink:href="#glyph1-18" x="363.943997" y="75.603"/> + <use xlink:href="#glyph1-14" x="370.668061" y="75.603"/> + <use xlink:href="#glyph1-6" x="375.740877" y="75.603"/> + <use xlink:href="#glyph1-11" x="379.044807" y="75.603"/> + <use xlink:href="#glyph1-15" x="386.068707" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-23" x="231.724" y="117.459"/> + <use xlink:href="#glyph1-6" x="241.569797" y="117.459"/> + <use xlink:href="#glyph1-7" x="244.873727" y="117.459"/> + <use xlink:href="#glyph1-7" x="252.079823" y="117.459"/> + <use xlink:href="#glyph1-9" x="259.285919" y="117.459"/> + <use xlink:href="#glyph1-15" x="265.529386" y="117.459"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="277.412343" y="117.459"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-24" x="291.078533" y="117.459"/> + <use xlink:href="#glyph1-25" x="300.360525" y="117.459"/> + <use xlink:href="#glyph1-26" x="309.68412" y="117.459"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-27" x="68.742" y="89.962"/> + <use xlink:href="#glyph1-18" x="76.546333" y="89.962"/> + <use xlink:href="#glyph1-16" x="83.270397" y="89.962"/> + <use xlink:href="#glyph1-9" x="87.56278" y="89.962"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-12" x="37.407" y="103.909"/> + <use xlink:href="#glyph1-14" x="42.791129" y="103.909"/> + <use xlink:href="#glyph1-5" x="47.863945" y="103.909"/> + <use xlink:href="#glyph1-18" x="52.638361" y="103.909"/> + <use xlink:href="#glyph1-6" x="59.362424" y="103.909"/> + <use xlink:href="#glyph1-8" x="62.666354" y="103.909"/> + <use xlink:href="#glyph1-28" x="69.690254" y="103.909"/> + <use xlink:href="#glyph1-14" x="76.89635" y="103.909"/> + <use xlink:href="#glyph1-16" x="81.969166" y="103.909"/> + <use xlink:href="#glyph1-11" x="86.261549" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="92.898102" y="103.909"/> + <use xlink:href="#glyph1-29" x="97.672517" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-18" x="106.832566" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="113.154936" y="103.909"/> + <use xlink:href="#glyph1-7" x="117.929351" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-20" x="51.871" y="117.857"/> + <use xlink:href="#glyph1-17" x="60.911975" y="117.857"/> + <use xlink:href="#glyph1-12" x="68.118072" y="117.857"/> + <use xlink:href="#glyph1-14" x="73.5022" y="117.857"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-24" x="83.251878" y="117.857"/> + <use xlink:href="#glyph1-30" x="92.533869" y="117.857"/> + <use xlink:href="#glyph1-26" x="101.467248" y="117.857"/> + <use xlink:href="#glyph1-12" x="105.286206" y="117.857"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-27" x="418.874" y="103.909"/> + <use xlink:href="#glyph1-14" x="426.678333" y="103.909"/> + <use xlink:href="#glyph1-5" x="431.751149" y="103.909"/> + <use xlink:href="#glyph1-18" x="436.525564" y="103.909"/> + <use xlink:href="#glyph1-6" x="443.249628" y="103.909"/> + <use xlink:href="#glyph1-8" x="446.553558" y="103.909"/> + <use xlink:href="#glyph1-28" x="453.577458" y="103.909"/> + <use xlink:href="#glyph1-14" x="460.783554" y="103.909"/> + <use xlink:href="#glyph1-16" x="465.85637" y="103.909"/> + <use xlink:href="#glyph1-11" x="470.148753" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="476.785306" y="103.909"/> + <use xlink:href="#glyph1-29" x="481.559721" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-18" x="490.705423" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="497.04214" y="103.909"/> + <use xlink:href="#glyph1-7" x="501.816555" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="436.031" y="117.857"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-4" x="445.005" y="117.857"/> + <use xlink:href="#glyph0-4" x="452.387555" y="117.857"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-24" x="464.452" y="117.857"/> + <use xlink:href="#glyph1-30" x="473.733991" y="117.857"/> + <use xlink:href="#glyph1-26" x="482.66737" y="117.857"/> + <use xlink:href="#glyph1-12" x="486.486329" y="117.857"/> +</g> +</g> </svg> diff --git a/book/src/tutorial.md b/book/src/tutorial.md index c9fa00cb..2467282f 100644 --- a/book/src/tutorial.md +++ b/book/src/tutorial.md @@ -356,6 +356,7 @@ relative path of the Rust source file within the crate, and a `.rs.h` extension. ##include "cxx-demo/include/blobstore.h" ##include "cxx-demo/src/main.rs.h" ##include <functional> +##include <string> # # BlobstoreClient::BlobstoreClient() {} # @@ -560,9 +561,9 @@ fn main() { ```cpp,hidelines // include/blobstore.h -# -# #pragma once -# #include "rust/cxx.h" + +##pragma once +##include "rust/cxx.h" # #include <memory> struct MultiBuf; diff --git a/book/theme/head.hbs b/book/theme/head.hbs new file mode 100644 index 00000000..4210276b --- /dev/null +++ b/book/theme/head.hbs @@ -0,0 +1,7 @@ + <script async src="https://www.googletagmanager.com/gtag/js?id=G-DG41MK6DDN"></script> + <script> + window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'G-DG41MK6DDN', {'anonymize_ip': true}); + </script> @@ -3,6 +3,7 @@ load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_binary( name = "demo", srcs = glob(["src/**/*.rs"]), + edition = "2018", deps = [ ":blobstore-sys", ":bridge", @@ -28,6 +29,6 @@ cxx_library( cxx_library( name = "blobstore-include", + exported_deps = ["//:core"], exported_headers = ["include/blobstore.h"], - deps = ["//:core"], ) @@ -1,10 +1,11 @@ load("@rules_cc//cc:defs.bzl", "cc_library") -load("@rules_rust//rust:rust.bzl", "rust_binary") +load("@rules_rust//rust:defs.bzl", "rust_binary") load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_binary( name = "demo", srcs = glob(["src/**/*.rs"]), + edition = "2018", deps = [ ":blobstore-sys", ":bridge", diff --git a/demo/Cargo.toml b/demo/Cargo.toml index 8115b1e4..cee0bc2c 100644 --- a/demo/Cargo.toml +++ b/demo/Cargo.toml @@ -2,11 +2,11 @@ name = "demo" version = "0.0.0" authors = ["David Tolnay <dtolnay@gmail.com>"] -license = "MIT OR Apache-2.0" description = "Toy project from https://github.com/dtolnay/cxx" -repository = "https://github.com/dtolnay/cxx" edition = "2018" +license = "MIT OR Apache-2.0" publish = false +repository = "https://github.com/dtolnay/cxx" [dependencies] cxx = "1.0" diff --git a/flags/Cargo.toml b/flags/Cargo.toml index baf1157a..8958481c 100644 --- a/flags/Cargo.toml +++ b/flags/Cargo.toml @@ -1,11 +1,13 @@ [package] name = "cxxbridge-flags" -version = "1.0.54" +version = "1.0.85" authors = ["David Tolnay <dtolnay@gmail.com>"] +categories = ["development-tools::ffi", "compilers"] +description = "Compiler configuration of the `cxx` crate (implementation detail)" edition = "2018" license = "MIT OR Apache-2.0" -description = "Compiler configuration of the `cxx` crate (implementation detail)" repository = "https://github.com/dtolnay/cxx" +rust-version = "1.48" [features] default = [] # c++11 diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml index 393fc1ce..ea19af89 100644 --- a/gen/build/Cargo.toml +++ b/gen/build/Cargo.toml @@ -1,31 +1,38 @@ [package] name = "cxx-build" -version = "1.0.54" +version = "1.0.85" authors = ["David Tolnay <dtolnay@gmail.com>"] +categories = ["development-tools::build-utils", "development-tools::ffi"] +description = "C++ code generator for integrating `cxx` crate into a Cargo build." edition = "2018" +exclude = ["build.rs"] +homepage = "https://cxx.rs" +keywords = ["ffi", "build-dependencies"] license = "MIT OR Apache-2.0" -description = "C++ code generator for integrating `cxx` crate into a Cargo build." repository = "https://github.com/dtolnay/cxx" -homepage = "https://cxx.rs" -exclude = ["build.rs"] -keywords = ["ffi"] -categories = ["development-tools::ffi"] +rust-version = "1.48" [features] parallel = ["cc/parallel"] +# incomplete features that are not covered by a compatibility guarantee: +experimental-async-fn = [] [dependencies] cc = "1.0.49" -codespan-reporting = "0.11" -lazy_static = "1.4" -proc-macro2 = { version = "1.0.26", default-features = false, features = ["span-locations"] } +codespan-reporting = "0.11.1" +once_cell = "1.9" +proc-macro2 = { version = "1.0.39", default-features = false, features = ["span-locations"] } quote = { version = "1.0", default-features = false } scratch = "1.0" -syn = { version = "1.0.70", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] } +syn = { version = "1.0.95", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] } [dev-dependencies] +cxx = { version = "1.0", path = "../.." } cxx-gen = { version = "0.7", path = "../lib" } pkg-config = "0.3" +[lib] +doc-scrape-examples = false + [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs new file mode 100644 index 00000000..cbaa58a4 --- /dev/null +++ b/gen/build/src/cargo.rs @@ -0,0 +1,157 @@ +use crate::gen::{CfgEvaluator, CfgResult}; +use once_cell::sync::OnceCell; +use std::borrow::Borrow; +use std::cmp::Ordering; +use std::collections::{BTreeMap as Map, BTreeSet as Set}; +use std::env; + +static ENV: OnceCell<CargoEnv> = OnceCell::new(); + +struct CargoEnv { + features: Set<Name>, + cfgs: Map<Name, String>, +} + +pub(super) struct CargoEnvCfgEvaluator; + +impl CfgEvaluator for CargoEnvCfgEvaluator { + fn eval(&self, name: &str, query_value: Option<&str>) -> CfgResult { + let env = ENV.get_or_init(CargoEnv::load); + if name == "feature" { + return if let Some(query_value) = query_value { + CfgResult::from(env.features.contains(Lookup::new(query_value))) + } else { + let msg = "expected `feature = \"...\"`".to_owned(); + CfgResult::Undetermined { msg } + }; + } + if name == "test" && query_value.is_none() { + let msg = "cfg(test) is not supported because Cargo runs your build script only once across the lib and test build of the same crate".to_owned(); + return CfgResult::Undetermined { msg }; + } + if let Some(cargo_value) = env.cfgs.get(Lookup::new(name)) { + return if let Some(query_value) = query_value { + CfgResult::from(cargo_value.split(',').any(|value| value == query_value)) + } else { + CfgResult::True + }; + } + if name == "debug_assertions" && query_value.is_none() { + return CfgResult::from(cfg!(debug_assertions)); + } + CfgResult::False + } +} + +impl CargoEnv { + fn load() -> Self { + const CARGO_FEATURE_PREFIX: &str = "CARGO_FEATURE_"; + const CARGO_CFG_PREFIX: &str = "CARGO_CFG_"; + + let mut features = Set::new(); + let mut cfgs = Map::new(); + for (k, v) in env::vars_os() { + let k = match k.to_str() { + Some(k) => k, + None => continue, + }; + let v = match v.into_string() { + Ok(v) => v, + Err(_) => continue, + }; + if let Some(feature_name) = k.strip_prefix(CARGO_FEATURE_PREFIX) { + let feature_name = Name(feature_name.to_owned()); + features.insert(feature_name); + } else if let Some(cfg_name) = k.strip_prefix(CARGO_CFG_PREFIX) { + let cfg_name = Name(cfg_name.to_owned()); + cfgs.insert(cfg_name, v); + } + } + CargoEnv { features, cfgs } + } +} + +struct Name(String); + +impl Ord for Name { + fn cmp(&self, rhs: &Self) -> Ordering { + Lookup::new(&self.0).cmp(Lookup::new(&rhs.0)) + } +} + +impl PartialOrd for Name { + fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { + Some(self.cmp(rhs)) + } +} + +impl Eq for Name {} + +impl PartialEq for Name { + fn eq(&self, rhs: &Self) -> bool { + Lookup::new(&self.0).eq(Lookup::new(&rhs.0)) + } +} + +#[repr(transparent)] +struct Lookup(str); + +impl Lookup { + fn new(name: &str) -> &Self { + unsafe { &*(name as *const str as *const Self) } + } +} + +impl Borrow<Lookup> for Name { + fn borrow(&self) -> &Lookup { + Lookup::new(&self.0) + } +} + +impl Ord for Lookup { + fn cmp(&self, rhs: &Self) -> Ordering { + self.0 + .bytes() + .map(CaseAgnosticByte) + .cmp(rhs.0.bytes().map(CaseAgnosticByte)) + } +} + +impl PartialOrd for Lookup { + fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { + Some(self.cmp(rhs)) + } +} + +impl Eq for Lookup {} + +impl PartialEq for Lookup { + fn eq(&self, rhs: &Self) -> bool { + self.0 + .bytes() + .map(CaseAgnosticByte) + .eq(rhs.0.bytes().map(CaseAgnosticByte)) + } +} + +struct CaseAgnosticByte(u8); + +impl Ord for CaseAgnosticByte { + fn cmp(&self, rhs: &Self) -> Ordering { + self.0.to_ascii_lowercase().cmp(&rhs.0.to_ascii_lowercase()) + } +} + +impl PartialOrd for CaseAgnosticByte { + fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { + Some(self.cmp(rhs)) + } +} + +impl Eq for CaseAgnosticByte {} + +impl PartialEq for CaseAgnosticByte { + fn eq(&self, rhs: &Self) -> bool { + self.cmp(rhs) == Ordering::Equal + } +} diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs index 6818bdaa..69eb6945 100644 --- a/gen/build/src/cfg.rs +++ b/gen/build/src/cfg.rs @@ -12,6 +12,8 @@ pub struct Cfg<'a> { pub exported_header_prefixes: Vec<&'a str>, /// See [`CFG.exported_header_links`][CFG#cfgexported_header_links]. pub exported_header_links: Vec<&'a str>, + /// See [`CFG.doxygen`][CFG#cfgdoxygen]. + pub doxygen: bool, marker: PhantomData<*const ()>, // !Send + !Sync } @@ -19,7 +21,7 @@ pub struct Cfg<'a> { /// /// <br> /// -/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;color:#444"><strong>&str</strong></div> +/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>&str</strong></div> /// /// ## **`CFG.include_prefix`** /// @@ -71,7 +73,7 @@ pub struct Cfg<'a> { /// /// <br> /// -/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;color:#444"><strong>Vec<&Path></strong></div> +/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>Vec<&Path></strong></div> /// /// ## **`CFG.exported_header_dirs`** /// @@ -146,7 +148,7 @@ pub struct Cfg<'a> { /// /// <p style="margin:0"><br><br></p> /// -/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;color:#444"><strong>Vec<&str></strong></div> +/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>Vec<&str></strong></div> /// /// ## **`CFG.exported_header_prefixes`** /// @@ -203,7 +205,7 @@ pub struct Cfg<'a> { /// /// <p style="margin:0"><br><br></p> /// -/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;color:#444"><strong>Vec<&str></strong></div> +/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>Vec<&str></strong></div> /// /// ## **`CFG.exported_header_links`** /// @@ -232,12 +234,84 @@ pub struct Cfg<'a> { /// cxx_build::bridge("src/bridge.rs").compile("demo"); /// } /// ``` +/// +/// <p style="margin:0"><br><br></p> +/// +/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>bool</strong></div> +/// +/// ## **`CFG.doxygen`** +/// +/// Boolean. Whether to propagate Rust documentation from inside the cxx::bridge +/// module as Doxygen-style comments in the generated C++ header. +/// +/// Documentation on the following are supported: +/// +/// - shared structs, and fields of shared structs +/// - shared enums, and their variants +/// - extern "Rust" opaque types +/// - extern "Rust" functions, including methods/member functions +/// +/// ### Example +/// +/// ```no_run +/// // build.rs +/// +/// use cxx_build::CFG; +/// +/// fn main() { +/// CFG.doxygen = true; +/// +/// cxx_build::bridge("src/bridge.rs").compile("demo"); +/// } +/// ``` +/// +/// ```rust +/// // src/bridge.rs +/// +/// #[cxx::bridge] +/// mod ffi { +/// /// documentation of MyStruct +/// pub struct MyStruct { +/// /// documentation of the struct field +/// lol: String, +/// } +/// +/// extern "Rust" { +/// /// documentation of MyType +/// type MyType; +/// +/// /// function documentation +/// fn asdf() -> bool; +/// } +/// } +/// # +/// # pub struct MyType; +/// # fn asdf() -> bool { true } +/// # fn main() {} +/// ``` +/// +/// With `CFG.doxygen` enabled, the generated C++ header through which +/// downstream C++ code will be able to access these shared structs and extern +/// "Rust" signatures will have the Rust documentation comments propagated as +/// Doxygen-style comments: +/// +/// ```cpp +/// /// documentation of MyStruct +/// struct MyStruct final { +/// /// documentation of the struct field +/// ::rust::String lol; +/// … +/// }; +/// ``` +/// +/// Otherwise by default (without `CFG.doxygen`) they'll just be `//` comments. #[cfg(doc)] pub static mut CFG: Cfg = Cfg { include_prefix: "", exported_header_dirs: Vec::new(), exported_header_prefixes: Vec::new(), exported_header_links: Vec::new(), + doxygen: false, marker: PhantomData, }; @@ -248,6 +322,7 @@ impl<'a> Debug for Cfg<'a> { exported_header_dirs, exported_header_prefixes, exported_header_links, + doxygen, marker: _, } = self; formatter @@ -256,6 +331,7 @@ impl<'a> Debug for Cfg<'a> { .field("exported_header_dirs", exported_header_dirs) .field("exported_header_prefixes", exported_header_prefixes) .field("exported_header_links", exported_header_links) + .field("doxygen", doxygen) .finish() } } @@ -268,7 +344,7 @@ mod r#impl { use crate::intern::{intern, InternedString}; use crate::syntax::map::UnorderedMap as Map; use crate::vec::{self, InternedVec as _}; - use lazy_static::lazy_static; + use once_cell::sync::Lazy; use std::cell::RefCell; use std::fmt::{self, Debug}; use std::marker::PhantomData; @@ -280,6 +356,7 @@ mod r#impl { exported_header_dirs: Vec<InternedString>, exported_header_prefixes: Vec<InternedString>, exported_header_links: Vec<InternedString>, + doxygen: bool, } impl CurrentCfg { @@ -290,18 +367,18 @@ mod r#impl { let exported_header_dirs = Vec::new(); let exported_header_prefixes = Vec::new(); let exported_header_links = Vec::new(); + let doxygen = false; CurrentCfg { include_prefix, exported_header_dirs, exported_header_prefixes, exported_header_links, + doxygen, } } } - lazy_static! { - static ref CURRENT: RwLock<CurrentCfg> = RwLock::new(CurrentCfg::default()); - } + static CURRENT: Lazy<RwLock<CurrentCfg>> = Lazy::new(|| RwLock::new(CurrentCfg::default())); thread_local! { // FIXME: If https://github.com/rust-lang/rust/issues/77425 is resolved, @@ -329,11 +406,13 @@ mod r#impl { let exported_header_dirs = current.exported_header_dirs.vec(); let exported_header_prefixes = current.exported_header_prefixes.vec(); let exported_header_links = current.exported_header_links.vec(); + let doxygen = current.doxygen; super::Cfg { include_prefix, exported_header_dirs, exported_header_prefixes, exported_header_links, + doxygen, marker: PhantomData, } } @@ -394,11 +473,20 @@ mod r#impl { impl<'a> Drop for Cfg<'a> { fn drop(&mut self) { if let Cfg::Mut(cfg) = self { + let super::Cfg { + include_prefix, + exported_header_dirs, + exported_header_prefixes, + exported_header_links, + doxygen, + marker: _, + } = cfg; let mut current = CURRENT.write().unwrap_or_else(PoisonError::into_inner); - current.include_prefix = intern(cfg.include_prefix); - current.exported_header_dirs = vec::intern(&cfg.exported_header_dirs); - current.exported_header_prefixes = vec::intern(&cfg.exported_header_prefixes); - current.exported_header_links = vec::intern(&cfg.exported_header_links); + current.include_prefix = intern(include_prefix); + current.exported_header_dirs = vec::intern(exported_header_dirs); + current.exported_header_prefixes = vec::intern(exported_header_prefixes); + current.exported_header_links = vec::intern(exported_header_links); + current.doxygen = *doxygen; } else { CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle())); } diff --git a/gen/build/src/intern.rs b/gen/build/src/intern.rs index 25b87061..c8b57d89 100644 --- a/gen/build/src/intern.rs +++ b/gen/build/src/intern.rs @@ -1,5 +1,5 @@ use crate::syntax::set::UnorderedSet as Set; -use lazy_static::lazy_static; +use once_cell::sync::OnceCell; use std::sync::{Mutex, PoisonError}; #[derive(Copy, Clone, Default)] @@ -12,11 +12,13 @@ impl InternedString { } pub fn intern(s: &str) -> InternedString { - lazy_static! { - static ref INTERN: Mutex<Set<&'static str>> = Mutex::new(Set::new()); - } + static INTERN: OnceCell<Mutex<Set<&'static str>>> = OnceCell::new(); + + let mut set = INTERN + .get_or_init(|| Mutex::new(Set::new())) + .lock() + .unwrap_or_else(PoisonError::into_inner); - let mut set = INTERN.lock().unwrap_or_else(PoisonError::into_inner); InternedString(match set.get(s) { Some(interned) => *interned, None => { diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs index b8a463c3..225042c2 100644 --- a/gen/build/src/lib.rs +++ b/gen/build/src/lib.rs @@ -48,9 +48,11 @@ #![allow( clippy::cast_sign_loss, clippy::default_trait_access, + clippy::derive_partial_eq_without_eq, clippy::doc_markdown, clippy::drop_copy, clippy::enum_glob_use, + clippy::explicit_auto_deref, clippy::if_same_then_else, clippy::inherent_to_string, clippy::items_after_statements, @@ -67,6 +69,7 @@ clippy::or_fun_call, clippy::redundant_else, clippy::shadow_unrelated, + clippy::significant_drop_in_scrutinee, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, @@ -78,6 +81,7 @@ clippy::wrong_self_convention )] +mod cargo; mod cfg; mod deps; mod error; @@ -89,6 +93,7 @@ mod syntax; mod target; mod vec; +use crate::cargo::CargoEnvCfgEvaluator; use crate::deps::{Crate, HeaderDir}; use crate::error::{Error, Result}; use crate::gen::error::report; @@ -393,6 +398,8 @@ fn make_include_dir(prj: &Project) -> Result<PathBuf> { fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> { let opt = Opt { allow_dot_includes: false, + cfg_evaluator: Box::new(CargoEnvCfgEvaluator), + doxygen: CFG.doxygen, ..Opt::default() }; let generated = gen::generate_from_path(rust_source_file, &opt); diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs index e275049c..a52aab25 100644 --- a/gen/build/src/out.rs +++ b/gen/build/src/out.rs @@ -1,13 +1,14 @@ use crate::error::{Error, Result}; use crate::gen::fs; use crate::paths; +use std::io; use std::path::Path; pub(crate) fn write(path: impl AsRef<Path>, content: &[u8]) -> Result<()> { let path = path.as_ref(); let mut create_dir_error = None; - if path.exists() { + if fs::exists(path) { if let Ok(existing) = fs::read(path) { if existing == content { // Avoid bumping modified time with unchanged contents. @@ -33,7 +34,7 @@ pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) - let link = link.as_ref(); let mut create_dir_error = None; - if link.exists() { + if fs::exists(link) { best_effort_remove(link); } else { let parent = link.parent().unwrap(); @@ -43,8 +44,22 @@ pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) - match paths::symlink_or_copy(original, link) { // As long as symlink_or_copy succeeded, ignore any create_dir_all error. Ok(()) => Ok(()), - // If create_dir_all and symlink_or_copy both failed, prefer the first error. - Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))), + Err(err) => { + if err.kind() == io::ErrorKind::AlreadyExists { + // This is fine, a different simultaneous build script already + // created the same link or copy. The cxx_build target directory + // is laid out such that the same path never refers to two + // different targets during the same multi-crate build, so if + // some other build script already created the same path then we + // know it refers to the identical target that the current build + // script was trying to create. + Ok(()) + } else { + // If create_dir_all and symlink_or_copy both failed, prefer the + // first error. + Err(Error::Fs(create_dir_error.unwrap_or(err))) + } + } } } @@ -53,7 +68,7 @@ pub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> let link = link.as_ref(); let mut create_dir_error = None; - if link.exists() { + if fs::exists(link) { best_effort_remove(link); } else { let parent = link.parent().unwrap(); @@ -71,24 +86,34 @@ pub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> fn best_effort_remove(path: &Path) { use std::fs; - let file_type = match if cfg!(windows) { + if cfg!(windows) { // On Windows, the correct choice of remove_file vs remove_dir needs to // be used according to what the symlink *points to*. Trying to use // remove_file to remove a symlink which points to a directory fails // with "Access is denied". - fs::metadata(path) + if let Ok(metadata) = fs::metadata(path) { + if metadata.is_dir() { + let _ = fs::remove_dir_all(path); + } else { + let _ = fs::remove_file(path); + } + } else if fs::symlink_metadata(path).is_ok() { + // The symlink might exist but be dangling, in which case there is + // no standard way to determine what "kind" of symlink it is. Try + // deleting both ways. + if fs::remove_dir_all(path).is_err() { + let _ = fs::remove_file(path); + } + } } else { // On non-Windows, we check metadata not following symlinks. All // symlinks are removed using remove_file. - fs::symlink_metadata(path) - } { - Ok(metadata) => metadata.file_type(), - Err(_) => return, - }; - - if file_type.is_dir() { - let _ = fs::remove_dir_all(path); - } else { - let _ = fs::remove_file(path); + if let Ok(metadata) = fs::symlink_metadata(path) { + if metadata.is_dir() { + let _ = fs::remove_dir_all(path); + } else { + let _ = fs::remove_file(path); + } + } } } diff --git a/gen/cmd/Android.bp b/gen/cmd/Android.bp index bff1cb4b..ffda7dbc 100644 --- a/gen/cmd/Android.bp +++ b/gen/cmd/Android.bp @@ -1,4 +1,5 @@ -// This file is generated by cargo2android.py --run --dependencies --add_workspace --host-first-multilib. +// This file is generated by cargo2android.py --run --dependencies --add_workspace --host-first-multilib --no-pkg-vers. +// Do not modify this file as changes will be overridden on upgrade. package { // See: http://go/android-license-faq @@ -13,6 +14,7 @@ package { rust_binary_host { name: "cxxbridge", crate_name: "cxxbridge", + cargo_env_compat: true, srcs: ["src/main.rs"], edition: "2018", rustlibs: [ @@ -29,6 +31,7 @@ rust_binary_host { rust_library_host { name: "libcxxbridge_cmd", crate_name: "cxxbridge_cmd", + cargo_env_compat: true, srcs: ["src/lib.rs"], edition: "2018", rustlibs: [ @@ -40,20 +43,3 @@ rust_library_host { ], compile_multilib: "first", } - -// dependent_library ["feature_list"] -// ansi_term-0.11.0 -// atty-0.2.14 -// bitflags-1.2.1 "default" -// clap-2.33.3 "ansi_term,atty,color,default,strsim,suggestions,vec_map" -// codespan-reporting-0.9.5 -// libc-0.2.80 -// proc-macro2-1.0.24 "span-locations" -// quote-1.0.7 -// strsim-0.8.0 -// syn-1.0.50 "clone-impls,full,parsing,printing,quote" -// termcolor-1.1.2 -// textwrap-0.11.0 -// unicode-width-0.1.8 "default" -// unicode-xid-0.2.1 "default" -// vec_map-0.8.2 diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml index 4b3a299f..39d9a617 100644 --- a/gen/cmd/Cargo.toml +++ b/gen/cmd/Cargo.toml @@ -1,26 +1,31 @@ [package] name = "cxxbridge-cmd" -version = "1.0.54" +version = "1.0.85" authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -license = "MIT OR Apache-2.0" +categories = ["development-tools::build-utils", "development-tools::ffi"] description = "C++ code generator for integrating `cxx` crate into a non-Cargo build." -repository = "https://github.com/dtolnay/cxx" -homepage = "https://cxx.rs" +edition = "2018" exclude = ["build.rs"] +homepage = "https://cxx.rs" keywords = ["ffi"] -categories = ["development-tools::ffi"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/cxx" +rust-version = "1.56" [[bin]] name = "cxxbridge" path = "src/main.rs" +[features] +# incomplete features that are not covered by a compatibility guarantee: +experimental-async-fn = [] + [dependencies] -clap = "2.33" +clap = { version = "4", default-features = false, features = ["error-context", "help", "std", "suggestions", "usage"] } codespan-reporting = "0.11" -proc-macro2 = { version = "1.0.26", default-features = false, features = ["span-locations"] } +proc-macro2 = { version = "1.0.39", default-features = false, features = ["span-locations"] } quote = { version = "1.0", default-features = false } -syn = { version = "1.0.70", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] } +syn = { version = "1.0.95", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs index c233ad77..bfad8562 100644 --- a/gen/cmd/src/app.rs +++ b/gen/cmd/src/app.rs @@ -3,14 +3,16 @@ mod test; use super::{Opt, Output}; +use crate::cfg::{self, CfgValue}; use crate::gen::include::Include; use crate::syntax::IncludeKind; -use clap::AppSettings; -use std::ffi::{OsStr, OsString}; +use clap::builder::{ArgAction, ValueParser}; +use clap::{Arg, Command}; +use std::collections::{BTreeMap as Map, BTreeSet as Set}; use std::path::PathBuf; - -type App = clap::App<'static, 'static>; -type Arg = clap::Arg<'static, 'static>; +use std::process; +use std::sync::{Arc, Mutex, PoisonError}; +use syn::parse::Parser; const USAGE: &str = "\ cxxbridge <input>.rs Emit .cc file for bridge to stdout @@ -23,47 +25,56 @@ const TEMPLATE: &str = "\ David Tolnay <dtolnay@gmail.com> https://github.com/dtolnay/cxx -USAGE: +{usage-heading} {usage} -ARGS: -{positionals} -OPTIONS: -{unified}\ +{all-args}\ "; -fn app() -> App { - let mut app = App::new("cxxbridge") - .usage(USAGE) - .template(TEMPLATE) - .setting(AppSettings::NextLineHelp) +fn app() -> Command { + let mut app = Command::new("cxxbridge") + .override_usage(USAGE) + .help_template(TEMPLATE) + .next_line_help(true) + .disable_help_flag(true) + .disable_version_flag(true) .arg(arg_input()) + .arg(arg_cfg()) .arg(arg_cxx_impl_annotations()) .arg(arg_header()) + .arg(arg_help()) .arg(arg_include()) - .arg(arg_output()) - .help_message("Print help information.") - .version_message("Print version information."); + .arg(arg_output()); if let Some(version) = option_env!("CARGO_PKG_VERSION") { - app = app.version(version); + app = app.arg(arg_version()).version(version); } app } const INPUT: &str = "input"; +const CFG: &str = "cfg"; const CXX_IMPL_ANNOTATIONS: &str = "cxx-impl-annotations"; +const HELP: &str = "help"; const HEADER: &str = "header"; const INCLUDE: &str = "include"; const OUTPUT: &str = "output"; +const VERSION: &str = "version"; pub(super) fn from_args() -> Opt { let matches = app().get_matches(); - let input = matches.value_of_os(INPUT).map(PathBuf::from); - let cxx_impl_annotations = matches.value_of(CXX_IMPL_ANNOTATIONS).map(str::to_owned); - let header = matches.is_present(HEADER); + if matches.get_flag(HELP) { + let _ = app().print_long_help(); + process::exit(0); + } + + let input = matches.get_one::<PathBuf>(INPUT).cloned(); + let cxx_impl_annotations = matches + .get_one::<String>(CXX_IMPL_ANNOTATIONS) + .map(String::clone); + let header = matches.get_flag(HEADER); let include = matches - .values_of(INCLUDE) + .get_many::<String>(INCLUDE) .unwrap_or_default() .map(|include| { if include.starts_with('<') && include.ends_with('>') { @@ -81,38 +92,65 @@ pub(super) fn from_args() -> Opt { .collect(); let mut outputs = Vec::new(); - for path in matches.values_of_os(OUTPUT).unwrap_or_default() { - outputs.push(if path == "-" { + for path in matches.get_many::<PathBuf>(OUTPUT).unwrap_or_default() { + outputs.push(if path.as_os_str() == "-" { Output::Stdout } else { - Output::File(PathBuf::from(path)) + Output::File(path.clone()) }); } if outputs.is_empty() { outputs.push(Output::Stdout); } + let mut cfg = Map::new(); + for arg in matches.get_many::<String>(CFG).unwrap_or_default() { + let (name, value) = cfg::parse.parse_str(arg).unwrap(); + cfg.entry(name).or_insert_with(Set::new).insert(value); + } + Opt { input, header, cxx_impl_annotations, include, outputs, - } -} - -fn validate_utf8(arg: &OsStr) -> Result<(), OsString> { - if arg.to_str().is_some() { - Ok(()) - } else { - Err(OsString::from("invalid utf-8 sequence")) + cfg, } } fn arg_input() -> Arg { - Arg::with_name(INPUT) + Arg::new(INPUT) .help("Input Rust source file containing #[cxx::bridge].") - .required_unless(HEADER) + .required_unless_present_any(&[HEADER, HELP]) + .value_parser(ValueParser::path_buf()) +} + +fn arg_cfg() -> Arg { + const HELP: &str = "\ +Compilation configuration matching what will be used to build +the Rust side of the bridge."; + let bool_cfgs = Arc::new(Mutex::new(Map::<String, bool>::new())); + Arg::new(CFG) + .long(CFG) + .num_args(1) + .value_name("name=\"value\" | name[=true] | name=false") + .action(ArgAction::Append) + .value_parser(move |arg: &str| match cfg::parse.parse_str(arg) { + Ok((_, CfgValue::Str(_))) => Ok(arg.to_owned()), + Ok((name, CfgValue::Bool(value))) => { + let mut bool_cfgs = bool_cfgs.lock().unwrap_or_else(PoisonError::into_inner); + if let Some(&prev) = bool_cfgs.get(&name) { + if prev != value { + return Err(format!("cannot have both {0}=false and {0}=true", name)); + } + } + bool_cfgs.insert(name, value); + Ok(arg.to_owned()) + } + Err(_) => Err("expected name=\"value\", name=true, or name=false".to_owned()), + }) + .help(HELP) } fn arg_cxx_impl_annotations() -> Arg { @@ -121,51 +159,59 @@ Optional annotation for implementations of C++ function wrappers that may be exposed to Rust. You may for example need to provide __declspec(dllexport) or __attribute__((visibility(\"default\"))) if Rust code from one shared object or executable depends on -these C++ functions in another. - "; - Arg::with_name(CXX_IMPL_ANNOTATIONS) +these C++ functions in another."; + Arg::new(CXX_IMPL_ANNOTATIONS) .long(CXX_IMPL_ANNOTATIONS) - .takes_value(true) + .num_args(1) .value_name("annotation") - .validator_os(validate_utf8) + .value_parser(ValueParser::string()) .help(HELP) } fn arg_header() -> Arg { const HELP: &str = "\ Emit header with declarations only. Optional if using `-o` with -a path ending in `.h`. - "; - Arg::with_name(HEADER).long(HEADER).help(HELP) +a path ending in `.h`."; + Arg::new(HEADER).long(HEADER).num_args(0).help(HELP) +} + +fn arg_help() -> Arg { + Arg::new(HELP) + .long(HELP) + .help("Print help information.") + .num_args(0) } fn arg_include() -> Arg { const HELP: &str = "\ Any additional headers to #include. The cxxbridge tool does not parse or even require the given paths to exist; they simply go -into the generated C++ code as #include lines. - "; - Arg::with_name(INCLUDE) +into the generated C++ code as #include lines."; + Arg::new(INCLUDE) .long(INCLUDE) - .short("i") - .takes_value(true) - .multiple(true) - .number_of_values(1) - .validator_os(validate_utf8) + .short('i') + .num_args(1) + .action(ArgAction::Append) + .value_parser(ValueParser::string()) .help(HELP) } fn arg_output() -> Arg { const HELP: &str = "\ Path of file to write as output. Output goes to stdout if -o is -not specified. - "; - Arg::with_name(OUTPUT) +not specified."; + Arg::new(OUTPUT) .long(OUTPUT) - .short("o") - .takes_value(true) - .multiple(true) - .number_of_values(1) - .validator_os(validate_utf8) + .short('o') + .num_args(1) + .action(ArgAction::Append) + .value_parser(ValueParser::path_buf()) .help(HELP) } + +fn arg_version() -> Arg { + Arg::new(VERSION) + .long(VERSION) + .help("Print version information.") + .action(ArgAction::Version) +} diff --git a/gen/cmd/src/cfg.rs b/gen/cmd/src/cfg.rs new file mode 100644 index 00000000..29f0b9bc --- /dev/null +++ b/gen/cmd/src/cfg.rs @@ -0,0 +1,93 @@ +use crate::gen::{CfgEvaluator, CfgResult}; +use std::collections::{BTreeMap as Map, BTreeSet as Set}; +use std::fmt::{self, Debug}; +use syn::parse::ParseStream; +use syn::{Ident, LitBool, LitStr, Token}; + +#[derive(Ord, PartialOrd, Eq, PartialEq)] +pub enum CfgValue { + Bool(bool), + Str(String), +} + +impl CfgValue { + const FALSE: Self = CfgValue::Bool(false); + const TRUE: Self = CfgValue::Bool(true); +} + +pub struct FlagsCfgEvaluator { + map: Map<String, Set<CfgValue>>, +} + +impl FlagsCfgEvaluator { + pub fn new(map: Map<String, Set<CfgValue>>) -> Self { + FlagsCfgEvaluator { map } + } +} + +impl CfgEvaluator for FlagsCfgEvaluator { + fn eval(&self, name: &str, value: Option<&str>) -> CfgResult { + let set = self.map.get(name); + if let Some(value) = value { + if let Some(set) = set { + CfgResult::from(set.contains(&CfgValue::Str(value.to_owned()))) + } else if name == "feature" { + CfgResult::False + } else { + let msg = format!( + "pass `--cfg {}=\"...\"` to be able to use this attribute", + name, + ); + CfgResult::Undetermined { msg } + } + } else { + let (mut is_false, mut is_true) = (false, false); + if let Some(set) = set { + is_false = set.contains(&CfgValue::FALSE); + is_true = set.contains(&CfgValue::TRUE); + } + if is_false && is_true { + let msg = format!("the cxxbridge flags say both {0}=false and {0}=true", name); + CfgResult::Undetermined { msg } + } else if is_false { + CfgResult::False + } else if is_true { + CfgResult::True + } else { + let msg = format!( + "pass either `--cfg {0}=true` or `--cfg {0}=false` to be able to use this cfg attribute", + name, + ); + CfgResult::Undetermined { msg } + } + } + } +} + +impl Debug for CfgValue { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self { + CfgValue::Bool(value) => Debug::fmt(value, formatter), + CfgValue::Str(value) => Debug::fmt(value, formatter), + } + } +} + +pub fn parse(input: ParseStream) -> syn::Result<(String, CfgValue)> { + let ident: Ident = input.parse()?; + let name = ident.to_string(); + if input.is_empty() { + return Ok((name, CfgValue::TRUE)); + } + input.parse::<Token![=]>()?; + let lookahead = input.lookahead1(); + if lookahead.peek(LitBool) { + let lit: LitBool = input.parse()?; + Ok((name, CfgValue::Bool(lit.value))) + } else if lookahead.peek(LitStr) { + let lit: LitStr = input.parse()?; + Ok((name, CfgValue::Str(lit.value()))) + } else { + Err(lookahead.error()) + } +} diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs index 1c15db63..4d5edfd1 100644 --- a/gen/cmd/src/main.rs +++ b/gen/cmd/src/main.rs @@ -2,6 +2,7 @@ clippy::cast_sign_loss, clippy::cognitive_complexity, clippy::default_trait_access, + clippy::derive_partial_eq_without_eq, clippy::enum_glob_use, clippy::if_same_then_else, clippy::inherent_to_string, @@ -29,14 +30,17 @@ )] mod app; +mod cfg; mod gen; mod output; mod syntax; +use crate::cfg::{CfgValue, FlagsCfgEvaluator}; use crate::gen::error::{report, Result}; use crate::gen::fs; use crate::gen::include::{self, Include}; use crate::output::Output; +use std::collections::{BTreeMap as Map, BTreeSet as Set}; use std::io::{self, Write}; use std::path::PathBuf; use std::process; @@ -48,6 +52,7 @@ struct Opt { cxx_impl_annotations: Option<String>, include: Vec<Include>, outputs: Vec<Output>, + cfg: Map<String, Set<CfgValue>>, } fn main() { @@ -91,6 +96,7 @@ fn try_main() -> Result<()> { cxx_impl_annotations: opt.cxx_impl_annotations, gen_header, gen_implementation, + cfg_evaluator: Box::new(FlagsCfgEvaluator::new(opt.cfg)), ..Default::default() }; diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs index 17023e4d..c04c28e8 100644 --- a/gen/cmd/src/test.rs +++ b/gen/cmd/src/test.rs @@ -3,41 +3,45 @@ cxxbridge $VERSION David Tolnay <dtolnay@gmail.com> https://github.com/dtolnay/cxx -USAGE: +Usage: cxxbridge <input>.rs Emit .cc file for bridge to stdout cxxbridge <input>.rs --header Emit .h file for bridge to stdout cxxbridge --header Emit \"rust/cxx.h\" header to stdout -ARGS: - <input> - Input Rust source file containing #[cxx::bridge]. - -OPTIONS: - --cxx-impl-annotations <annotation> - Optional annotation for implementations of C++ function wrappers - that may be exposed to Rust. You may for example need to provide - __declspec(dllexport) or __attribute__((visibility(\"default\"))) - if Rust code from one shared object or executable depends on - these C++ functions in another. - \x20 - -h, --help - Print help information. - - --header - Emit header with declarations only. Optional if using `-o` with - a path ending in `.h`. - \x20 - -i, --include <include>... - Any additional headers to #include. The cxxbridge tool does not - parse or even require the given paths to exist; they simply go - into the generated C++ code as #include lines. - \x20 - -o, --output <output>... - Path of file to write as output. Output goes to stdout if -o is - not specified. - \x20 - -V, --version - Print version information. +Arguments: + [input] + Input Rust source file containing #[cxx::bridge]. + +Options: + --cfg <name=\"value\" | name[=true] | name=false> + Compilation configuration matching what will be used to build + the Rust side of the bridge. + + --cxx-impl-annotations <annotation> + Optional annotation for implementations of C++ function wrappers + that may be exposed to Rust. You may for example need to provide + __declspec(dllexport) or __attribute__((visibility(\"default\"))) + if Rust code from one shared object or executable depends on + these C++ functions in another. + + --header + Emit header with declarations only. Optional if using `-o` with + a path ending in `.h`. + + --help + Print help information. + + -i, --include <include> + Any additional headers to #include. The cxxbridge tool does not + parse or even require the given paths to exist; they simply go + into the generated C++ code as #include lines. + + -o, --output <output> + Path of file to write as output. Output goes to stdout if -o is + not specified. + + --version + Print version information. "; #[test] @@ -50,3 +54,9 @@ fn test_help() { let expected = EXPECTED.replace("$VERSION", version); assert_eq!(help, expected); } + +#[test] +fn test_cli() { + let app = super::app(); + app.debug_assert(); +} diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml index 37d81687..df8c8558 100644 --- a/gen/lib/Cargo.toml +++ b/gen/lib/Cargo.toml @@ -1,21 +1,24 @@ [package] name = "cxx-gen" -version = "0.7.54" +version = "0.7.85" authors = ["Adrian Taylor <adetaylor@chromium.org>"] -edition = "2018" -license = "MIT OR Apache-2.0" +categories = ["development-tools::ffi"] description = "C++ code generator for integrating `cxx` crate into higher level tools." -repository = "https://github.com/dtolnay/cxx" +edition = "2018" exclude = ["build.rs"] keywords = ["ffi"] -categories = ["development-tools::ffi"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/cxx" +rust-version = "1.48" [dependencies] -cc = "1.0.49" codespan-reporting = "0.11" -proc-macro2 = { version = "1.0.26", default-features = false, features = ["span-locations"] } +proc-macro2 = { version = "1.0.39", default-features = false, features = ["span-locations"] } quote = { version = "1.0", default-features = false } -syn = { version = "1.0.70", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] } +syn = { version = "1.0.95", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] } + +[lib] +doc-scrape-examples = false [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/gen/lib/src/error.rs b/gen/lib/src/error.rs index 26249be3..bb53a7fc 100644 --- a/gen/lib/src/error.rs +++ b/gen/lib/src/error.rs @@ -4,6 +4,7 @@ use std::error::Error as StdError; use std::fmt::{self, Debug, Display}; +#[allow(missing_docs)] pub struct Error { pub(crate) err: crate::gen::Error, } diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs index 411953b2..47cfa18d 100644 --- a/gen/lib/src/lib.rs +++ b/gen/lib/src/lib.rs @@ -7,10 +7,12 @@ //! [dtolnay/cxx#235]: https://github.com/dtolnay/cxx/issues/235 //! [https://github.com/google/autocxx]: https://github.com/google/autocxx +#![deny(missing_docs)] #![allow(dead_code)] #![allow( clippy::cast_sign_loss, clippy::default_trait_access, + clippy::derive_partial_eq_without_eq, clippy::enum_glob_use, clippy::if_same_then_else, clippy::inherent_to_string, diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs index 7ac9209c..277c64f8 100644 --- a/gen/src/builtin.rs +++ b/gen/src/builtin.rs @@ -26,8 +26,8 @@ pub struct Builtins<'a> { pub rust_str_repr: bool, pub rust_slice_new: bool, pub rust_slice_repr: bool, - pub exception: bool, pub relocatable: bool, + pub relocatable_or_array: bool, pub friend_impl: bool, pub is_complete: bool, pub destroy: bool, @@ -113,6 +113,11 @@ pub(super) fn write(out: &mut OutFile) { include.sys_types = true; } + if builtin.relocatable_or_array { + include.cstddef = true; + builtin.relocatable = true; + } + if builtin.relocatable { include.type_traits = true; } @@ -132,6 +137,10 @@ pub(super) fn write(out: &mut OutFile) { builtin.unsafe_bitcopy_t = true; } + if builtin.trycatch { + builtin.ptr_len = true; + } + out.begin_block(Block::Namespace("rust")); out.begin_block(Block::InlineNamespace("cxxbridge1")); @@ -199,6 +208,26 @@ pub(super) fn write(out: &mut OutFile) { writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}"); } + out.begin_block(Block::Namespace("repr")); + + if builtin.repr_fat { + include.array = true; + include.cstdint = true; + out.next_section(); + writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;"); + } + + if builtin.ptr_len { + include.cstddef = true; + out.next_section(); + writeln!(out, "struct PtrLen final {{"); + writeln!(out, " void *ptr;"); + writeln!(out, " ::std::size_t len;"); + writeln!(out, "}};"); + } + + out.end_block(Block::Namespace("repr")); + out.begin_block(Block::Namespace("detail")); if builtin.maybe_uninit { @@ -225,6 +254,21 @@ pub(super) fn write(out: &mut OutFile) { writeln!(out, "}};"); } + if builtin.trycatch { + include.string = true; + out.next_section(); + writeln!(out, "class Fail final {{"); + writeln!(out, " ::rust::repr::PtrLen &throw$;"); + writeln!(out, "public:"); + writeln!( + out, + " Fail(::rust::repr::PtrLen &throw$) noexcept : throw$(throw$) {{}}", + ); + writeln!(out, " void operator()(char const *) noexcept;"); + writeln!(out, " void operator()(std::string const &) noexcept;"); + writeln!(out, "}};"); + } + out.end_block(Block::Namespace("detail")); if builtin.manually_drop { @@ -258,26 +302,6 @@ pub(super) fn write(out: &mut OutFile) { out.begin_block(Block::AnonymousNamespace); - if builtin.repr_fat { - include.array = true; - include.cstdint = true; - out.next_section(); - out.begin_block(Block::Namespace("repr")); - writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;"); - out.end_block(Block::Namespace("repr")); - } - - if builtin.ptr_len { - include.cstddef = true; - out.next_section(); - out.begin_block(Block::Namespace("repr")); - writeln!(out, "struct PtrLen final {{"); - writeln!(out, " void *ptr;"); - writeln!(out, " ::std::size_t len;"); - writeln!(out, "}};"); - out.end_block(Block::Namespace("repr")); - } - if builtin.rust_str_new_unchecked || builtin.rust_str_repr { out.next_section(); writeln!(out, "template <>"); @@ -328,7 +352,7 @@ pub(super) fn write(out: &mut OutFile) { writeln!(out, "public:"); writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{"); writeln!(out, " Error error;"); - writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);"); + writeln!(out, " error.msg = static_cast<char const *>(repr.ptr);"); writeln!(out, " error.len = repr.len;"); writeln!(out, " return error;"); writeln!(out, " }}"); @@ -357,6 +381,17 @@ pub(super) fn write(out: &mut OutFile) { writeln!(out, "}};"); } + if builtin.relocatable_or_array { + out.next_section(); + writeln!(out, "template <typename T>"); + writeln!(out, "struct IsRelocatableOrArray : IsRelocatable<T> {{}};"); + writeln!(out, "template <typename T, ::std::size_t N>"); + writeln!( + out, + "struct IsRelocatableOrArray<T[N]> : IsRelocatableOrArray<T> {{}};", + ); + } + out.end_block(Block::AnonymousNamespace); out.end_block(Block::InlineNamespace("cxxbridge1")); @@ -377,21 +412,11 @@ pub(super) fn write(out: &mut OutFile) { writeln!(out, " missing>::value>::type"); writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{"); writeln!(out, " func();"); - writeln!(out, "}} catch (const ::std::exception &e) {{"); + writeln!(out, "}} catch (::std::exception const &e) {{"); writeln!(out, " fail(e.what());"); writeln!(out, "}}"); out.end_block(Block::Namespace("behavior")); } out.end_block(Block::Namespace("rust")); - - if builtin.exception { - include.cstddef = true; - out.begin_block(Block::ExternC); - writeln!( - out, - "const char *cxxbridge1$exception(const char *, ::std::size_t);", - ); - out.end_block(Block::ExternC); - } } diff --git a/gen/src/cfg.rs b/gen/src/cfg.rs new file mode 100644 index 00000000..da589085 --- /dev/null +++ b/gen/src/cfg.rs @@ -0,0 +1,133 @@ +use crate::gen::{CfgEvaluator, CfgResult}; +use crate::syntax::cfg::CfgExpr; +use crate::syntax::report::Errors; +use crate::syntax::Api; +use quote::quote; +use std::collections::BTreeSet as Set; +use syn::Error; + +pub(super) struct UnsupportedCfgEvaluator; + +impl CfgEvaluator for UnsupportedCfgEvaluator { + fn eval(&self, name: &str, value: Option<&str>) -> CfgResult { + let _ = name; + let _ = value; + let msg = "cfg attribute is not supported".to_owned(); + CfgResult::Undetermined { msg } + } +} + +pub(super) fn strip( + cx: &mut Errors, + cfg_errors: &mut Set<String>, + cfg_evaluator: &dyn CfgEvaluator, + apis: &mut Vec<Api>, +) { + apis.retain(|api| eval(cx, cfg_errors, cfg_evaluator, api.cfg())); + for api in apis { + match api { + Api::Struct(strct) => strct + .fields + .retain(|field| eval(cx, cfg_errors, cfg_evaluator, &field.cfg)), + Api::Enum(enm) => enm + .variants + .retain(|variant| eval(cx, cfg_errors, cfg_evaluator, &variant.cfg)), + _ => {} + } + } +} + +pub(super) fn eval( + cx: &mut Errors, + cfg_errors: &mut Set<String>, + cfg_evaluator: &dyn CfgEvaluator, + expr: &CfgExpr, +) -> bool { + match try_eval(cfg_evaluator, expr) { + Ok(value) => value, + Err(errors) => { + for error in errors { + if cfg_errors.insert(error.to_string()) { + cx.push(error); + } + } + false + } + } +} + +fn try_eval(cfg_evaluator: &dyn CfgEvaluator, expr: &CfgExpr) -> Result<bool, Vec<Error>> { + match expr { + CfgExpr::Unconditional => Ok(true), + CfgExpr::Eq(ident, string) => { + let key = ident.to_string(); + let value = string.as_ref().map(|string| string.value()); + match cfg_evaluator.eval(&key, value.as_deref()) { + CfgResult::True => Ok(true), + CfgResult::False => Ok(false), + CfgResult::Undetermined { msg } => { + let span = quote!(#ident #string); + Err(vec![Error::new_spanned(span, msg)]) + } + } + } + CfgExpr::All(list) => { + let mut all_errors = Vec::new(); + for subexpr in list { + match try_eval(cfg_evaluator, subexpr) { + Ok(true) => {} + Ok(false) => return Ok(false), + Err(errors) => all_errors.extend(errors), + } + } + if all_errors.is_empty() { + Ok(true) + } else { + Err(all_errors) + } + } + CfgExpr::Any(list) => { + let mut all_errors = Vec::new(); + for subexpr in list { + match try_eval(cfg_evaluator, subexpr) { + Ok(true) => return Ok(true), + Ok(false) => {} + Err(errors) => all_errors.extend(errors), + } + } + if all_errors.is_empty() { + Ok(false) + } else { + Err(all_errors) + } + } + CfgExpr::Not(subexpr) => match try_eval(cfg_evaluator, subexpr) { + Ok(value) => Ok(!value), + Err(errors) => Err(errors), + }, + } +} + +impl Api { + fn cfg(&self) -> &CfgExpr { + match self { + Api::Include(include) => &include.cfg, + Api::Struct(strct) => &strct.cfg, + Api::Enum(enm) => &enm.cfg, + Api::CxxType(ety) | Api::RustType(ety) => &ety.cfg, + Api::CxxFunction(efn) | Api::RustFunction(efn) => &efn.cfg, + Api::TypeAlias(alias) => &alias.cfg, + Api::Impl(imp) => &imp.cfg, + } + } +} + +impl From<bool> for CfgResult { + fn from(value: bool) -> Self { + if value { + CfgResult::True + } else { + CfgResult::False + } + } +} diff --git a/gen/src/fs.rs b/gen/src/fs.rs index 7053cc44..7bc3bbcb 100644 --- a/gen/src/fs.rs +++ b/gen/src/fs.rs @@ -13,6 +13,15 @@ pub(crate) struct Error { message: String, } +impl Error { + pub fn kind(&self) -> io::ErrorKind { + match &self.source { + Some(io_error) => io_error.kind(), + None => io::ErrorKind::Other, + } + } +} + impl Display for Error { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(&self.message) @@ -59,6 +68,13 @@ pub(crate) fn current_dir() -> Result<PathBuf> { } } +pub(crate) fn exists(path: impl AsRef<Path>) -> bool { + let path = path.as_ref(); + // If path is a symlink, this returns true, regardless of whether the + // symlink points to a path that exists. + std::fs::symlink_metadata(path).is_ok() +} + pub(crate) fn read(path: impl AsRef<Path>) -> Result<Vec<u8>> { let path = path.as_ref(); match std::fs::read(path) { diff --git a/gen/src/mod.rs b/gen/src/mod.rs index d8b90d0d..f24846a7 100644 --- a/gen/src/mod.rs +++ b/gen/src/mod.rs @@ -3,25 +3,31 @@ mod block; mod builtin; +mod cfg; mod check; pub(super) mod error; mod file; pub(super) mod fs; mod ifndef; pub(super) mod include; +mod names; mod namespace; mod nested; pub(super) mod out; mod write; -pub(super) use self::error::Error; +use self::cfg::UnsupportedCfgEvaluator; use self::error::{format_err, Result}; use self::file::File; use self::include::Include; +use crate::syntax::cfg::CfgExpr; use crate::syntax::report::Errors; -use crate::syntax::{self, Types}; +use crate::syntax::{self, attrs, Types}; +use std::collections::BTreeSet as Set; use std::path::Path; +pub(super) use self::error::Error; + /// Options for C++ code generation. /// /// We expect options to be added over time, so this is a non-exhaustive struct. @@ -52,6 +58,18 @@ pub struct Opt { pub(super) gen_header: bool, pub(super) gen_implementation: bool, pub(super) allow_dot_includes: bool, + pub(super) cfg_evaluator: Box<dyn CfgEvaluator>, + pub(super) doxygen: bool, +} + +pub(super) trait CfgEvaluator { + fn eval(&self, name: &str, value: Option<&str>) -> CfgResult; +} + +pub(super) enum CfgResult { + True, + False, + Undetermined { msg: String }, } /// Results of code generation. @@ -71,6 +89,8 @@ impl Default for Opt { gen_header: true, gen_implementation: true, allow_dot_includes: true, + cfg_evaluator: Box::new(UnsupportedCfgEvaluator), + doxygen: false, } } } @@ -116,20 +136,37 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> { let ref mut apis = Vec::new(); let ref mut errors = Errors::new(); + let ref mut cfg_errors = Set::new(); for bridge in syntax.modules { - let ref namespace = bridge.namespace; - let trusted = bridge.unsafety.is_some(); - apis.extend(syntax::parse_items( + let mut cfg = CfgExpr::Unconditional; + attrs::parse( errors, - bridge.content, - trusted, - namespace, - )); + bridge.attrs, + attrs::Parser { + cfg: Some(&mut cfg), + ignore_unrecognized: true, + ..Default::default() + }, + ); + if cfg::eval(errors, cfg_errors, opt.cfg_evaluator.as_ref(), &cfg) { + let ref namespace = bridge.namespace; + let trusted = bridge.unsafety.is_some(); + apis.extend(syntax::parse_items( + errors, + bridge.content, + trusted, + namespace, + )); + } } + cfg::strip(errors, cfg_errors, opt.cfg_evaluator.as_ref(), apis); + errors.propagate()?; + let ref types = Types::collect(errors, apis); check::precheck(errors, apis, opt); errors.propagate()?; + let generator = check::Generator::Build; check::typecheck(errors, apis, types, generator); errors.propagate()?; diff --git a/gen/src/names.rs b/gen/src/names.rs new file mode 100644 index 00000000..834424bb --- /dev/null +++ b/gen/src/names.rs @@ -0,0 +1,14 @@ +use crate::syntax::Pair; + +impl Pair { + pub fn to_fully_qualified(&self) -> String { + let mut fully_qualified = String::new(); + for segment in &self.namespace { + fully_qualified += "::"; + fully_qualified += &segment.to_string(); + } + fully_qualified += "::"; + fully_qualified += &self.cxx.to_string(); + fully_qualified + } +} diff --git a/gen/src/nested.rs b/gen/src/nested.rs index 2129d10f..32cc5f15 100644 --- a/gen/src/nested.rs +++ b/gen/src/nested.rs @@ -52,6 +52,7 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries { mod tests { use super::NamespaceEntries; use crate::syntax::attrs::OtherAttrs; + use crate::syntax::cfg::CfgExpr; use crate::syntax::namespace::Namespace; use crate::syntax::{Api, Doc, ExternType, ForeignName, Lang, Lifetimes, Pair}; use proc_macro2::{Ident, Span}; @@ -128,6 +129,7 @@ mod tests { fn make_api(ns: Option<&str>, ident: &str) -> Api { let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap()); Api::CxxType(ExternType { + cfg: CfgExpr::Unconditional, lang: Lang::Rust, doc: Doc::new(), derives: Vec::new(), diff --git a/gen/src/write.rs b/gen/src/write.rs index a3b9c9fa..6f535ccb 100644 --- a/gen/src/write.rs +++ b/gen/src/write.rs @@ -6,7 +6,7 @@ use crate::syntax::atom::Atom::{self, *}; use crate::syntax::instantiate::{ImplKey, NamedImplKey}; use crate::syntax::map::UnorderedMap as Map; use crate::syntax::set::UnorderedSet; -use crate::syntax::symbol::Symbol; +use crate::syntax::symbol::{self, Symbol}; use crate::syntax::trivial::{self, TrivialReason}; use crate::syntax::{ derive, mangle, Api, Doc, Enum, EnumRepr, ExternFn, ExternType, Pair, Signature, Struct, Trait, @@ -177,7 +177,7 @@ fn write_std_specializations(out: &mut OutFile, apis: &[Api]) { writeln!(out, "template <> struct hash<{}> {{", qualified); writeln!( out, - " ::std::size_t operator()(const {} &self) const noexcept {{", + " ::std::size_t operator()({} const &self) const noexcept {{", qualified, ); let link_name = mangle::operator(&strct.name, "hash"); @@ -227,6 +227,25 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) { } } +fn write_doc(out: &mut OutFile, indent: &str, doc: &Doc) { + let mut lines = 0; + for line in doc.to_string().lines() { + if out.opt.doxygen { + writeln!(out, "{}///{}", indent, line); + } else { + writeln!(out, "{}//{}", indent, line); + } + lines += 1; + } + // According to https://www.doxygen.nl/manual/docblocks.html, Doxygen only + // interprets `///` as a Doxygen comment block if there are at least 2 of + // them. In Rust, a single `///` is definitely still documentation so we + // make sure to propagate that as a Doxygen comment. + if out.opt.doxygen && lines == 1 { + writeln!(out, "{}///", indent); + } +} + fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) { let operator_eq = derive::contains(&strct.derives, Trait::PartialEq); let operator_ord = derive::contains(&strct.derives, Trait::PartialOrd); @@ -235,15 +254,11 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol()); writeln!(out, "#ifndef {}", guard); writeln!(out, "#define {}", guard); - for line in strct.doc.to_string().lines() { - writeln!(out, "//{}", line); - } + write_doc(out, "", &strct.doc); writeln!(out, "struct {} final {{", strct.name.cxx); for field in &strct.fields { - for line in field.doc.to_string().lines() { - writeln!(out, " //{}", line); - } + write_doc(out, " ", &field.doc); write!(out, " "); write_type_space(out, &field.ty); writeln!(out, "{};", field.name.cxx); @@ -255,9 +270,7 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern if !method.doc.is_empty() { out.next_section(); } - for line in method.doc.to_string().lines() { - writeln!(out, " //{}", line); - } + write_doc(out, " ", &method.doc); write!(out, " "); let sig = &method.sig; let local_name = method.name.cxx.to_string(); @@ -272,12 +285,12 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern if operator_eq { writeln!( out, - " bool operator==(const {} &) const noexcept;", + " bool operator==({} const &) const noexcept;", strct.name.cxx, ); writeln!( out, - " bool operator!=(const {} &) const noexcept;", + " bool operator!=({} const &) const noexcept;", strct.name.cxx, ); } @@ -285,22 +298,22 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern if operator_ord { writeln!( out, - " bool operator<(const {} &) const noexcept;", + " bool operator<({} const &) const noexcept;", strct.name.cxx, ); writeln!( out, - " bool operator<=(const {} &) const noexcept;", + " bool operator<=({} const &) const noexcept;", strct.name.cxx, ); writeln!( out, - " bool operator>(const {} &) const noexcept;", + " bool operator>({} const &) const noexcept;", strct.name.cxx, ); writeln!( out, - " bool operator>=(const {} &) const noexcept;", + " bool operator>=({} const &) const noexcept;", strct.name.cxx, ); } @@ -318,6 +331,7 @@ fn write_struct_decl(out: &mut OutFile, ident: &Pair) { fn write_enum_decl(out: &mut OutFile, enm: &Enum) { let repr = match &enm.repr { + #[cfg(feature = "experimental-enum-variants-from-header")] EnumRepr::Foreign { .. } => return, EnumRepr::Native { atom, .. } => *atom, }; @@ -335,9 +349,7 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[ let guard = format!("CXXBRIDGE1_STRUCT_{}", ety.name.to_symbol()); writeln!(out, "#ifndef {}", guard); writeln!(out, "#define {}", guard); - for line in ety.doc.to_string().lines() { - writeln!(out, "//{}", line); - } + write_doc(out, "", &ety.doc); out.builtin.opaque = true; writeln!( @@ -350,9 +362,7 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[ if i > 0 && !method.doc.is_empty() { out.next_section(); } - for line in method.doc.to_string().lines() { - writeln!(out, " //{}", line); - } + write_doc(out, " ", &method.doc); write!(out, " "); let sig = &method.sig; let local_name = method.name.cxx.to_string(); @@ -381,6 +391,7 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) { let repr = match &enm.repr { + #[cfg(feature = "experimental-enum-variants-from-header")] EnumRepr::Foreign { .. } => return, EnumRepr::Native { atom, .. } => *atom, }; @@ -388,16 +399,12 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) { let guard = format!("CXXBRIDGE1_ENUM_{}", enm.name.to_symbol()); writeln!(out, "#ifndef {}", guard); writeln!(out, "#define {}", guard); - for line in enm.doc.to_string().lines() { - writeln!(out, "//{}", line); - } + write_doc(out, "", &enm.doc); write!(out, "enum class {} : ", enm.name.cxx); write_atom(out, repr); writeln!(out, " {{"); for variant in &enm.variants { - for line in variant.doc.to_string().lines() { - writeln!(out, " //{}", line); - } + write_doc(out, " ", &variant.doc); writeln!(out, " {} = {},", variant.name.cxx, variant.discriminant); } writeln!(out, "}};"); @@ -406,6 +413,7 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) { fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) { let repr = match &enm.repr { + #[cfg(feature = "experimental-enum-variants-from-header")] EnumRepr::Foreign { .. } => return, EnumRepr::Native { atom, .. } => *atom, }; @@ -467,7 +475,25 @@ fn check_trivial_extern_type(out: &mut OutFile, alias: &TypeAlias, reasons: &[Tr let id = alias.name.to_fully_qualified(); out.builtin.relocatable = true; writeln!(out, "static_assert("); - writeln!(out, " ::rust::IsRelocatable<{}>::value,", id); + if reasons + .iter() + .all(|r| matches!(r, TrivialReason::StructField(_) | TrivialReason::VecElement)) + { + // If the type is only used as a struct field or Vec element, not as + // by-value function argument or return value, then C array of trivially + // relocatable type is also permissible. + // + // --- means something sane: + // struct T { char buf[N]; }; + // + // --- means something totally different: + // void f(char buf[N]); + // + out.builtin.relocatable_or_array = true; + writeln!(out, " ::rust::IsRelocatableOrArray<{}>::value,", id); + } else { + writeln!(out, " ::rust::IsRelocatable<{}>::value,", id); + } writeln!( out, " \"type {} should be trivially move constructible and trivially destructible in C++ to be used as {} in Rust\");", @@ -484,7 +510,7 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { let link_name = mangle::operator(&strct.name, "eq"); writeln!( out, - "bool {}(const {1} &, const {1} &) noexcept;", + "bool {}({1} const &, {1} const &) noexcept;", link_name, strct.name.cxx, ); @@ -492,7 +518,7 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { let link_name = mangle::operator(&strct.name, "ne"); writeln!( out, - "bool {}(const {1} &, const {1} &) noexcept;", + "bool {}({1} const &, {1} const &) noexcept;", link_name, strct.name.cxx, ); } @@ -502,14 +528,14 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { let link_name = mangle::operator(&strct.name, "lt"); writeln!( out, - "bool {}(const {1} &, const {1} &) noexcept;", + "bool {}({1} const &, {1} const &) noexcept;", link_name, strct.name.cxx, ); let link_name = mangle::operator(&strct.name, "le"); writeln!( out, - "bool {}(const {1} &, const {1} &) noexcept;", + "bool {}({1} const &, {1} const &) noexcept;", link_name, strct.name.cxx, ); @@ -517,14 +543,14 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { let link_name = mangle::operator(&strct.name, "gt"); writeln!( out, - "bool {}(const {1} &, const {1} &) noexcept;", + "bool {}({1} const &, {1} const &) noexcept;", link_name, strct.name.cxx, ); let link_name = mangle::operator(&strct.name, "ge"); writeln!( out, - "bool {}(const {1} &, const {1} &) noexcept;", + "bool {}({1} const &, {1} const &) noexcept;", link_name, strct.name.cxx, ); } @@ -535,7 +561,7 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { let link_name = mangle::operator(&strct.name, "hash"); writeln!( out, - "::std::size_t {}(const {} &) noexcept;", + "::std::size_t {}({} const &) noexcept;", link_name, strct.name.cxx, ); } @@ -554,7 +580,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { out.next_section(); writeln!( out, - "bool {0}::operator==(const {0} &rhs) const noexcept {{", + "bool {0}::operator==({0} const &rhs) const noexcept {{", strct.name.cxx, ); let link_name = mangle::operator(&strct.name, "eq"); @@ -564,7 +590,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { out.next_section(); writeln!( out, - "bool {0}::operator!=(const {0} &rhs) const noexcept {{", + "bool {0}::operator!=({0} const &rhs) const noexcept {{", strct.name.cxx, ); if derive::contains(&strct.derives, Trait::Eq) { @@ -580,7 +606,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { out.next_section(); writeln!( out, - "bool {0}::operator<(const {0} &rhs) const noexcept {{", + "bool {0}::operator<({0} const &rhs) const noexcept {{", strct.name.cxx, ); let link_name = mangle::operator(&strct.name, "lt"); @@ -590,7 +616,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { out.next_section(); writeln!( out, - "bool {0}::operator<=(const {0} &rhs) const noexcept {{", + "bool {0}::operator<=({0} const &rhs) const noexcept {{", strct.name.cxx, ); let link_name = mangle::operator(&strct.name, "le"); @@ -600,7 +626,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { out.next_section(); writeln!( out, - "bool {0}::operator>(const {0} &rhs) const noexcept {{", + "bool {0}::operator>({0} const &rhs) const noexcept {{", strct.name.cxx, ); if derive::contains(&strct.derives, Trait::Ord) { @@ -614,7 +640,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { out.next_section(); writeln!( out, - "bool {0}::operator>=(const {0} &rhs) const noexcept {{", + "bool {0}::operator>=({0} const &rhs) const noexcept {{", strct.name.cxx, ); if derive::contains(&strct.derives, Trait::Ord) { @@ -688,25 +714,29 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { let mangled = mangle::extern_fn(efn, out.types); write!(out, "{}(", mangled); if let Some(receiver) = &efn.receiver { - if !receiver.mutable { - write!(out, "const "); - } write!( out, - "{} &self", + "{}", out.types.resolve(&receiver.ty).name.to_fully_qualified(), ); + if !receiver.mutable { + write!(out, " const"); + } + write!(out, " &self"); } for (i, arg) in efn.args.iter().enumerate() { if i > 0 || efn.receiver.is_some() { write!(out, ", "); } if arg.ty == RustString { - write!(out, "const "); + write_type_space(out, &arg.ty); + write!(out, "const *{}", arg.name.cxx); } else if let Type::RustVec(_) = arg.ty { - write!(out, "const "); + write_type_space(out, &arg.ty); + write!(out, "const *{}", arg.name.cxx); + } else { + write_extern_arg(out, arg); } - write_extern_arg(out, arg); } let indirect_return = indirect_return(efn, out.types); if indirect_return { @@ -826,17 +856,9 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { } writeln!(out, ";"); if efn.throws { - out.include.cstring = true; - out.builtin.exception = true; writeln!(out, " throw$.ptr = nullptr;"); writeln!(out, " }},"); - writeln!(out, " [&](const char *catch$) noexcept {{"); - writeln!(out, " throw$.len = ::std::strlen(catch$);"); - writeln!( - out, - " throw$.ptr = const_cast<char *>(::cxxbridge1$exception(catch$, throw$.len));", - ); - writeln!(out, " }});"); + writeln!(out, " ::rust::detail::Fail(throw$));"); writeln!(out, " return throw$;"); } writeln!(out, "}}"); @@ -885,14 +907,15 @@ fn write_rust_function_decl_impl( write!(out, "{}(", link_name); let mut needs_comma = false; if let Some(receiver) = &sig.receiver { - if !receiver.mutable { - write!(out, "const "); - } write!( out, - "{} &self", + "{}", out.types.resolve(&receiver.ty).name.to_fully_qualified(), ); + if !receiver.mutable { + write!(out, " const"); + } + write!(out, " &self"); needs_comma = true; } for arg in &sig.args { @@ -908,8 +931,11 @@ fn write_rust_function_decl_impl( } match sig.ret.as_ref().unwrap() { Type::Ref(ret) => { - write_pointee_type(out, &ret.inner, ret.mutable); - write!(out, " *"); + write_type_space(out, &ret.inner); + if !ret.mutable { + write!(out, "const "); + } + write!(out, "*"); } ret => write_type_space(out, ret), } @@ -988,9 +1014,7 @@ fn write_rust_function_shim_impl( } if sig.receiver.is_none() { // Member functions already documented at their declaration. - for line in doc.to_string().lines() { - writeln!(out, "//{}", line); - } + write_doc(out, "", doc); } write_rust_function_shim_decl(out, local_name, sig, indirect_call); if out.header { @@ -1014,8 +1038,11 @@ fn write_rust_function_shim_impl( write!(out, "::rust::MaybeUninit<"); match sig.ret.as_ref().unwrap() { Type::Ref(ret) => { - write_pointee_type(out, &ret.inner, ret.mutable); - write!(out, " *"); + write_type_space(out, &ret.inner); + if !ret.mutable { + write!(out, "const "); + } + write!(out, "*"); } ret => write_type(out, ret), } @@ -1134,11 +1161,11 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) { write!(out, "*"); } Type::Ref(ty) => { + write_type_space(out, &ty.inner); if !ty.mutable { write!(out, "const "); } - write_type(out, &ty.inner); - write!(out, " *"); + write!(out, "*"); } _ => write_type(out, ty), } @@ -1160,11 +1187,11 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) { write!(out, "*"); } Some(Type::Ref(ty)) => { + write_type_space(out, &ty.inner); if !ty.mutable { write!(out, "const "); } - write_type(out, &ty.inner); - write!(out, " *"); + write!(out, "*"); } Some(Type::Str(_)) | Some(Type::SliceRef(_)) => { out.builtin.repr_fat = true; @@ -1230,22 +1257,28 @@ fn write_type(out: &mut OutFile, ty: &Type) { write!(out, ">"); } Type::Ref(r) => { - write_pointee_type(out, &r.inner, r.mutable); - write!(out, " &"); + write_type_space(out, &r.inner); + if !r.mutable { + write!(out, "const "); + } + write!(out, "&"); } Type::Ptr(p) => { - write_pointee_type(out, &p.inner, p.mutable); - write!(out, " *"); + write_type_space(out, &p.inner); + if !p.mutable { + write!(out, "const "); + } + write!(out, "*"); } Type::Str(_) => { write!(out, "::rust::Str"); } Type::SliceRef(slice) => { write!(out, "::rust::Slice<"); + write_type_space(out, &slice.inner); if slice.mutability.is_none() { - write!(out, "const "); + write!(out, "const"); } - write_type(out, &slice.inner); write!(out, ">"); } Type::Fn(f) => { @@ -1272,21 +1305,6 @@ fn write_type(out: &mut OutFile, ty: &Type) { } } -// Write just the T type behind a &T or &mut T or *const T or *mut T. -fn write_pointee_type(out: &mut OutFile, inner: &Type, mutable: bool) { - if let Type::Ptr(_) = inner { - write_type_space(out, inner); - if !mutable { - write!(out, "const"); - } - } else { - if !mutable { - write!(out, "const "); - } - write_type(out, inner); - } -} - fn write_atom(out: &mut OutFile, atom: Atom) { match atom { Bool => write!(out, "bool"), @@ -1372,7 +1390,9 @@ impl<'a> ToMangled for UniquePtr<'a> { fn to_mangled(&self, types: &Types) -> Symbol { match self { UniquePtr::Ident(ident) => ident.to_mangled(types), - UniquePtr::CxxVector(element) => element.to_mangled(types).prefix_with("std$vector$"), + UniquePtr::CxxVector(element) => { + symbol::join(&[&"std", &"vector", &element.to_mangled(types)]) + } } } } @@ -1442,7 +1462,7 @@ fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) { writeln!( out, - "void cxxbridge1$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;", + "void cxxbridge1$rust_vec${}$new(::rust::Vec<{}> const *ptr) noexcept;", instance, inner, ); writeln!( @@ -1452,17 +1472,17 @@ fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) { ); writeln!( out, - "::std::size_t cxxbridge1$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;", + "::std::size_t cxxbridge1$rust_vec${}$len(::rust::Vec<{}> const *ptr) noexcept;", instance, inner, ); writeln!( out, - "::std::size_t cxxbridge1$rust_vec${}$capacity(const ::rust::Vec<{}> *ptr) noexcept;", + "::std::size_t cxxbridge1$rust_vec${}$capacity(::rust::Vec<{}> const *ptr) noexcept;", instance, inner, ); writeln!( out, - "const {} *cxxbridge1$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;", + "{} const *cxxbridge1$rust_vec${}$data(::rust::Vec<{0}> const *ptr) noexcept;", inner, instance, ); writeln!( @@ -1475,6 +1495,11 @@ fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) { "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;", instance, inner, ); + writeln!( + out, + "void cxxbridge1$rust_vec${}$truncate(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;", + instance, inner, + ); } fn write_rust_box_impl(out: &mut OutFile, key: NamedImplKey) { @@ -1554,7 +1579,7 @@ fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) { writeln!(out, "template <>"); begin_function_definition(out); - writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner); + writeln!(out, "{} const *Vec<{0}>::data() const noexcept {{", inner); writeln!(out, " return cxxbridge1$rust_vec${}$data(this);", instance); writeln!(out, "}}"); @@ -1585,6 +1610,16 @@ fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) { instance, ); writeln!(out, "}}"); + + writeln!(out, "template <>"); + begin_function_definition(out); + writeln!(out, "void Vec<{}>::truncate(::std::size_t len) {{", inner,); + writeln!( + out, + " return cxxbridge1$rust_vec${}$truncate(this, len);", + instance, + ); + writeln!(out, "}}"); } fn write_unique_ptr(out: &mut OutFile, key: NamedImplKey) { @@ -1637,6 +1672,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) { "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");", inner, ); + begin_function_definition(out); writeln!( out, "void cxxbridge1$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{", @@ -1646,6 +1682,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) { writeln!(out, "}}"); if can_construct_from_value { out.builtin.maybe_uninit = true; + begin_function_definition(out); writeln!( out, "{} *cxxbridge1$unique_ptr${}$uninit(::std::unique_ptr<{}> *ptr) noexcept {{", @@ -1660,6 +1697,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) { writeln!(out, " return uninit;"); writeln!(out, "}}"); } + begin_function_definition(out); writeln!( out, "void cxxbridge1$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{", @@ -1667,20 +1705,23 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) { ); writeln!(out, " ::new (ptr) ::std::unique_ptr<{}>(raw);", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, - "const {} *cxxbridge1$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{", + "{} const *cxxbridge1$unique_ptr${}$get(::std::unique_ptr<{}> const &ptr) noexcept {{", inner, instance, inner, ); writeln!(out, " return ptr.get();"); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, - "{} *cxxbridge1$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{", + "{} *cxxbridge1$unique_ptr${}$release(::std::unique_ptr<{}> &ptr) noexcept {{", inner, instance, inner, ); writeln!(out, " return ptr.release();"); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, "void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{", @@ -1724,6 +1765,7 @@ fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) { "static_assert(alignof(::std::shared_ptr<{}>) == alignof(void *), \"\");", inner, ); + begin_function_definition(out); writeln!( out, "void cxxbridge1$shared_ptr${}$null(::std::shared_ptr<{}> *ptr) noexcept {{", @@ -1733,6 +1775,7 @@ fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) { writeln!(out, "}}"); if can_construct_from_value { out.builtin.maybe_uninit = true; + begin_function_definition(out); writeln!( out, "{} *cxxbridge1$shared_ptr${}$uninit(::std::shared_ptr<{}> *ptr) noexcept {{", @@ -1747,20 +1790,23 @@ fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) { writeln!(out, " return uninit;"); writeln!(out, "}}"); } + begin_function_definition(out); writeln!( out, - "void cxxbridge1$shared_ptr${}$clone(const ::std::shared_ptr<{}>& self, ::std::shared_ptr<{}> *ptr) noexcept {{", + "void cxxbridge1$shared_ptr${}$clone(::std::shared_ptr<{}> const &self, ::std::shared_ptr<{}> *ptr) noexcept {{", instance, inner, inner, ); writeln!(out, " ::new (ptr) ::std::shared_ptr<{}>(self);", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, - "const {} *cxxbridge1$shared_ptr${}$get(const ::std::shared_ptr<{}>& self) noexcept {{", + "{} const *cxxbridge1$shared_ptr${}$get(::std::shared_ptr<{}> const &self) noexcept {{", inner, instance, inner, ); writeln!(out, " return self.get();"); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, "void cxxbridge1$shared_ptr${}$drop(::std::shared_ptr<{}> *self) noexcept {{", @@ -1795,23 +1841,26 @@ fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) { ); writeln!(out, " ::new (ptr) ::std::weak_ptr<{}>();", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, - "void cxxbridge1$weak_ptr${}$clone(const ::std::weak_ptr<{}>& self, ::std::weak_ptr<{}> *ptr) noexcept {{", + "void cxxbridge1$weak_ptr${}$clone(::std::weak_ptr<{}> const &self, ::std::weak_ptr<{}> *ptr) noexcept {{", instance, inner, inner, ); writeln!(out, " ::new (ptr) ::std::weak_ptr<{}>(self);", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, - "void cxxbridge1$weak_ptr${}$downgrade(const ::std::shared_ptr<{}>& shared, ::std::weak_ptr<{}> *weak) noexcept {{", + "void cxxbridge1$weak_ptr${}$downgrade(::std::shared_ptr<{}> const &shared, ::std::weak_ptr<{}> *weak) noexcept {{", instance, inner, inner, ); writeln!(out, " ::new (weak) ::std::weak_ptr<{}>(shared);", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, - "void cxxbridge1$weak_ptr${}$upgrade(const ::std::weak_ptr<{}>& weak, ::std::shared_ptr<{}> *shared) noexcept {{", + "void cxxbridge1$weak_ptr${}$upgrade(::std::weak_ptr<{}> const &weak, ::std::shared_ptr<{}> *shared) noexcept {{", instance, inner, inner, ); writeln!( @@ -1820,6 +1869,7 @@ fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) { inner, ); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, "void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{", @@ -1840,12 +1890,13 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) { writeln!( out, - "::std::size_t cxxbridge1$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{", + "::std::size_t cxxbridge1$std$vector${}$size(::std::vector<{}> const &s) noexcept {{", instance, inner, ); writeln!(out, " return s.size();"); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, "{} *cxxbridge1$std$vector${}$get_unchecked(::std::vector<{}> *s, ::std::size_t pos) noexcept {{", @@ -1855,6 +1906,7 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) { writeln!(out, "}}"); if out.types.is_maybe_trivial(element) { + begin_function_definition(out); writeln!( out, "void cxxbridge1$std$vector${}$push_back(::std::vector<{}> *v, {} *value) noexcept {{", @@ -1864,6 +1916,7 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) { writeln!(out, " ::rust::destroy(value);"); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, "void cxxbridge1$std$vector${}$pop_back(::std::vector<{}> *v, {} *out) noexcept {{", diff --git a/include/cxx.h b/include/cxx.h index dffcb01a..907ee829 100644 --- a/include/cxx.h +++ b/include/cxx.h @@ -46,6 +46,13 @@ public: String(const char16_t *); String(const char16_t *, std::size_t); + // Replace invalid Unicode data with the replacement character (U+FFFD). + static String lossy(const std::string &) noexcept; + static String lossy(const char *) noexcept; + static String lossy(const char *, std::size_t) noexcept; + static String lossy(const char16_t *) noexcept; + static String lossy(const char16_t *, std::size_t) noexcept; + String &operator=(const String &) &noexcept; String &operator=(String &&) &noexcept; @@ -85,6 +92,9 @@ public: String(unsafe_bitcopy_t, const String &) noexcept; private: + struct lossy_t; + String(lossy_t, const char *, std::size_t) noexcept; + String(lossy_t, const char16_t *, std::size_t) noexcept; friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); } // Size and alignment statically verified by rust_string.rs. @@ -324,6 +334,8 @@ public: void push_back(T &&value); template <typename... Args> void emplace_back(Args &&...args); + void truncate(std::size_t len); + void clear(); using iterator = typename Slice<T>::iterator; iterator begin() noexcept; @@ -945,6 +957,11 @@ void Vec<T>::emplace_back(Args &&...args) { } template <typename T> +void Vec<T>::clear() { + this->truncate(0); +} + +template <typename T> typename Vec<T>::iterator Vec<T>::begin() noexcept { return Slice<T>(this->data(), this->size()).begin(); } diff --git a/macro/Android.bp b/macro/Android.bp index 6f418506..6f6b12a3 100644 --- a/macro/Android.bp +++ b/macro/Android.bp @@ -1,4 +1,5 @@ // This file is generated by cargo2android.py --run --dependencies --add_workspace. +// Do not modify this file as changes will be overridden on upgrade. package { // See: http://go/android-license-faq @@ -13,6 +14,8 @@ package { rust_proc_macro { name: "libcxxbridge_macro", crate_name: "cxxbridge_macro", + cargo_env_compat: true, + cargo_pkg_version: "1.0.85", srcs: ["src/lib.rs"], edition: "2018", rustlibs: [ @@ -21,9 +24,3 @@ rust_proc_macro { "libsyn", ], } - -// dependent_library ["feature_list"] -// proc-macro2-1.0.19 "default,proc-macro" -// quote-1.0.7 "default,proc-macro" -// syn-1.0.36 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote" -// unicode-xid-0.2.1 "default" diff --git a/macro/Cargo.toml b/macro/Cargo.toml index 65f15c3a..ed230388 100644 --- a/macro/Cargo.toml +++ b/macro/Cargo.toml @@ -1,28 +1,31 @@ [package] name = "cxxbridge-macro" -version = "1.0.54" +version = "1.0.85" authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -license = "MIT OR Apache-2.0" +categories = ["development-tools::ffi"] description = "Implementation detail of the `cxx` crate." -repository = "https://github.com/dtolnay/cxx" -homepage = "https://cxx.rs" +edition = "2018" exclude = ["build.rs", "README.md"] +homepage = "https://cxx.rs" keywords = ["ffi"] -categories = ["development-tools::ffi"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/cxx" +rust-version = "1.48" [lib] proc-macro = true [features] -experimental = ["clang-ast", "flate2", "memmap", "serde", "serde_json"] +# incomplete features that are not covered by a compatibility guarantee: +experimental-async-fn = [] +experimental-enum-variants-from-header = ["clang-ast", "flate2", "memmap", "serde", "serde_json"] [dependencies] -proc-macro2 = "1.0" +proc-macro2 = "1.0.39" quote = "1.0.4" -syn = { version = "1.0.70", features = ["full"] } +syn = { version = "1.0.95", features = ["full"] } -# optional dependencies +# optional dependencies: clang-ast = { version = "0.1", optional = true } flate2 = { version = "1.0", optional = true } memmap = { version = "0.7", optional = true } diff --git a/macro/src/clang.rs b/macro/src/clang.rs index 099d5a68..381e5086 100644 --- a/macro/src/clang.rs +++ b/macro/src/clang.rs @@ -48,4 +48,4 @@ pub struct Type { } #[cfg(all(test, target_pointer_width = "64"))] -const _: [(); std::mem::size_of::<Node>()] = [(); 88]; +const _: [(); core::mem::size_of::<Node>()] = [(); 88]; diff --git a/macro/src/derive.rs b/macro/src/derive.rs index ea36e3e3..afe85d1c 100644 --- a/macro/src/derive.rs +++ b/macro/src/derive.rs @@ -15,12 +15,14 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) - Trait::Clone => expanded.extend(struct_clone(strct, span)), Trait::Debug => expanded.extend(struct_debug(strct, span)), Trait::Default => expanded.extend(struct_default(strct, span)), - Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)), + Trait::Eq => traits.push(quote_spanned!(span=> ::cxx::core::cmp::Eq)), Trait::ExternType => unreachable!(), - Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)), + Trait::Hash => traits.push(quote_spanned!(span=> ::cxx::core::hash::Hash)), Trait::Ord => expanded.extend(struct_ord(strct, span)), - Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)), + Trait::PartialEq => traits.push(quote_spanned!(span=> ::cxx::core::cmp::PartialEq)), Trait::PartialOrd => expanded.extend(struct_partial_ord(strct, span)), + Trait::Serialize => traits.push(quote_spanned!(span=> ::serde::Serialize)), + Trait::Deserialize => traits.push(quote_spanned!(span=> ::serde::Deserialize)), } } @@ -55,17 +57,19 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke Trait::Debug => expanded.extend(enum_debug(enm, span)), Trait::Default => unreachable!(), Trait::Eq => { - traits.push(quote_spanned!(span=> ::std::cmp::Eq)); + traits.push(quote_spanned!(span=> ::cxx::core::cmp::Eq)); has_eq = true; } Trait::ExternType => unreachable!(), - Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)), + Trait::Hash => traits.push(quote_spanned!(span=> ::cxx::core::hash::Hash)), Trait::Ord => expanded.extend(enum_ord(enm, span)), Trait::PartialEq => { - traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)); + traits.push(quote_spanned!(span=> ::cxx::core::cmp::PartialEq)); has_partial_eq = true; } Trait::PartialOrd => expanded.extend(enum_partial_ord(enm, span)), + Trait::Serialize => traits.push(quote_spanned!(span=> ::serde::Serialize)), + Trait::Deserialize => traits.push(quote_spanned!(span=> ::serde::Deserialize)), } } @@ -79,10 +83,10 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke if !has_eq { // Required to be derived in order for the enum's "variants" to be // usable in patterns. - traits.push(quote!(::std::cmp::Eq)); + traits.push(quote!(::cxx::core::cmp::Eq)); } if !has_partial_eq { - traits.push(quote!(::std::cmp::PartialEq)); + traits.push(quote!(::cxx::core::cmp::PartialEq)); } *actual_derives = Some(quote!(#[derive(#(#traits),*)])); @@ -95,7 +99,7 @@ fn struct_copy(strct: &Struct, span: Span) -> TokenStream { let generics = &strct.generics; quote_spanned! {span=> - impl #generics ::std::marker::Copy for #ident #generics {} + impl #generics ::cxx::core::marker::Copy for #ident #generics {} } } @@ -114,12 +118,12 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream { quote_spanned!(span=> &self.#ident) }); quote_spanned!(span=> #ident { - #(#fields: ::std::clone::Clone::clone(#values),)* + #(#fields: ::cxx::core::clone::Clone::clone(#values),)* }) }; quote_spanned! {span=> - impl #generics ::std::clone::Clone for #ident #generics { + impl #generics ::cxx::core::clone::Clone for #ident #generics { fn clone(&self) -> Self { #body } @@ -135,8 +139,8 @@ fn struct_debug(strct: &Struct, span: Span) -> TokenStream { let field_names = fields.clone().map(Ident::to_string); quote_spanned! {span=> - impl #generics ::std::fmt::Debug for #ident #generics { - fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + impl #generics ::cxx::core::fmt::Debug for #ident #generics { + fn fmt(&self, formatter: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { formatter.debug_struct(#struct_name) #(.field(#field_names, &self.#fields))* .finish() @@ -152,11 +156,11 @@ fn struct_default(strct: &Struct, span: Span) -> TokenStream { quote_spanned! {span=> #[allow(clippy::derivable_impls)] // different spans than the derived impl - impl #generics ::std::default::Default for #ident #generics { + impl #generics ::cxx::core::default::Default for #ident #generics { fn default() -> Self { #ident { #( - #fields: ::std::default::Default::default(), + #fields: ::cxx::core::default::Default::default(), )* } } @@ -170,15 +174,15 @@ fn struct_ord(strct: &Struct, span: Span) -> TokenStream { let fields = strct.fields.iter().map(|field| &field.name.rust); quote_spanned! {span=> - impl #generics ::std::cmp::Ord for #ident #generics { - fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { + impl #generics ::cxx::core::cmp::Ord for #ident #generics { + fn cmp(&self, other: &Self) -> ::cxx::core::cmp::Ordering { #( - match ::std::cmp::Ord::cmp(&self.#fields, &other.#fields) { - ::std::cmp::Ordering::Equal => {} + match ::cxx::core::cmp::Ord::cmp(&self.#fields, &other.#fields) { + ::cxx::core::cmp::Ordering::Equal => {} ordering => return ordering, } )* - ::std::cmp::Ordering::Equal + ::cxx::core::cmp::Ordering::Equal } } } @@ -190,24 +194,24 @@ fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream { let body = if derive::contains(&strct.derives, Trait::Ord) { quote! { - ::std::option::Option::Some(::std::cmp::Ord::cmp(self, other)) + ::cxx::core::option::Option::Some(::cxx::core::cmp::Ord::cmp(self, other)) } } else { let fields = strct.fields.iter().map(|field| &field.name.rust); quote! { #( - match ::std::cmp::PartialOrd::partial_cmp(&self.#fields, &other.#fields) { - ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {} + match ::cxx::core::cmp::PartialOrd::partial_cmp(&self.#fields, &other.#fields) { + ::cxx::core::option::Option::Some(::cxx::core::cmp::Ordering::Equal) => {} ordering => return ordering, } )* - ::std::option::Option::Some(::std::cmp::Ordering::Equal) + ::cxx::core::option::Option::Some(::cxx::core::cmp::Ordering::Equal) } }; quote_spanned! {span=> - impl #generics ::std::cmp::PartialOrd for #ident #generics { - fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> { + impl #generics ::cxx::core::cmp::PartialOrd for #ident #generics { + fn partial_cmp(&self, other: &Self) -> ::cxx::core::option::Option<::cxx::core::cmp::Ordering> { #body } } @@ -218,7 +222,7 @@ fn enum_copy(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; quote_spanned! {span=> - impl ::std::marker::Copy for #ident {} + impl ::cxx::core::marker::Copy for #ident {} } } @@ -226,7 +230,7 @@ fn enum_clone(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; quote_spanned! {span=> - impl ::std::clone::Clone for #ident { + impl ::cxx::core::clone::Clone for #ident { fn clone(&self) -> Self { *self } @@ -246,11 +250,11 @@ fn enum_debug(enm: &Enum, span: Span) -> TokenStream { let fallback = format!("{}({{}})", ident); quote_spanned! {span=> - impl ::std::fmt::Debug for #ident { - fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + impl ::cxx::core::fmt::Debug for #ident { + fn fmt(&self, formatter: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { match *self { #(#variants)* - _ => ::std::write!(formatter, #fallback, self.repr), + _ => ::cxx::core::write!(formatter, #fallback, self.repr), } } } @@ -261,9 +265,9 @@ fn enum_ord(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; quote_spanned! {span=> - impl ::std::cmp::Ord for #ident { - fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { - ::std::cmp::Ord::cmp(&self.repr, &other.repr) + impl ::cxx::core::cmp::Ord for #ident { + fn cmp(&self, other: &Self) -> ::cxx::core::cmp::Ordering { + ::cxx::core::cmp::Ord::cmp(&self.repr, &other.repr) } } } @@ -273,9 +277,9 @@ fn enum_partial_ord(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; quote_spanned! {span=> - impl ::std::cmp::PartialOrd for #ident { - fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> { - ::std::cmp::PartialOrd::partial_cmp(&self.repr, &other.repr) + impl ::cxx::core::cmp::PartialOrd for #ident { + fn partial_cmp(&self, other: &Self) -> ::cxx::core::option::Option<::cxx::core::cmp::Ordering> { + ::cxx::core::cmp::PartialOrd::partial_cmp(&self.repr, &other.repr) } } } diff --git a/macro/src/expand.rs b/macro/src/expand.rs index 5a879cbd..8f5836a6 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -1,5 +1,6 @@ use crate::syntax::atom::Atom::*; use crate::syntax::attrs::{self, OtherAttrs}; +use crate::syntax::cfg::CfgExpr; use crate::syntax::file::Module; use crate::syntax::instantiate::{ImplKey, NamedImplKey}; use crate::syntax::qualified::QualifiedName; @@ -19,11 +20,13 @@ use syn::{parse_quote, punctuated, Generics, Lifetime, Result, Token}; pub fn bridge(mut ffi: Module) -> Result<TokenStream> { let ref mut errors = Errors::new(); + let mut cfg = CfgExpr::Unconditional; let mut doc = Doc::new(); let attrs = attrs::parse( errors, mem::take(&mut ffi.attrs), attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), ..Default::default() }, @@ -33,7 +36,7 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> { let trusted = ffi.unsafety.is_some(); let namespace = &ffi.namespace; let ref mut apis = syntax::parse_items(errors, content, trusted, namespace); - #[cfg(feature = "experimental")] + #[cfg(feature = "experimental-enum-variants-from-header")] crate::load::load(errors, apis); let ref types = Types::collect(errors, apis); errors.propagate()?; @@ -53,7 +56,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) for api in apis { if let Api::RustType(ety) = api { expanded.extend(expand_rust_type_import(ety)); - hidden.extend(expand_rust_type_assert_sized(ety)); + hidden.extend(expand_rust_type_assert_unpin(ety, types)); } } @@ -70,7 +73,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) let ident = &ety.name.rust; if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) { expanded.extend(expand_cxx_type(ety)); - hidden.extend(expand_cxx_type_assert_pinned(ety)); + hidden.extend(expand_cxx_type_assert_pinned(ety, types)); } } Api::CxxFunction(efn) => { @@ -78,7 +81,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) } Api::RustType(ety) => { expanded.extend(expand_rust_type_impl(ety)); - hidden.extend(expand_rust_type_layout(ety)); + hidden.extend(expand_rust_type_layout(ety, types)); } Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)), Api::TypeAlias(alias) => { @@ -169,12 +172,13 @@ fn expand_struct(strct: &Struct) -> TokenStream { quote! { #doc - #attrs #derives + #attrs #[repr(C)] #struct_def unsafe impl #generics ::cxx::ExternType for #ident #generics { + #[allow(unused_attributes)] // incorrect lint #[doc(hidden)] type Id = #type_id; type Kind = ::cxx::kind::Trivial; @@ -186,6 +190,7 @@ fn expand_struct(strct: &Struct) -> TokenStream { fn expand_struct_operators(strct: &Struct) -> TokenStream { let ident = &strct.name.rust; + let generics = &strct.generics; let mut operators = TokenStream::new(); for derive in &strct.derives { @@ -194,22 +199,26 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { Trait::PartialEq => { let link_name = mangle::operator(&strct.name, "eq"); let local_name = format_ident!("__operator_eq_{}", strct.name.rust); + let prevent_unwind_label = format!("::{} as PartialEq>::eq", strct.name.rust); operators.extend(quote_spanned! {span=> #[doc(hidden)] #[export_name = #link_name] - extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool { - *lhs == *rhs + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { + let __fn = concat!("<", module_path!(), #prevent_unwind_label); + ::cxx::private::prevent_unwind(__fn, || *lhs == *rhs) } }); if !derive::contains(&strct.derives, Trait::Eq) { let link_name = mangle::operator(&strct.name, "ne"); let local_name = format_ident!("__operator_ne_{}", strct.name.rust); + let prevent_unwind_label = format!("::{} as PartialEq>::ne", strct.name.rust); operators.extend(quote_spanned! {span=> #[doc(hidden)] #[export_name = #link_name] - extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool { - *lhs != *rhs + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { + let __fn = concat!("<", module_path!(), #prevent_unwind_label); + ::cxx::private::prevent_unwind(__fn, || *lhs != *rhs) } }); } @@ -217,42 +226,50 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { Trait::PartialOrd => { let link_name = mangle::operator(&strct.name, "lt"); let local_name = format_ident!("__operator_lt_{}", strct.name.rust); + let prevent_unwind_label = format!("::{} as PartialOrd>::lt", strct.name.rust); operators.extend(quote_spanned! {span=> #[doc(hidden)] #[export_name = #link_name] - extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool { - *lhs < *rhs + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { + let __fn = concat!("<", module_path!(), #prevent_unwind_label); + ::cxx::private::prevent_unwind(__fn, || *lhs < *rhs) } }); let link_name = mangle::operator(&strct.name, "le"); let local_name = format_ident!("__operator_le_{}", strct.name.rust); + let prevent_unwind_label = format!("::{} as PartialOrd>::le", strct.name.rust); operators.extend(quote_spanned! {span=> #[doc(hidden)] #[export_name = #link_name] - extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool { - *lhs <= *rhs + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { + let __fn = concat!("<", module_path!(), #prevent_unwind_label); + ::cxx::private::prevent_unwind(__fn, || *lhs <= *rhs) } }); if !derive::contains(&strct.derives, Trait::Ord) { let link_name = mangle::operator(&strct.name, "gt"); let local_name = format_ident!("__operator_gt_{}", strct.name.rust); + let prevent_unwind_label = format!("::{} as PartialOrd>::gt", strct.name.rust); operators.extend(quote_spanned! {span=> #[doc(hidden)] #[export_name = #link_name] - extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool { - *lhs > *rhs + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { + let __fn = concat!("<", module_path!(), #prevent_unwind_label); + ::cxx::private::prevent_unwind(__fn, || *lhs > *rhs) } }); let link_name = mangle::operator(&strct.name, "ge"); let local_name = format_ident!("__operator_ge_{}", strct.name.rust); + let prevent_unwind_label = format!("::{} as PartialOrd>::ge", strct.name.rust); operators.extend(quote_spanned! {span=> #[doc(hidden)] #[export_name = #link_name] - extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool { - *lhs >= *rhs + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { + let __fn = concat!("<", module_path!(), #prevent_unwind_label); + ::cxx::private::prevent_unwind(__fn, || *lhs >= *rhs) } }); } @@ -260,14 +277,14 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { Trait::Hash => { let link_name = mangle::operator(&strct.name, "hash"); let local_name = format_ident!("__operator_hash_{}", strct.name.rust); + let prevent_unwind_label = format!("::{} as Hash>::hash", strct.name.rust); operators.extend(quote_spanned! {span=> #[doc(hidden)] #[export_name = #link_name] #[allow(clippy::cast_possible_truncation)] - extern "C" fn #local_name(this: &#ident) -> usize { - let mut hasher = ::std::collections::hash_map::DefaultHasher::new(); - ::std::hash::Hash::hash(this, &mut hasher); - ::std::hash::Hasher::finish(&hasher) as usize + extern "C" fn #local_name #generics(this: &#ident #generics) -> usize { + let __fn = concat!("<", module_path!(), #prevent_unwind_label); + ::cxx::private::prevent_unwind(__fn, || ::cxx::private::hash(this)) } }); } @@ -325,8 +342,8 @@ fn expand_enum(enm: &Enum) -> TokenStream { quote! { #doc - #attrs #derives + #attrs #[repr(transparent)] #enum_def @@ -336,6 +353,7 @@ fn expand_enum(enm: &Enum) -> TokenStream { } unsafe impl ::cxx::ExternType for #ident { + #[allow(unused_attributes)] // incorrect lint #[doc(hidden)] type Id = #type_id; type Kind = ::cxx::kind::Trivial; @@ -354,7 +372,7 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream { let lifetime_fields = ety.generics.lifetimes.iter().map(|lifetime| { let field = format_ident!("_lifetime_{}", lifetime.ident); - quote!(#field: ::std::marker::PhantomData<&#lifetime ()>) + quote!(#field: ::cxx::core::marker::PhantomData<&#lifetime ()>) }); let repr_fields = quote! { _private: ::cxx::private::Opaque, @@ -377,6 +395,7 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream { #extern_type_def unsafe impl #generics ::cxx::ExternType for #ident #generics { + #[allow(unused_attributes)] // incorrect lint #[doc(hidden)] type Id = #type_id; type Kind = ::cxx::kind::Opaque; @@ -384,12 +403,15 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream { } } -fn expand_cxx_type_assert_pinned(ety: &ExternType) -> TokenStream { +fn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream { let ident = &ety.name.rust; let infer = Token![_](ident.span()); + let resolve = types.resolve(ident); + let lifetimes = resolve.generics.to_underscore_lifetimes(); + quote! { - let _ = { + let _: fn() = { // Derived from https://github.com/nvzqz/static-assertions-rs. trait __AmbiguousIfImpl<A> { fn infer() {} @@ -397,7 +419,7 @@ fn expand_cxx_type_assert_pinned(ety: &ExternType) -> TokenStream { impl<T> __AmbiguousIfImpl<()> for T where - T: ?::std::marker::Sized + T: ?::cxx::core::marker::Sized {} #[allow(dead_code)] @@ -405,14 +427,14 @@ fn expand_cxx_type_assert_pinned(ety: &ExternType) -> TokenStream { impl<T> __AmbiguousIfImpl<__Invalid> for T where - T: ?::std::marker::Sized + ::std::marker::Unpin, + T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin, {} // If there is only one specialized trait impl, type inference with // `_` can be resolved and this can compile. Fails to compile if // user has added a manual Unpin impl for their opaque C++ type as // then `__AmbiguousIfImpl<__Invalid>` also exists. - <#ident as __AmbiguousIfImpl<#infer>>::infer + <#ident #lifetimes as __AmbiguousIfImpl<#infer>>::infer }; } } @@ -482,7 +504,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { Some(ret) => quote!(#ret), None => quote!(()), }; - quote!(-> ::std::result::Result<#ok, ::cxx::Exception>) + quote!(-> ::cxx::core::result::Result<#ok, ::cxx::Exception>) } else { expand_return_type(&efn.ret) }; @@ -500,9 +522,9 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { } Type::RustBox(ty) => { if types.is_considered_improper_ctype(&ty.inner) { - quote_spanned!(span=> ::std::boxed::Box::into_raw(#var).cast()) + quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var).cast()) } else { - quote_spanned!(span=> ::std::boxed::Box::into_raw(#var)) + quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var)) } } Type::UniquePtr(ty) => { @@ -529,13 +551,13 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { inner if types.is_considered_improper_ctype(inner) => { let var = match ty.pinned { false => quote!(#var), - true => quote_spanned!(span=> ::std::pin::Pin::into_inner_unchecked(#var)), + true => quote_spanned!(span=> ::cxx::core::pin::Pin::into_inner_unchecked(#var)), }; match ty.mutable { false => { - quote_spanned!(span=> #var as *const #inner as *const ::std::ffi::c_void) + quote_spanned!(span=> #var as *const #inner as *const ::cxx::core::ffi::c_void) } - true => quote_spanned!(span=> #var as *mut #inner as *mut ::std::ffi::c_void), + true => quote_spanned!(span=> #var as *mut #inner as *mut ::cxx::core::ffi::c_void), } } _ => quote!(#var), @@ -579,7 +601,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { // These are arguments for which C++ has taken ownership of the data // behind the mut reference it received. quote_spanned! {span=> - let mut #var = ::std::mem::MaybeUninit::new(#var); + let mut #var = ::cxx::core::mem::MaybeUninit::new(#var); } }) .collect::<TokenStream>(); @@ -588,7 +610,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { let call = if indirect_return { let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true); setup.extend(quote_spanned! {span=> - let mut __return = ::std::mem::MaybeUninit::<#ret>::uninit(); + let mut __return = ::cxx::core::mem::MaybeUninit::<#ret>::uninit(); }); setup.extend(if efn.throws { quote_spanned! {span=> @@ -621,9 +643,9 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { } Type::RustBox(ty) => { if types.is_considered_improper_ctype(&ty.inner) { - quote_spanned!(span=> ::std::boxed::Box::from_raw(#call.cast())) + quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call.cast())) } else { - quote_spanned!(span=> ::std::boxed::Box::from_raw(#call)) + quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call)) } } Type::RustVec(vec) => { @@ -659,7 +681,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { match ty.pinned { false => deref_mut, true => { - quote_spanned!(span=> ::std::pin::Pin::new_unchecked(#deref_mut)) + quote_spanned!(span=> ::cxx::core::pin::Pin::new_unchecked(#deref_mut)) } } } @@ -684,7 +706,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { }, }; if efn.throws { - expr = quote_spanned!(span=> ::std::result::Result::Ok(#expr)); + expr = quote_spanned!(span=> ::cxx::core::result::Result::Ok(#expr)); } }; let mut dispatch = quote!(#setup #expr); @@ -755,16 +777,17 @@ fn expand_function_pointer_trampoline( let c_trampoline = mangle::c_trampoline(efn, var, types); let r_trampoline = mangle::r_trampoline(efn, var, types); let local_name = parse_quote!(__); - let catch_unwind_label = format!("::{}::{}", efn.name.rust, var.rust); + let prevent_unwind_label = format!("::{}::{}", efn.name.rust, var.rust); let body_span = efn.semi_token.span; let shim = expand_rust_function_shim_impl( sig, types, &r_trampoline, local_name, - catch_unwind_label, + prevent_unwind_label, None, Some(&efn.generics), + &efn.attrs, body_span, ); let var = &var.rust; @@ -777,9 +800,9 @@ fn expand_function_pointer_trampoline( fn trampoline(); } #shim - trampoline as usize as *const ::std::ffi::c_void + trampoline as usize as *const ::cxx::core::ffi::c_void }, - ptr: #var as usize as *const ::std::ffi::c_void, + ptr: #var as usize as *const ::cxx::core::ffi::c_void, }; } } @@ -810,6 +833,7 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream { let span = derive.span; impls.extend(quote_spanned! {span=> unsafe impl #generics ::cxx::ExternType for #ident #generics { + #[allow(unused_attributes)] // incorrect lint #[doc(hidden)] type Id = #type_id; type Kind = ::cxx::kind::Opaque; @@ -821,33 +845,37 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream { impls } -fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream { - // Rustc will render as follows if not sized: - // - // type TheirType; - // -----^^^^^^^^^- - // | | - // | doesn't have a size known at compile-time - // required by this bound in `ffi::_::__AssertSized` - +fn expand_rust_type_assert_unpin(ety: &ExternType, types: &Types) -> TokenStream { let ident = &ety.name.rust; let begin_span = Token![::](ety.type_token.span); let unpin = quote_spanned! {ety.semi_token.span=> - #begin_span std::marker::Unpin + #begin_span cxx::core::marker::Unpin }; + + let resolve = types.resolve(ident); + let lifetimes = resolve.generics.to_underscore_lifetimes(); + quote_spanned! {ident.span()=> let _ = { - fn __AssertUnpin<T: ?::std::marker::Sized + #unpin>() {} - __AssertUnpin::<#ident> + fn __AssertUnpin<T: ?::cxx::core::marker::Sized + #unpin>() {} + __AssertUnpin::<#ident #lifetimes> }; } } -fn expand_rust_type_layout(ety: &ExternType) -> TokenStream { +fn expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStream { + // Rustc will render as follows if not sized: + // + // type TheirType; + // -----^^^^^^^^^- + // | | + // | doesn't have a size known at compile-time + // required by this bound in `__AssertSized` + let ident = &ety.name.rust; let begin_span = Token![::](ety.type_token.span); let sized = quote_spanned! {ety.semi_token.span=> - #begin_span std::marker::Sized + #begin_span cxx::core::marker::Sized }; let link_sizeof = mangle::operator(&ety.name, "sizeof"); @@ -856,21 +884,24 @@ fn expand_rust_type_layout(ety: &ExternType) -> TokenStream { let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust); let local_alignof = format_ident!("__alignof_{}", ety.name.rust); + let resolve = types.resolve(ident); + let lifetimes = resolve.generics.to_underscore_lifetimes(); + quote_spanned! {ident.span()=> { #[doc(hidden)] - fn __AssertSized<T: ?#sized + #sized>() -> ::std::alloc::Layout { - ::std::alloc::Layout::new::<T>() + fn __AssertSized<T: ?#sized + #sized>() -> ::cxx::core::alloc::Layout { + ::cxx::core::alloc::Layout::new::<T>() } #[doc(hidden)] #[export_name = #link_sizeof] extern "C" fn #local_sizeof() -> usize { - __AssertSized::<#ident>().size() + __AssertSized::<#ident #lifetimes>().size() } #[doc(hidden)] #[export_name = #link_alignof] extern "C" fn #local_alignof() -> usize { - __AssertSized::<#ident>().align() + __AssertSized::<#ident #lifetimes>().align() } } } @@ -881,7 +912,7 @@ fn expand_forbid(impls: TokenStream) -> TokenStream { mod forbid { pub trait Drop {} #[allow(drop_bounds)] - impl<T: ?::std::marker::Sized + ::std::ops::Drop> self::Drop for T {} + impl<T: ?::cxx::core::marker::Sized + ::cxx::core::ops::Drop> self::Drop for T {} #impls } } @@ -893,7 +924,7 @@ fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { None => format_ident!("__{}", efn.name.rust), Some(receiver) => format_ident!("__{}__{}", receiver.ty.rust, efn.name.rust), }; - let catch_unwind_label = match &efn.receiver { + let prevent_unwind_label = match &efn.receiver { None => format!("::{}", efn.name.rust), Some(receiver) => format!("::{}::{}", receiver.ty.rust, efn.name.rust), }; @@ -904,9 +935,10 @@ fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { types, &link_name, local_name, - catch_unwind_label, + prevent_unwind_label, invoke, None, + &efn.attrs, body_span, ) } @@ -916,9 +948,10 @@ fn expand_rust_function_shim_impl( types: &Types, link_name: &Symbol, local_name: Ident, - catch_unwind_label: String, + prevent_unwind_label: String, invoke: Option<&Ident>, outer_generics: Option<&Generics>, + attrs: &OtherAttrs, body_span: Span, ) -> TokenStream { let generics = outer_generics.unwrap_or(&sig.generics); @@ -948,14 +981,14 @@ fn expand_rust_function_shim_impl( let span = var.span(); match &arg.ty { Type::Ident(i) if i.rust == RustString => { - quote_spanned!(span=> ::std::mem::take((*#var).as_mut_string())) + quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_string())) } - Type::RustBox(_) => quote_spanned!(span=> ::std::boxed::Box::from_raw(#var)), + Type::RustBox(_) => quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#var)), Type::RustVec(vec) => { if vec.inner == RustString { - quote_spanned!(span=> ::std::mem::take((*#var).as_mut_vec_string())) + quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec_string())) } else { - quote_spanned!(span=> ::std::mem::take((*#var).as_mut_vec())) + quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec())) } } Type::UniquePtr(_) => quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#var)), @@ -982,7 +1015,9 @@ fn expand_rust_function_shim_impl( true => quote_spanned!(span=> #var.as_mut_slice::<#inner>()), } } - ty if types.needs_indirect_abi(ty) => quote_spanned!(span=> ::std::ptr::read(#var)), + ty if types.needs_indirect_abi(ty) => { + quote_spanned!(span=> ::cxx::core::ptr::read(#var)) + } _ => quote!(#var), } }); @@ -998,7 +1033,7 @@ fn expand_rust_function_shim_impl( } None => { requires_closure = true; - quote!(::std::mem::transmute::<*const (), #sig>(__extern)) + quote!(::cxx::core::mem::transmute::<*const (), #sig>(__extern)) } }; requires_closure |= !vars.is_empty(); @@ -1009,7 +1044,7 @@ fn expand_rust_function_shim_impl( Type::Ident(ident) if ident.rust == RustString => { Some(quote_spanned!(span=> ::cxx::private::RustString::from)) } - Type::RustBox(_) => Some(quote_spanned!(span=> ::std::boxed::Box::into_raw)), + Type::RustBox(_) => Some(quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw)), Type::RustVec(vec) => { if vec.inner == RustString { Some(quote_spanned!(span=> ::cxx::private::RustVec::from_vec_string)) @@ -1049,7 +1084,7 @@ fn expand_rust_function_shim_impl( } Some(conversion) => { requires_closure = true; - quote_spanned!(span=> ::std::result::Result::map(#call, #conversion)) + quote_spanned!(span=> ::cxx::core::result::Result::map(#call, #conversion)) } }; @@ -1068,7 +1103,7 @@ fn expand_rust_function_shim_impl( expr = quote_spanned!(span=> ::cxx::private::r#try(#out, #expr)); } else if indirect_return { requires_closure = true; - expr = quote_spanned!(span=> ::std::ptr::write(__return, #expr)); + expr = quote_spanned!(span=> ::cxx::core::ptr::write(__return, #expr)); } let closure = if requires_closure { @@ -1077,7 +1112,7 @@ fn expand_rust_function_shim_impl( quote!(#local_name) }; - expr = quote_spanned!(span=> ::cxx::private::catch_unwind(__fn, #closure)); + expr = quote_spanned!(span=> ::cxx::private::prevent_unwind(__fn, #closure)); let ret = if sig.throws { quote!(-> ::cxx::private::Result) @@ -1091,10 +1126,11 @@ fn expand_rust_function_shim_impl( }; quote_spanned! {span=> + #attrs #[doc(hidden)] #[export_name = #link_name] unsafe extern "C" fn #local_name #generics(#(#all_args,)* #outparam #pointer) #ret { - let __fn = concat!(module_path!(), #catch_unwind_label); + let __fn = ::cxx::private::concat!(::cxx::private::module_path!(), #prevent_unwind_label); #wrap_super #expr } @@ -1129,8 +1165,8 @@ fn expand_rust_function_shim_super( }; // Set spans that result in the `Result<...>` written by the user being // highlighted as the cause if their error type has no Display impl. - let result_begin = quote_spanned!(result.span=> ::std::result::Result<#ok, impl); - let result_end = quote_spanned!(rangle.span=> ::std::fmt::Display>); + let result_begin = quote_spanned!(result.span=> ::cxx::core::result::Result<#ok, impl); + let result_end = quote_spanned!(rangle.span=> ::cxx::core::fmt::Display>); quote!(-> #result_begin #result_end) } else { expand_return_type(&sig.ret) @@ -1222,24 +1258,32 @@ fn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span); let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span); let unsafe_token = format_ident!("unsafe", span = begin_span); + let prevent_unwind_drop_label = format!("::{} as Drop>::drop", ident); quote_spanned! {end_span=> #[doc(hidden)] #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {} #[doc(hidden)] #[export_name = #link_alloc] - unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::std::mem::MaybeUninit<#ident #ty_generics> { - ::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit())) + unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics> { + // No prevent_unwind: the global allocator is not allowed to panic. + // + // TODO: replace with Box::new_uninit when stable. + // https://doc.rust-lang.org/std/boxed/struct.Box.html#method.new_uninit + // https://github.com/rust-lang/rust/issues/63291 + ::cxx::alloc::boxed::Box::into_raw(::cxx::alloc::boxed::Box::new(::cxx::core::mem::MaybeUninit::uninit())) } #[doc(hidden)] #[export_name = #link_dealloc] - unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::std::mem::MaybeUninit<#ident #ty_generics>) { - ::std::boxed::Box::from_raw(ptr); + unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics>) { + // No prevent_unwind: the global allocator is not allowed to panic. + let _ = ::cxx::alloc::boxed::Box::from_raw(ptr); } #[doc(hidden)] #[export_name = #link_drop] - unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::std::boxed::Box<#ident #ty_generics>) { - ::std::ptr::drop_in_place(this); + unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::alloc::boxed::Box<#ident #ty_generics>) { + let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label); + ::cxx::private::prevent_unwind(__fn, || ::cxx::core::ptr::drop_in_place(this)); } } } @@ -1255,6 +1299,7 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl let link_data = format!("{}data", link_prefix); let link_reserve_total = format!("{}reserve_total", link_prefix); let link_set_len = format!("{}set_len", link_prefix); + let link_truncate = format!("{}truncate", link_prefix); let local_prefix = format_ident!("{}__vec_", elem); let local_new = format_ident!("{}new", local_prefix); @@ -1264,12 +1309,14 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl let local_data = format_ident!("{}data", local_prefix); let local_reserve_total = format_ident!("{}reserve_total", local_prefix); let local_set_len = format_ident!("{}set_len", local_prefix); + let local_truncate = format_ident!("{}truncate", local_prefix); let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve); let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span); let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span); let unsafe_token = format_ident!("unsafe", span = begin_span); + let prevent_unwind_drop_label = format!("::{} as Drop>::drop", elem); quote_spanned! {end_span=> #[doc(hidden)] @@ -1277,38 +1324,51 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl #[doc(hidden)] #[export_name = #link_new] unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) { - ::std::ptr::write(this, ::cxx::private::RustVec::new()); + // No prevent_unwind: cannot panic. + ::cxx::core::ptr::write(this, ::cxx::private::RustVec::new()); } #[doc(hidden)] #[export_name = #link_drop] unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) { - ::std::ptr::drop_in_place(this); + let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label); + ::cxx::private::prevent_unwind(__fn, || ::cxx::core::ptr::drop_in_place(this)); } #[doc(hidden)] #[export_name = #link_len] unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize { + // No prevent_unwind: cannot panic. (*this).len() } #[doc(hidden)] #[export_name = #link_capacity] unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize { + // No prevent_unwind: cannot panic. (*this).capacity() } #[doc(hidden)] #[export_name = #link_data] unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics { + // No prevent_unwind: cannot panic. (*this).as_ptr() } #[doc(hidden)] #[export_name = #link_reserve_total] unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, new_cap: usize) { + // No prevent_unwind: the global allocator is not allowed to panic. (*this).reserve_total(new_cap); } #[doc(hidden)] #[export_name = #link_set_len] unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) { + // No prevent_unwind: cannot panic. (*this).set_len(len); } + #[doc(hidden)] + #[export_name = #link_truncate] + unsafe extern "C" fn #local_truncate #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) { + let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label); + ::cxx::private::prevent_unwind(__fn, || (*this).truncate(len)); + } } } @@ -1333,13 +1393,12 @@ fn expand_unique_ptr( let can_construct_from_value = types.is_maybe_trivial(ident); let new_method = if can_construct_from_value { Some(quote! { - #[doc(hidden)] - fn __new(value: Self) -> ::std::mem::MaybeUninit<*mut ::std::ffi::c_void> { + fn __new(value: Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { extern "C" { #[link_name = #link_uninit] - fn __uninit(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *mut ::std::ffi::c_void; + fn __uninit(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void; } - let mut repr = ::std::mem::MaybeUninit::uninit(); + let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); unsafe { __uninit(&mut repr).cast::<#ident #ty_generics>().write(value) } repr } @@ -1354,52 +1413,46 @@ fn expand_unique_ptr( quote_spanned! {end_span=> #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics { - #[doc(hidden)] - fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { f.write_str(#name) } - #[doc(hidden)] - fn __null() -> ::std::mem::MaybeUninit<*mut ::std::ffi::c_void> { + fn __null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { extern "C" { #[link_name = #link_null] - fn __null(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>); + fn __null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>); } - let mut repr = ::std::mem::MaybeUninit::uninit(); + let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); unsafe { __null(&mut repr) } repr } #new_method - #[doc(hidden)] - unsafe fn __raw(raw: *mut Self) -> ::std::mem::MaybeUninit<*mut ::std::ffi::c_void> { + unsafe fn __raw(raw: *mut Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { extern "C" { #[link_name = #link_raw] - fn __raw(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>, raw: *mut ::std::ffi::c_void); + fn __raw(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::core::ffi::c_void); } - let mut repr = ::std::mem::MaybeUninit::uninit(); + let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); __raw(&mut repr, raw.cast()); repr } - #[doc(hidden)] - unsafe fn __get(repr: ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *const Self { + unsafe fn __get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const Self { extern "C" { #[link_name = #link_get] - fn __get(this: *const ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *const ::std::ffi::c_void; + fn __get(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::core::ffi::c_void; } __get(&repr).cast() } - #[doc(hidden)] - unsafe fn __release(mut repr: ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *mut Self { + unsafe fn __release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut Self { extern "C" { #[link_name = #link_release] - fn __release(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *mut ::std::ffi::c_void; + fn __release(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void; } __release(&mut repr).cast() } - #[doc(hidden)] - unsafe fn __drop(mut repr: ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) { + unsafe fn __drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) { extern "C" { #[link_name = #link_drop] - fn __drop(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>); + fn __drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>); } __drop(&mut repr); } @@ -1427,11 +1480,10 @@ fn expand_shared_ptr( let can_construct_from_value = types.is_maybe_trivial(ident); let new_method = if can_construct_from_value { Some(quote! { - #[doc(hidden)] - unsafe fn __new(value: Self, new: *mut ::std::ffi::c_void) { + unsafe fn __new(value: Self, new: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_uninit] - fn __uninit(new: *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void; + fn __uninit(new: *mut ::cxx::core::ffi::c_void) -> *mut ::cxx::core::ffi::c_void; } __uninit(new).cast::<#ident #ty_generics>().write(value); } @@ -1446,40 +1498,35 @@ fn expand_shared_ptr( quote_spanned! {end_span=> #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics { - #[doc(hidden)] - fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { f.write_str(#name) } - #[doc(hidden)] - unsafe fn __null(new: *mut ::std::ffi::c_void) { + unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_null] - fn __null(new: *mut ::std::ffi::c_void); + fn __null(new: *mut ::cxx::core::ffi::c_void); } __null(new); } #new_method - #[doc(hidden)] - unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) { + unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_clone] - fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void); + fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void); } __clone(this, new); } - #[doc(hidden)] - unsafe fn __get(this: *const ::std::ffi::c_void) -> *const Self { + unsafe fn __get(this: *const ::cxx::core::ffi::c_void) -> *const Self { extern "C" { #[link_name = #link_get] - fn __get(this: *const ::std::ffi::c_void) -> *const ::std::ffi::c_void; + fn __get(this: *const ::cxx::core::ffi::c_void) -> *const ::cxx::core::ffi::c_void; } __get(this).cast() } - #[doc(hidden)] - unsafe fn __drop(this: *mut ::std::ffi::c_void) { + unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_drop] - fn __drop(this: *mut ::std::ffi::c_void); + fn __drop(this: *mut ::cxx::core::ffi::c_void); } __drop(this); } @@ -1506,47 +1553,41 @@ fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl quote_spanned! {end_span=> #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics { - #[doc(hidden)] - fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { f.write_str(#name) } - #[doc(hidden)] - unsafe fn __null(new: *mut ::std::ffi::c_void) { + unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_null] - fn __null(new: *mut ::std::ffi::c_void); + fn __null(new: *mut ::cxx::core::ffi::c_void); } __null(new); } - #[doc(hidden)] - unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) { + unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_clone] - fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void); + fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void); } __clone(this, new); } - #[doc(hidden)] - unsafe fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void) { + unsafe fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_downgrade] - fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void); + fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void); } __downgrade(shared, weak); } - #[doc(hidden)] - unsafe fn __upgrade(weak: *const ::std::ffi::c_void, shared: *mut ::std::ffi::c_void) { + unsafe fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_upgrade] - fn __upgrade(weak: *const ::std::ffi::c_void, shared: *mut ::std::ffi::c_void); + fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void); } __upgrade(weak, shared); } - #[doc(hidden)] - unsafe fn __drop(this: *mut ::std::ffi::c_void) { + unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) { extern "C" { #[link_name = #link_drop] - fn __drop(this: *mut ::std::ffi::c_void); + fn __drop(this: *mut ::cxx::core::ffi::c_void); } __drop(this); } @@ -1586,33 +1627,31 @@ fn expand_cxx_vector( let can_pass_element_by_value = types.is_maybe_trivial(elem); let by_value_methods = if can_pass_element_by_value { Some(quote_spanned! {end_span=> - #[doc(hidden)] unsafe fn __push_back( - this: ::std::pin::Pin<&mut ::cxx::CxxVector<Self>>, - value: &mut ::std::mem::ManuallyDrop<Self>, + this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>, + value: &mut ::cxx::core::mem::ManuallyDrop<Self>, ) { extern "C" { #[link_name = #link_push_back] fn __push_back #impl_generics( - this: ::std::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>, - value: *mut ::std::ffi::c_void, + this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>, + value: *mut ::cxx::core::ffi::c_void, ); } - __push_back(this, value as *mut ::std::mem::ManuallyDrop<Self> as *mut ::std::ffi::c_void); + __push_back(this, value as *mut ::cxx::core::mem::ManuallyDrop<Self> as *mut ::cxx::core::ffi::c_void); } - #[doc(hidden)] unsafe fn __pop_back( - this: ::std::pin::Pin<&mut ::cxx::CxxVector<Self>>, - out: &mut ::std::mem::MaybeUninit<Self>, + this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>, + out: &mut ::cxx::core::mem::MaybeUninit<Self>, ) { extern "C" { #[link_name = #link_pop_back] fn __pop_back #impl_generics( - this: ::std::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>, - out: *mut ::std::ffi::c_void, + this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>, + out: *mut ::cxx::core::ffi::c_void, ); } - __pop_back(this, out as *mut ::std::mem::MaybeUninit<Self> as *mut ::std::ffi::c_void); + __pop_back(this, out as *mut ::cxx::core::mem::MaybeUninit<Self> as *mut ::cxx::core::ffi::c_void); } }) } else { @@ -1621,11 +1660,9 @@ fn expand_cxx_vector( quote_spanned! {end_span=> #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics { - #[doc(hidden)] - fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { f.write_str(#name) } - #[doc(hidden)] fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize { extern "C" { #[link_name = #link_size] @@ -1633,59 +1670,53 @@ fn expand_cxx_vector( } unsafe { __vector_size(v) } } - #[doc(hidden)] unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self { extern "C" { #[link_name = #link_get_unchecked] fn __get_unchecked #impl_generics( v: *mut ::cxx::CxxVector<#elem #ty_generics>, pos: usize, - ) -> *mut ::std::ffi::c_void; + ) -> *mut ::cxx::core::ffi::c_void; } __get_unchecked(v, pos) as *mut Self } #by_value_methods - #[doc(hidden)] - fn __unique_ptr_null() -> ::std::mem::MaybeUninit<*mut ::std::ffi::c_void> { + fn __unique_ptr_null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { extern "C" { #[link_name = #link_unique_ptr_null] - fn __unique_ptr_null(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>); + fn __unique_ptr_null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>); } - let mut repr = ::std::mem::MaybeUninit::uninit(); + let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); unsafe { __unique_ptr_null(&mut repr) } repr } - #[doc(hidden)] - unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> ::std::mem::MaybeUninit<*mut ::std::ffi::c_void> { + unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { extern "C" { #[link_name = #link_unique_ptr_raw] - fn __unique_ptr_raw #impl_generics(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>, raw: *mut ::cxx::CxxVector<#elem #ty_generics>); + fn __unique_ptr_raw #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::CxxVector<#elem #ty_generics>); } - let mut repr = ::std::mem::MaybeUninit::uninit(); + let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); __unique_ptr_raw(&mut repr, raw); repr } - #[doc(hidden)] - unsafe fn __unique_ptr_get(repr: ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *const ::cxx::CxxVector<Self> { + unsafe fn __unique_ptr_get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<Self> { extern "C" { #[link_name = #link_unique_ptr_get] - fn __unique_ptr_get #impl_generics(this: *const ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *const ::cxx::CxxVector<#elem #ty_generics>; + fn __unique_ptr_get #impl_generics(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<#elem #ty_generics>; } __unique_ptr_get(&repr) } - #[doc(hidden)] - unsafe fn __unique_ptr_release(mut repr: ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *mut ::cxx::CxxVector<Self> { + unsafe fn __unique_ptr_release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<Self> { extern "C" { #[link_name = #link_unique_ptr_release] - fn __unique_ptr_release #impl_generics(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) -> *mut ::cxx::CxxVector<#elem #ty_generics>; + fn __unique_ptr_release #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<#elem #ty_generics>; } __unique_ptr_release(&mut repr) } - #[doc(hidden)] - unsafe fn __unique_ptr_drop(mut repr: ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>) { + unsafe fn __unique_ptr_drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) { extern "C" { #[link_name = #link_unique_ptr_drop] - fn __unique_ptr_drop(this: *mut ::std::mem::MaybeUninit<*mut ::std::ffi::c_void>); + fn __unique_ptr_drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>); } __unique_ptr_drop(&mut repr); } @@ -1715,7 +1746,7 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream { Type::RustBox(ty) | Type::UniquePtr(ty) => { let span = ty.name.span(); if proper && types.is_considered_improper_ctype(&ty.inner) { - quote_spanned!(span=> *mut ::std::ffi::c_void) + quote_spanned!(span=> *mut ::cxx::core::ffi::c_void) } else { let inner = expand_extern_type(&ty.inner, types, proper); quote_spanned!(span=> *mut #inner) @@ -1747,8 +1778,8 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream { inner if proper && types.is_considered_improper_ctype(inner) => { let star = Token![*](ampersand.span); match ty.mutable { - false => quote!(#star const ::std::ffi::c_void), - true => quote!(#star #mutability ::std::ffi::c_void), + false => quote!(#star const ::cxx::core::ffi::c_void), + true => quote!(#star #mutability ::cxx::core::ffi::c_void), } } _ => quote!(#ty), @@ -1759,7 +1790,7 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream { let star = ty.star; let mutability = ty.mutability; let constness = ty.constness; - quote!(#star #mutability #constness ::std::ffi::c_void) + quote!(#star #mutability #constness ::cxx::core::ffi::c_void) } else { quote!(#ty) } diff --git a/macro/src/generics.rs b/macro/src/generics.rs index 3de0330b..7862536d 100644 --- a/macro/src/generics.rs +++ b/macro/src/generics.rs @@ -1,9 +1,9 @@ use crate::syntax::instantiate::NamedImplKey; use crate::syntax::resolve::Resolution; -use crate::syntax::Impl; +use crate::syntax::{Impl, Lifetimes}; use proc_macro2::TokenStream; use quote::ToTokens; -use syn::Token; +use syn::{Lifetime, Token}; pub struct ImplGenerics<'a> { explicit_impl: Option<&'a Impl>, @@ -61,3 +61,31 @@ impl<'a> ToTokens for TyGenerics<'a> { } } } + +pub struct UnderscoreLifetimes<'a> { + generics: &'a Lifetimes, +} + +impl Lifetimes { + pub fn to_underscore_lifetimes(&self) -> UnderscoreLifetimes { + UnderscoreLifetimes { generics: self } + } +} + +impl<'a> ToTokens for UnderscoreLifetimes<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let Lifetimes { + lt_token, + lifetimes, + gt_token, + } = self.generics; + lt_token.to_tokens(tokens); + for pair in lifetimes.pairs() { + let (lifetime, punct) = pair.into_tuple(); + let lifetime = Lifetime::new("'_", lifetime.span()); + lifetime.to_tokens(tokens); + punct.to_tokens(tokens); + } + gt_token.to_tokens(tokens); + } +} diff --git a/macro/src/lib.rs b/macro/src/lib.rs index 324881d8..138e3a29 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -1,6 +1,7 @@ #![allow( clippy::cast_sign_loss, clippy::default_trait_access, + clippy::derive_partial_eq_without_eq, clippy::doc_markdown, clippy::enum_glob_use, clippy::if_same_then_else, @@ -34,11 +35,12 @@ mod derive; mod expand; mod generics; mod syntax; +mod tokens; mod type_id; -#[cfg(feature = "experimental")] +#[cfg(feature = "experimental-enum-variants-from-header")] mod clang; -#[cfg(feature = "experimental")] +#[cfg(feature = "experimental-enum-variants-from-header")] mod load; use crate::syntax::file::Module; diff --git a/macro/src/load.rs b/macro/src/load.rs index d769ebf6..dccece44 100644 --- a/macro/src/load.rs +++ b/macro/src/load.rs @@ -1,5 +1,6 @@ use crate::clang::{Clang, Node}; use crate::syntax::attrs::OtherAttrs; +use crate::syntax::cfg::CfgExpr; use crate::syntax::namespace::Namespace; use crate::syntax::report::Errors; use crate::syntax::{Api, Discriminant, Doc, Enum, EnumRepr, ForeignName, Pair, Variant}; @@ -58,10 +59,10 @@ pub fn load(cx: &mut Errors, apis: &mut [Api]) { let is_gzipped = memmap.get(..2) == Some(b"\x1f\x8b"); if is_gzipped { gunzipped = Vec::new(); - let decode_result = GzDecoder::new(&mut gunzipped).write_all(&memmap); + let decode_result = GzDecoder::new(&mut gunzipped).write_all(memmap); decode_result.map(|_| gunzipped.as_slice()) } else { - Ok(&memmap as &[u8]) + Ok(memmap as &[u8]) } } Err(error) => Err(error), @@ -142,7 +143,7 @@ fn traverse<'a>( }; let repr = translate_qual_type( cx, - &enm, + enm, fixed_underlying_type .desugared_qual_type .as_ref() @@ -207,6 +208,7 @@ fn traverse<'a>( } }; enm.variants.push(Variant { + cfg: CfgExpr::Unconditional, doc: Doc::new(), attrs: OtherAttrs::none(), name: Pair { @@ -262,7 +264,7 @@ fn translate_qual_type(cx: &mut Errors, enm: &Enum, qual_type: &str) -> Path { .unwrap() .span(); let ident = Ident::new(rust_std_name, span); - let path = quote_spanned!(span=> ::std::os::raw::#ident); + let path = quote_spanned!(span=> ::cxx::core::ffi::#ident); parse_quote!(#path) } diff --git a/macro/src/tokens.rs b/macro/src/tokens.rs new file mode 100644 index 00000000..805af227 --- /dev/null +++ b/macro/src/tokens.rs @@ -0,0 +1,75 @@ +use crate::syntax::Receiver; +use proc_macro2::TokenStream; +use quote::{quote_spanned, ToTokens}; +use syn::Token; + +pub struct ReceiverType<'a>(&'a Receiver); +pub struct ReceiverTypeSelf<'a>(&'a Receiver); + +impl Receiver { + // &TheType + pub fn ty(&self) -> ReceiverType { + ReceiverType(self) + } + + // &Self + pub fn ty_self(&self) -> ReceiverTypeSelf { + ReceiverTypeSelf(self) + } +} + +impl ToTokens for ReceiverType<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let Receiver { + pinned: _, + ampersand, + lifetime, + mutable: _, + var: _, + colon_token: _, + ty, + shorthand: _, + pin_tokens, + mutability, + } = &self.0; + if let Some((pin, langle, _rangle)) = pin_tokens { + tokens.extend(quote_spanned!(pin.span=> ::cxx::core::pin::Pin)); + langle.to_tokens(tokens); + } + ampersand.to_tokens(tokens); + lifetime.to_tokens(tokens); + mutability.to_tokens(tokens); + ty.to_tokens(tokens); + if let Some((_pin, _langle, rangle)) = pin_tokens { + rangle.to_tokens(tokens); + } + } +} + +impl ToTokens for ReceiverTypeSelf<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let Receiver { + pinned: _, + ampersand, + lifetime, + mutable: _, + var: _, + colon_token: _, + ty, + shorthand: _, + pin_tokens, + mutability, + } = &self.0; + if let Some((pin, langle, _rangle)) = pin_tokens { + tokens.extend(quote_spanned!(pin.span=> ::cxx::core::pin::Pin)); + langle.to_tokens(tokens); + } + ampersand.to_tokens(tokens); + lifetime.to_tokens(tokens); + mutability.to_tokens(tokens); + Token![Self](ty.rust.span()).to_tokens(tokens); + if let Some((_pin, _langle, rangle)) = pin_tokens { + rangle.to_tokens(tokens); + } + } +} diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs index 74f0c1c9..7bca67b1 100644 --- a/macro/src/type_id.rs +++ b/macro/src/type_id.rs @@ -1,6 +1,7 @@ use crate::syntax::qualified::QualifiedName; use proc_macro2::{TokenStream, TokenTree}; use quote::{format_ident, quote, ToTokens}; +use syn::ext::IdentExt; pub enum Crate { Cxx, @@ -24,7 +25,7 @@ pub fn expand(krate: Crate, arg: QualifiedName) -> TokenStream { if !ids.is_empty() { ids.push(quote!(())); } - for ch in word.to_string().chars() { + for ch in word.unraw().to_string().chars() { ids.push(match ch { 'A'..='Z' | 'a'..='z' => { let t = format_ident!("{}", ch); diff --git a/src/c_char.rs b/src/c_char.rs new file mode 100644 index 00000000..333d8491 --- /dev/null +++ b/src/c_char.rs @@ -0,0 +1,69 @@ +#[allow(missing_docs)] +pub type c_char = c_char_definition::c_char; + +// Validate that our definition is consistent with libstd's definition, without +// introducing a dependency on libstd in ordinary builds. +#[cfg(all(test, feature = "std"))] +const _: self::c_char = 0 as std::os::raw::c_char; + +#[allow(dead_code)] +mod c_char_definition { + // These are the targets on which c_char is unsigned. + #[cfg(any( + all( + target_os = "linux", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "hexagon", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "s390x", + target_arch = "riscv64", + target_arch = "riscv32" + ) + ), + all( + target_os = "android", + any(target_arch = "aarch64", target_arch = "arm") + ), + all(target_os = "l4re", target_arch = "x86_64"), + all( + target_os = "freebsd", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "riscv64" + ) + ), + all( + target_os = "netbsd", + any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc") + ), + all(target_os = "openbsd", target_arch = "aarch64"), + all( + target_os = "vxworks", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc64", + target_arch = "powerpc" + ) + ), + all(target_os = "fuchsia", target_arch = "aarch64") + ))] + pub use self::unsigned::c_char; + + // On every other target, c_char is signed. + pub use self::signed::*; + + mod unsigned { + pub type c_char = u8; + } + + mod signed { + pub type c_char = i8; + } +} @@ -40,8 +40,12 @@ void cxxbridge1$string$clone(rust::String *self, const rust::String &other) noexcept; bool cxxbridge1$string$from_utf8(rust::String *self, const char *ptr, std::size_t len) noexcept; +void cxxbridge1$string$from_utf8_lossy(rust::String *self, const char *ptr, + std::size_t len) noexcept; bool cxxbridge1$string$from_utf16(rust::String *self, const char16_t *ptr, std::size_t len) noexcept; +void cxxbridge1$string$from_utf16_lossy(rust::String *self, const char16_t *ptr, + std::size_t len) noexcept; void cxxbridge1$string$drop(rust::String *self) noexcept; const char *cxxbridge1$string$ptr(const rust::String *self) noexcept; std::size_t cxxbridge1$string$len(const rust::String *self) noexcept; @@ -81,6 +85,12 @@ void panic [[noreturn]] (const char *msg) { template void panic<std::out_of_range> [[noreturn]] (const char *msg); +template <typename T> +static bool is_aligned(const void *ptr) noexcept { + auto iptr = reinterpret_cast<std::uintptr_t>(ptr); + return !(iptr % alignof(T)); +} + String::String() noexcept { cxxbridge1$string$new(this); } String::String(const String &other) noexcept { @@ -121,17 +131,60 @@ String::String(const char *s, std::size_t len) { String::String(const char16_t *s) { assert(s != nullptr); + assert(is_aligned<char16_t>(s)); initString(this, s, std::char_traits<char16_t>::length(s)); } String::String(const char16_t *s, std::size_t len) { assert(s != nullptr || len == 0); + assert(is_aligned<char16_t>(s)); initString(this, s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2) : s, len); } +struct String::lossy_t {}; + +String::String(lossy_t, const char *s, std::size_t len) noexcept { + cxxbridge1$string$from_utf8_lossy( + this, s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s, + len); +} + +String::String(lossy_t, const char16_t *s, std::size_t len) noexcept { + cxxbridge1$string$from_utf16_lossy( + this, + s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2) : s, + len); +} + +String String::lossy(const std::string &s) noexcept { + return String::lossy(s.data(), s.length()); +} + +String String::lossy(const char *s) noexcept { + assert(s != nullptr); + return String::lossy(s, std::strlen(s)); +} + +String String::lossy(const char *s, std::size_t len) noexcept { + assert(s != nullptr || len == 0); + return String(lossy_t{}, s, len); +} + +String String::lossy(const char16_t *s) noexcept { + assert(s != nullptr); + assert(is_aligned<char16_t>(s)); + return String(lossy_t{}, s, std::char_traits<char16_t>::length(s)); +} + +String String::lossy(const char16_t *s, std::size_t len) noexcept { + assert(s != nullptr || len == 0); + assert(is_aligned<char16_t>(s)); + return String(lossy_t{}, s, len); +} + String &String::operator=(const String &other) &noexcept { if (this != &other) { cxxbridge1$string$drop(this); @@ -453,6 +506,17 @@ union MaybeUninit { }; } // namespace +namespace repr { +struct PtrLen final { + void *ptr; + std::size_t len; +}; +} // namespace repr + +extern "C" { +repr::PtrLen cxxbridge1$exception(const char *, std::size_t len) noexcept; +} + namespace detail { // On some platforms size_t is the same C++ type as one of the sized integer // types; on others it is a distinct type. Only in the latter case do we need to @@ -466,6 +530,23 @@ using isize_if_unique = typename std::conditional<std::is_same<rust::isize, int64_t>::value || std::is_same<rust::isize, int32_t>::value, struct isize_ignore, rust::isize>::type; + +class Fail final { + repr::PtrLen &throw$; + +public: + Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {} + void operator()(const char *) noexcept; + void operator()(const std::string &) noexcept; +}; + +void Fail::operator()(const char *catch$) noexcept { + throw$ = cxxbridge1$exception(catch$, std::strlen(catch$)); +} + +void Fail::operator()(const std::string &catch$) noexcept { + throw$ = cxxbridge1$exception(catch$.data(), catch$.length()); +} } // namespace detail } // namespace cxxbridge1 @@ -568,7 +649,9 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \ rust::Vec<CXX_TYPE> *ptr, std::size_t new_cap) noexcept; \ void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \ - std::size_t len) noexcept; + std::size_t len) noexcept; \ + void cxxbridge1$rust_vec$##RUST_TYPE##$truncate(rust::Vec<CXX_TYPE> *ptr, \ + std::size_t len) noexcept; #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \ template <> \ @@ -598,6 +681,10 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), template <> \ void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \ cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \ + } \ + template <> \ + void Vec<CXX_TYPE>::truncate(std::size_t len) { \ + cxxbridge1$rust_vec$##RUST_TYPE##$truncate(this, len); \ } #define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \ diff --git a/src/cxx_string.rs b/src/cxx_string.rs index 626c2c85..9ecbcc64 100644 --- a/src/cxx_string.rs +++ b/src/cxx_string.rs @@ -1,5 +1,8 @@ use crate::actually_private::Private; +use crate::lossy; +#[cfg(feature = "alloc")] use alloc::borrow::Cow; +#[cfg(feature = "alloc")] use alloc::string::String; use core::cmp::Ordering; use core::fmt::{self, Debug, Display}; @@ -144,6 +147,8 @@ impl CxxString { /// Cow::Owned String. /// /// [replacement character]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub fn to_string_lossy(&self) -> Cow<str> { String::from_utf8_lossy(self.as_bytes()) } @@ -204,13 +209,13 @@ impl CxxString { impl Display for CxxString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(self.to_string_lossy().as_ref(), f) + lossy::display(self.as_bytes(), f) } } impl Debug for CxxString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Debug::fmt(self.to_string_lossy().as_ref(), f) + lossy::debug(self.as_bytes(), f) } } diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs index d1fa23a2..abf9297a 100644 --- a/src/cxx_vector.rs +++ b/src/cxx_vector.rs @@ -368,7 +368,6 @@ pub unsafe trait VectorElement: Sized { macro_rules! vector_element_by_value_methods { (opaque, $segment:expr, $ty:ty) => {}; (trivial, $segment:expr, $ty:ty) => { - #[doc(hidden)] unsafe fn __push_back(v: Pin<&mut CxxVector<$ty>>, value: &mut ManuallyDrop<$ty>) { extern "C" { attr! { @@ -378,7 +377,6 @@ macro_rules! vector_element_by_value_methods { } unsafe { __push_back(v, value) } } - #[doc(hidden)] unsafe fn __pop_back(v: Pin<&mut CxxVector<$ty>>, out: &mut MaybeUninit<$ty>) { extern "C" { attr! { @@ -397,11 +395,9 @@ macro_rules! impl_vector_element { const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>()); unsafe impl VectorElement for $ty { - #[doc(hidden)] fn __typename(f: &mut fmt::Formatter) -> fmt::Result { f.write_str($name) } - #[doc(hidden)] fn __vector_size(v: &CxxVector<$ty>) -> usize { extern "C" { attr! { @@ -411,7 +407,6 @@ macro_rules! impl_vector_element { } unsafe { __vector_size(v) } } - #[doc(hidden)] unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty { extern "C" { attr! { @@ -422,7 +417,6 @@ macro_rules! impl_vector_element { unsafe { __get_unchecked(v, pos) } } vector_element_by_value_methods!($kind, $segment, $ty); - #[doc(hidden)] fn __unique_ptr_null() -> MaybeUninit<*mut c_void> { extern "C" { attr! { @@ -434,7 +428,6 @@ macro_rules! impl_vector_element { unsafe { __unique_ptr_null(&mut repr) } repr } - #[doc(hidden)] unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void> { extern "C" { attr! { @@ -446,7 +439,6 @@ macro_rules! impl_vector_element { unsafe { __unique_ptr_raw(&mut repr, raw) } repr } - #[doc(hidden)] unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self> { extern "C" { attr! { @@ -456,7 +448,6 @@ macro_rules! impl_vector_element { } unsafe { __unique_ptr_get(&repr) } } - #[doc(hidden)] unsafe fn __unique_ptr_release(mut repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self> { extern "C" { attr! { @@ -466,7 +457,6 @@ macro_rules! impl_vector_element { } unsafe { __unique_ptr_release(&mut repr) } } - #[doc(hidden)] unsafe fn __unique_ptr_drop(mut repr: MaybeUninit<*mut c_void>) { extern "C" { attr! { diff --git a/src/exception.rs b/src/exception.rs index 2ae470e7..259b27d4 100644 --- a/src/exception.rs +++ b/src/exception.rs @@ -1,7 +1,10 @@ +#![cfg(feature = "alloc")] + use alloc::boxed::Box; use core::fmt::{self, Display}; /// Exception thrown from an `extern "C++"` function. +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] #[derive(Debug)] pub struct Exception { pub(crate) what: Box<str>, @@ -13,6 +16,8 @@ impl Display for Exception { } } +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl std::error::Error for Exception {} impl Exception { diff --git a/src/extern_type.rs b/src/extern_type.rs index 8c9c2860..d131ae12 100644 --- a/src/extern_type.rs +++ b/src/extern_type.rs @@ -1,5 +1,6 @@ use self::kind::{Kind, Opaque, Trivial}; use crate::CxxString; +#[cfg(feature = "alloc")] use alloc::string::String; /// A type for which the layout is determined by its C++ definition. @@ -186,9 +187,11 @@ pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {} pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {} macro_rules! impl_extern_type { - ($([$kind:ident] $($ty:path = $cxxpath:literal)*)*) => { + ($([$kind:ident] $($(#[$($attr:tt)*])* $ty:path = $cxxpath:literal)*)*) => { $($( + $(#[$($attr)*])* unsafe impl ExternType for $ty { + #[allow(unused_attributes)] // incorrect lint; this doc(hidden) attr *is* respected by rustdoc #[doc(hidden)] type Id = crate::type_id!($cxxpath); type Kind = $kind; @@ -212,6 +215,9 @@ impl_extern_type! { isize = "rust::isize" f32 = "float" f64 = "double" + + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] String = "rust::String" [Opaque] @@ -1,4 +1,4 @@ -use std::fmt::{self, Display}; +use core::fmt::{self, Display}; pub(crate) fn display(fmt: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl Display { DisplayInvoke(fmt) diff --git a/src/hash.rs b/src/hash.rs new file mode 100644 index 00000000..4c92173f --- /dev/null +++ b/src/hash.rs @@ -0,0 +1,12 @@ +use core::hash::{Hash, Hasher}; + +#[doc(hidden)] +pub fn hash<V: Hash>(value: &V) -> usize { + #[cfg(feature = "std")] + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + #[cfg(not(feature = "std"))] + let mut hasher = crate::sip::SipHasher13::new(); + + Hash::hash(value, &mut hasher); + Hasher::finish(&hasher) as usize +} @@ -2,7 +2,7 @@ //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust -//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //! <br> //! @@ -364,10 +364,11 @@ //! </table> #![no_std] -#![doc(html_root_url = "https://docs.rs/cxx/1.0.54")] +#![doc(html_root_url = "https://docs.rs/cxx/1.0.85")] #![deny(improper_ctypes, improper_ctypes_definitions, missing_docs)] #![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))] #![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))] +#![cfg_attr(doc_cfg, feature(doc_cfg))] #![allow(non_camel_case_types)] #![allow( clippy::cognitive_complexity, @@ -388,6 +389,7 @@ clippy::or_fun_call, clippy::ptr_arg, clippy::toplevel_ref_arg, + clippy::transmute_undefined_repr, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8417 clippy::useless_let_if_seq, clippy::wrong_self_convention )] @@ -395,18 +397,53 @@ #[cfg(built_with_cargo)] extern crate link_cplusplus; -extern crate alloc; extern crate self as cxx; -extern crate std; + +#[doc(hidden)] +pub extern crate core; + +#[cfg(feature = "alloc")] +#[doc(hidden)] +pub extern crate alloc; + +#[cfg(not(feature = "alloc"))] +extern crate core as alloc; + +#[cfg(feature = "std")] +#[doc(hidden)] +pub extern crate std; + +// Block inadvertent use of items from libstd, which does not otherwise produce +// a compile-time error on edition 2018+. +#[cfg(not(feature = "std"))] +extern crate core as std; + +#[cfg(not(any(feature = "alloc", cxx_experimental_no_alloc)))] +compile_error! { + r#"cxx support for no_alloc is incomplete and semver exempt; you must build with at least one of feature="std", feature="alloc", or RUSTFLAGS='--cfg cxx_experimental_no_alloc'"# +} + +#[cfg(all(compile_error_if_alloc, feature = "alloc"))] +compile_error! { + r#"feature="alloc" is unexpectedly enabled"# +} + +#[cfg(all(compile_error_if_std, feature = "std"))] +compile_error! { + r#"feature="std" is unexpectedly enabled"# +} #[macro_use] mod macros; +mod c_char; mod cxx_vector; mod exception; mod extern_type; mod fmt; mod function; +mod hash; +mod lossy; pub mod memory; mod opaque; mod result; @@ -416,6 +453,7 @@ mod rust_string; mod rust_type; mod rust_vec; mod shared_ptr; +mod sip; #[path = "cxx_string.rs"] mod string; mod symbols; @@ -426,6 +464,7 @@ pub mod vector; mod weak_ptr; pub use crate::cxx_vector::CxxVector; +#[cfg(feature = "alloc")] pub use crate::exception::Exception; pub use crate::extern_type::{kind, ExternType}; pub use crate::shared_ptr::SharedPtr; @@ -451,21 +490,27 @@ pub type Vector<T> = CxxVector<T>; // Not public API. #[doc(hidden)] pub mod private { + pub use crate::c_char::c_char; pub use crate::cxx_vector::VectorElement; pub use crate::extern_type::{verify_extern_kind, verify_extern_type}; pub use crate::function::FatFunction; + pub use crate::hash::hash; pub use crate::opaque::Opaque; + #[cfg(feature = "alloc")] pub use crate::result::{r#try, Result}; pub use crate::rust_slice::RustSlice; pub use crate::rust_str::RustStr; + #[cfg(feature = "alloc")] pub use crate::rust_string::RustString; pub use crate::rust_type::{ImplBox, ImplVec, RustType}; + #[cfg(feature = "alloc")] pub use crate::rust_vec::RustVec; pub use crate::shared_ptr::SharedPtrTarget; pub use crate::string::StackString; pub use crate::unique_ptr::UniquePtrTarget; - pub use crate::unwind::catch_unwind; + pub use crate::unwind::prevent_unwind; pub use crate::weak_ptr::WeakPtrTarget; + pub use core::{concat, module_path}; pub use cxxbridge_macro::type_id; } diff --git a/src/lossy.rs b/src/lossy.rs new file mode 100644 index 00000000..d68a2e7b --- /dev/null +++ b/src/lossy.rs @@ -0,0 +1,67 @@ +use core::char; +use core::fmt::{self, Write as _}; +use core::str; + +pub fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { + loop { + match str::from_utf8(bytes) { + Ok(valid) => return f.write_str(valid), + Err(utf8_error) => { + let valid_up_to = utf8_error.valid_up_to(); + let valid = unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) }; + f.write_str(valid)?; + f.write_char(char::REPLACEMENT_CHARACTER)?; + if let Some(error_len) = utf8_error.error_len() { + bytes = &bytes[valid_up_to + error_len..]; + } else { + return Ok(()); + } + } + } + } +} + +pub fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { + f.write_char('"')?; + + while !bytes.is_empty() { + let from_utf8_result = str::from_utf8(bytes); + let valid = match from_utf8_result { + Ok(valid) => valid, + Err(utf8_error) => { + let valid_up_to = utf8_error.valid_up_to(); + unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) } + } + }; + + let mut written = 0; + for (i, ch) in valid.char_indices() { + let esc = ch.escape_debug(); + if esc.len() != 1 { + f.write_str(&valid[written..i])?; + for ch in esc { + f.write_char(ch)?; + } + written = i + ch.len_utf8(); + } + } + f.write_str(&valid[written..])?; + + match from_utf8_result { + Ok(_valid) => break, + Err(utf8_error) => { + let end_of_broken = if let Some(error_len) = utf8_error.error_len() { + valid.len() + error_len + } else { + bytes.len() + }; + for b in &bytes[valid.len()..end_of_broken] { + write!(f, "\\x{:02x}", b)?; + } + bytes = &bytes[end_of_broken..]; + } + } + } + + f.write_char('"') +} diff --git a/src/result.rs b/src/result.rs index d7a31f02..ba77858e 100644 --- a/src/result.rs +++ b/src/result.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "alloc")] #![allow(missing_docs)] use crate::exception::Exception; @@ -11,9 +12,9 @@ use core::str; #[repr(C)] #[derive(Copy, Clone)] -struct PtrLen { - ptr: NonNull<u8>, - len: usize, +pub struct PtrLen { + pub ptr: NonNull<u8>, + pub len: usize, } #[repr(C)] diff --git a/src/rust_string.rs b/src/rust_string.rs index 051e35c3..0e0c5a83 100644 --- a/src/rust_string.rs +++ b/src/rust_string.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "alloc")] #![allow(missing_docs)] use alloc::string::String; diff --git a/src/rust_vec.rs b/src/rust_vec.rs index 9f4484db..acb7e890 100644 --- a/src/rust_vec.rs +++ b/src/rust_vec.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "alloc")] #![allow(missing_docs)] use crate::rust_string::RustString; @@ -67,6 +68,10 @@ impl<T> RustVec<T> { pub unsafe fn set_len(&mut self, len: usize) { unsafe { self.as_mut_vec().set_len(len) } } + + pub fn truncate(&mut self, len: usize) { + self.as_mut_vec().truncate(len); + } } impl RustVec<RustString> { diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs index 317773d4..64c86619 100644 --- a/src/shared_ptr.rs +++ b/src/shared_ptr.rs @@ -101,6 +101,10 @@ where } } +// SharedPtr is not a self-referential type and is safe to move out of a Pin, +// regardless whether the pointer's target is Unpin. +impl<T> Unpin for SharedPtr<T> where T: SharedPtrTarget {} + impl<T> Drop for SharedPtr<T> where T: SharedPtrTarget, @@ -204,11 +208,9 @@ pub unsafe trait SharedPtrTarget { macro_rules! impl_shared_ptr_target { ($segment:expr, $name:expr, $ty:ty) => { unsafe impl SharedPtrTarget for $ty { - #[doc(hidden)] fn __typename(f: &mut fmt::Formatter) -> fmt::Result { f.write_str($name) } - #[doc(hidden)] unsafe fn __null(new: *mut c_void) { extern "C" { attr! { @@ -218,7 +220,6 @@ macro_rules! impl_shared_ptr_target { } unsafe { __null(new) } } - #[doc(hidden)] unsafe fn __new(value: Self, new: *mut c_void) { extern "C" { attr! { @@ -228,7 +229,6 @@ macro_rules! impl_shared_ptr_target { } unsafe { __uninit(new).cast::<$ty>().write(value) } } - #[doc(hidden)] unsafe fn __clone(this: *const c_void, new: *mut c_void) { extern "C" { attr! { @@ -238,7 +238,6 @@ macro_rules! impl_shared_ptr_target { } unsafe { __clone(this, new) } } - #[doc(hidden)] unsafe fn __get(this: *const c_void) -> *const Self { extern "C" { attr! { @@ -248,7 +247,6 @@ macro_rules! impl_shared_ptr_target { } unsafe { __get(this) }.cast() } - #[doc(hidden)] unsafe fn __drop(this: *mut c_void) { extern "C" { attr! { diff --git a/src/sip.rs b/src/sip.rs new file mode 100644 index 00000000..9e1d050a --- /dev/null +++ b/src/sip.rs @@ -0,0 +1,228 @@ +// Vendored from libstd: +// https://github.com/rust-lang/rust/blob/1.57.0/library/core/src/hash/sip.rs +// +// TODO: maybe depend on a hasher from crates.io if this becomes annoying to +// maintain, or change this to a simpler one. + +#![cfg(not(feature = "std"))] + +use core::cmp; +use core::hash::Hasher; +use core::mem; +use core::ptr; + +/// An implementation of SipHash 1-3. +/// +/// This is currently the default hashing function used by standard library +/// (e.g., `collections::HashMap` uses it by default). +/// +/// See: <https://131002.net/siphash> +pub struct SipHasher13 { + k0: u64, + k1: u64, + length: usize, // how many bytes we've processed + state: State, // hash State + tail: u64, // unprocessed bytes le + ntail: usize, // how many bytes in tail are valid +} + +#[derive(Clone, Copy)] +#[repr(C)] +struct State { + // v0, v2 and v1, v3 show up in pairs in the algorithm, + // and simd implementations of SipHash will use vectors + // of v02 and v13. By placing them in this order in the struct, + // the compiler can pick up on just a few simd optimizations by itself. + v0: u64, + v2: u64, + v1: u64, + v3: u64, +} + +macro_rules! compress { + ($state:expr) => { + compress!($state.v0, $state.v1, $state.v2, $state.v3) + }; + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => { + $v0 = $v0.wrapping_add($v1); + $v1 = $v1.rotate_left(13); + $v1 ^= $v0; + $v0 = $v0.rotate_left(32); + $v2 = $v2.wrapping_add($v3); + $v3 = $v3.rotate_left(16); + $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); + $v3 = $v3.rotate_left(21); + $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); + $v1 = $v1.rotate_left(17); + $v1 ^= $v2; + $v2 = $v2.rotate_left(32); + }; +} + +/// Loads an integer of the desired type from a byte stream, in LE order. Uses +/// `copy_nonoverlapping` to let the compiler generate the most efficient way +/// to load it from a possibly unaligned address. +/// +/// Unsafe because: unchecked indexing at i..i+size_of(int_ty) +macro_rules! load_int_le { + ($buf:expr, $i:expr, $int_ty:ident) => {{ + debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); + let mut data = 0 as $int_ty; + ptr::copy_nonoverlapping( + $buf.as_ptr().add($i), + &mut data as *mut _ as *mut u8, + mem::size_of::<$int_ty>(), + ); + data.to_le() + }}; +} + +/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the +/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed +/// sizes and avoid calling `memcpy`, which is good for speed. +/// +/// Unsafe because: unchecked indexing at start..start+len +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + debug_assert!(len < 8); + let mut i = 0; // current byte index (from LSB) in the output u64 + let mut out = 0; + if i + 3 < len { + // SAFETY: `i` cannot be greater than `len`, and the caller must guarantee + // that the index start..start+len is in bounds. + out = unsafe { load_int_le!(buf, start + i, u32) } as u64; + i += 4; + } + if i + 1 < len { + // SAFETY: same as above. + out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << (i * 8); + i += 2 + } + if i < len { + // SAFETY: same as above. + out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8); + i += 1; + } + debug_assert_eq!(i, len); + out +} + +impl SipHasher13 { + /// Creates a new `SipHasher13` with the two initial keys set to 0. + pub fn new() -> Self { + Self::new_with_keys(0, 0) + } + + /// Creates a `SipHasher13` that is keyed off the provided keys. + fn new_with_keys(key0: u64, key1: u64) -> Self { + let mut state = SipHasher13 { + k0: key0, + k1: key1, + length: 0, + state: State { + v0: 0, + v1: 0, + v2: 0, + v3: 0, + }, + tail: 0, + ntail: 0, + }; + state.reset(); + state + } + + fn reset(&mut self) { + self.length = 0; + self.state.v0 = self.k0 ^ 0x736f6d6570736575; + self.state.v1 = self.k1 ^ 0x646f72616e646f6d; + self.state.v2 = self.k0 ^ 0x6c7967656e657261; + self.state.v3 = self.k1 ^ 0x7465646279746573; + self.ntail = 0; + } +} + +impl Hasher for SipHasher13 { + // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined + // for this type. We could add them, copy the `short_write` implementation + // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*` + // methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would + // greatly speed up integer hashing by those hashers, at the cost of + // slightly slowing down compile speeds on some benchmarks. See #69152 for + // details. + fn write(&mut self, msg: &[u8]) { + let length = msg.len(); + self.length += length; + + let mut needed = 0; + + if self.ntail != 0 { + needed = 8 - self.ntail; + // SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length` + self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail); + if length < needed { + self.ntail += length; + return; + } else { + self.state.v3 ^= self.tail; + Sip13Rounds::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + self.ntail = 0; + } + } + + // Buffered tail is now flushed, process new input. + let len = length - needed; + let left = len & 0x7; // len % 8 + + let mut i = needed; + while i < len - left { + // SAFETY: because `len - left` is the biggest multiple of 8 under + // `len`, and because `i` starts at `needed` where `len` is `length - needed`, + // `i + 8` is guaranteed to be less than or equal to `length`. + let mi = unsafe { load_int_le!(msg, i, u64) }; + + self.state.v3 ^= mi; + Sip13Rounds::c_rounds(&mut self.state); + self.state.v0 ^= mi; + + i += 8; + } + + // SAFETY: `i` is now `needed + len.div_euclid(8) * 8`, + // so `i + left` = `needed + len` = `length`, which is by + // definition equal to `msg.len()`. + self.tail = unsafe { u8to64_le(msg, i, left) }; + self.ntail = left; + } + + fn finish(&self) -> u64 { + let mut state = self.state; + + let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail; + + state.v3 ^= b; + Sip13Rounds::c_rounds(&mut state); + state.v0 ^= b; + + state.v2 ^= 0xff; + Sip13Rounds::d_rounds(&mut state); + + state.v0 ^ state.v1 ^ state.v2 ^ state.v3 + } +} + +struct Sip13Rounds; + +impl Sip13Rounds { + fn c_rounds(state: &mut State) { + compress!(state); + } + + fn d_rounds(state: &mut State) { + compress!(state); + compress!(state); + compress!(state); + } +} diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs index cf0701ba..b8fe1b5d 100644 --- a/src/symbols/exception.rs +++ b/src/symbols/exception.rs @@ -1,10 +1,18 @@ +#![cfg(feature = "alloc")] + +use crate::result::PtrLen; use alloc::boxed::Box; use alloc::string::String; +use core::ptr::NonNull; use core::slice; #[export_name = "cxxbridge1$exception"] -unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 { +unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> PtrLen { let slice = unsafe { slice::from_raw_parts(ptr, len) }; - let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str(); - Box::leak(boxed).as_ptr() + let string = String::from_utf8_lossy(slice); + let len = string.len(); + let raw_str = Box::into_raw(string.into_owned().into_boxed_str()); + let raw_u8 = raw_str.cast::<u8>(); + let nonnull = unsafe { NonNull::new_unchecked(raw_u8) }; + PtrLen { ptr: nonnull, len } } diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs index 3d5ec344..3b33bc4a 100644 --- a/src/symbols/rust_str.rs +++ b/src/symbols/rust_str.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "alloc")] use alloc::string::String; use core::mem::MaybeUninit; use core::ptr; @@ -10,6 +11,7 @@ unsafe extern "C" fn str_new(this: &mut MaybeUninit<&str>) { unsafe { ptr::write(this, "") } } +#[cfg(feature = "alloc")] #[export_name = "cxxbridge1$str$ref"] unsafe extern "C" fn str_ref<'a>(this: &mut MaybeUninit<&'a str>, string: &'a String) { let this = this.as_mut_ptr(); diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs index 49d40697..8b7c8c48 100644 --- a/src/symbols/rust_string.rs +++ b/src/symbols/rust_string.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "alloc")] + use alloc::borrow::ToOwned; use alloc::string::String; use core::mem::{ManuallyDrop, MaybeUninit}; @@ -37,6 +39,18 @@ unsafe extern "C" fn string_from_utf8( } } +#[export_name = "cxxbridge1$string$from_utf8_lossy"] +unsafe extern "C" fn string_from_utf8_lossy( + this: &mut MaybeUninit<String>, + ptr: *const u8, + len: usize, +) { + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + let owned = String::from_utf8_lossy(slice).into_owned(); + let this = this.as_mut_ptr(); + unsafe { ptr::write(this, owned) } +} + #[export_name = "cxxbridge1$string$from_utf16"] unsafe extern "C" fn string_from_utf16( this: &mut MaybeUninit<String>, @@ -54,6 +68,18 @@ unsafe extern "C" fn string_from_utf16( } } +#[export_name = "cxxbridge1$string$from_utf16_lossy"] +unsafe extern "C" fn string_from_utf16_lossy( + this: &mut MaybeUninit<String>, + ptr: *const u16, + len: usize, +) { + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + let owned = String::from_utf16_lossy(slice); + let this = this.as_mut_ptr(); + unsafe { ptr::write(this, owned) } +} + #[export_name = "cxxbridge1$string$drop"] unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) { unsafe { ManuallyDrop::drop(this) } diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs index 6f2dab9d..89c7da44 100644 --- a/src/symbols/rust_vec.rs +++ b/src/symbols/rust_vec.rs @@ -1,9 +1,11 @@ +#![cfg(feature = "alloc")] + +use crate::c_char::c_char; use crate::rust_string::RustString; use crate::rust_vec::RustVec; use alloc::vec::Vec; use core::mem; use core::ptr; -use std::os::raw::c_char; macro_rules! rust_vec_shims { ($segment:expr, $ty:ty) => { @@ -54,6 +56,12 @@ macro_rules! rust_vec_shims { unsafe { (*this).set_len(len) } } } + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$truncate")] + unsafe extern "C" fn __truncate(this: *mut RustVec<$ty>, len: usize) { + unsafe { (*this).truncate(len) } + } + } }; }; } diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs index 63a1ca78..33992059 100644 --- a/src/unique_ptr.rs +++ b/src/unique_ptr.rs @@ -112,6 +112,10 @@ where unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {} unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {} +// UniquePtr is not a self-referential type and is safe to move out of a Pin, +// regardless whether the pointer's target is Unpin. +impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {} + impl<T> Drop for UniquePtr<T> where T: UniquePtrTarget, @@ -241,11 +245,9 @@ extern "C" { } unsafe impl UniquePtrTarget for CxxString { - #[doc(hidden)] fn __typename(f: &mut fmt::Formatter) -> fmt::Result { f.write_str("CxxString") } - #[doc(hidden)] fn __null() -> MaybeUninit<*mut c_void> { let mut repr = MaybeUninit::uninit(); unsafe { @@ -253,21 +255,17 @@ unsafe impl UniquePtrTarget for CxxString { } repr } - #[doc(hidden)] unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { let mut repr = MaybeUninit::uninit(); unsafe { unique_ptr_std_string_raw(&mut repr, raw) } repr } - #[doc(hidden)] unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self { unsafe { unique_ptr_std_string_get(&repr) } } - #[doc(hidden)] unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self { unsafe { unique_ptr_std_string_release(&mut repr) } } - #[doc(hidden)] unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) { unsafe { unique_ptr_std_string_drop(&mut repr) } } @@ -277,27 +275,21 @@ unsafe impl<T> UniquePtrTarget for CxxVector<T> where T: VectorElement, { - #[doc(hidden)] fn __typename(f: &mut fmt::Formatter) -> fmt::Result { write!(f, "CxxVector<{}>", display(T::__typename)) } - #[doc(hidden)] fn __null() -> MaybeUninit<*mut c_void> { T::__unique_ptr_null() } - #[doc(hidden)] unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { unsafe { T::__unique_ptr_raw(raw) } } - #[doc(hidden)] unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self { unsafe { T::__unique_ptr_get(repr) } } - #[doc(hidden)] unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self { unsafe { T::__unique_ptr_release(repr) } } - #[doc(hidden)] unsafe fn __drop(repr: MaybeUninit<*mut c_void>) { unsafe { T::__unique_ptr_drop(repr) } } diff --git a/src/unwind.rs b/src/unwind.rs index 4967a219..18852da7 100644 --- a/src/unwind.rs +++ b/src/unwind.rs @@ -1,26 +1,39 @@ #![allow(missing_docs)] -use std::io::{self, Write}; -use std::panic::{self, AssertUnwindSafe}; -use std::process; +use core::mem; -pub fn catch_unwind<F, R>(label: &'static str, foreign_call: F) -> R +pub fn prevent_unwind<F, R>(label: &'static str, foreign_call: F) -> R where F: FnOnce() -> R, { - // Regarding the AssertUnwindSafe: we immediately abort on panic so it - // doesn't matter whether the types involved are unwind-safe. The UnwindSafe - // bound on catch_unwind is about ensuring nothing is in a broken state if - // your program plans to continue after the panic. - match panic::catch_unwind(AssertUnwindSafe(foreign_call)) { - Ok(ret) => ret, - Err(_) => abort(label), - } + // Goal is to make it impossible to propagate a panic across the C interface + // of an extern "Rust" function, which would be Undefined Behavior. We + // transform such panicks into a deterministic abort instead. When cxx is + // built in an application using panic=abort, this guard object is compiled + // out because its destructor is statically unreachable. When built with + // panic=unwind, an unwind from the foreign call will attempt to drop the + // guard object leading to a double panic, which is defined by Rust to + // abort. In no_std programs, on most platforms the current mechanism for + // this is for core::intrinsics::abort to invoke an invalid instruction. On + // Unix, the process will probably terminate with a signal like SIGABRT, + // SIGILL, SIGTRAP, SIGSEGV or SIGBUS. The precise behaviour is not + // guaranteed and not stable, but is safe. + let guard = Guard { label }; + + let ret = foreign_call(); + + // If we made it here, no uncaught panic occurred during the foreign call. + mem::forget(guard); + ret } -#[cold] -fn abort(label: &'static str) -> ! { - let mut stderr = io::stderr(); - let _ = writeln!(stderr, "Error: panic in ffi function {}, aborting.", label); - process::abort(); +struct Guard { + label: &'static str, +} + +impl Drop for Guard { + #[cold] + fn drop(&mut self) { + panic!("panic in ffi function {}, aborting.", self.label); + } } diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs index 8a9f1a68..e9320f37 100644 --- a/src/weak_ptr.rs +++ b/src/weak_ptr.rs @@ -114,11 +114,9 @@ pub unsafe trait WeakPtrTarget { macro_rules! impl_weak_ptr_target { ($segment:expr, $name:expr, $ty:ty) => { unsafe impl WeakPtrTarget for $ty { - #[doc(hidden)] fn __typename(f: &mut fmt::Formatter) -> fmt::Result { f.write_str($name) } - #[doc(hidden)] unsafe fn __null(new: *mut c_void) { extern "C" { attr! { @@ -128,7 +126,6 @@ macro_rules! impl_weak_ptr_target { } unsafe { __null(new) } } - #[doc(hidden)] unsafe fn __clone(this: *const c_void, new: *mut c_void) { extern "C" { attr! { @@ -138,7 +135,6 @@ macro_rules! impl_weak_ptr_target { } unsafe { __clone(this, new) } } - #[doc(hidden)] unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) { extern "C" { attr! { @@ -148,7 +144,6 @@ macro_rules! impl_weak_ptr_target { } unsafe { __downgrade(shared, weak) } } - #[doc(hidden)] unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) { extern "C" { attr! { @@ -158,7 +153,6 @@ macro_rules! impl_weak_ptr_target { } unsafe { __upgrade(weak, shared) } } - #[doc(hidden)] unsafe fn __drop(this: *mut c_void) { extern "C" { attr! { diff --git a/syntax/attrs.rs b/syntax/attrs.rs index fa6c8097..46d010e0 100644 --- a/syntax/attrs.rs +++ b/syntax/attrs.rs @@ -1,11 +1,12 @@ +use crate::syntax::cfg::CfgExpr; use crate::syntax::namespace::Namespace; use crate::syntax::report::Errors; use crate::syntax::Atom::{self, *}; -use crate::syntax::{Derive, Doc, ForeignName}; +use crate::syntax::{cfg, Derive, Doc, ForeignName}; use proc_macro2::{Ident, TokenStream}; use quote::ToTokens; use syn::parse::{Nothing, Parse, ParseStream, Parser as _}; -use syn::{Attribute, Error, LitStr, Path, Result, Token}; +use syn::{parenthesized, token, Attribute, Error, LitStr, Path, Result, Token}; // Intended usage: // @@ -27,6 +28,7 @@ use syn::{Attribute, Error, LitStr, Path, Result, Token}; // #[derive(Default)] pub struct Parser<'a> { + pub cfg: Option<&'a mut CfgExpr>, pub doc: Option<&'a mut Doc>, pub derives: Option<&'a mut Vec<Derive>>, pub repr: Option<&'a mut Option<Atom>>, @@ -34,6 +36,7 @@ pub struct Parser<'a> { pub cxx_name: Option<&'a mut Option<ForeignName>>, pub rust_name: Option<&'a mut Option<Ident>>, pub variants_from_header: Option<&'a mut Option<Attribute>>, + pub ignore_unrecognized: bool, // Suppress clippy needless_update lint ("struct update has no effect, all // the fields in the struct have already been specified") when preemptively @@ -46,9 +49,12 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe for attr in attrs { if attr.path.is_ident("doc") { match parse_doc_attribute.parse2(attr.tokens.clone()) { - Ok(lit) => { + Ok(attr) => { if let Some(doc) = &mut parser.doc { - doc.push(lit); + match attr { + DocAttribute::Doc(lit) => doc.push(lit), + DocAttribute::Hidden => doc.hidden = true, + } continue; } } @@ -122,7 +128,23 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe break; } } - } else if attr.path.is_ident("variants_from_header") && cfg!(feature = "experimental") { + } else if attr.path.is_ident("cfg") { + match cfg::parse_attribute.parse2(attr.tokens.clone()) { + Ok(cfg_expr) => { + if let Some(cfg) = &mut parser.cfg { + cfg.merge(cfg_expr); + passthrough_attrs.push(attr); + continue; + } + } + Err(err) => { + cx.push(err); + break; + } + } + } else if attr.path.is_ident("variants_from_header") + && cfg!(feature = "experimental-enum-variants-from-header") + { if let Err(err) = Nothing::parse.parse2(attr.tokens.clone()) { cx.push(err); } @@ -140,6 +162,9 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe // https://doc.rust-lang.org/reference/attributes/diagnostics.html passthrough_attrs.push(attr); continue; + } else if attr.path.is_ident("serde") { + passthrough_attrs.push(attr); + continue; } else if attr.path.segments.len() > 1 { let tool = &attr.path.segments.first().unwrap().ident; if tool == "rustfmt" { @@ -150,16 +175,37 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe continue; } } - cx.error(attr, "unsupported attribute"); - break; + if !parser.ignore_unrecognized { + cx.error(attr, "unsupported attribute"); + break; + } } OtherAttrs(passthrough_attrs) } -fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> { - input.parse::<Token![=]>()?; - let lit: LitStr = input.parse()?; - Ok(lit) +enum DocAttribute { + Doc(LitStr), + Hidden, +} + +mod kw { + syn::custom_keyword!(hidden); +} + +fn parse_doc_attribute(input: ParseStream) -> Result<DocAttribute> { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![=]) { + input.parse::<Token![=]>()?; + let lit: LitStr = input.parse()?; + Ok(DocAttribute::Doc(lit)) + } else if lookahead.peek(token::Paren) { + let content; + parenthesized!(content in input); + content.parse::<kw::hidden>()?; + Ok(DocAttribute::Hidden) + } else { + Err(lookahead.error()) + } } fn parse_derive_attribute(cx: &mut Errors, input: ParseStream) -> Result<Vec<Derive>> { @@ -222,12 +268,17 @@ fn parse_rust_name_attribute(input: ParseStream) -> Result<Ident> { } } +#[derive(Clone)] pub struct OtherAttrs(Vec<Attribute>); impl OtherAttrs { pub fn none() -> Self { OtherAttrs(Vec::new()) } + + pub fn extend(&mut self, other: Self) { + self.0.extend(other.0); + } } impl ToTokens for OtherAttrs { diff --git a/syntax/cfg.rs b/syntax/cfg.rs new file mode 100644 index 00000000..d486b995 --- /dev/null +++ b/syntax/cfg.rs @@ -0,0 +1,77 @@ +use proc_macro2::Ident; +use std::mem; +use syn::parse::{Error, ParseStream, Result}; +use syn::{parenthesized, token, LitStr, Token}; + +#[derive(Clone)] +pub enum CfgExpr { + Unconditional, + Eq(Ident, Option<LitStr>), + All(Vec<CfgExpr>), + Any(Vec<CfgExpr>), + Not(Box<CfgExpr>), +} + +impl CfgExpr { + pub fn merge(&mut self, expr: CfgExpr) { + if let CfgExpr::Unconditional = self { + *self = expr; + } else if let CfgExpr::All(list) = self { + list.push(expr); + } else { + let prev = mem::replace(self, CfgExpr::Unconditional); + *self = CfgExpr::All(vec![prev, expr]); + } + } +} + +pub fn parse_attribute(input: ParseStream) -> Result<CfgExpr> { + let content; + parenthesized!(content in input); + let cfg_expr = content.call(parse_single)?; + content.parse::<Option<Token![,]>>()?; + Ok(cfg_expr) +} + +fn parse_single(input: ParseStream) -> Result<CfgExpr> { + let ident: Ident = input.parse()?; + let lookahead = input.lookahead1(); + if input.peek(token::Paren) { + let content; + parenthesized!(content in input); + if ident == "all" { + let list = content.call(parse_multiple)?; + Ok(CfgExpr::All(list)) + } else if ident == "any" { + let list = content.call(parse_multiple)?; + Ok(CfgExpr::Any(list)) + } else if ident == "not" { + let expr = content.call(parse_single)?; + content.parse::<Option<Token![,]>>()?; + Ok(CfgExpr::Not(Box::new(expr))) + } else { + Err(Error::new(ident.span(), "unrecognized cfg expression")) + } + } else if lookahead.peek(Token![=]) { + input.parse::<Token![=]>()?; + let string: LitStr = input.parse()?; + Ok(CfgExpr::Eq(ident, Some(string))) + } else if lookahead.peek(Token![,]) || input.is_empty() { + Ok(CfgExpr::Eq(ident, None)) + } else { + Err(lookahead.error()) + } +} + +fn parse_multiple(input: ParseStream) -> Result<Vec<CfgExpr>> { + let mut vec = Vec::new(); + while !input.is_empty() { + let expr = input.call(parse_single)?; + vec.push(expr); + if input.is_empty() { + break; + } + input.parse::<Token![,]>()?; + } + Ok(vec) +} diff --git a/syntax/check.rs b/syntax/check.rs index 698782f9..b203ca1f 100644 --- a/syntax/check.rs +++ b/syntax/check.rs @@ -123,10 +123,9 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) { } match Atom::from(&ident.rust) { - None | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) - | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) - | Some(F64) | Some(RustString) => return, - Some(Bool) => { /* todo */ } + None | Some(Bool) | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) + | Some(Usize) | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) + | Some(F32) | Some(F64) | Some(RustString) => return, Some(CxxString) => {} } } diff --git a/syntax/derive.rs b/syntax/derive.rs index 96b3eea7..7727fbc9 100644 --- a/syntax/derive.rs +++ b/syntax/derive.rs @@ -19,6 +19,8 @@ pub enum Trait { Ord, PartialEq, PartialOrd, + Serialize, + Deserialize, } impl Derive { @@ -34,6 +36,8 @@ impl Derive { "Ord" => Trait::Ord, "PartialEq" => Trait::PartialEq, "PartialOrd" => Trait::PartialOrd, + "Serialize" => Trait::Serialize, + "Deserialize" => Trait::Deserialize, _ => return None, }; let span = ident.span(); @@ -60,6 +64,8 @@ impl AsRef<str> for Trait { Trait::Ord => "Ord", Trait::PartialEq => "PartialEq", Trait::PartialOrd => "PartialOrd", + Trait::Serialize => "Serialize", + Trait::Deserialize => "Deserialize", } } } diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs index fff8f758..21a6d00a 100644 --- a/syntax/discriminant.rs +++ b/syntax/discriminant.rs @@ -180,6 +180,7 @@ impl Discriminant { } } + #[cfg(feature = "experimental-enum-variants-from-header")] pub const fn checked_succ(self) -> Option<Self> { match self.sign { Sign::Negative => { diff --git a/syntax/doc.rs b/syntax/doc.rs index cd764fac..5de824f3 100644 --- a/syntax/doc.rs +++ b/syntax/doc.rs @@ -3,12 +3,14 @@ use quote::{quote, ToTokens}; use syn::LitStr; pub struct Doc { + pub(crate) hidden: bool, fragments: Vec<LitStr>, } impl Doc { pub fn new() -> Self { Doc { + hidden: false, fragments: Vec::new(), } } @@ -17,10 +19,12 @@ impl Doc { self.fragments.push(lit); } + #[allow(dead_code)] // only used by cxx-build, not cxxbridge-macro pub fn is_empty(&self) -> bool { self.fragments.is_empty() } + #[allow(dead_code)] // only used by cxx-build, not cxxbridge-macro pub fn to_string(&self) -> String { let mut doc = String::new(); for lit in &self.fragments { @@ -34,8 +38,9 @@ impl Doc { impl ToTokens for Doc { fn to_tokens(&self, tokens: &mut TokenStream) { let fragments = &self.fragments; - tokens.extend(quote! { - #(#[doc = #fragments])* - }); + tokens.extend(quote! { #(#[doc = #fragments])* }); + if self.hidden { + tokens.extend(quote! { #[doc(hidden)] }); + } } } diff --git a/syntax/file.rs b/syntax/file.rs index 99466b8e..71f11eec 100644 --- a/syntax/file.rs +++ b/syntax/file.rs @@ -1,3 +1,4 @@ +use crate::syntax::cfg::CfgExpr; use crate::syntax::namespace::Namespace; use quote::quote; use syn::parse::{Error, Parse, ParseStream, Result}; @@ -7,6 +8,7 @@ use syn::{ }; pub struct Module { + pub cfg: CfgExpr, pub namespace: Namespace, pub attrs: Vec<Attribute>, pub vis: Visibility, @@ -36,6 +38,7 @@ pub struct ItemForeignMod { impl Parse for Module { fn parse(input: ParseStream) -> Result<Self> { + let cfg = CfgExpr::Unconditional; let namespace = Namespace::ROOT; let mut attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; @@ -62,6 +65,7 @@ impl Parse for Module { } Ok(Module { + cfg, namespace, attrs, vis, diff --git a/syntax/impls.rs b/syntax/impls.rs index 06d68dc2..36e1f322 100644 --- a/syntax/impls.rs +++ b/syntax/impls.rs @@ -8,12 +8,14 @@ use std::ops::{Deref, DerefMut}; impl PartialEq for Include { fn eq(&self, other: &Self) -> bool { let Include { + cfg: _, path, kind, begin_span: _, end_span: _, } = self; let Include { + cfg: _, path: path2, kind: kind2, begin_span: _, @@ -307,6 +309,7 @@ impl Eq for Signature {} impl PartialEq for Signature { fn eq(&self, other: &Self) -> bool { let Signature { + asyncness, unsafety, fn_token: _, generics: _, @@ -318,6 +321,7 @@ impl PartialEq for Signature { throws_tokens: _, } = self; let Signature { + asyncness: asyncness2, unsafety: unsafety2, fn_token: _, generics: _, @@ -328,13 +332,15 @@ impl PartialEq for Signature { paren_token: _, throws_tokens: _, } = other; - unsafety.is_some() == unsafety2.is_some() + asyncness.is_some() == asyncness2.is_some() + && unsafety.is_some() == unsafety2.is_some() && receiver == receiver2 && ret == ret2 && throws == throws2 && args.len() == args2.len() && args.iter().zip(args2).all(|(arg, arg2)| { let Var { + cfg: _, doc: _, attrs: _, visibility: _, @@ -343,6 +349,7 @@ impl PartialEq for Signature { ty, } = arg; let Var { + cfg: _, doc: _, attrs: _, visibility: _, @@ -358,6 +365,7 @@ impl PartialEq for Signature { impl Hash for Signature { fn hash<H: Hasher>(&self, state: &mut H) { let Signature { + asyncness, unsafety, fn_token: _, generics: _, @@ -368,10 +376,12 @@ impl Hash for Signature { paren_token: _, throws_tokens: _, } = self; + asyncness.is_some().hash(state); unsafety.is_some().hash(state); receiver.hash(state); for arg in args { let Var { + cfg: _, doc: _, attrs: _, visibility: _, diff --git a/syntax/map.rs b/syntax/map.rs index 4873409d..526b793b 100644 --- a/syntax/map.rs +++ b/syntax/map.rs @@ -124,6 +124,7 @@ mod unordered { self.0.entry(key) } + #[allow(dead_code)] // only used by cxx-build, not cxxbridge-macro pub fn remove<Q>(&mut self, key: &Q) -> Option<V> where K: Borrow<Q>, diff --git a/syntax/mod.rs b/syntax/mod.rs index 1d986345..4f19d964 100644 --- a/syntax/mod.rs +++ b/syntax/mod.rs @@ -2,6 +2,7 @@ pub mod atom; pub mod attrs; +pub mod cfg; pub mod check; pub mod derive; mod discriminant; @@ -30,13 +31,14 @@ pub mod types; mod visit; use self::attrs::OtherAttrs; +use self::cfg::CfgExpr; use self::namespace::Namespace; use self::parse::kw; use self::symbol::Symbol; use proc_macro2::{Ident, Span}; use syn::punctuated::Punctuated; use syn::token::{Brace, Bracket, Paren}; -use syn::{Attribute, Expr, Generics, Lifetime, LitInt, Path, Token, Type as RustType}; +use syn::{Attribute, Expr, Generics, Lifetime, LitInt, Token, Type as RustType}; pub use self::atom::Atom; pub use self::derive::{Derive, Trait}; @@ -59,6 +61,7 @@ pub enum Api { } pub struct Include { + pub cfg: CfgExpr, pub path: String, pub kind: IncludeKind, pub begin_span: Span, @@ -75,6 +78,7 @@ pub enum IncludeKind { } pub struct ExternType { + pub cfg: CfgExpr, pub lang: Lang, pub doc: Doc, pub derives: Vec<Derive>, @@ -90,6 +94,7 @@ pub struct ExternType { } pub struct Struct { + pub cfg: CfgExpr, pub doc: Doc, pub derives: Vec<Derive>, pub attrs: OtherAttrs, @@ -102,6 +107,7 @@ pub struct Struct { } pub struct Enum { + pub cfg: CfgExpr, pub doc: Doc, pub derives: Vec<Derive>, pub attrs: OtherAttrs, @@ -118,11 +124,18 @@ pub struct Enum { } pub enum EnumRepr { - Native { atom: Atom, repr_type: Type }, - Foreign { rust_type: Path }, + Native { + atom: Atom, + repr_type: Type, + }, + #[cfg(feature = "experimental-enum-variants-from-header")] + Foreign { + rust_type: syn::Path, + }, } pub struct ExternFn { + pub cfg: CfgExpr, pub lang: Lang, pub doc: Doc, pub attrs: OtherAttrs, @@ -134,6 +147,7 @@ pub struct ExternFn { } pub struct TypeAlias { + pub cfg: CfgExpr, pub doc: Doc, pub derives: Vec<Derive>, pub attrs: OtherAttrs, @@ -147,6 +161,7 @@ pub struct TypeAlias { } pub struct Impl { + pub cfg: CfgExpr, pub impl_token: Token![impl], pub impl_generics: Lifetimes, pub negative: bool, @@ -164,6 +179,7 @@ pub struct Lifetimes { } pub struct Signature { + pub asyncness: Option<Token![async]>, pub unsafety: Option<Token![unsafe]>, pub fn_token: Token![fn], pub generics: Generics, @@ -176,6 +192,7 @@ pub struct Signature { } pub struct Var { + pub cfg: CfgExpr, pub doc: Doc, pub attrs: OtherAttrs, pub visibility: Token![pub], @@ -198,6 +215,7 @@ pub struct Receiver { } pub struct Variant { + pub cfg: CfgExpr, pub doc: Doc, pub attrs: OtherAttrs, pub name: Pair, diff --git a/syntax/names.rs b/syntax/names.rs index 7a125ae7..8b93ac5c 100644 --- a/syntax/names.rs +++ b/syntax/names.rs @@ -20,17 +20,6 @@ impl Pair { .chain(iter::once(&self.cxx as &dyn Segment)); Symbol::from_idents(segments) } - - pub fn to_fully_qualified(&self) -> String { - let mut fully_qualified = String::new(); - for segment in &self.namespace { - fully_qualified += "::"; - fully_qualified += &segment.to_string(); - } - fully_qualified += "::"; - fully_qualified += &self.cxx.to_string(); - fully_qualified - } } impl NamedType { diff --git a/syntax/parse.rs b/syntax/parse.rs index 32d36eb3..1754c600 100644 --- a/syntax/parse.rs +++ b/syntax/parse.rs @@ -1,4 +1,5 @@ use crate::syntax::attrs::OtherAttrs; +use crate::syntax::cfg::CfgExpr; use crate::syntax::discriminant::DiscriminantSet; use crate::syntax::file::{Item, ItemForeignMod}; use crate::syntax::report::Errors; @@ -43,7 +44,7 @@ pub fn parse_items( Item::ForeignMod(foreign_mod) => { parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace) } - Item::Impl(item) => match parse_impl(item) { + Item::Impl(item) => match parse_impl(cx, item) { Ok(imp) => apis.push(imp), Err(err) => cx.push(err), }, @@ -55,6 +56,7 @@ pub fn parse_items( } fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api> { + let mut cfg = CfgExpr::Unconditional; let mut doc = Doc::new(); let mut derives = Vec::new(); let mut namespace = namespace.clone(); @@ -64,6 +66,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> cx, mem::take(&mut item.attrs), attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), derives: Some(&mut derives), namespace: Some(&mut namespace), @@ -124,6 +127,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> let mut fields = Vec::new(); for field in named_fields.named { let ident = field.ident.unwrap(); + let mut cfg = CfgExpr::Unconditional; let mut doc = Doc::new(); let mut cxx_name = None; let mut rust_name = None; @@ -131,6 +135,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> cx, field.attrs, attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), cxx_name: Some(&mut cxx_name), rust_name: Some(&mut rust_name), @@ -148,6 +153,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> let name = pair(Namespace::default(), &ident, cxx_name, rust_name); let colon_token = field.colon_token.unwrap(); fields.push(Var { + cfg, doc, attrs, visibility, @@ -168,6 +174,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> let brace_token = named_fields.brace_token; Ok(Api::Struct(Struct { + cfg, doc, derives, attrs, @@ -181,6 +188,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> } fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { + let mut cfg = CfgExpr::Unconditional; let mut doc = Doc::new(); let mut derives = Vec::new(); let mut repr = None; @@ -192,6 +200,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { cx, item.attrs, attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), derives: Some(&mut derives), repr: Some(&mut repr), @@ -254,6 +263,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { let variants_from_header = variants_from_header_attr.is_some(); Api::Enum(Enum { + cfg, doc, derives, attrs, @@ -275,6 +285,7 @@ fn parse_variant( mut variant: RustVariant, discriminants: &mut DiscriminantSet, ) -> Result<Variant> { + let mut cfg = CfgExpr::Unconditional; let mut doc = Doc::new(); let mut cxx_name = None; let mut rust_name = None; @@ -282,6 +293,7 @@ fn parse_variant( cx, mem::take(&mut variant.attrs), attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), cxx_name: Some(&mut cxx_name), rust_name: Some(&mut rust_name), @@ -311,6 +323,7 @@ fn parse_variant( let expr = variant.discriminant.map(|(_, expr)| expr); Ok(Variant { + cfg, doc, attrs, name, @@ -345,11 +358,13 @@ fn parse_foreign_mod( let trusted = trusted || foreign_mod.unsafety.is_some(); + let mut cfg = CfgExpr::Unconditional; let mut namespace = namespace.clone(); - attrs::parse( + let attrs = attrs::parse( cx, foreign_mod.attrs, attrs::Parser { + cfg: Some(&mut cfg), namespace: Some(&mut namespace), ..Default::default() }, @@ -359,23 +374,26 @@ fn parse_foreign_mod( for foreign in foreign_mod.items { match foreign { ForeignItem::Type(foreign) => { - let ety = parse_extern_type(cx, foreign, lang, trusted, &namespace); + let ety = parse_extern_type(cx, foreign, lang, trusted, &cfg, &namespace, &attrs); items.push(ety); } ForeignItem::Fn(foreign) => { - match parse_extern_fn(cx, foreign, lang, trusted, &namespace) { + match parse_extern_fn(cx, foreign, lang, trusted, &cfg, &namespace, &attrs) { Ok(efn) => items.push(efn), Err(err) => cx.push(err), } } ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => { match foreign.mac.parse_body_with(parse_include) { - Ok(include) => items.push(Api::Include(include)), + Ok(mut include) => { + include.cfg = cfg.clone(); + items.push(Api::Include(include)); + } Err(err) => cx.push(err), } } ForeignItem::Verbatim(tokens) => { - match parse_extern_verbatim(cx, tokens, lang, trusted, &namespace) { + match parse_extern_verbatim(cx, tokens, lang, trusted, &cfg, &namespace, &attrs) { Ok(api) => items.push(api), Err(err) => cx.push(err), } @@ -443,17 +461,22 @@ fn parse_extern_type( foreign_type: ForeignItemType, lang: Lang, trusted: bool, + extern_block_cfg: &CfgExpr, namespace: &Namespace, + attrs: &OtherAttrs, ) -> Api { + let mut cfg = extern_block_cfg.clone(); let mut doc = Doc::new(); let mut derives = Vec::new(); let mut namespace = namespace.clone(); let mut cxx_name = None; let mut rust_name = None; - let attrs = attrs::parse( + let mut attrs = attrs.clone(); + attrs.extend(attrs::parse( cx, foreign_type.attrs, attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), derives: Some(&mut derives), namespace: Some(&mut namespace), @@ -461,7 +484,7 @@ fn parse_extern_type( rust_name: Some(&mut rust_name), ..Default::default() }, - ); + )); let type_token = foreign_type.type_token; let visibility = visibility_pub(&foreign_type.vis, type_token.span); @@ -479,6 +502,7 @@ fn parse_extern_type( Lang::Cxx => Api::CxxType, Lang::Rust => Api::RustType, })(ExternType { + cfg, lang, doc, derives, @@ -499,23 +523,28 @@ fn parse_extern_fn( mut foreign_fn: ForeignItemFn, lang: Lang, trusted: bool, + extern_block_cfg: &CfgExpr, namespace: &Namespace, + attrs: &OtherAttrs, ) -> Result<Api> { + let mut cfg = extern_block_cfg.clone(); let mut doc = Doc::new(); let mut namespace = namespace.clone(); let mut cxx_name = None; let mut rust_name = None; - let attrs = attrs::parse( + let mut attrs = attrs.clone(); + attrs.extend(attrs::parse( cx, mem::take(&mut foreign_fn.attrs), attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), namespace: Some(&mut namespace), cxx_name: Some(&mut cxx_name), rust_name: Some(&mut rust_name), ..Default::default() }, - ); + )); let generics = &foreign_fn.sig.generics; if generics.where_clause.is_some() @@ -537,10 +566,13 @@ fn parse_extern_fn( )); } - if foreign_fn.sig.asyncness.is_some() { + if foreign_fn.sig.asyncness.is_some() && !cfg!(feature = "experimental-async-fn") { return Err(Error::new_spanned( foreign_fn, - "async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach", + "async function is not directly supported yet, but see https://cxx.rs/async.html \ + for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; \ + eventually what you wrote will work but it isn't integrated into the cxx::bridge \ + macro yet", )); } @@ -591,12 +623,14 @@ fn parse_extern_fn( }; let ty = parse_type(&arg.ty)?; if ident != "self" { + let cfg = CfgExpr::Unconditional; let doc = Doc::new(); let attrs = OtherAttrs::none(); let visibility = Token![pub](ident.span()); let name = pair(Namespace::default(), &ident, None, None); let colon_token = arg.colon_token; args.push_value(Var { + cfg, doc, attrs, visibility, @@ -634,6 +668,7 @@ fn parse_extern_fn( let mut throws_tokens = None; let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?; let throws = throws_tokens.is_some(); + let asyncness = foreign_fn.sig.asyncness; let unsafety = foreign_fn.sig.unsafety; let fn_token = foreign_fn.sig.fn_token; let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span); @@ -647,12 +682,14 @@ fn parse_extern_fn( Lang::Cxx => Api::CxxFunction, Lang::Rust => Api::RustFunction, }(ExternFn { + cfg, lang, doc, attrs, visibility, name, sig: Signature { + asyncness, unsafety, fn_token, generics, @@ -673,13 +710,25 @@ fn parse_extern_verbatim( tokens: TokenStream, lang: Lang, trusted: bool, + extern_block_cfg: &CfgExpr, namespace: &Namespace, + attrs: &OtherAttrs, ) -> Result<Api> { |input: ParseStream| -> Result<Api> { - let attrs = input.call(Attribute::parse_outer)?; + let unparsed_attrs = input.call(Attribute::parse_outer)?; let visibility: Visibility = input.parse()?; if input.peek(Token![type]) { - parse_extern_verbatim_type(cx, attrs, visibility, input, lang, trusted, namespace) + parse_extern_verbatim_type( + cx, + unparsed_attrs, + visibility, + input, + lang, + trusted, + extern_block_cfg, + namespace, + attrs, + ) } else if input.peek(Token![fn]) { parse_extern_verbatim_fn(input) } else { @@ -695,12 +744,14 @@ fn parse_extern_verbatim( fn parse_extern_verbatim_type( cx: &mut Errors, - attrs: Vec<Attribute>, + unparsed_attrs: Vec<Attribute>, visibility: Visibility, input: ParseStream, lang: Lang, trusted: bool, + extern_block_cfg: &CfgExpr, namespace: &Namespace, + attrs: &OtherAttrs, ) -> Result<Api> { let type_token: Token![type] = input.parse()?; let ident: Ident = input.parse()?; @@ -746,12 +797,33 @@ fn parse_extern_verbatim_type( if lookahead.peek(Token![=]) { // type Alias = crate::path::to::Type; parse_type_alias( - cx, attrs, visibility, type_token, ident, lifetimes, input, lang, namespace, + cx, + unparsed_attrs, + visibility, + type_token, + ident, + lifetimes, + input, + lang, + extern_block_cfg, + namespace, + attrs, ) } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) { // type Opaque: Bound2 + Bound2; parse_extern_type_bounded( - cx, attrs, visibility, type_token, ident, lifetimes, input, lang, trusted, namespace, + cx, + unparsed_attrs, + visibility, + type_token, + ident, + lifetimes, + input, + lang, + trusted, + extern_block_cfg, + namespace, + attrs, ) } else { Err(lookahead.error()) @@ -766,28 +838,33 @@ fn parse_extern_verbatim_fn(input: ParseStream) -> Result<Api> { fn parse_type_alias( cx: &mut Errors, - attrs: Vec<Attribute>, + unparsed_attrs: Vec<Attribute>, visibility: Visibility, type_token: Token![type], ident: Ident, generics: Lifetimes, input: ParseStream, lang: Lang, + extern_block_cfg: &CfgExpr, namespace: &Namespace, + attrs: &OtherAttrs, ) -> Result<Api> { let eq_token: Token![=] = input.parse()?; let ty: RustType = input.parse()?; let semi_token: Token![;] = input.parse()?; + let mut cfg = extern_block_cfg.clone(); let mut doc = Doc::new(); let mut derives = Vec::new(); let mut namespace = namespace.clone(); let mut cxx_name = None; let mut rust_name = None; - let attrs = attrs::parse( + let mut attrs = attrs.clone(); + attrs.extend(attrs::parse( cx, - attrs, + unparsed_attrs, attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), derives: Some(&mut derives), namespace: Some(&mut namespace), @@ -795,7 +872,7 @@ fn parse_type_alias( rust_name: Some(&mut rust_name), ..Default::default() }, - ); + )); if lang == Lang::Rust { let span = quote!(#type_token #semi_token); @@ -807,6 +884,7 @@ fn parse_type_alias( let name = pair(namespace, &ident, cxx_name, rust_name); Ok(Api::TypeAlias(TypeAlias { + cfg, doc, derives, attrs, @@ -822,7 +900,7 @@ fn parse_type_alias( fn parse_extern_type_bounded( cx: &mut Errors, - attrs: Vec<Attribute>, + unparsed_attrs: Vec<Attribute>, visibility: Visibility, type_token: Token![type], ident: Ident, @@ -830,7 +908,9 @@ fn parse_extern_type_bounded( input: ParseStream, lang: Lang, trusted: bool, + extern_block_cfg: &CfgExpr, namespace: &Namespace, + attrs: &OtherAttrs, ) -> Result<Api> { let mut bounds = Vec::new(); let colon_token: Option<Token![:]> = input.parse()?; @@ -865,15 +945,18 @@ fn parse_extern_type_bounded( } let semi_token: Token![;] = input.parse()?; + let mut cfg = extern_block_cfg.clone(); let mut doc = Doc::new(); let mut derives = Vec::new(); let mut namespace = namespace.clone(); let mut cxx_name = None; let mut rust_name = None; - let attrs = attrs::parse( + let mut attrs = attrs.clone(); + attrs.extend(attrs::parse( cx, - attrs, + unparsed_attrs, attrs::Parser { + cfg: Some(&mut cfg), doc: Some(&mut doc), derives: Some(&mut derives), namespace: Some(&mut namespace), @@ -881,7 +964,7 @@ fn parse_extern_type_bounded( rust_name: Some(&mut rust_name), ..Default::default() }, - ); + )); let visibility = visibility_pub(&visibility, type_token.span); let name = pair(namespace, &ident, cxx_name, rust_name); @@ -890,6 +973,7 @@ fn parse_extern_type_bounded( Lang::Cxx => Api::CxxType, Lang::Rust => Api::RustType, }(ExternType { + cfg, lang, doc, derives, @@ -905,9 +989,19 @@ fn parse_extern_type_bounded( })) } -fn parse_impl(imp: ItemImpl) -> Result<Api> { +fn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result<Api> { let impl_token = imp.impl_token; + let mut cfg = CfgExpr::Unconditional; + attrs::parse( + cx, + imp.attrs, + attrs::Parser { + cfg: Some(&mut cfg), + ..Default::default() + }, + ); + if !imp.items.is_empty() { let mut span = Group::new(Delimiter::Brace, TokenStream::new()); span.set_span(imp.brace_token.span); @@ -993,6 +1087,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> { let brace_token = imp.brace_token; Ok(Api::Impl(Impl { + cfg, impl_token, impl_generics, negative, @@ -1008,6 +1103,7 @@ fn parse_include(input: ParseStream) -> Result<Include> { let lit: LitStr = input.parse()?; let span = lit.span(); return Ok(Include { + cfg: CfgExpr::Unconditional, path: lit.value(), kind: IncludeKind::Quoted, begin_span: span, @@ -1037,6 +1133,7 @@ fn parse_include(input: ParseStream) -> Result<Include> { let rangle: Token![>] = input.parse()?; return Ok(Include { + cfg: CfgExpr::Unconditional, path, kind: IncludeKind::Bracketed, begin_span: langle.span, @@ -1297,11 +1394,13 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> { } }; let ty = parse_type(&arg.ty)?; + let cfg = CfgExpr::Unconditional; let doc = Doc::new(); let attrs = OtherAttrs::none(); let visibility = Token![pub](ident.span()); let name = pair(Namespace::default(), &ident, None, None); Ok(Var { + cfg, doc, attrs, visibility, @@ -1316,6 +1415,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> { let ret = parse_return_type(&ty.output, &mut throws_tokens)?; let throws = throws_tokens.is_some(); + let asyncness = None; let unsafety = ty.unsafety; let fn_token = ty.fn_token; let generics = Generics::default(); @@ -1323,6 +1423,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> { let paren_token = ty.paren_token; Ok(Type::Fn(Box::new(Signature { + asyncness, unsafety, fn_token, generics, diff --git a/syntax/qualified.rs b/syntax/qualified.rs index 96f07c19..5f182fa9 100644 --- a/syntax/qualified.rs +++ b/syntax/qualified.rs @@ -1,5 +1,5 @@ use syn::ext::IdentExt; -use syn::parse::{ParseStream, Result}; +use syn::parse::{Error, ParseStream, Result}; use syn::{Ident, LitStr, Token}; pub struct QualifiedName { @@ -8,21 +8,8 @@ pub struct QualifiedName { impl QualifiedName { pub fn parse_unquoted(input: ParseStream) -> Result<Self> { - let mut segments = Vec::new(); - let mut trailing_punct = true; - let leading_colons: Option<Token![::]> = input.parse()?; - while trailing_punct && input.peek(Ident::peek_any) { - let ident = Ident::parse_any(input)?; - segments.push(ident); - let colons: Option<Token![::]> = input.parse()?; - trailing_punct = colons.is_some(); - } - if segments.is_empty() && leading_colons.is_none() { - return Err(input.error("expected path")); - } else if trailing_punct { - return Err(input.error("expected path segment")); - } - Ok(QualifiedName { segments }) + let allow_raw = true; + parse_unquoted(input, allow_raw) } pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result<Self> { @@ -32,10 +19,41 @@ impl QualifiedName { let segments = Vec::new(); Ok(QualifiedName { segments }) } else { - lit.parse_with(Self::parse_unquoted) + lit.parse_with(|input: ParseStream| { + let allow_raw = false; + parse_unquoted(input, allow_raw) + }) } } else { Self::parse_unquoted(input) } } } + +fn parse_unquoted(input: ParseStream, allow_raw: bool) -> Result<QualifiedName> { + let mut segments = Vec::new(); + let mut trailing_punct = true; + let leading_colons: Option<Token![::]> = input.parse()?; + while trailing_punct && input.peek(Ident::peek_any) { + let mut ident = Ident::parse_any(input)?; + if let Some(unraw) = ident.to_string().strip_prefix("r#") { + if !allow_raw { + let msg = format!( + "raw identifier `{}` is not allowed in a quoted namespace; use `{}`, or remove quotes", + ident, unraw, + ); + return Err(Error::new(ident.span(), msg)); + } + ident = Ident::new(unraw, ident.span()); + } + segments.push(ident); + let colons: Option<Token![::]> = input.parse()?; + trailing_punct = colons.is_some(); + } + if segments.is_empty() && leading_colons.is_none() { + return Err(input.error("expected path")); + } else if trailing_punct { + return Err(input.error("expected path segment")); + } + Ok(QualifiedName { segments }) +} diff --git a/syntax/symbol.rs b/syntax/symbol.rs index a13a4f3c..4c1607e3 100644 --- a/syntax/symbol.rs +++ b/syntax/symbol.rs @@ -38,12 +38,6 @@ impl Symbol { assert!(!symbol.0.is_empty()); symbol } - - /// For example, for taking a symbol and then making a new symbol - /// for a vec of that symbol. - pub fn prefix_with(&self, prefix: &str) -> Symbol { - Symbol(format!("{}{}", prefix, self.to_string())) - } } pub trait Segment { diff --git a/syntax/tokens.rs b/syntax/tokens.rs index 33f20fa3..a9f42bd4 100644 --- a/syntax/tokens.rs +++ b/syntax/tokens.rs @@ -1,7 +1,7 @@ use crate::syntax::atom::Atom::*; use crate::syntax::{ Array, Atom, Derive, Enum, EnumRepr, ExternFn, ExternType, Impl, Lifetimes, NamedType, Ptr, - Receiver, Ref, Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, + Ref, Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, }; use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote_spanned, ToTokens}; @@ -13,10 +13,13 @@ impl ToTokens for Type { Type::Ident(ident) => { if ident.rust == Char { let span = ident.rust.span(); - tokens.extend(quote_spanned!(span=> ::std::os::raw::)); + tokens.extend(quote_spanned!(span=> ::cxx::private::)); } else if ident.rust == CxxString { let span = ident.rust.span(); tokens.extend(quote_spanned!(span=> ::cxx::)); + } else if ident.rust == RustString { + let span = ident.rust.span(); + tokens.extend(quote_spanned!(span=> ::cxx::alloc::string::)); } ident.to_tokens(tokens); } @@ -39,6 +42,7 @@ impl ToTokens for Type { impl ToTokens for Var { fn to_tokens(&self, tokens: &mut TokenStream) { let Var { + cfg: _, doc: _, attrs: _, visibility: _, @@ -65,8 +69,11 @@ impl ToTokens for Ty1 { "UniquePtr" | "SharedPtr" | "WeakPtr" | "CxxVector" => { tokens.extend(quote_spanned!(span=> ::cxx::)); } + "Box" => { + tokens.extend(quote_spanned!(span=> ::cxx::alloc::boxed::)); + } "Vec" => { - tokens.extend(quote_spanned!(span=> ::std::vec::)); + tokens.extend(quote_spanned!(span=> ::cxx::alloc::vec::)); } _ => {} } @@ -89,7 +96,7 @@ impl ToTokens for Ref { mutability, } = self; if let Some((pin, langle, _rangle)) = pin_tokens { - tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin)); + tokens.extend(quote_spanned!(pin.span=> ::cxx::core::pin::Pin)); langle.to_tokens(tokens); } ampersand.to_tokens(tokens); @@ -214,6 +221,7 @@ impl ToTokens for ExternFn { impl ToTokens for Impl { fn to_tokens(&self, tokens: &mut TokenStream) { let Impl { + cfg: _, impl_token, impl_generics, negative: _, @@ -246,6 +254,7 @@ impl ToTokens for Lifetimes { impl ToTokens for Signature { fn to_tokens(&self, tokens: &mut TokenStream) { let Signature { + asyncness: _, unsafety: _, fn_token, generics: _, @@ -284,6 +293,7 @@ impl ToTokens for EnumRepr { fn to_tokens(&self, tokens: &mut TokenStream) { match self { EnumRepr::Native { atom, repr_type: _ } => atom.to_tokens(tokens), + #[cfg(feature = "experimental-enum-variants-from-header")] EnumRepr::Foreign { rust_type } => rust_type.to_tokens(tokens), } } @@ -296,74 +306,3 @@ impl ToTokens for NamedType { generics.to_tokens(tokens); } } - -pub struct ReceiverType<'a>(&'a Receiver); -pub struct ReceiverTypeSelf<'a>(&'a Receiver); - -impl Receiver { - // &TheType - pub fn ty(&self) -> ReceiverType { - ReceiverType(self) - } - - // &Self - pub fn ty_self(&self) -> ReceiverTypeSelf { - ReceiverTypeSelf(self) - } -} - -impl ToTokens for ReceiverType<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) { - let Receiver { - pinned: _, - ampersand, - lifetime, - mutable: _, - var: _, - colon_token: _, - ty, - shorthand: _, - pin_tokens, - mutability, - } = &self.0; - if let Some((pin, langle, _rangle)) = pin_tokens { - tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin)); - langle.to_tokens(tokens); - } - ampersand.to_tokens(tokens); - lifetime.to_tokens(tokens); - mutability.to_tokens(tokens); - ty.to_tokens(tokens); - if let Some((_pin, _langle, rangle)) = pin_tokens { - rangle.to_tokens(tokens); - } - } -} - -impl ToTokens for ReceiverTypeSelf<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) { - let Receiver { - pinned: _, - ampersand, - lifetime, - mutable: _, - var: _, - colon_token: _, - ty, - shorthand: _, - pin_tokens, - mutability, - } = &self.0; - if let Some((pin, langle, _rangle)) = pin_tokens { - tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin)); - langle.to_tokens(tokens); - } - ampersand.to_tokens(tokens); - lifetime.to_tokens(tokens); - mutability.to_tokens(tokens); - Token![Self](ty.rust.span()).to_tokens(tokens); - if let Some((_pin, _langle, rangle)) = pin_tokens { - rangle.to_tokens(tokens); - } - } -} diff --git a/syntax/types.rs b/syntax/types.rs index c54682bd..82b45300 100644 --- a/syntax/types.rs +++ b/syntax/types.rs @@ -92,6 +92,7 @@ impl<'a> Types<'a> { EnumRepr::Native { atom: _, repr_type } => { all.insert(repr_type); } + #[cfg(feature = "experimental-enum-variants-from-header")] EnumRepr::Foreign { rust_type: _ } => {} } let ident = &enm.name.rust; @@ -3,6 +3,7 @@ load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_test( name = "test", srcs = ["test.rs"], + edition = "2018", deps = [ ":ffi", "//:cxx", @@ -17,6 +18,7 @@ rust_library( "ffi/module.rs", ], crate = "cxx_test_suite", + edition = "2018", deps = [ ":impl", "//:cxx", @@ -30,20 +32,26 @@ cxx_library( ":bridge/source", ":module/source", ], - headers = { + exported_deps = ["//:core"], + exported_headers = { "ffi/lib.rs.h": ":bridge/header", "ffi/module.rs.h": ":module/header", "ffi/tests.h": "ffi/tests.h", }, - deps = ["//:core"], ) rust_cxx_bridge( name = "bridge", src = "ffi/lib.rs", + deps = [ + ":impl", + ], ) rust_cxx_bridge( name = "module", src = "ffi/module.rs", + deps = [ + ":impl", + ], ) diff --git a/tests/BUILD b/tests/BUILD index d4af3aff..3c25d963 100644 --- a/tests/BUILD +++ b/tests/BUILD @@ -1,11 +1,12 @@ load("@rules_cc//cc:defs.bzl", "cc_library") -load("@rules_rust//rust:rust.bzl", "rust_library", "rust_test") +load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_test( name = "test", size = "small", srcs = ["test.rs"], + edition = "2018", deps = [ ":cxx_test_suite", "//:cxx", @@ -19,6 +20,7 @@ rust_library( "ffi/lib.rs", "ffi/module.rs", ], + edition = "2018", deps = [ ":impl", "//:cxx", diff --git a/tests/compiletest.rs b/tests/compiletest.rs index d2b516f5..cd58514f 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -1,5 +1,7 @@ +#[allow(unused_attributes)] #[rustversion::attr(not(nightly), ignore)] #[cfg_attr(skip_ui_tests, ignore)] +#[cfg_attr(miri, ignore)] #[test] fn ui() { let t = trybuild::TestCases::new(); diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml index e62d0906..ef91f4f6 100644 --- a/tests/ffi/Cargo.toml +++ b/tests/ffi/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "cxx-test-suite" version = "0.0.0" +authors = ["David Tolnay <dtolnay@gmail.com>"] edition = "2018" publish = false @@ -8,7 +9,7 @@ publish = false path = "lib.rs" [dependencies] -cxx = { path = "../.." } +cxx = { path = "../..", default-features = false } [build-dependencies] cxx-build = { path = "../../gen/build" } diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs index 25b4ccdc..9286cf7a 100644 --- a/tests/ffi/lib.rs +++ b/tests/ffi/lib.rs @@ -1,5 +1,6 @@ #![allow( clippy::boxed_local, + clippy::derive_partial_eq_without_eq, clippy::just_underscores_and_digits, clippy::let_underscore_drop, clippy::missing_safety_doc, @@ -15,7 +16,7 @@ pub mod cast; pub mod module; -use cxx::{CxxString, CxxVector, SharedPtr, UniquePtr}; +use cxx::{type_id, CxxString, CxxVector, ExternType, SharedPtr, UniquePtr}; use std::fmt::{self, Display}; use std::mem::MaybeUninit; use std::os::raw::c_char; @@ -80,6 +81,7 @@ pub mod ffi { pub struct Array { a: [i32; 4], + b: Buffer, } #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] @@ -103,6 +105,7 @@ pub mod ffi { fn c_return_slice_char(shared: &Shared) -> &[c_char]; fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8]; fn c_return_rust_string() -> String; + fn c_return_rust_string_lossy() -> String; fn c_return_unique_ptr_string() -> UniquePtr<CxxString>; fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>; fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>; @@ -111,10 +114,11 @@ pub mod ffi { fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>; fn c_return_ref_vector(c: &C) -> &CxxVector<u8>; fn c_return_mut_vector(c: Pin<&mut C>) -> Pin<&mut CxxVector<u8>>; - fn c_return_rust_vec() -> Vec<u8>; + fn c_return_rust_vec_u8() -> Vec<u8>; fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>; fn c_return_mut_rust_vec(c: Pin<&mut C>) -> &mut Vec<u8>; fn c_return_rust_vec_string() -> Vec<String>; + fn c_return_rust_vec_bool() -> Vec<bool>; fn c_return_identity(_: usize) -> usize; fn c_return_sum(_: usize, _: usize) -> usize; fn c_return_enum(n: u16) -> Enum; @@ -149,6 +153,8 @@ pub mod ffi { fn c_take_rust_vec_index(v: Vec<u8>); fn c_take_rust_vec_shared_index(v: Vec<Shared>); fn c_take_rust_vec_shared_push(v: Vec<Shared>); + fn c_take_rust_vec_shared_truncate(v: Vec<Shared>); + fn c_take_rust_vec_shared_clear(v: Vec<Shared>); fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>); fn c_take_rust_vec_shared_sort(v: Vec<Shared>); fn c_take_ref_rust_vec(v: &Vec<u8>); @@ -245,6 +251,10 @@ pub mod ffi { CVal2, } + extern "C++" { + type Buffer = crate::Buffer; + } + extern "Rust" { type R; @@ -409,6 +419,15 @@ impl ffi::Array { } } +#[derive(Default)] +#[repr(C)] +pub struct Buffer([c_char; 12]); + +unsafe impl ExternType for Buffer { + type Id = type_id!("tests::Buffer"); + type Kind = cxx::kind::Trivial; +} + #[derive(Debug)] struct Error; diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index df7ded07..984e2220 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -110,6 +110,10 @@ rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) { rust::String c_return_rust_string() { return "2020"; } +rust::String c_return_rust_string_lossy() { + return rust::String::lossy("Hello \xf0\x90\x80World"); +} + std::unique_ptr<std::string> c_return_unique_ptr_string() { return std::unique_ptr<std::string>(new std::string("2020")); } @@ -154,7 +158,7 @@ const std::vector<uint8_t> &c_return_ref_vector(const C &c) { std::vector<uint8_t> &c_return_mut_vector(C &c) { return c.get_v(); } -rust::Vec<uint8_t> c_return_rust_vec() { +rust::Vec<uint8_t> c_return_rust_vec_u8() { rust::Vec<uint8_t> vec{2, 0, 2, 0}; return vec; } @@ -173,6 +177,8 @@ rust::Vec<rust::String> c_return_rust_vec_string() { return {"2", "0", "2", "0"}; } +rust::Vec<bool> c_return_rust_vec_bool() { return {true, true, false}; } + size_t c_return_identity(size_t n) { return n; } size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; } @@ -452,6 +458,23 @@ void c_take_rust_vec_shared_push(rust::Vec<Shared> v) { } } +void c_take_rust_vec_shared_truncate(rust::Vec<Shared> v) { + v.truncate(1); + if (v.size() == 1) { + v.truncate(0); + if (v.size() == 0) { + cxx_test_suite_set_correct(); + } + } +} + +void c_take_rust_vec_shared_clear(rust::Vec<Shared> v) { + v.clear(); + if (v.size() == 0) { + cxx_test_suite_set_correct(); + } +} + void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) { uint8_t sum = std::accumulate(v.begin(), v.end(), 0); if (sum == 200) { @@ -853,6 +876,12 @@ extern "C" const char *cxx_run_test() noexcept { rust::String utf16_rstring = utf16_literal; ASSERT(utf8_rstring == utf16_rstring); + const char *bad_utf8_literal = "test\x80"; + const char16_t *bad_utf16_literal = u"test\xDD1E"; + rust::String bad_utf8_rstring = rust::String::lossy(bad_utf8_literal); + rust::String bad_utf16_rstring = rust::String::lossy(bad_utf16_literal); + ASSERT(bad_utf8_rstring == bad_utf16_rstring); + rust::Vec<int> vec1{1, 2}; rust::Vec<int> vec2{3, 4}; swap(vec1, vec2); diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h index b624d393..dc02e4ff 100644 --- a/tests/ffi/tests.h +++ b/tests/ffi/tests.h @@ -84,6 +84,8 @@ struct Borrow { const std::string &s; }; +typedef char Buffer[12]; + size_t c_return_primitive(); Shared c_return_shared(); ::A::AShared c_return_ns_shared(); @@ -100,6 +102,7 @@ rust::Str c_return_str(const Shared &shared); rust::Slice<const char> c_return_slice_char(const Shared &shared); rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice); rust::String c_return_rust_string(); +rust::String c_return_rust_string_lossy(); std::unique_ptr<std::string> c_return_unique_ptr_string(); std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8(); std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64(); @@ -108,10 +111,11 @@ std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared(); std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque(); const std::vector<uint8_t> &c_return_ref_vector(const C &c); std::vector<uint8_t> &c_return_mut_vector(C &c); -rust::Vec<uint8_t> c_return_rust_vec(); +rust::Vec<uint8_t> c_return_rust_vec_u8(); const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c); rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c); rust::Vec<rust::String> c_return_rust_vec_string(); +rust::Vec<bool> c_return_rust_vec_bool(); size_t c_return_identity(size_t n); size_t c_return_sum(size_t n1, size_t n2); Enum c_return_enum(uint16_t n); @@ -152,6 +156,8 @@ void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v); void c_take_rust_vec_string(rust::Vec<rust::String> v); void c_take_rust_vec_shared_index(rust::Vec<Shared> v); void c_take_rust_vec_shared_push(rust::Vec<Shared> v); +void c_take_rust_vec_shared_truncate(rust::Vec<Shared> v); +void c_take_rust_vec_shared_clear(rust::Vec<Shared> v); void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v); void c_take_rust_vec_shared_sort(rust::Vec<Shared> v); void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v); diff --git a/tests/test.rs b/tests/test.rs index 1f0b1660..bcf0a2cd 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,5 +1,6 @@ #![allow( clippy::assertions_on_constants, + clippy::assertions_on_result_states, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::float_cmp, @@ -51,6 +52,7 @@ fn test_c_return() { cast::c_char_to_unsigned(ffi::c_return_slice_char(&shared)), ); assert_eq!("2020", ffi::c_return_rust_string()); + assert_eq!("Hello \u{fffd}World", ffi::c_return_rust_string_lossy()); assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap()); assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len()); assert_eq!( @@ -69,6 +71,8 @@ fn test_c_return() { .map(|o| o.z) .sum(), ); + assert_eq!(b"\x02\0\x02\0"[..], ffi::c_return_rust_vec_u8()); + assert_eq!([true, true, false][..], ffi::c_return_rust_vec_bool()); assert_eq!(2020, ffi::c_return_identity(2020)); assert_eq!(2021, ffi::c_return_sum(2020, 1)); match ffi::c_return_enum(0) { @@ -167,6 +171,10 @@ fn test_c_take() { check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone())); check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone())); check!(ffi::c_take_rust_vec_shared_push(shared_test_vec.clone())); + check!(ffi::c_take_rust_vec_shared_truncate( + shared_test_vec.clone() + )); + check!(ffi::c_take_rust_vec_shared_clear(shared_test_vec.clone())); check!(ffi::c_take_rust_vec_shared_forward_iterator( shared_test_vec, )); @@ -256,7 +264,10 @@ fn test_c_method_calls() { assert_eq!(2023, *ffi::Shared { z: 2023 }.c_method_mut_on_shared()); let val = 42; - let mut array = ffi::Array { a: [0, 0, 0, 0] }; + let mut array = ffi::Array { + a: [0, 0, 0, 0], + b: ffi::Buffer::default(), + }; array.c_set_array(val); assert_eq!(array.a.len() as i32 * val, array.r_get_array_sum()); } diff --git a/tests/ui/array_len_expr.stderr b/tests/ui/array_len_expr.stderr index 4b45a0b9..c58cfbc2 100644 --- a/tests/ui/array_len_expr.stderr +++ b/tests/ui/array_len_expr.stderr @@ -1,17 +1,17 @@ error: array length must be an integer literal - --> $DIR/array_len_expr.rs:4:28 + --> tests/ui/array_len_expr.rs:4:28 | 4 | arraystr: [String; "13"], | ^^^^ error: unsupported expression, array length must be an integer literal - --> $DIR/array_len_expr.rs:5:28 + --> tests/ui/array_len_expr.rs:5:28 | 5 | arraysub: [String; 15 - 1], | ^^^^^^ error: array with zero size is not supported - --> $DIR/array_len_expr.rs:6:20 + --> tests/ui/array_len_expr.rs:6:20 | 6 | arrayzero: [String; 0], | ^^^^^^^^^^^ diff --git a/tests/ui/array_len_suffix.stderr b/tests/ui/array_len_suffix.stderr index 143bcb04..1dde790e 100644 --- a/tests/ui/array_len_suffix.stderr +++ b/tests/ui/array_len_suffix.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/array_len_suffix.rs:4:32 + --> tests/ui/array_len_suffix.rs:4:32 | 4 | fn array() -> [String; 12u16]; | ^^^^^ expected `usize`, found `u16` diff --git a/tests/ui/async_fn.rs b/tests/ui/async_fn.rs index 69f26421..4e663a0b 100644 --- a/tests/ui/async_fn.rs +++ b/tests/ui/async_fn.rs @@ -3,6 +3,10 @@ mod ffi { extern "Rust" { async fn f(); } + + extern "C++" { + async fn g(); + } } async fn f() {} diff --git a/tests/ui/async_fn.stderr b/tests/ui/async_fn.stderr index dedec7bb..78108650 100644 --- a/tests/ui/async_fn.stderr +++ b/tests/ui/async_fn.stderr @@ -1,5 +1,11 @@ -error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach - --> $DIR/async_fn.rs:4:9 +error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; eventually what you wrote will work but it isn't integrated into the cxx::bridge macro yet + --> tests/ui/async_fn.rs:4:9 | 4 | async fn f(); | ^^^^^^^^^^^^^ + +error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; eventually what you wrote will work but it isn't integrated into the cxx::bridge macro yet + --> tests/ui/async_fn.rs:8:9 + | +8 | async fn g(); + | ^^^^^^^^^^^^^ diff --git a/tests/ui/bad_explicit_impl.stderr b/tests/ui/bad_explicit_impl.stderr index cd0a3173..c4748f42 100644 --- a/tests/ui/bad_explicit_impl.stderr +++ b/tests/ui/bad_explicit_impl.stderr @@ -1,5 +1,5 @@ error: unsupported Self type of explicit impl - --> $DIR/bad_explicit_impl.rs:7:5 + --> tests/ui/bad_explicit_impl.rs:7:5 | 7 | impl fn() -> &S {} | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr index 7288c93b..254c7bb4 100644 --- a/tests/ui/by_value_not_supported.stderr +++ b/tests/ui/by_value_not_supported.stderr @@ -1,59 +1,59 @@ error: using opaque C++ type by value is not supported - --> $DIR/by_value_not_supported.rs:4:9 + --> tests/ui/by_value_not_supported.rs:4:9 | 4 | c: C, | ^^^^ error: using opaque Rust type by value is not supported - --> $DIR/by_value_not_supported.rs:5:9 + --> tests/ui/by_value_not_supported.rs:5:9 | 5 | r: R, | ^^^^ error: using C++ string by value is not supported - --> $DIR/by_value_not_supported.rs:6:9 + --> tests/ui/by_value_not_supported.rs:6:9 | 6 | s: CxxString, | ^^^^^^^^^^^^ error: needs a cxx::ExternType impl in order to be used as a field of `S`, argument of `f` or return value of `f` - --> $DIR/by_value_not_supported.rs:10:9 + --> tests/ui/by_value_not_supported.rs:10:9 | 10 | type C; | ^^^^^^ error: passing opaque C++ type by value is not supported - --> $DIR/by_value_not_supported.rs:16:14 + --> tests/ui/by_value_not_supported.rs:16:14 | 16 | fn f(c: C) -> C; | ^^^^ error: returning opaque C++ type by value is not supported - --> $DIR/by_value_not_supported.rs:16:23 + --> tests/ui/by_value_not_supported.rs:16:23 | 16 | fn f(c: C) -> C; | ^ error: passing opaque Rust type by value is not supported - --> $DIR/by_value_not_supported.rs:17:14 + --> tests/ui/by_value_not_supported.rs:17:14 | 17 | fn g(r: R) -> R; | ^^^^ error: returning opaque Rust type by value is not supported - --> $DIR/by_value_not_supported.rs:17:23 + --> tests/ui/by_value_not_supported.rs:17:23 | 17 | fn g(r: R) -> R; | ^ error: passing C++ string by value is not supported - --> $DIR/by_value_not_supported.rs:18:14 + --> tests/ui/by_value_not_supported.rs:18:14 | 18 | fn h(s: CxxString) -> CxxString; | ^^^^^^^^^^^^ error: returning C++ string by value is not supported - --> $DIR/by_value_not_supported.rs:18:31 + --> tests/ui/by_value_not_supported.rs:18:31 | 18 | fn h(s: CxxString) -> CxxString; | ^^^^^^^^^ diff --git a/tests/ui/const_fn.stderr b/tests/ui/const_fn.stderr index a62ca837..2dd6608a 100644 --- a/tests/ui/const_fn.stderr +++ b/tests/ui/const_fn.stderr @@ -1,5 +1,5 @@ error: const extern function is not supported - --> $DIR/const_fn.rs:4:9 + --> tests/ui/const_fn.rs:4:9 | 4 | const fn f(); | ^^^^^^^^^^^^^ diff --git a/tests/ui/data_enums.stderr b/tests/ui/data_enums.stderr index c78bce55..d8aa09e3 100644 --- a/tests/ui/data_enums.stderr +++ b/tests/ui/data_enums.stderr @@ -1,5 +1,5 @@ error: enums with data are not supported yet - --> $DIR/data_enums.rs:4:9 + --> tests/ui/data_enums.rs:4:9 | 4 | Field(u64), | ^^^^^^^^^^ diff --git a/tests/ui/deny_elided_lifetimes.rs b/tests/ui/deny_elided_lifetimes.rs new file mode 100644 index 00000000..0ab3f750 --- /dev/null +++ b/tests/ui/deny_elided_lifetimes.rs @@ -0,0 +1,27 @@ +#![deny(elided_lifetimes_in_paths)] + +#[cxx::bridge] +mod ffi { + #[derive(PartialEq, PartialOrd, Hash)] + struct Struct<'a> { + reference: &'a i32, + } + + extern "Rust" { + type Rust<'a>; + } + + unsafe extern "C++" { + type Cpp<'a>; + + fn lifetime_named<'a>(s: &'a i32) -> UniquePtr<Cpp<'a>>; + + fn lifetime_underscore(s: &i32) -> UniquePtr<Cpp<'_>>; + + fn lifetime_elided(s: &i32) -> UniquePtr<Cpp>; + } +} + +pub struct Rust<'a>(&'a i32); + +fn main() {} diff --git a/tests/ui/deny_elided_lifetimes.stderr b/tests/ui/deny_elided_lifetimes.stderr new file mode 100644 index 00000000..857bb5b7 --- /dev/null +++ b/tests/ui/deny_elided_lifetimes.stderr @@ -0,0 +1,15 @@ +error: hidden lifetime parameters in types are deprecated + --> tests/ui/deny_elided_lifetimes.rs:21:50 + | +21 | fn lifetime_elided(s: &i32) -> UniquePtr<Cpp>; + | ^^^ expected lifetime parameter + | +note: the lint level is defined here + --> tests/ui/deny_elided_lifetimes.rs:1:9 + | +1 | #![deny(elided_lifetimes_in_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +21 | fn lifetime_elided(s: &i32) -> UniquePtr<Cpp<'_>>; + | ++++ diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr index e7aadfbe..54ab987b 100644 --- a/tests/ui/deny_missing_docs.stderr +++ b/tests/ui/deny_missing_docs.stderr @@ -1,47 +1,47 @@ error: missing documentation for a struct - --> $DIR/deny_missing_docs.rs:11:5 + --> tests/ui/deny_missing_docs.rs:11:5 | 11 | pub struct UndocumentedStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/deny_missing_docs.rs:6:9 + --> tests/ui/deny_missing_docs.rs:6:9 | 6 | #![deny(missing_docs)] | ^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/deny_missing_docs.rs:12:9 + --> tests/ui/deny_missing_docs.rs:12:9 | 12 | pub undocumented_field: u8, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct - --> $DIR/deny_missing_docs.rs:21:5 + --> tests/ui/deny_missing_docs.rs:21:5 | 21 | pub enum UndocumentedEnum { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated constant - --> $DIR/deny_missing_docs.rs:22:9 + --> tests/ui/deny_missing_docs.rs:22:9 | 22 | UndocumentedVariant = 0, | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct - --> $DIR/deny_missing_docs.rs:44:9 + --> tests/ui/deny_missing_docs.rs:44:9 | 44 | pub type UndocumentedForeignType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a type alias - --> $DIR/deny_missing_docs.rs:49:9 + --> tests/ui/deny_missing_docs.rs:49:9 | 49 | pub type UndocumentedTypeAlias = crate::bindgen::UndocumentedTypeAlias; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/deny_missing_docs.rs:54:9 + --> tests/ui/deny_missing_docs.rs:54:9 | 54 | pub fn undocumented_foreign_fn() -> u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/derive_duplicate.stderr b/tests/ui/derive_duplicate.stderr index ce271632..75920862 100644 --- a/tests/ui/derive_duplicate.stderr +++ b/tests/ui/derive_duplicate.stderr @@ -1,7 +1,7 @@ -error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `ffi::Struct` - --> $DIR/derive_duplicate.rs:3:21 +error[E0119]: conflicting implementations of trait `Clone` for type `Struct` + --> tests/ui/derive_duplicate.rs:3:21 | 3 | #[derive(Clone, Clone)] - | ----- ^^^^^ conflicting implementation for `ffi::Struct` + | ----- ^^^^^ conflicting implementation for `Struct` | | | first implementation here diff --git a/tests/ui/derive_noncopy.stderr b/tests/ui/derive_noncopy.stderr index d6410280..419b0f22 100644 --- a/tests/ui/derive_noncopy.stderr +++ b/tests/ui/derive_noncopy.stderr @@ -1,8 +1,7 @@ error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/derive_noncopy.rs:3:14 + --> tests/ui/derive_noncopy.rs:4:12 | -3 | #[derive(Copy)] - | ^^^^ 4 | struct TryCopy { + | ^^^^^^^ 5 | other: Other, | ------------ this field does not implement `Copy` diff --git a/tests/ui/drop_shared.stderr b/tests/ui/drop_shared.stderr index f2724e35..41a5287f 100644 --- a/tests/ui/drop_shared.stderr +++ b/tests/ui/drop_shared.stderr @@ -1,8 +1,8 @@ -error[E0119]: conflicting implementations of trait `ffi::_::forbid::Drop` for type `ffi::Shared` - --> $DIR/drop_shared.rs:3:5 +error[E0119]: conflicting implementations of trait `forbid::Drop` for type `Shared` + --> tests/ui/drop_shared.rs:3:5 | 1 | #[cxx::bridge] | -------------- first implementation here 2 | mod ffi { 3 | struct Shared { - | ^^^^^^^^^^^^^ conflicting implementation for `ffi::Shared` + | ^^^^^^^^^^^^^ conflicting implementation for `Shared` diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr index 0556da9a..60d3b5da 100644 --- a/tests/ui/empty_enum.stderr +++ b/tests/ui/empty_enum.stderr @@ -1,5 +1,5 @@ error: explicit #[repr(...)] is required for enum without any variants - --> $DIR/empty_enum.rs:3:5 + --> tests/ui/empty_enum.rs:3:5 | 3 | enum A {} | ^^^^^^^^^ diff --git a/tests/ui/empty_struct.stderr b/tests/ui/empty_struct.stderr index 612476bd..f6fbfc11 100644 --- a/tests/ui/empty_struct.stderr +++ b/tests/ui/empty_struct.stderr @@ -1,5 +1,5 @@ error: structs without any fields are not supported - --> $DIR/empty_struct.rs:3:5 + --> tests/ui/empty_struct.rs:3:5 | 3 | struct Empty {} | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/enum_inconsistent.stderr b/tests/ui/enum_inconsistent.stderr index c5b427a8..d6d7837e 100644 --- a/tests/ui/enum_inconsistent.stderr +++ b/tests/ui/enum_inconsistent.stderr @@ -1,5 +1,5 @@ error: expected u16, found i64 - --> $DIR/enum_inconsistent.rs:5:9 + --> tests/ui/enum_inconsistent.rs:5:9 | 5 | B = 2i64, | ^^^^^^^^ diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr index f43678f7..5808d6f8 100644 --- a/tests/ui/enum_match_without_wildcard.stderr +++ b/tests/ui/enum_match_without_wildcard.stderr @@ -1,11 +1,17 @@ -error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered - --> $DIR/enum_match_without_wildcard.rs:12:11 +error[E0004]: non-exhaustive patterns: `ffi::A { repr: 2_u8..=u8::MAX }` not covered + --> tests/ui/enum_match_without_wildcard.rs:12:11 | -3 | enum A { - | ------ `ffi::A` defined here -... 12 | match a { - | ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered + | ^ pattern `ffi::A { repr: 2_u8..=u8::MAX }` not covered + | +note: `ffi::A` defined here + --> tests/ui/enum_match_without_wildcard.rs:3:10 | - = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms +3 | enum A { + | ^ = note: the matched value is of type `ffi::A` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +14 ~ ffi::A::FieldB => 2021, +15 ~ ffi::A { repr: 2_u8..=u8::MAX } => todo!(), + | diff --git a/tests/ui/enum_out_of_bounds.stderr b/tests/ui/enum_out_of_bounds.stderr index 5d02e206..3244b6a7 100644 --- a/tests/ui/enum_out_of_bounds.stderr +++ b/tests/ui/enum_out_of_bounds.stderr @@ -1,11 +1,11 @@ error: discriminant value `18446744073709551615` is outside the limits of u32 - --> $DIR/enum_out_of_bounds.rs:5:9 + --> tests/ui/enum_out_of_bounds.rs:5:9 | 5 | A = 0xFFFF_FFFF_FFFF_FFFF, | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: discriminant value `2000` is outside the limits of u8 - --> $DIR/enum_out_of_bounds.rs:9:9 + --> tests/ui/enum_out_of_bounds.rs:9:9 | 9 | B = 1u8, | ^^^^^^^ diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr index ed58b61c..76c37bb0 100644 --- a/tests/ui/enum_overflows.stderr +++ b/tests/ui/enum_overflows.stderr @@ -1,5 +1,5 @@ error: discriminant overflow on value after 18446744073709551615 - --> $DIR/enum_overflows.rs:13:9 + --> tests/ui/enum_overflows.rs:13:9 | 13 | F, | ^ diff --git a/tests/ui/enum_receiver.stderr b/tests/ui/enum_receiver.stderr index e09b4e39..ace76776 100644 --- a/tests/ui/enum_receiver.stderr +++ b/tests/ui/enum_receiver.stderr @@ -1,5 +1,5 @@ error: unsupported receiver type; C++ does not allow member functions on enums - --> $DIR/enum_receiver.rs:7:20 + --> tests/ui/enum_receiver.rs:7:20 | 7 | fn f(self: &Enum); | ^^^^^ diff --git a/tests/ui/enum_unsatisfiable.stderr b/tests/ui/enum_unsatisfiable.stderr index 99852ca6..e2b37bdd 100644 --- a/tests/ui/enum_unsatisfiable.stderr +++ b/tests/ui/enum_unsatisfiable.stderr @@ -1,5 +1,5 @@ error: these discriminant values do not fit in any supported enum repr type - --> $DIR/enum_unsatisfiable.rs:3:5 + --> tests/ui/enum_unsatisfiable.rs:3:5 | 3 | / enum Bad { 4 | | A = -0xFFFF_FFFF_FFFF_FFFF, diff --git a/tests/ui/expected_named.stderr b/tests/ui/expected_named.stderr index dab3b5a3..0068bdf3 100644 --- a/tests/ui/expected_named.stderr +++ b/tests/ui/expected_named.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/expected_named.rs:5:36 + --> tests/ui/expected_named.rs:5:36 | 5 | fn borrowed() -> UniquePtr<Borrowed>; | ^^^^^^^^ expected named lifetime parameter @@ -8,4 +8,4 @@ error[E0106]: missing lifetime specifier help: consider using the `'static` lifetime | 5 | fn borrowed() -> UniquePtr<Borrowed<'static>>; - | ~~~~~~~~~~~~~~~~~ + | +++++++++ diff --git a/tests/ui/extern_fn_abi.stderr b/tests/ui/extern_fn_abi.stderr index 3abf47ab..32ef9c3e 100644 --- a/tests/ui/extern_fn_abi.stderr +++ b/tests/ui/extern_fn_abi.stderr @@ -1,5 +1,5 @@ error: explicit ABI on extern function is not supported - --> $DIR/extern_fn_abi.rs:4:9 + --> tests/ui/extern_fn_abi.rs:4:9 | 4 | extern "Java" fn f(); | ^^^^^^^^^^^^^ diff --git a/tests/ui/extern_type_bound.stderr b/tests/ui/extern_type_bound.stderr index ca07ef7f..1d6796bc 100644 --- a/tests/ui/extern_type_bound.stderr +++ b/tests/ui/extern_type_bound.stderr @@ -1,11 +1,11 @@ error: extern type bounds are not implemented yet - --> $DIR/extern_type_bound.rs:4:22 + --> tests/ui/extern_type_bound.rs:4:22 | 4 | type Opaque: PartialEq + PartialOrd; | ^^^^^^^^^^^^^^^^^^^^^^ error: unsupported trait - --> $DIR/extern_type_bound.rs:11:22 + --> tests/ui/extern_type_bound.rs:11:22 | 11 | type Opaque: for<'de> Deserialize<'de>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/extern_type_generic.stderr b/tests/ui/extern_type_generic.stderr index 95faec6c..2b312f0e 100644 --- a/tests/ui/extern_type_generic.stderr +++ b/tests/ui/extern_type_generic.stderr @@ -1,5 +1,5 @@ error: extern type with generic type parameter is not supported yet - --> $DIR/extern_type_generic.rs:4:22 + --> tests/ui/extern_type_generic.rs:4:22 | 4 | type Generic<T>; | ^ diff --git a/tests/ui/extern_type_lifetime_bound.stderr b/tests/ui/extern_type_lifetime_bound.stderr index 8c58050a..6c3fc7f1 100644 --- a/tests/ui/extern_type_lifetime_bound.stderr +++ b/tests/ui/extern_type_lifetime_bound.stderr @@ -1,5 +1,5 @@ error: lifetime parameter with bounds is not supported yet - --> $DIR/extern_type_lifetime_bound.rs:4:26 + --> tests/ui/extern_type_lifetime_bound.rs:4:26 | 4 | type Complex<'a, 'b: 'a>; | ^^^^^^ diff --git a/tests/ui/fallible_fnptr.stderr b/tests/ui/fallible_fnptr.stderr index 1d3fbe42..4635ec8f 100644 --- a/tests/ui/fallible_fnptr.stderr +++ b/tests/ui/fallible_fnptr.stderr @@ -1,5 +1,5 @@ error: function pointer returning Result is not supported yet - --> $DIR/fallible_fnptr.rs:4:24 + --> tests/ui/fallible_fnptr.rs:4:24 | 4 | fn f(callback: fn() -> Result<()>); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/function_with_body.stderr b/tests/ui/function_with_body.stderr index c5641db8..f2078df4 100644 --- a/tests/ui/function_with_body.stderr +++ b/tests/ui/function_with_body.stderr @@ -1,5 +1,5 @@ error: expected `;` - --> $DIR/function_with_body.rs:4:16 + --> tests/ui/function_with_body.rs:4:16 | 4 | fn f() {} | ^ diff --git a/tests/ui/generic_enum.stderr b/tests/ui/generic_enum.stderr index ea83d7c8..2529af73 100644 --- a/tests/ui/generic_enum.stderr +++ b/tests/ui/generic_enum.stderr @@ -1,17 +1,17 @@ error: enum with generic parameters is not supported - --> $DIR/generic_enum.rs:3:5 + --> tests/ui/generic_enum.rs:3:5 | 3 | enum A<T> { | ^^^^^^^^^ error: enum with generic parameters is not supported - --> $DIR/generic_enum.rs:7:5 + --> tests/ui/generic_enum.rs:7:5 | 7 | enum B<T> where T: Copy { | ^^^^^^^^^ error: enum with where-clause is not supported - --> $DIR/generic_enum.rs:11:12 + --> tests/ui/generic_enum.rs:11:12 | 11 | enum C where void: Copy { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl_trait_for_type.stderr b/tests/ui/impl_trait_for_type.stderr index e05a461e..fa99de5a 100644 --- a/tests/ui/impl_trait_for_type.stderr +++ b/tests/ui/impl_trait_for_type.stderr @@ -1,5 +1,5 @@ error: unexpected impl, expected something like `impl UniquePtr<T> {}` - --> $DIR/impl_trait_for_type.rs:7:10 + --> tests/ui/impl_trait_for_type.rs:7:10 | 7 | impl UniquePtrTarget for S {} | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/include.stderr b/tests/ui/include.stderr index c85a83ea..45cc5591 100644 --- a/tests/ui/include.stderr +++ b/tests/ui/include.stderr @@ -1,29 +1,29 @@ error: unexpected token - --> $DIR/include.rs:4:28 + --> tests/ui/include.rs:4:28 | 4 | include!("path/to" what); | ^^^^ error: unexpected token - --> $DIR/include.rs:5:28 + --> tests/ui/include.rs:5:28 | 5 | include!(<path/to> what); | ^^^^ error: expected `>` - --> $DIR/include.rs:6:17 + --> tests/ui/include.rs:6:17 | 6 | include!(<path/to); | ^^^^^^^^^^ error: unexpected token in include path - --> $DIR/include.rs:7:23 + --> tests/ui/include.rs:7:23 | 7 | include!(<path[to]>); | ^^^^ error: expected "quoted/path/to" or <bracketed/path/to> - --> $DIR/include.rs:8:18 + --> tests/ui/include.rs:8:18 | 8 | include!(...); - | ^^^ + | ^ diff --git a/tests/ui/lifetime_extern_cxx.stderr b/tests/ui/lifetime_extern_cxx.stderr index 099c6ce4..a5cc3bda 100644 --- a/tests/ui/lifetime_extern_cxx.stderr +++ b/tests/ui/lifetime_extern_cxx.stderr @@ -1,5 +1,5 @@ error: extern C++ function with lifetimes must be declared in `unsafe extern "C++"` block - --> $DIR/lifetime_extern_cxx.rs:5:9 + --> tests/ui/lifetime_extern_cxx.rs:5:9 | 5 | unsafe fn f<'a>(&'a self, arg: &str) -> &'a str; | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/lifetime_extern_rust.stderr b/tests/ui/lifetime_extern_rust.stderr index 0fc806ad..b2ca4950 100644 --- a/tests/ui/lifetime_extern_rust.stderr +++ b/tests/ui/lifetime_extern_rust.stderr @@ -1,5 +1,5 @@ error: must be `unsafe fn f` in order to expose explicit lifetimes to C++ - --> $DIR/lifetime_extern_rust.rs:5:9 + --> tests/ui/lifetime_extern_rust.rs:5:9 | 5 | fn f<'a>(&'a self, arg: &str) -> &'a str; | ^^^^^^^^ diff --git a/tests/ui/missing_unsafe.stderr b/tests/ui/missing_unsafe.stderr index df1bce22..e7dcba74 100644 --- a/tests/ui/missing_unsafe.stderr +++ b/tests/ui/missing_unsafe.stderr @@ -1,7 +1,9 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/missing_unsafe.rs:4:12 + --> tests/ui/missing_unsafe.rs:4:12 | 4 | fn f(x: i32); - | ^ call to unsafe function + | ^ - items do not inherit unsafety from separate enclosing items + | | + | call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr index f736fd1f..32b8e560 100644 --- a/tests/ui/multiple_parse_error.stderr +++ b/tests/ui/multiple_parse_error.stderr @@ -1,11 +1,11 @@ error: unit structs are not supported - --> $DIR/multiple_parse_error.rs:3:5 + --> tests/ui/multiple_parse_error.rs:3:5 | 3 | struct Monad<T>; | ^^^^^^^^^^^^^^^^ error: unrecognized ABI, requires either "C++" or "Rust" - --> $DIR/multiple_parse_error.rs:5:5 + --> tests/ui/multiple_parse_error.rs:5:5 | 5 | extern "Haskell" {} | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/mut_return.stderr b/tests/ui/mut_return.stderr index e33393d8..37e947a7 100644 --- a/tests/ui/mut_return.stderr +++ b/tests/ui/mut_return.stderr @@ -1,11 +1,11 @@ error: &mut return type is not allowed unless there is a &mut argument - --> $DIR/mut_return.rs:10:9 + --> tests/ui/mut_return.rs:10:9 | 10 | fn f(t: &Thing) -> Pin<&mut CxxString>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: &mut return type is not allowed unless there is a &mut argument - --> $DIR/mut_return.rs:14:9 + --> tests/ui/mut_return.rs:14:9 | 14 | fn j(t: &Thing) -> &mut [u8]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/non_integer_discriminant_enum.stderr b/tests/ui/non_integer_discriminant_enum.stderr index 926fd905..aa4388fb 100644 --- a/tests/ui/non_integer_discriminant_enum.stderr +++ b/tests/ui/non_integer_discriminant_enum.stderr @@ -1,5 +1,5 @@ error: enums with non-integer literal discriminants are not supported yet - --> $DIR/non_integer_discriminant_enum.rs:4:9 + --> tests/ui/non_integer_discriminant_enum.rs:4:9 | 4 | Field = 2020 + 1, | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/nonempty_impl_block.stderr b/tests/ui/nonempty_impl_block.stderr index e7881bb0..6f698305 100644 --- a/tests/ui/nonempty_impl_block.stderr +++ b/tests/ui/nonempty_impl_block.stderr @@ -1,5 +1,5 @@ error: expected an empty impl block - --> $DIR/nonempty_impl_block.rs:7:23 + --> tests/ui/nonempty_impl_block.rs:7:23 | 7 | impl UniquePtr<S> { | _______________________^ diff --git a/tests/ui/nonlocal_rust_type.stderr b/tests/ui/nonlocal_rust_type.stderr index d266353c..f6cb06cb 100644 --- a/tests/ui/nonlocal_rust_type.stderr +++ b/tests/ui/nonlocal_rust_type.stderr @@ -1,5 +1,5 @@ -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/nonlocal_rust_type.rs:10:9 +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> tests/ui/nonlocal_rust_type.rs:10:9 | 10 | type OptBuilder<'a>; | ^^^^^-------------- @@ -9,11 +9,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar | = note: define and implement a trait or new type instead -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/nonlocal_rust_type.rs:14:13 +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> tests/ui/nonlocal_rust_type.rs:14:13 | 14 | rs: Box<OptBuilder<'a>>, - | ^^^^--------------- + | ^^^^-------------- | | | | | `Option` is not defined in the current crate | impl doesn't use only types from inside the current crate diff --git a/tests/ui/opaque_autotraits.stderr b/tests/ui/opaque_autotraits.stderr index 15a2b64c..521d9864 100644 --- a/tests/ui/opaque_autotraits.stderr +++ b/tests/ui/opaque_autotraits.stderr @@ -1,59 +1,59 @@ error[E0277]: `*const cxx::void` cannot be sent between threads safely - --> $DIR/opaque_autotraits.rs:13:5 + --> tests/ui/opaque_autotraits.rs:13:19 | 13 | assert_send::<ffi::Opaque>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const cxx::void` cannot be sent between threads safely + | ^^^^^^^^^^^ `*const cxx::void` cannot be sent between threads safely | = help: within `ffi::Opaque`, the trait `Send` is not implemented for `*const cxx::void` = note: required because it appears within the type `[*const cxx::void; 0]` = note: required because it appears within the type `cxx::private::Opaque` note: required because it appears within the type `ffi::Opaque` - --> $DIR/opaque_autotraits.rs:4:14 + --> tests/ui/opaque_autotraits.rs:4:14 | 4 | type Opaque; | ^^^^^^ note: required by a bound in `assert_send` - --> $DIR/opaque_autotraits.rs:8:19 + --> tests/ui/opaque_autotraits.rs:8:19 | 8 | fn assert_send<T: Send>() {} | ^^^^ required by this bound in `assert_send` error[E0277]: `*const cxx::void` cannot be shared between threads safely - --> $DIR/opaque_autotraits.rs:14:5 + --> tests/ui/opaque_autotraits.rs:14:19 | 14 | assert_sync::<ffi::Opaque>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const cxx::void` cannot be shared between threads safely + | ^^^^^^^^^^^ `*const cxx::void` cannot be shared between threads safely | = help: within `ffi::Opaque`, the trait `Sync` is not implemented for `*const cxx::void` = note: required because it appears within the type `[*const cxx::void; 0]` = note: required because it appears within the type `cxx::private::Opaque` note: required because it appears within the type `ffi::Opaque` - --> $DIR/opaque_autotraits.rs:4:14 + --> tests/ui/opaque_autotraits.rs:4:14 | 4 | type Opaque; | ^^^^^^ note: required by a bound in `assert_sync` - --> $DIR/opaque_autotraits.rs:9:19 + --> tests/ui/opaque_autotraits.rs:9:19 | 9 | fn assert_sync<T: Sync>() {} | ^^^^ required by this bound in `assert_sync` error[E0277]: `PhantomPinned` cannot be unpinned - --> $DIR/opaque_autotraits.rs:15:5 + --> tests/ui/opaque_autotraits.rs:15:20 | 15 | assert_unpin::<ffi::Opaque>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ffi::Opaque`, the trait `Unpin` is not implemented for `PhantomPinned` + | ^^^^^^^^^^^ within `ffi::Opaque`, the trait `Unpin` is not implemented for `PhantomPinned` | = note: consider using `Box::pin` = note: required because it appears within the type `PhantomData<PhantomPinned>` = note: required because it appears within the type `cxx::private::Opaque` note: required because it appears within the type `ffi::Opaque` - --> $DIR/opaque_autotraits.rs:4:14 + --> tests/ui/opaque_autotraits.rs:4:14 | 4 | type Opaque; | ^^^^^^ note: required by a bound in `assert_unpin` - --> $DIR/opaque_autotraits.rs:10:20 + --> tests/ui/opaque_autotraits.rs:10:20 | 10 | fn assert_unpin<T: Unpin>() {} | ^^^^^ required by this bound in `assert_unpin` diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr index b50a2699..85be4af3 100644 --- a/tests/ui/opaque_not_sized.stderr +++ b/tests/ui/opaque_not_sized.stderr @@ -1,17 +1,17 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/opaque_not_sized.rs:4:14 + --> tests/ui/opaque_not_sized.rs:4:14 | 4 | type TypeR; | ^^^^^ doesn't have a size known at compile-time | = help: within `TypeR`, the trait `Sized` is not implemented for `str` note: required because it appears within the type `TypeR` - --> $DIR/opaque_not_sized.rs:8:8 + --> tests/ui/opaque_not_sized.rs:8:8 | 8 | struct TypeR(str); | ^^^^^ note: required by a bound in `__AssertSized` - --> $DIR/opaque_not_sized.rs:4:9 + --> tests/ui/opaque_not_sized.rs:4:9 | 4 | type TypeR; | ^^^^^^^^^^^ required by this bound in `__AssertSized` diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr index 95af3cd9..8a5e019b 100644 --- a/tests/ui/pin_mut_opaque.stderr +++ b/tests/ui/pin_mut_opaque.stderr @@ -1,35 +1,35 @@ error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque> - --> $DIR/pin_mut_opaque.rs:5:19 + --> tests/ui/pin_mut_opaque.rs:5:19 | 5 | fn f(arg: &mut Opaque); | ^^^^^^^^^^^ error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString> - --> $DIR/pin_mut_opaque.rs:8:17 + --> tests/ui/pin_mut_opaque.rs:8:17 | 8 | fn s(s: &mut CxxString); | ^^^^^^^^^^^^^^ error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>> - --> $DIR/pin_mut_opaque.rs:9:17 + --> tests/ui/pin_mut_opaque.rs:9:17 | 9 | fn v(v: &mut CxxVector<u8>); | ^^^^^^^^^^^^^^^^^^ error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference in signature of `f`, `g`, `h` - --> $DIR/pin_mut_opaque.rs:4:9 + --> tests/ui/pin_mut_opaque.rs:4:9 | 4 | type Opaque; | ^^^^^^^^^^^ error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` - --> $DIR/pin_mut_opaque.rs:6:14 + --> tests/ui/pin_mut_opaque.rs:6:14 | 6 | fn g(&mut self); | ^^^^^^^^^ error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` - --> $DIR/pin_mut_opaque.rs:7:20 + --> tests/ui/pin_mut_opaque.rs:7:20 | 7 | fn h(self: &mut Opaque); | ^^^^^^^^^^^ diff --git a/tests/ui/ptr_in_fnptr.stderr b/tests/ui/ptr_in_fnptr.stderr index 372d4cd9..f429b1bd 100644 --- a/tests/ui/ptr_in_fnptr.stderr +++ b/tests/ui/ptr_in_fnptr.stderr @@ -1,5 +1,5 @@ error: pointer argument requires that the function pointer be marked unsafe - --> $DIR/ptr_in_fnptr.rs:4:27 + --> tests/ui/ptr_in_fnptr.rs:4:27 | 4 | fn f(callback: fn(p: *const u8)); | ^^^^^^^^^^^^ diff --git a/tests/ui/ptr_missing_unsafe.stderr b/tests/ui/ptr_missing_unsafe.stderr index 65f53a98..d65481bc 100644 --- a/tests/ui/ptr_missing_unsafe.stderr +++ b/tests/ui/ptr_missing_unsafe.stderr @@ -1,5 +1,5 @@ error: pointer argument requires that the function be marked unsafe - --> $DIR/ptr_missing_unsafe.rs:6:27 + --> tests/ui/ptr_missing_unsafe.rs:6:27 | 6 | fn not_unsafe_ptr(c: *mut C); | ^^^^^^^^^ diff --git a/tests/ui/ptr_no_const_mut.stderr b/tests/ui/ptr_no_const_mut.stderr index 8a391852..4b1bf06f 100644 --- a/tests/ui/ptr_no_const_mut.stderr +++ b/tests/ui/ptr_no_const_mut.stderr @@ -1,13 +1,18 @@ -error: expected mut or const in raw pointer type - --> $DIR/ptr_no_const_mut.rs:6:43 +error: expected `mut` or `const` keyword in raw pointer type + --> tests/ui/ptr_no_const_mut.rs:6:43 | 6 | fn get_neither_const_nor_mut() -> *C; - | ^ expected mut or const in raw pointer type + | ^ | - = help: use `*mut T` or `*const T` as appropriate +help: add `mut` or `const` here + | +6 | fn get_neither_const_nor_mut() -> *const C; + | +++++ +6 | fn get_neither_const_nor_mut() -> *mut C; + | +++ error: expected `const` or `mut` - --> $DIR/ptr_no_const_mut.rs:6:44 + --> tests/ui/ptr_no_const_mut.rs:6:44 | 6 | fn get_neither_const_nor_mut() -> *C; | ^ diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr index a3e93434..ea1dafd8 100644 --- a/tests/ui/ptr_unsupported.stderr +++ b/tests/ui/ptr_unsupported.stderr @@ -1,17 +1,17 @@ error: C++ does not allow pointer to reference as a type - --> $DIR/ptr_unsupported.rs:6:38 + --> tests/ui/ptr_unsupported.rs:6:38 | 6 | fn get_ptr_to_reference() -> *mut &C; | ^^^^^^^ error: unsupported unique_ptr target type - --> $DIR/ptr_unsupported.rs:7:38 + --> tests/ui/ptr_unsupported.rs:7:38 | 7 | fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>; | ^^^^^^^^^^^^^^^^^ error: unsupported vector element type - --> $DIR/ptr_unsupported.rs:8:45 + --> tests/ui/ptr_unsupported.rs:8:45 | 8 | fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/raw_ident_namespace.rs b/tests/ui/raw_ident_namespace.rs new file mode 100644 index 00000000..2c8286c7 --- /dev/null +++ b/tests/ui/raw_ident_namespace.rs @@ -0,0 +1,53 @@ +use cxx::{type_id, ExternType}; + +#[repr(transparent)] +pub struct QuotedRaw(usize); + +unsafe impl ExternType for QuotedRaw { + type Id = type_id!("org::r#box::implementation::QuotedRaw"); + type Kind = cxx::kind::Trivial; +} + +#[repr(transparent)] +pub struct QuotedKeyword(usize); + +unsafe impl ExternType for QuotedKeyword { + type Id = type_id!("org::box::implementation::QuotedKeyword"); + type Kind = cxx::kind::Trivial; +} + +#[repr(transparent)] +pub struct UnquotedRaw(usize); + +unsafe impl ExternType for UnquotedRaw { + type Id = type_id!(org::r#box::implementation::UnquotedRaw); + type Kind = cxx::kind::Trivial; +} + +#[repr(transparent)] +pub struct UnquotedKeyword(usize); + +unsafe impl ExternType for UnquotedKeyword { + type Id = type_id!(org::box::implementation::UnquotedKeyword); + type Kind = cxx::kind::Trivial; +} + +#[cxx::bridge] +pub mod ffi { + extern "C++" { + #[namespace = "org::r#box::implementation"] + type QuotedRaw = crate::QuotedRaw; + + #[namespace = "org::box::implementation"] + type QuotedKeyword = crate::QuotedKeyword; + + #[namespace = org::r#box::implementation] + type UnquotedRaw = crate::UnquotedRaw; + + // Not allowed by rustc (independent of cxx): + // #[namespace = org::box::implementation] + // type UnquotedKeyword = crate::UnquotedKeyword; + } +} + +fn main() {} diff --git a/tests/ui/raw_ident_namespace.stderr b/tests/ui/raw_ident_namespace.stderr new file mode 100644 index 00000000..86c8b6fd --- /dev/null +++ b/tests/ui/raw_ident_namespace.stderr @@ -0,0 +1,11 @@ +error: raw identifier `r#box` is not allowed in a quoted namespace; use `box`, or remove quotes + --> tests/ui/raw_ident_namespace.rs:7:24 + | +7 | type Id = type_id!("org::r#box::implementation::QuotedRaw"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: raw identifier `r#box` is not allowed in a quoted namespace; use `box`, or remove quotes + --> tests/ui/raw_ident_namespace.rs:38:23 + | +38 | #[namespace = "org::r#box::implementation"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/reference_to_reference.stderr b/tests/ui/reference_to_reference.stderr index d4069c18..765e4427 100644 --- a/tests/ui/reference_to_reference.stderr +++ b/tests/ui/reference_to_reference.stderr @@ -1,11 +1,11 @@ error: C++ does not allow references to references - --> $DIR/reference_to_reference.rs:5:23 + --> tests/ui/reference_to_reference.rs:5:23 | 5 | fn repro_c(t: &&ThingC); | ^^^^^^^^ error: C++ does not allow references to references - --> $DIR/reference_to_reference.rs:9:23 + --> tests/ui/reference_to_reference.rs:9:23 | 9 | fn repro_r(t: &&ThingR); | ^^^^^^^^ diff --git a/tests/ui/reserved_lifetime.stderr b/tests/ui/reserved_lifetime.stderr index 723572d9..e9582671 100644 --- a/tests/ui/reserved_lifetime.stderr +++ b/tests/ui/reserved_lifetime.stderr @@ -1,5 +1,5 @@ error[E0262]: invalid lifetime parameter name: `'static` - --> $DIR/reserved_lifetime.rs:6:19 + --> tests/ui/reserved_lifetime.rs:6:19 | 6 | fn logger<'static>() -> Pin<&'static Logger>; | ^^^^^^^ 'static is a reserved lifetime name diff --git a/tests/ui/reserved_name.stderr b/tests/ui/reserved_name.stderr index 6684771a..7636f872 100644 --- a/tests/ui/reserved_name.stderr +++ b/tests/ui/reserved_name.stderr @@ -1,17 +1,17 @@ error: reserved name - --> $DIR/reserved_name.rs:3:12 + --> tests/ui/reserved_name.rs:3:12 | 3 | struct UniquePtr { | ^^^^^^^^^ error: reserved name - --> $DIR/reserved_name.rs:8:14 + --> tests/ui/reserved_name.rs:8:14 | 8 | type Box; | ^^^ error: reserved name - --> $DIR/reserved_name.rs:12:14 + --> tests/ui/reserved_name.rs:12:14 | 12 | type String; | ^^^^^^ diff --git a/tests/ui/result_no_display.stderr b/tests/ui/result_no_display.stderr index d0502f9b..44d4b31d 100644 --- a/tests/ui/result_no_display.stderr +++ b/tests/ui/result_no_display.stderr @@ -1,5 +1,5 @@ error[E0277]: `NonError` doesn't implement `std::fmt::Display` - --> $DIR/result_no_display.rs:4:19 + --> tests/ui/result_no_display.rs:4:19 | 4 | fn f() -> Result<()>; | ^^^^^^^^^^ `NonError` cannot be formatted with the default formatter diff --git a/tests/ui/root_namespace.stderr b/tests/ui/root_namespace.stderr index a9c01a2e..b834d91a 100644 --- a/tests/ui/root_namespace.stderr +++ b/tests/ui/root_namespace.stderr @@ -1,5 +1,5 @@ error: expected expression, found `]` - --> $DIR/root_namespace.rs:9:19 + --> tests/ui/root_namespace.rs:9:19 | 9 | #[namespace = ] | ^ expected expression diff --git a/tests/ui/rust_pinned.stderr b/tests/ui/rust_pinned.stderr index 8857681c..a0fc0338 100644 --- a/tests/ui/rust_pinned.stderr +++ b/tests/ui/rust_pinned.stderr @@ -1,17 +1,17 @@ error[E0277]: `PhantomPinned` cannot be unpinned - --> $DIR/rust_pinned.rs:6:14 + --> tests/ui/rust_pinned.rs:6:14 | 6 | type Pinned; | ^^^^^^ within `Pinned`, the trait `Unpin` is not implemented for `PhantomPinned` | = note: consider using `Box::pin` note: required because it appears within the type `Pinned` - --> $DIR/rust_pinned.rs:10:12 + --> tests/ui/rust_pinned.rs:10:12 | 10 | pub struct Pinned { | ^^^^^^ note: required by a bound in `__AssertUnpin` - --> $DIR/rust_pinned.rs:6:9 + --> tests/ui/rust_pinned.rs:6:9 | 6 | type Pinned; | ^^^^^^^^^^^^ required by this bound in `__AssertUnpin` diff --git a/tests/ui/slice_of_type_alias.stderr b/tests/ui/slice_of_type_alias.stderr index aff06f8d..9339da37 100644 --- a/tests/ui/slice_of_type_alias.stderr +++ b/tests/ui/slice_of_type_alias.stderr @@ -1,11 +1,16 @@ error[E0271]: type mismatch resolving `<ElementOpaque as ExternType>::Kind == Trivial` - --> $DIR/slice_of_type_alias.rs:13:9 - | -13 | type ElementOpaque = crate::ElementOpaque; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque` - | + --> tests/ui/slice_of_type_alias.rs:13:14 + | +13 | type ElementOpaque = crate::ElementOpaque; + | ^^^^^^^^^^^^^ type mismatch resolving `<ElementOpaque as ExternType>::Kind == Trivial` + | +note: expected this to be `Trivial` + --> tests/ui/slice_of_type_alias.rs:27:17 + | +27 | type Kind = cxx::kind::Opaque; + | ^^^^^^^^^^^^^^^^^ note: required by a bound in `verify_extern_kind` - --> $DIR/extern_type.rs:186:41 - | -186 | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {} - | ^^^^^^^^^^^ required by this bound in `verify_extern_kind` + --> src/extern_type.rs + | + | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {} + | ^^^^^^^^^^^ required by this bound in `verify_extern_kind` diff --git a/tests/ui/slice_unsupported.stderr b/tests/ui/slice_unsupported.stderr index 2cbd26da..b781bfd4 100644 --- a/tests/ui/slice_unsupported.stderr +++ b/tests/ui/slice_unsupported.stderr @@ -1,11 +1,11 @@ error: unsupported &mut [T] element type: opaque C++ type is not supported yet - --> $DIR/slice_unsupported.rs:6:17 + --> tests/ui/slice_unsupported.rs:6:17 | 6 | fn f(_: &mut [Opaque]); | ^^^^^^^^^^^^^ error: needs a cxx::ExternType impl in order to be used as a slice element in &mut [Opaque] - --> $DIR/slice_unsupported.rs:4:9 + --> tests/ui/slice_unsupported.rs:4:9 | 4 | type Opaque; | ^^^^^^^^^^^ diff --git a/tests/ui/struct_cycle.stderr b/tests/ui/struct_cycle.stderr index 49bcb5f6..9ee2d831 100644 --- a/tests/ui/struct_cycle.stderr +++ b/tests/ui/struct_cycle.stderr @@ -1,23 +1,23 @@ error: unsupported cyclic data structure - --> $DIR/struct_cycle.rs:26:9 + --> tests/ui/struct_cycle.rs:26:9 | 26 | node2: Node2, | ^^^^^^^^^^^^ error: unsupported cyclic data structure - --> $DIR/struct_cycle.rs:22:9 + --> tests/ui/struct_cycle.rs:22:9 | 22 | node5: Node5, | ^^^^^^^^^^^^ error: unsupported cyclic data structure - --> $DIR/struct_cycle.rs:13:9 + --> tests/ui/struct_cycle.rs:13:9 | 13 | node4: Node4, | ^^^^^^^^^^^^ error: unsupported cyclic data structure - --> $DIR/struct_cycle.rs:8:9 + --> tests/ui/struct_cycle.rs:8:9 | 8 | node2: Node2, | ^^^^^^^^^^^^ diff --git a/tests/ui/type_alias_rust.stderr b/tests/ui/type_alias_rust.stderr index 1b08f67c..8cf9a56f 100644 --- a/tests/ui/type_alias_rust.stderr +++ b/tests/ui/type_alias_rust.stderr @@ -1,5 +1,5 @@ error: type alias in extern "Rust" block is not supported - --> $DIR/type_alias_rust.rs:5:9 + --> tests/ui/type_alias_rust.rs:5:9 | 5 | type Alias = crate::Type; | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unique_ptr_as_mut.stderr b/tests/ui/unique_ptr_as_mut.stderr index a41f716a..a8248dbe 100644 --- a/tests/ui/unique_ptr_as_mut.stderr +++ b/tests/ui/unique_ptr_as_mut.stderr @@ -1,5 +1,5 @@ -error[E0596]: cannot borrow data in a dereference of `UniquePtr<ffi::Opaque>` as mutable - --> $DIR/unique_ptr_as_mut.rs:22:31 +error[E0596]: cannot borrow data in dereference of `UniquePtr<ffi::Opaque>` as mutable + --> tests/ui/unique_ptr_as_mut.rs:22:31 | 22 | let _: &mut ffi::Opaque = &mut opaque; | ^^^^^^^^^^^ cannot borrow as mutable diff --git a/tests/ui/unique_ptr_to_opaque.stderr b/tests/ui/unique_ptr_to_opaque.stderr index 28e45cf5..6f028f5a 100644 --- a/tests/ui/unique_ptr_to_opaque.stderr +++ b/tests/ui/unique_ptr_to_opaque.stderr @@ -1,13 +1,18 @@ error[E0271]: type mismatch resolving `<outside::C as ExternType>::Kind == Trivial` - --> $DIR/unique_ptr_to_opaque.rs:22:5 + --> tests/ui/unique_ptr_to_opaque.rs:22:25 | 22 | cxx::UniquePtr::new(outside::C { a: 4 }); - | ^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque` + | ------------------- ^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<outside::C as ExternType>::Kind == Trivial` + | | + | required by a bound introduced by this call | -note: required by `UniquePtr::<T>::new` - --> $DIR/unique_ptr.rs:38:5 +note: expected this to be `Trivial` + --> tests/ui/unique_ptr_to_opaque.rs:8:21 | -38 | / pub fn new(value: T) -> Self -39 | | where -40 | | T: ExternType<Kind = Trivial>, - | |______________________________________^ +8 | type Kind = cxx::kind::Opaque; + | ^^^^^^^^^^^^^^^^^ +note: required by a bound in `UniquePtr::<T>::new` + --> src/unique_ptr.rs + | + | T: ExternType<Kind = Trivial>, + | ^^^^^^^^^^^^^^ required by this bound in `UniquePtr::<T>::new` diff --git a/tests/ui/unique_ptr_twice.stderr b/tests/ui/unique_ptr_twice.stderr index ee26b646..b21791fb 100644 --- a/tests/ui/unique_ptr_twice.stderr +++ b/tests/ui/unique_ptr_twice.stderr @@ -1,8 +1,8 @@ -error[E0119]: conflicting implementations of trait `cxx::memory::UniquePtrTarget` for type `here::C` - --> $DIR/unique_ptr_twice.rs:16:5 +error[E0119]: conflicting implementations of trait `UniquePtrTarget` for type `here::C` + --> tests/ui/unique_ptr_twice.rs:16:5 | 7 | impl UniquePtr<C> {} - | ----------------- first implementation here + | ---------------- first implementation here ... 16 | impl UniquePtr<C> {} - | ^^^^^^^^^^^^^^^^^ conflicting implementation for `here::C` + | ^^^^^^^^^^^^^^^^ conflicting implementation for `here::C` diff --git a/tests/ui/unnamed_receiver.stderr b/tests/ui/unnamed_receiver.stderr index e66d9e3c..d903b231 100644 --- a/tests/ui/unnamed_receiver.stderr +++ b/tests/ui/unnamed_receiver.stderr @@ -1,11 +1,11 @@ error: unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &mut TheType` - --> $DIR/unnamed_receiver.rs:6:14 + --> tests/ui/unnamed_receiver.rs:6:14 | 6 | fn f(&mut self); | ^^^^^^^^^ error: unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &TheType` - --> $DIR/unnamed_receiver.rs:10:20 + --> tests/ui/unnamed_receiver.rs:10:20 | 10 | fn f(self: &Self); | ^^^^^ diff --git a/tests/ui/unpin_impl.stderr b/tests/ui/unpin_impl.stderr index 01ee19c1..18099bb6 100644 --- a/tests/ui/unpin_impl.stderr +++ b/tests/ui/unpin_impl.stderr @@ -1,8 +1,20 @@ -error[E0282]: type annotations needed for `fn()` - --> $DIR/unpin_impl.rs:4:14 +error[E0282]: type annotations needed + --> tests/ui/unpin_impl.rs:1:1 | 1 | #[cxx::bridge] - | -------------- consider giving this pattern the explicit type `fn()`, with the type parameters specified -... -4 | type Opaque; - | ^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `__AmbiguousIfImpl` + | + = note: this error originates in the attribute macro `cxx::bridge` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0283]: type annotations needed + --> tests/ui/unpin_impl.rs:1:1 + | +1 | #[cxx::bridge] + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `__AmbiguousIfImpl` + | +note: multiple `impl`s satisfying `ffi::Opaque: __AmbiguousIfImpl<_>` found + --> tests/ui/unpin_impl.rs:1:1 + | +1 | #[cxx::bridge] + | ^^^^^^^^^^^^^^ + = note: this error originates in the attribute macro `cxx::bridge` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/unrecognized_receiver.stderr b/tests/ui/unrecognized_receiver.stderr index a44bec1a..bc645fec 100644 --- a/tests/ui/unrecognized_receiver.stderr +++ b/tests/ui/unrecognized_receiver.stderr @@ -1,5 +1,5 @@ error: unrecognized receiver type - --> $DIR/unrecognized_receiver.rs:4:20 + --> tests/ui/unrecognized_receiver.rs:4:20 | 4 | fn f(self: &Unrecognized); | ^^^^^^^^^^^^^ diff --git a/tests/ui/unsupported_elided.stderr b/tests/ui/unsupported_elided.stderr index 8e8a986b..6926b824 100644 --- a/tests/ui/unsupported_elided.stderr +++ b/tests/ui/unsupported_elided.stderr @@ -1,13 +1,17 @@ error[E0726]: implicit elided lifetime not allowed here - --> $DIR/unsupported_elided.rs:6:14 + --> tests/ui/unsupported_elided.rs:6:14 | 6 | type T; - | ^- help: indicate the anonymous lifetime: `<'_>` + | ^ expected lifetime parameter | = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +6 | type T<'_>; + | ++++ error[E0106]: missing lifetime specifier - --> $DIR/unsupported_elided.rs:8:24 + --> tests/ui/unsupported_elided.rs:8:24 | 8 | fn f(t: &T) -> &str; | -- ^ expected named lifetime parameter @@ -15,5 +19,5 @@ error[E0106]: missing lifetime specifier = help: this function's return type contains a borrowed value, but the signature does not say which one of `t`'s 2 lifetimes it is borrowed from help: consider introducing a named lifetime parameter | -8 | fn f<'a>(t: &'a T) -> &'a str; - | ++++ ++ ++ +8 | fn f<'a>(t: &'a T<'a>) -> &'a str; + | ++++ ++ ++++ ++ diff --git a/tests/ui/vec_opaque.stderr b/tests/ui/vec_opaque.stderr index 3f208fec..cd038e66 100644 --- a/tests/ui/vec_opaque.stderr +++ b/tests/ui/vec_opaque.stderr @@ -1,23 +1,23 @@ error: Rust Vec containing C++ type is not supported yet - --> $DIR/vec_opaque.rs:15:19 + --> tests/ui/vec_opaque.rs:15:19 | 15 | fn f() -> Vec<Job>; | ^^^^^^^^ error: needs a cxx::ExternType impl in order to be used as a vector element in Vec<Job> - --> $DIR/vec_opaque.rs:11:9 + --> tests/ui/vec_opaque.rs:11:9 | 11 | type Job; | ^^^^^^^^ error[E0271]: type mismatch resolving `<handle::Job as ExternType>::Kind == Trivial` - --> $DIR/vec_opaque.rs:22:9 - | -22 | type Job = crate::handle::Job; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque` - | + --> tests/ui/vec_opaque.rs:22:14 + | +22 | type Job = crate::handle::Job; + | ^^^ expected enum `Trivial`, found enum `Opaque` + | note: required by a bound in `verify_extern_kind` - --> $DIR/extern_type.rs:186:41 - | -186 | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {} - | ^^^^^^^^^^^ required by this bound in `verify_extern_kind` + --> src/extern_type.rs + | + | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {} + | ^^^^^^^^^^^ required by this bound in `verify_extern_kind` diff --git a/tests/ui/vector_autotraits.stderr b/tests/ui/vector_autotraits.stderr index 52fd2a41..d8559d00 100644 --- a/tests/ui/vector_autotraits.stderr +++ b/tests/ui/vector_autotraits.stderr @@ -1,14 +1,14 @@ error[E0277]: `*const cxx::void` cannot be sent between threads safely - --> $DIR/vector_autotraits.rs:20:5 + --> tests/ui/vector_autotraits.rs:20:19 | 20 | assert_send::<CxxVector<ffi::NotThreadSafe>>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const cxx::void` cannot be sent between threads safely + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const cxx::void` cannot be sent between threads safely | = help: within `CxxVector<NotThreadSafe>`, the trait `Send` is not implemented for `*const cxx::void` = note: required because it appears within the type `[*const cxx::void; 0]` = note: required because it appears within the type `cxx::private::Opaque` note: required because it appears within the type `NotThreadSafe` - --> $DIR/vector_autotraits.rs:7:14 + --> tests/ui/vector_autotraits.rs:7:14 | 7 | type NotThreadSafe; | ^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ note: required because it appears within the type `NotThreadSafe` = note: required because it appears within the type `PhantomData<[NotThreadSafe]>` = note: required because it appears within the type `CxxVector<NotThreadSafe>` note: required by a bound in `assert_send` - --> $DIR/vector_autotraits.rs:16:19 + --> tests/ui/vector_autotraits.rs:16:19 | 16 | fn assert_send<T: Send>() {} | ^^^^ required by this bound in `assert_send` diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr index b66bb266..8cb78980 100644 --- a/tests/ui/wrong_type_id.stderr +++ b/tests/ui/wrong_type_id.stderr @@ -1,13 +1,13 @@ error[E0271]: type mismatch resolving `<StringPiece as ExternType>::Id == (f, o, l, l, y, (), B, y, t, e, R, a, n, g, e)` - --> $DIR/wrong_type_id.rs:11:9 - | -11 | type ByteRange = crate::here::StringPiece; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements - | - = note: expected tuple `(f, o, l, l, y, (), B, y, t, e, R, a, n, g, e)` - found tuple `(f, o, l, l, y, (), S, t, r, i, n, g, P, i, e, c, e)` + --> tests/ui/wrong_type_id.rs:11:14 + | +11 | type ByteRange = crate::here::StringPiece; + | ^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements + | + = note: expected tuple `(f, o, l, l, y, (), B, y, t, e, R, a, n, g, e)` + found tuple `(f, o, l, l, y, (), S, t, r, i, n, g, P, i, e, c, e)` note: required by a bound in `verify_extern_type` - --> $DIR/extern_type.rs:183:41 - | -183 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {} - | ^^^^^^^ required by this bound in `verify_extern_type` + --> src/extern_type.rs + | + | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {} + | ^^^^^^^ required by this bound in `verify_extern_type` diff --git a/third-party/.gitignore b/third-party/.gitignore index 61ead866..b0509488 100644 --- a/third-party/.gitignore +++ b/third-party/.gitignore @@ -1 +1,2 @@ +/.cargo /vendor diff --git a/third-party/BUCK b/third-party/BUCK index 2633da87..8036117e 100644 --- a/third-party/BUCK +++ b/third-party/BUCK @@ -1,110 +1,540 @@ -# To be generated by Facebook's `reindeer` tool once that is open source. +# @generated by `reindeer buckify` -load("//tools/buck:rust_library.bzl", "rust_library") +load("//tools/buck:buildscript.bzl", "buildscript_args") rust_library( - name = "bitflags", - srcs = glob(["vendor/bitflags-1.3.2/src/**"]), + name = "bitflags-1.3.2", + srcs = [ + "vendor/bitflags-1.3.2/src/example_generated.rs", + "vendor/bitflags-1.3.2/src/lib.rs", + ], + crate = "bitflags", + crate_root = "vendor/bitflags-1.3.2/src/lib.rs", + edition = "2018", + features = ["default"], + rustc_flags = ["--cap-lints=allow"], + visibility = [], ) -rust_library( +alias( name = "cc", - srcs = glob(["vendor/cc-1.0.69/src/**"]), + actual = ":cc-1.0.77", visibility = ["PUBLIC"], ) rust_library( + name = "cc-1.0.77", + srcs = [ + "vendor/cc-1.0.77/src/com.rs", + "vendor/cc-1.0.77/src/lib.rs", + "vendor/cc-1.0.77/src/registry.rs", + "vendor/cc-1.0.77/src/setup_config.rs", + "vendor/cc-1.0.77/src/vs_instances.rs", + "vendor/cc-1.0.77/src/winapi.rs", + "vendor/cc-1.0.77/src/windows_registry.rs", + ], + crate = "cc", + crate_root = "vendor/cc-1.0.77/src/lib.rs", + edition = "2018", + rustc_flags = ["--cap-lints=allow"], + visibility = [], +) + +alias( name = "clap", - srcs = glob(["vendor/clap-2.33.3/src/**"]), - edition = "2015", + actual = ":clap-4.0.29", visibility = ["PUBLIC"], +) + +rust_library( + name = "clap-4.0.29", + srcs = [ + "vendor/clap-4.0.29/examples/demo.md", + "vendor/clap-4.0.29/examples/demo.rs", + "vendor/clap-4.0.29/src/_cookbook/cargo_example.rs", + "vendor/clap-4.0.29/src/_cookbook/cargo_example_derive.rs", + "vendor/clap-4.0.29/src/_cookbook/escaped_positional.rs", + "vendor/clap-4.0.29/src/_cookbook/escaped_positional_derive.rs", + "vendor/clap-4.0.29/src/_cookbook/find.rs", + "vendor/clap-4.0.29/src/_cookbook/git.rs", + "vendor/clap-4.0.29/src/_cookbook/git_derive.rs", + "vendor/clap-4.0.29/src/_cookbook/mod.rs", + "vendor/clap-4.0.29/src/_cookbook/multicall_busybox.rs", + "vendor/clap-4.0.29/src/_cookbook/multicall_hostname.rs", + "vendor/clap-4.0.29/src/_cookbook/pacman.rs", + "vendor/clap-4.0.29/src/_cookbook/repl.rs", + "vendor/clap-4.0.29/src/_cookbook/typed_derive.rs", + "vendor/clap-4.0.29/src/_derive/_tutorial.rs", + "vendor/clap-4.0.29/src/_derive/mod.rs", + "vendor/clap-4.0.29/src/_faq.rs", + "vendor/clap-4.0.29/src/_features.rs", + "vendor/clap-4.0.29/src/_tutorial.rs", + "vendor/clap-4.0.29/src/builder/action.rs", + "vendor/clap-4.0.29/src/builder/app_settings.rs", + "vendor/clap-4.0.29/src/builder/arg.rs", + "vendor/clap-4.0.29/src/builder/arg_group.rs", + "vendor/clap-4.0.29/src/builder/arg_predicate.rs", + "vendor/clap-4.0.29/src/builder/arg_settings.rs", + "vendor/clap-4.0.29/src/builder/command.rs", + "vendor/clap-4.0.29/src/builder/debug_asserts.rs", + "vendor/clap-4.0.29/src/builder/mod.rs", + "vendor/clap-4.0.29/src/builder/os_str.rs", + "vendor/clap-4.0.29/src/builder/possible_value.rs", + "vendor/clap-4.0.29/src/builder/range.rs", + "vendor/clap-4.0.29/src/builder/resettable.rs", + "vendor/clap-4.0.29/src/builder/str.rs", + "vendor/clap-4.0.29/src/builder/styled_str.rs", + "vendor/clap-4.0.29/src/builder/tests.rs", + "vendor/clap-4.0.29/src/builder/value_hint.rs", + "vendor/clap-4.0.29/src/builder/value_parser.rs", + "vendor/clap-4.0.29/src/derive.rs", + "vendor/clap-4.0.29/src/error/context.rs", + "vendor/clap-4.0.29/src/error/format.rs", + "vendor/clap-4.0.29/src/error/kind.rs", + "vendor/clap-4.0.29/src/error/mod.rs", + "vendor/clap-4.0.29/src/lib.rs", + "vendor/clap-4.0.29/src/macros.rs", + "vendor/clap-4.0.29/src/mkeymap.rs", + "vendor/clap-4.0.29/src/output/fmt.rs", + "vendor/clap-4.0.29/src/output/help.rs", + "vendor/clap-4.0.29/src/output/help_template.rs", + "vendor/clap-4.0.29/src/output/mod.rs", + "vendor/clap-4.0.29/src/output/textwrap/core.rs", + "vendor/clap-4.0.29/src/output/textwrap/mod.rs", + "vendor/clap-4.0.29/src/output/textwrap/word_separators.rs", + "vendor/clap-4.0.29/src/output/textwrap/wrap_algorithms.rs", + "vendor/clap-4.0.29/src/output/usage.rs", + "vendor/clap-4.0.29/src/parser/arg_matcher.rs", + "vendor/clap-4.0.29/src/parser/error.rs", + "vendor/clap-4.0.29/src/parser/features/mod.rs", + "vendor/clap-4.0.29/src/parser/features/suggestions.rs", + "vendor/clap-4.0.29/src/parser/matches/any_value.rs", + "vendor/clap-4.0.29/src/parser/matches/arg_matches.rs", + "vendor/clap-4.0.29/src/parser/matches/matched_arg.rs", + "vendor/clap-4.0.29/src/parser/matches/mod.rs", + "vendor/clap-4.0.29/src/parser/matches/value_source.rs", + "vendor/clap-4.0.29/src/parser/mod.rs", + "vendor/clap-4.0.29/src/parser/parser.rs", + "vendor/clap-4.0.29/src/parser/validator.rs", + "vendor/clap-4.0.29/src/util/color.rs", + "vendor/clap-4.0.29/src/util/flat_map.rs", + "vendor/clap-4.0.29/src/util/flat_set.rs", + "vendor/clap-4.0.29/src/util/graph.rs", + "vendor/clap-4.0.29/src/util/id.rs", + "vendor/clap-4.0.29/src/util/mod.rs", + "vendor/clap-4.0.29/src/util/str_to_bool.rs", + ], + crate = "clap", + crate_root = "vendor/clap-4.0.29/src/lib.rs", + edition = "2021", + features = [ + "error-context", + "help", + "std", + "usage", + ], + rustc_flags = ["--cap-lints=allow"], + visibility = [], deps = [ - ":bitflags", - ":textwrap", - ":unicode-width", + ":bitflags-1.3.2", + ":clap_lex-0.3.0", ], ) rust_library( + name = "clap_lex-0.3.0", + srcs = ["vendor/clap_lex-0.3.0/src/lib.rs"], + crate = "clap_lex", + crate_root = "vendor/clap_lex-0.3.0/src/lib.rs", + edition = "2021", + rustc_flags = ["--cap-lints=allow"], + visibility = [], + deps = [":os_str_bytes-6.4.1"], +) + +alias( name = "codespan-reporting", - srcs = glob(["vendor/codespan-reporting-0.11.1/src/**"]), + actual = ":codespan-reporting-0.11.1", visibility = ["PUBLIC"], +) + +rust_library( + name = "codespan-reporting-0.11.1", + srcs = [ + "vendor/codespan-reporting-0.11.1/src/diagnostic.rs", + "vendor/codespan-reporting-0.11.1/src/files.rs", + "vendor/codespan-reporting-0.11.1/src/lib.rs", + "vendor/codespan-reporting-0.11.1/src/term.rs", + "vendor/codespan-reporting-0.11.1/src/term/config.rs", + "vendor/codespan-reporting-0.11.1/src/term/renderer.rs", + "vendor/codespan-reporting-0.11.1/src/term/views.rs", + ], + crate = "codespan_reporting", + crate_root = "vendor/codespan-reporting-0.11.1/src/lib.rs", + edition = "2018", + rustc_flags = ["--cap-lints=allow"], + visibility = [], deps = [ - ":termcolor", - ":unicode-width", + ":termcolor-1.1.3", + ":unicode-width-0.1.10", ], ) -rust_library( - name = "lazy_static", - srcs = glob(["vendor/lazy_static-1.4.0/src/**"]), +alias( + name = "once_cell", + actual = ":once_cell-1.16.0", visibility = ["PUBLIC"], ) rust_library( + name = "once_cell-1.16.0", + srcs = [ + "vendor/once_cell-1.16.0/src/imp_cs.rs", + "vendor/once_cell-1.16.0/src/imp_pl.rs", + "vendor/once_cell-1.16.0/src/imp_std.rs", + "vendor/once_cell-1.16.0/src/lib.rs", + "vendor/once_cell-1.16.0/src/race.rs", + ], + crate = "once_cell", + crate_root = "vendor/once_cell-1.16.0/src/lib.rs", + edition = "2021", + features = [ + "alloc", + "default", + "race", + "std", + ], + rustc_flags = ["--cap-lints=allow"], + visibility = [], +) + +rust_library( + name = "os_str_bytes-6.4.1", + srcs = [ + "vendor/os_str_bytes-6.4.1/src/common/mod.rs", + "vendor/os_str_bytes-6.4.1/src/common/raw.rs", + "vendor/os_str_bytes-6.4.1/src/iter.rs", + "vendor/os_str_bytes-6.4.1/src/lib.rs", + "vendor/os_str_bytes-6.4.1/src/pattern.rs", + "vendor/os_str_bytes-6.4.1/src/raw_str.rs", + "vendor/os_str_bytes-6.4.1/src/util.rs", + "vendor/os_str_bytes-6.4.1/src/wasm/mod.rs", + "vendor/os_str_bytes-6.4.1/src/wasm/raw.rs", + "vendor/os_str_bytes-6.4.1/src/windows/mod.rs", + "vendor/os_str_bytes-6.4.1/src/windows/raw.rs", + "vendor/os_str_bytes-6.4.1/src/windows/wtf8/code_points.rs", + "vendor/os_str_bytes-6.4.1/src/windows/wtf8/convert.rs", + "vendor/os_str_bytes-6.4.1/src/windows/wtf8/mod.rs", + "vendor/os_str_bytes-6.4.1/src/windows/wtf8/string.rs", + ], + crate = "os_str_bytes", + crate_root = "vendor/os_str_bytes-6.4.1/src/lib.rs", + edition = "2021", + features = ["raw_os_str"], + rustc_flags = ["--cap-lints=allow"], + visibility = [], +) + +alias( name = "proc-macro2", - srcs = glob(["vendor/proc-macro2-1.0.28/src/**"]), - build_script = "vendor/proc-macro2-1.0.28/build.rs", + actual = ":proc-macro2-1.0.47", + visibility = ["PUBLIC"], +) + +rust_library( + name = "proc-macro2-1.0.47", + srcs = [ + "vendor/proc-macro2-1.0.47/src/detection.rs", + "vendor/proc-macro2-1.0.47/src/fallback.rs", + "vendor/proc-macro2-1.0.47/src/lib.rs", + "vendor/proc-macro2-1.0.47/src/marker.rs", + "vendor/proc-macro2-1.0.47/src/parse.rs", + "vendor/proc-macro2-1.0.47/src/rcvec.rs", + "vendor/proc-macro2-1.0.47/src/wrapper.rs", + ], + crate = "proc_macro2", + crate_root = "vendor/proc-macro2-1.0.47/src/lib.rs", + edition = "2018", features = [ + "default", "proc-macro", "span-locations", ], - visibility = ["PUBLIC"], - deps = [":unicode-xid"], + rustc_flags = [ + "--cap-lints=allow", + "@$(location :proc-macro2-1.0.47-build-script-build-args)", + ], + visibility = [], + deps = [":unicode-ident-1.0.5"], ) -rust_library( +rust_binary( + name = "proc-macro2-1.0.47-build-script-build", + srcs = ["vendor/proc-macro2-1.0.47/build.rs"], + crate = "build_script_build", + crate_root = "vendor/proc-macro2-1.0.47/build.rs", + edition = "2018", + features = [ + "default", + "proc-macro", + "span-locations", + ], + rustc_flags = ["--cap-lints=allow"], + visibility = [], +) + +buildscript_args( + name = "proc-macro2-1.0.47-build-script-build-args", + package_name = "proc-macro2", + buildscript_rule = ":proc-macro2-1.0.47-build-script-build", + cfgs = [], + features = [ + "default", + "proc-macro", + "span-locations", + ], + outfile = "args.txt", + version = "1.0.47", +) + +alias( name = "quote", - srcs = glob(["vendor/quote-1.0.9/src/**"]), - features = ["proc-macro"], + actual = ":quote-1.0.21", visibility = ["PUBLIC"], - deps = [":proc-macro2"], ) rust_library( + name = "quote-1.0.21", + srcs = [ + "vendor/quote-1.0.21/src/ext.rs", + "vendor/quote-1.0.21/src/format.rs", + "vendor/quote-1.0.21/src/ident_fragment.rs", + "vendor/quote-1.0.21/src/lib.rs", + "vendor/quote-1.0.21/src/runtime.rs", + "vendor/quote-1.0.21/src/spanned.rs", + "vendor/quote-1.0.21/src/to_tokens.rs", + ], + crate = "quote", + crate_root = "vendor/quote-1.0.21/src/lib.rs", + edition = "2018", + features = [ + "default", + "proc-macro", + ], + rustc_flags = [ + "--cap-lints=allow", + "@$(location :quote-1.0.21-build-script-build-args)", + ], + visibility = [], + deps = [":proc-macro2-1.0.47"], +) + +rust_binary( + name = "quote-1.0.21-build-script-build", + srcs = ["vendor/quote-1.0.21/build.rs"], + crate = "build_script_build", + crate_root = "vendor/quote-1.0.21/build.rs", + edition = "2018", + features = [ + "default", + "proc-macro", + ], + rustc_flags = ["--cap-lints=allow"], + visibility = [], +) + +buildscript_args( + name = "quote-1.0.21-build-script-build-args", + package_name = "quote", + buildscript_rule = ":quote-1.0.21-build-script-build", + cfgs = [], + features = [ + "default", + "proc-macro", + ], + outfile = "args.txt", + version = "1.0.21", +) + +alias( name = "scratch", - srcs = glob(["vendor/scratch-1.0.0/src/**"]), - env = {"OUT_DIR": ""}, + actual = ":scratch-1.0.2", visibility = ["PUBLIC"], ) rust_library( + name = "scratch-1.0.2", + srcs = ["vendor/scratch-1.0.2/src/lib.rs"], + crate = "scratch", + crate_root = "vendor/scratch-1.0.2/src/lib.rs", + edition = "2015", + env = { + "OUT_DIR": "generated", + }, + rustc_flags = ["--cap-lints=allow"], + visibility = [], +) + +alias( name = "syn", - srcs = glob(["vendor/syn-1.0.75/src/**"]), - build_script = "vendor/syn-1.0.75/build.rs", + actual = ":syn-1.0.105", + visibility = ["PUBLIC"], +) + +rust_library( + name = "syn-1.0.105", + srcs = [ + "vendor/syn-1.0.105/src/attr.rs", + "vendor/syn-1.0.105/src/await.rs", + "vendor/syn-1.0.105/src/bigint.rs", + "vendor/syn-1.0.105/src/buffer.rs", + "vendor/syn-1.0.105/src/custom_keyword.rs", + "vendor/syn-1.0.105/src/custom_punctuation.rs", + "vendor/syn-1.0.105/src/data.rs", + "vendor/syn-1.0.105/src/derive.rs", + "vendor/syn-1.0.105/src/discouraged.rs", + "vendor/syn-1.0.105/src/drops.rs", + "vendor/syn-1.0.105/src/error.rs", + "vendor/syn-1.0.105/src/export.rs", + "vendor/syn-1.0.105/src/expr.rs", + "vendor/syn-1.0.105/src/ext.rs", + "vendor/syn-1.0.105/src/file.rs", + "vendor/syn-1.0.105/src/gen/clone.rs", + "vendor/syn-1.0.105/src/gen/debug.rs", + "vendor/syn-1.0.105/src/gen/eq.rs", + "vendor/syn-1.0.105/src/gen/fold.rs", + "vendor/syn-1.0.105/src/gen/hash.rs", + "vendor/syn-1.0.105/src/gen/visit.rs", + "vendor/syn-1.0.105/src/gen/visit_mut.rs", + "vendor/syn-1.0.105/src/gen_helper.rs", + "vendor/syn-1.0.105/src/generics.rs", + "vendor/syn-1.0.105/src/group.rs", + "vendor/syn-1.0.105/src/ident.rs", + "vendor/syn-1.0.105/src/item.rs", + "vendor/syn-1.0.105/src/lib.rs", + "vendor/syn-1.0.105/src/lifetime.rs", + "vendor/syn-1.0.105/src/lit.rs", + "vendor/syn-1.0.105/src/lookahead.rs", + "vendor/syn-1.0.105/src/mac.rs", + "vendor/syn-1.0.105/src/macros.rs", + "vendor/syn-1.0.105/src/op.rs", + "vendor/syn-1.0.105/src/parse.rs", + "vendor/syn-1.0.105/src/parse_macro_input.rs", + "vendor/syn-1.0.105/src/parse_quote.rs", + "vendor/syn-1.0.105/src/pat.rs", + "vendor/syn-1.0.105/src/path.rs", + "vendor/syn-1.0.105/src/print.rs", + "vendor/syn-1.0.105/src/punctuated.rs", + "vendor/syn-1.0.105/src/reserved.rs", + "vendor/syn-1.0.105/src/sealed.rs", + "vendor/syn-1.0.105/src/span.rs", + "vendor/syn-1.0.105/src/spanned.rs", + "vendor/syn-1.0.105/src/stmt.rs", + "vendor/syn-1.0.105/src/thread.rs", + "vendor/syn-1.0.105/src/token.rs", + "vendor/syn-1.0.105/src/tt.rs", + "vendor/syn-1.0.105/src/ty.rs", + "vendor/syn-1.0.105/src/verbatim.rs", + "vendor/syn-1.0.105/src/whitespace.rs", + ], + crate = "syn", + crate_root = "vendor/syn-1.0.105/src/lib.rs", + edition = "2018", features = [ "clone-impls", + "default", "derive", "full", "parsing", "printing", "proc-macro", + "quote", ], - visibility = ["PUBLIC"], + rustc_flags = [ + "--cap-lints=allow", + "@$(location :syn-1.0.105-build-script-build-args)", + ], + visibility = [], deps = [ - ":proc-macro2", - ":quote", - ":unicode-xid", + ":proc-macro2-1.0.47", + ":quote-1.0.21", + ":unicode-ident-1.0.5", ], ) -rust_library( - name = "termcolor", - srcs = glob(["vendor/termcolor-1.1.2/src/**"]), +rust_binary( + name = "syn-1.0.105-build-script-build", + srcs = ["vendor/syn-1.0.105/build.rs"], + crate = "build_script_build", + crate_root = "vendor/syn-1.0.105/build.rs", + edition = "2018", + features = [ + "clone-impls", + "default", + "derive", + "full", + "parsing", + "printing", + "proc-macro", + "quote", + ], + rustc_flags = ["--cap-lints=allow"], + visibility = [], +) + +buildscript_args( + name = "syn-1.0.105-build-script-build-args", + package_name = "syn", + buildscript_rule = ":syn-1.0.105-build-script-build", + cfgs = [], + features = [ + "clone-impls", + "default", + "derive", + "full", + "parsing", + "printing", + "proc-macro", + "quote", + ], + outfile = "args.txt", + version = "1.0.105", ) rust_library( - name = "textwrap", - srcs = glob(["vendor/textwrap-0.11.0/src/**"]), - deps = [":unicode-width"], + name = "termcolor-1.1.3", + srcs = ["vendor/termcolor-1.1.3/src/lib.rs"], + crate = "termcolor", + crate_root = "vendor/termcolor-1.1.3/src/lib.rs", + edition = "2018", + rustc_flags = ["--cap-lints=allow"], + visibility = [], ) rust_library( - name = "unicode-width", - srcs = glob(["vendor/unicode-width-0.1.8/src/**"]), + name = "unicode-ident-1.0.5", + srcs = [ + "vendor/unicode-ident-1.0.5/src/lib.rs", + "vendor/unicode-ident-1.0.5/src/tables.rs", + ], + crate = "unicode_ident", + crate_root = "vendor/unicode-ident-1.0.5/src/lib.rs", + edition = "2018", + rustc_flags = ["--cap-lints=allow"], + visibility = [], ) rust_library( - name = "unicode-xid", - srcs = glob(["vendor/unicode-xid-0.2.2/src/**"]), + name = "unicode-width-0.1.10", + srcs = [ + "vendor/unicode-width-0.1.10/src/lib.rs", + "vendor/unicode-width-0.1.10/src/tables.rs", + "vendor/unicode-width-0.1.10/src/tests.rs", + ], + crate = "unicode_width", + crate_root = "vendor/unicode-width-0.1.10/src/lib.rs", + edition = "2015", + features = ["default"], + rustc_flags = ["--cap-lints=allow"], + visibility = [], ) diff --git a/third-party/BUILD b/third-party/BUILD index 1760b707..1b599321 100644 --- a/third-party/BUILD +++ b/third-party/BUILD @@ -7,30 +7,48 @@ load( rust_library( name = "bitflags", - srcs = glob(["vendor/bitflags-1.3.2/src/**"]), + srcs = glob(["vendor/bitflags-1.3.2/src/**/*.rs"]), + edition = "2018", ) rust_library( name = "cc", - srcs = glob(["vendor/cc-1.0.69/src/**"]), + srcs = glob(["vendor/cc-1.0.77/src/**/*.rs"]), + edition = "2018", visibility = ["//visibility:public"], ) rust_library( name = "clap", - srcs = glob(["vendor/clap-2.33.3/src/**"]), - edition = "2015", + srcs = glob(["vendor/clap-4.0.29/src/**/*.rs"]) + ["vendor/clap-4.0.29/examples/demo.rs"], + crate_features = [ + "error-context", + "help", + "std", + "usage", + ], + data = ["vendor/clap-4.0.29/examples/demo.md"], + edition = "2021", visibility = ["//visibility:public"], deps = [ ":bitflags", - ":textwrap", - ":unicode-width", + ":clap_lex", + ], +) + +rust_library( + name = "clap_lex", + srcs = glob(["vendor/clap_lex-0.3.0/src/**/*.rs"]), + edition = "2021", + deps = [ + ":os_str_bytes", ], ) rust_library( name = "codespan-reporting", - srcs = glob(["vendor/codespan-reporting-0.11.1/src/**"]), + srcs = glob(["vendor/codespan-reporting-0.11.1/src/**/*.rs"]), + edition = "2018", visibility = ["//visibility:public"], deps = [ ":termcolor", @@ -39,101 +57,146 @@ rust_library( ) rust_library( - name = "lazy_static", - srcs = glob(["vendor/lazy_static-1.4.0/src/**"]), + name = "once_cell", + srcs = glob(["vendor/once_cell-1.16.0/src/**/*.rs"]), + crate_features = [ + "alloc", + "default", + "race", + "std", + ], + edition = "2021", visibility = ["//visibility:public"], ) rust_library( + name = "os_str_bytes", + srcs = glob(["vendor/os_str_bytes-6.4.1/src/**/*.rs"]), + crate_features = [ + "raw_os_str", + ], + edition = "2021", +) + +rust_library( name = "proc-macro2", - srcs = glob(["vendor/proc-macro2-1.0.28/src/**"]), + srcs = glob(["vendor/proc-macro2-1.0.47/src/**/*.rs"]), crate_features = [ + "default", "proc-macro", "span-locations", ], + edition = "2018", visibility = ["//visibility:public"], deps = [ ":proc-macro2@build", - ":unicode-xid", + ":unicode-ident", ], ) cargo_build_script( name = "proc-macro2@build", - srcs = ["vendor/proc-macro2-1.0.28/build.rs"], + srcs = ["vendor/proc-macro2-1.0.47/build.rs"], crate_features = [ + "default", "proc-macro", "span-locations", ], crate_name = "build", + edition = "2018", ) rust_library( name = "quote", - srcs = glob(["vendor/quote-1.0.9/src/**"]), - crate_features = ["proc-macro"], + srcs = glob(["vendor/quote-1.0.21/src/**/*.rs"]), + crate_features = [ + "default", + "proc-macro", + ], + edition = "2018", visibility = ["//visibility:public"], - deps = [":proc-macro2"], + deps = [ + ":proc-macro2", + ":quote@build", + ], +) + +cargo_build_script( + name = "quote@build", + srcs = ["vendor/quote-1.0.21/build.rs"], + crate_features = [ + "default", + "proc-macro", + ], + crate_name = "build", + edition = "2018", ) rust_library( name = "scratch", - srcs = glob(["vendor/scratch-1.0.0/src/**"]), + srcs = glob(["vendor/scratch-1.0.2/src/**/*.rs"]), + edition = "2015", rustc_env = {"OUT_DIR": ""}, visibility = ["//visibility:public"], ) rust_library( name = "syn", - srcs = glob(["vendor/syn-1.0.75/src/**"]), + srcs = glob(["vendor/syn-1.0.105/src/**/*.rs"]), crate_features = [ "clone-impls", + "default", "derive", "full", "parsing", "printing", "proc-macro", + "quote", ], + edition = "2018", visibility = ["//visibility:public"], deps = [ ":proc-macro2", ":quote", ":syn@build", - ":unicode-xid", + ":unicode-ident", ], ) cargo_build_script( name = "syn@build", - srcs = ["vendor/syn-1.0.75/build.rs"], + srcs = ["vendor/syn-1.0.105/build.rs"], crate_features = [ "clone-impls", + "default", "derive", "full", "parsing", "printing", "proc-macro", + "quote", ], crate_name = "build", + edition = "2018", ) rust_library( name = "termcolor", - srcs = glob(["vendor/termcolor-1.1.2/src/**"]), + srcs = glob(["vendor/termcolor-1.1.3/src/**/*.rs"]), + edition = "2018", ) rust_library( - name = "textwrap", - srcs = glob(["vendor/textwrap-0.11.0/src/**"]), - deps = [":unicode-width"], + name = "unicode-ident", + srcs = glob(["vendor/unicode-ident-1.0.5/src/**/*.rs"]), + edition = "2018", ) rust_library( name = "unicode-width", - srcs = glob(["vendor/unicode-width-0.1.8/src/**"]), -) - -rust_library( - name = "unicode-xid", - srcs = glob(["vendor/unicode-xid-0.2.2/src/**"]), + srcs = glob(["vendor/unicode-width-0.1.10/src/**/*.rs"]), + crate_features = [ + "default", + ], + edition = "2015", ) diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock index 0a3d543d..1c054218 100644 --- a/third-party/Cargo.lock +++ b/third-party/Cargo.lock @@ -3,38 +3,6 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -42,41 +10,27 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cc" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" [[package]] -name = "clang-ast" -version = "0.1.6" +name = "clap" +version = "4.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed6681036a96f9855a75b08a9f14199e212017508a967d1d1e868f575f7d8e9" +checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d" dependencies = [ - "serde", + "bitflags", + "clap_lex", ] [[package]] -name = "clap" -version = "2.33.3" +name = "clap_lex" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", + "os_str_bytes", ] [[package]] @@ -90,340 +44,86 @@ dependencies = [ ] [[package]] -name = "crc32fast" -version = "1.2.1" +name = "once_cell" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "cxx" -version = "1.0.54" -dependencies = [ - "cc", - "cxx-build", - "cxx-gen", - "cxx-test-suite", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", - "rustversion", - "trybuild", -] - -[[package]] -name = "cxx-build" -version = "1.0.54" -dependencies = [ - "cc", - "codespan-reporting", - "cxx-gen", - "lazy_static", - "pkg-config", - "proc-macro2", - "quote", - "scratch", - "syn", -] +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] -name = "cxx-gen" -version = "0.7.54" -dependencies = [ - "cc", - "codespan-reporting", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "cxx-test-suite" -version = "0.0.0" -dependencies = [ - "cxx", - "cxx-build", - "cxxbridge-flags", -] - -[[package]] -name = "cxxbridge-cmd" -version = "1.0.54" -dependencies = [ - "clap", - "codespan-reporting", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.54" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.54" -dependencies = [ - "clang-ast", - "cxx", - "flate2", - "memmap", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn", -] - -[[package]] -name = "demo" -version = "0.0.0" -dependencies = [ - "cxx", - "cxx-build", -] - -[[package]] -name = "dissimilar" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4b29f4b9bb94bf267d57269fd0706d343a160937108e9619fe380645428abb" - -[[package]] -name = "flate2" -version = "1.0.20" +name = "os_str_bytes" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" -dependencies = [ - "cfg-if", - "crc32fast", - "libc", - "miniz_oxide", -] - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "jobserver" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" -dependencies = [ - "libc", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" - -[[package]] -name = "link-cplusplus" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1becd27d473556dc610b8afa1636ef90747b574a84553bc11e82371d5ef2d1" -dependencies = [ - "cc", -] - -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "pkg-config" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] -name = "rustversion" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" - -[[package]] -name = "ryu" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" - -[[package]] name = "scratch" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69" - -[[package]] -name = "serde" -version = "1.0.129" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.129" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "strsim" -version = "0.8.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" [[package]] name = "syn" -version = "1.0.75" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +name = "third-party" +version = "0.0.0" dependencies = [ - "serde", + "cc", + "clap", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", ] [[package]] -name = "trybuild" -version = "1.0.45" +name = "unicode-ident" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bdaf2a1d317f3d58b44b31c7f6436b9b9acafe7bddfeace50897c2b804d7792" -dependencies = [ - "dissimilar", - "glob", - "lazy_static", - "serde", - "serde_json", - "termcolor", - "toml", -] +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "vec_map" -version = "0.8.2" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "winapi" diff --git a/third-party/Cargo.toml b/third-party/Cargo.toml new file mode 100644 index 00000000..84657de5 --- /dev/null +++ b/third-party/Cargo.toml @@ -0,0 +1,18 @@ +[workspace] +[package] +name = "third-party" +version = "0.0.0" +publish = false + +[lib] +path = "/dev/null" + +[dependencies] +cc = "1.0.49" +clap = { version = "4", default-features = false, features = ["error-context", "help", "std", "usage"] } +codespan-reporting = "0.11.1" +once_cell = "1.9" +proc-macro2 = { version = "1.0.39", features = ["span-locations"] } +quote = "1.0.4" +scratch = "1" +syn = { version = "1.0.95", features = ["full"] } diff --git a/third-party/fixups/cc/fixups.toml b/third-party/fixups/cc/fixups.toml new file mode 100644 index 00000000..e148831c --- /dev/null +++ b/third-party/fixups/cc/fixups.toml @@ -0,0 +1 @@ +omit_targets = ["gcc-shim"] diff --git a/third-party/fixups/clap/fixups.toml b/third-party/fixups/clap/fixups.toml new file mode 100644 index 00000000..36ad30f5 --- /dev/null +++ b/third-party/fixups/clap/fixups.toml @@ -0,0 +1,2 @@ +extra_srcs = ["examples/demo.md", "examples/demo.rs"] +omit_targets = ["stdio-fixture"] diff --git a/third-party/fixups/proc-macro2/fixups.toml b/third-party/fixups/proc-macro2/fixups.toml new file mode 100644 index 00000000..5e026f75 --- /dev/null +++ b/third-party/fixups/proc-macro2/fixups.toml @@ -0,0 +1,2 @@ +[[buildscript]] +[buildscript.rustc_flags] diff --git a/third-party/fixups/quote/fixups.toml b/third-party/fixups/quote/fixups.toml new file mode 100644 index 00000000..5e026f75 --- /dev/null +++ b/third-party/fixups/quote/fixups.toml @@ -0,0 +1,2 @@ +[[buildscript]] +[buildscript.rustc_flags] diff --git a/third-party/fixups/scratch/fixups.toml b/third-party/fixups/scratch/fixups.toml new file mode 100644 index 00000000..72f4bdd0 --- /dev/null +++ b/third-party/fixups/scratch/fixups.toml @@ -0,0 +1,4 @@ +buildscript = [] + +[env] +OUT_DIR = "generated" diff --git a/third-party/fixups/syn/fixups.toml b/third-party/fixups/syn/fixups.toml new file mode 100644 index 00000000..5e026f75 --- /dev/null +++ b/third-party/fixups/syn/fixups.toml @@ -0,0 +1,2 @@ +[[buildscript]] +[buildscript.rustc_flags] diff --git a/third-party/reindeer.toml b/third-party/reindeer.toml new file mode 100644 index 00000000..eb65857c --- /dev/null +++ b/third-party/reindeer.toml @@ -0,0 +1,13 @@ +precise_srcs = true +rustc_flags = ["--cap-lints=allow"] + +[cargo] +versioned_dirs = true + +[buck] +generated_file_header = """ +# \u0040generated by `reindeer buckify` +""" +buckfile_imports = """ +load("//tools/buck:buildscript.bzl", "buildscript_args") +""" diff --git a/tools/bazel/third_party.bzl b/tools/bazel/third_party.bzl index 7f51c466..5b2ec3fe 100644 --- a/tools/bazel/third_party.bzl +++ b/tools/bazel/third_party.bzl @@ -1,5 +1,5 @@ load("@rules_rust//cargo:cargo_build_script.bzl", "cargo_build_script") -load("@rules_rust//rust:rust.bzl", "rust_binary", "rust_library") +load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library") load("@third-party//:vendor.bzl", "vendored") def third_party_glob(include): diff --git a/tools/bazel/vendor.bzl b/tools/bazel/vendor.bzl index e51adb7b..0f199145 100644 --- a/tools/bazel/vendor.bzl +++ b/tools/bazel/vendor.bzl @@ -2,7 +2,9 @@ of a crate in the current workspace. """ -load("@rules_rust//rust:repositories.bzl", "DEFAULT_RUST_VERSION", "load_arbitrary_tool") +load("@rules_rust//rust:defs.bzl", "rust_common") +load("@rules_rust//rust:repositories.bzl", "load_arbitrary_tool") +load("@rules_rust//rust/platform:triple.bzl", "get_host_triple") def _impl(repository_ctx): # Link cxx repository into @third-party. @@ -10,21 +12,11 @@ def _impl(repository_ctx): workspace = lockfile.dirname.dirname repository_ctx.symlink(workspace, "workspace") - # Copy third-party/Cargo.lock since those are the crate versions that the - # BUILD file is written against. - vendor_lockfile = repository_ctx.path("workspace/third-party/Cargo.lock") - root_lockfile = repository_ctx.path("workspace/Cargo.lock") - _copy_file(repository_ctx, src = vendor_lockfile, dst = root_lockfile) - # Figure out which version of cargo to use. if repository_ctx.attr.target_triple: target_triple = repository_ctx.attr.target_triple - elif "mac" in repository_ctx.os.name: - target_triple = "x86_64-apple-darwin" - elif "windows" in repository_ctx.os.name: - target_triple = "x86_64-pc-windows-msvc" else: - target_triple = "x86_64-unknown-linux-gnu" + target_triple = get_host_triple(repository_ctx).str # Download cargo. load_arbitrary_tool( @@ -36,20 +28,16 @@ def _impl(repository_ctx): target_triple = target_triple, ) - cmd = ["{}/bin/cargo".format(repository_ctx.path(".")), "vendor", "--versioned-dirs", "third-party/vendor"] + cmd = ["{}/bin/cargo".format(repository_ctx.path(".")), "vendor", "--versioned-dirs"] result = repository_ctx.execute( cmd, quiet = True, - working_directory = "workspace", + working_directory = "workspace/third-party", ) _log_cargo_vendor(repository_ctx, result) if result.return_code != 0: fail("failed to execute `{}`".format(" ".join(cmd))) - # Copy lockfile back to third-party/Cargo.lock to reflect any modification - # performed by Cargo. - _copy_file(repository_ctx, src = root_lockfile, dst = vendor_lockfile) - # Produce a token for third_party_glob to depend on so that the necessary # sequencing is visible to Bazel. repository_ctx.file("BUILD", executable = False) @@ -77,7 +65,6 @@ vendor = repository_rule( attrs = { "cargo_version": attr.string( doc = "The version of cargo to use", - default = DEFAULT_RUST_VERSION, ), "cargo_iso_date": attr.string( doc = "The date of the tool (or None, if the version is a specific version)", diff --git a/tools/buck/buildscript.bzl b/tools/buck/buildscript.bzl new file mode 100644 index 00000000..bbcf1060 --- /dev/null +++ b/tools/buck/buildscript.bzl @@ -0,0 +1,13 @@ +def buildscript_args( + name, + package_name, + buildscript_rule, + cfgs, + features, + outfile, + version): + native.genrule( + name = name, + out = outfile, + cmd = "env RUSTC=rustc TARGET= $(exe %s) | sed -n s/^cargo:rustc-cfg=/--cfg=/p > ${OUT}" % buildscript_rule, + ) diff --git a/tools/buck/genrule.bzl b/tools/buck/genrule.bzl deleted file mode 100644 index b5364b7f..00000000 --- a/tools/buck/genrule.bzl +++ /dev/null @@ -1,8 +0,0 @@ -def genrule(cmd, **kwargs): - # Resolve a distracting inconsistency between Buck and Bazel. - # Bazel creates the directory for your output file, while Buck expects the - # cmd to create it. - # - # TODO: send this as a PR to Buck, because Bazel's behavior here is better. - cmd = "mkdir -p `dirname ${OUT}`; " + cmd - native.genrule(cmd = cmd, **kwargs) diff --git a/tools/buck/prelude b/tools/buck/prelude new file mode 160000 +Subproject bed5249482b20f591d9d231663b23f318b6c10b diff --git a/tools/buck/rust_cxx_bridge.bzl b/tools/buck/rust_cxx_bridge.bzl index 4acc7c66..49e38fce 100644 --- a/tools/buck/rust_cxx_bridge.bzl +++ b/tools/buck/rust_cxx_bridge.bzl @@ -1,19 +1,17 @@ -load("//tools/buck:genrule.bzl", "genrule") - def rust_cxx_bridge(name, src, deps = []): - genrule( + native.genrule( name = "%s/header" % name, out = src + ".h", cmd = "cp $(location :%s/generated)/generated.h ${OUT}" % name, ) - genrule( + native.genrule( name = "%s/source" % name, out = src + ".cc", cmd = "cp $(location :%s/generated)/generated.cc ${OUT}" % name, ) - genrule( + native.genrule( name = "%s/generated" % name, srcs = [src], out = ".", @@ -21,14 +19,14 @@ def rust_cxx_bridge(name, src, deps = []): type = "cxxbridge", ) - cxx_library( + native.cxx_library( name = name, srcs = [":%s/source" % name], preferred_linkage = "static", - deps = deps + [":%s/include" % name], + exported_deps = deps + [":%s/include" % name], ) - cxx_library( + native.cxx_library( name = "%s/include" % name, exported_headers = [":%s/header" % name], ) diff --git a/tools/buck/rust_library.bzl b/tools/buck/rust_library.bzl deleted file mode 100644 index 67ec2ac7..00000000 --- a/tools/buck/rust_library.bzl +++ /dev/null @@ -1,34 +0,0 @@ -load("//tools/buck:genrule.bzl", "genrule") - -def rust_library( - name, - srcs, - features = [], - rustc_flags = [], - build_script = None, - **kwargs): - if build_script: - rust_binary( - name = "%s@build" % name, - srcs = srcs + [build_script], - crate = "build", - crate_root = build_script, - features = features, - rustc_flags = rustc_flags, - ) - - genrule( - name = "%s@cfg" % name, - out = "output", - cmd = "env RUSTC=rustc TARGET= $(exe :%s@build) | sed -n s/^cargo:rustc-cfg=/--cfg=/p > ${OUT}" % name, - ) - - rustc_flags = rustc_flags + ["@$(location :%s@cfg)" % name] - - native.rust_library( - name = name, - srcs = srcs, - features = features, - rustc_flags = rustc_flags, - **kwargs - ) diff --git a/tools/buck/toolchains/BUCK b/tools/buck/toolchains/BUCK new file mode 100644 index 00000000..87ee8933 --- /dev/null +++ b/tools/buck/toolchains/BUCK @@ -0,0 +1,21 @@ +load("@prelude//toolchains:cxx.bzl", "system_cxx_toolchain") +load("@prelude//toolchains:python.bzl", "system_python_bootstrap_toolchain") +load("@prelude//toolchains:rust.bzl", "system_rust_toolchain") + +system_cxx_toolchain( + name = "cxx", + visibility = ["PUBLIC"], +) + +system_python_bootstrap_toolchain( + name = "python_bootstrap", + visibility = ["PUBLIC"], +) + +system_rust_toolchain( + name = "rust", + default_edition = None, + rustc_flags = ["-Clink-arg=-fuse-ld=lld"], + rustdoc_flags = ["-Zunstable-options"], # doc builds use unstable '--extern-html-root-url' + visibility = ["PUBLIC"], +) |