diff --git a/.bazelignore b/.bazelignore index c42dab314..be6cbc1f1 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1,2 +1,3 @@ +buck-out/ target/ tools/buck/buck2/ diff --git a/.bazelrc b/.bazelrc index 5e3ff76a0..09d078e38 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,2 +1,21 @@ +############################################################################### +## Bazel Configuration Flags +## +## `.bazelrc` is a Bazel configuration file. +## https://bazel.build/docs/best-practices#bazelrc-file +############################################################################### + build --enable_platform_specific_config build:linux --@rules_rust//:extra_rustc_flags=-Clink-arg=-fuse-ld=lld +build:linux --cxxopt=-std=c++17 +build:macos --cxxopt=-std=c++17 + +############################################################################### +## Custom user flags +## +## This should always be the last thing in the `.bazelrc` file to ensure +## consistent behavior when setting flags in that file as `.bazelrc` files are +## evaluated top to bottom. +############################################################################### + +try-import %workspace%/user.bazelrc diff --git a/.bcr/README.md b/.bcr/README.md new file mode 100644 index 000000000..44ae7fe55 --- /dev/null +++ b/.bcr/README.md @@ -0,0 +1,9 @@ +# Bazel Central Registry + +When the ruleset is released, we want it to be published to the +Bazel Central Registry automatically: + + +This folder contains configuration files to automate the publish step. +See +for authoritative documentation about these files. diff --git a/.bcr/config.yml b/.bcr/config.yml new file mode 100644 index 000000000..8531afc11 --- /dev/null +++ b/.bcr/config.yml @@ -0,0 +1,3 @@ +fixedReleaser: + login: dtolnay + email: dtolnay@gmail.com diff --git a/.bcr/metadata.template.json b/.bcr/metadata.template.json new file mode 100644 index 000000000..0982309d0 --- /dev/null +++ b/.bcr/metadata.template.json @@ -0,0 +1,16 @@ +{ + "homepage": "https://cxx.rs", + "maintainers": [ + { + "github": "dtolnay", + "github_user_id": 1940490, + "email": "dtolnay@gmail.com", + "name": "David Tolnay" + } + ], + "repository": [ + "github:dtolnay/cxx" + ], + "versions": [], + "yanked_versions": {} +} diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml new file mode 100644 index 000000000..b6a039872 --- /dev/null +++ b/.bcr/presubmit.yml @@ -0,0 +1,15 @@ +matrix: + platform: + - macos_arm64 + - ubuntu2404 + - windows + bazel: [8.x, 9.x] +tasks: + verify_targets: + name: Verify build targets + platform: ${{ platform }} + bazel: ${{ bazel }} + build_targets: + - '@cxx.rs//...' + test_targets: + - '@cxx.rs//...' diff --git a/.bcr/source.template.json b/.bcr/source.template.json new file mode 100644 index 000000000..902c2386c --- /dev/null +++ b/.bcr/source.template.json @@ -0,0 +1,5 @@ +{ + "integrity": "", + "strip_prefix": "{REPO}-{VERSION}", + "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{VERSION}.tar.gz" +} diff --git a/.buckconfig b/.buckconfig index 045974f7b..1878b580c 100644 --- a/.buckconfig +++ b/.buckconfig @@ -1,9 +1,14 @@ -[repositories] -repo = . +[cells] +root = . prelude = tools/buck/prelude toolchains = tools/buck/toolchains -ovr_config = tools/buck/prelude -buck = none +none = none + +[external_cells] +prelude = bundled + +[cell_aliases] +config = prelude fbcode = none fbsource = none @@ -11,7 +16,15 @@ fbsource = none # 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 +# +# Also hide some Bazel-managed directories that contain symlinks to the repo root. +ignore = \ + .git, \ + bazel-bin, \ + bazel-cxx, \ + bazel-out, \ + bazel-testlogs, \ + target [parser] -target_platform_detector_spec = target://...->ovr_config//platforms:default +target_platform_detector_spec = target:root//...->prelude//platforms:default diff --git a/.buckroot b/.buckroot new file mode 100644 index 000000000..e69de29bb diff --git a/.clang-format b/.clang-format index 208599798..8ea286f7e 100644 --- a/.clang-format +++ b/.clang-format @@ -1,2 +1,3 @@ AlwaysBreakTemplateDeclarations: true MaxEmptyLinesToKeep: 3 +ReflowComments: false diff --git a/.clang-tidy b/.clang-tidy index b0a6da98b..930628979 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -3,16 +3,19 @@ Checks: clang-diagnostic-*, cppcoreguidelines-*, modernize-*, + -cppcoreguidelines-avoid-const-or-ref-data-members, -cppcoreguidelines-macro-usage, -cppcoreguidelines-owning-memory, - -cppcoreguidelines-pro-bounds-array-to-pointer-decay, -cppcoreguidelines-pro-bounds-pointer-arithmetic, -cppcoreguidelines-pro-type-const-cast, -cppcoreguidelines-pro-type-member-init, -cppcoreguidelines-pro-type-reinterpret-cast, - -cppcoreguidelines-pro-type-vararg, -cppcoreguidelines-special-member-functions, - -modernize-use-default-member-init, - -modernize-use-equals-default, + -modernize-concat-nested-namespaces, + -modernize-return-braced-init-list, + -modernize-type-traits, + -modernize-use-constraints, + -modernize-use-nodiscard, + -modernize-use-ranges, -modernize-use-trailing-return-type, HeaderFilterRegex: cxx\.h diff --git a/.clippy.toml b/.clippy.toml deleted file mode 100644 index 11d46a73f..000000000 --- a/.clippy.toml +++ /dev/null @@ -1 +0,0 @@ -msrv = "1.48.0" diff --git a/.devcontainer/build.Dockerfile b/.devcontainer/build.Dockerfile index f27638843..74ddd7b6c 100644 --- a/.devcontainer/build.Dockerfile +++ b/.devcontainer/build.Dockerfile @@ -1,18 +1,14 @@ -FROM mcr.microsoft.com/vscode/devcontainers/rust:1 +FROM mcr.microsoft.com/devcontainers/rust:bookworm RUN apt-get update \ && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install --no-install-recommends openjdk-11-jdk lld \ - && rustup default nightly 2>&1 \ - && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \ - && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/4.0.0/bazel-4.0.0-installer-linux-x86_64.sh \ - && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/a5f0342ae3/buck-a5f0342ae3-java11.pex \ - && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \ - && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \ - && chmod +x bin/install-bazel bin/buck bin/buildifier \ - && bin/install-bazel \ - && unzip tmp/watchman.zip -d tmp \ - && mv tmp/watchman-v2020.09.21.00-linux/bin/watchman bin \ - && mv tmp/watchman-v2020.09.21.00-linux/lib/* /usr/local/lib \ - && mkdir -p /usr/local/var/run/watchman \ - && rm tmp/watchman.zip + && apt-get -y install --no-install-recommends clang lld zstd \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && wget -q -O /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-amd64 \ + && wget -q -O /tmp/buck.zst https://github.com/facebook/buck2/releases/download/latest/buck2-x86_64-unknown-linux-gnu.zst \ + && wget -q -O /usr/local/bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier-linux-amd64 \ + && unzstd /tmp/buck.zst -o /usr/local/bin/buck \ + && chmod +x /usr/local/bin/bazel /usr/local/bin/buck /usr/local/bin/buildifier \ + && rm /tmp/buck.zst \ + && rustup component add rust-analyzer rust-src diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b8deba2f5..b5b291161 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,8 +13,8 @@ }, "extensions": [ "BazelBuild.vscode-bazel", - "matklad.rust-analyzer", "ms-vscode.cpptools", + "rust-lang.rust-analyzer", "vadimcn.vscode-lldb" ] } diff --git a/.gitattributes b/.gitattributes index fc5f72273..985fcd6e8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ -third-party/BUCK linguist-generated -third-party/bazel/** linguist-generated +/MODULE.bazel.lock linguist-generated +/third-party/BUCK linguist-generated +/third-party/bazel/** linguist-generated diff --git a/.github/workflows/buck2.yml b/.github/workflows/buck2.yml new file mode 100644 index 000000000..390779c22 --- /dev/null +++ b/.github/workflows/buck2.yml @@ -0,0 +1,30 @@ +name: Buck2 + +on: + push: + workflow_dispatch: + schedule: [cron: "40 1,13 * * *"] + +permissions: + contents: read + +jobs: + buck2: + name: Buck2 on ${{matrix.os == 'ubuntu' && 'Linux' || matrix.os == 'macos' && 'macOS' || matrix.os == 'windows' && 'Windows' || '???'}} + runs-on: ${{matrix.os}}-latest + strategy: + fail-fast: false + matrix: + os: [ubuntu, macos, windows] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@stable + with: + components: rust-src + - uses: dtolnay/install-buck2@latest + - run: buck2 run demo + - run: buck2 build ... + - run: buck2 test ... + - name: Run buck2 starlark lint + run: git ls-files ':(glob)tools/buck/**/*.bzl' | xargs buck2 starlark lint diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00109ff8b..121908c17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,7 @@ name: CI on: push: pull_request: + workflow_dispatch: schedule: [cron: "40 1 * * *"] permissions: @@ -16,35 +17,101 @@ jobs: name: ${{matrix.name || format('Rust {0}', matrix.rust)}} needs: pre_ci if: needs.pre_ci.outputs.continue - runs-on: ${{matrix.os || 'ubuntu'}}-latest + runs-on: ${{matrix.runs-on || format('{0}-latest', matrix.os)}} strategy: fail-fast: false matrix: + rust: [nightly, beta, stable, 1.88.0] + os: [ubuntu] + cc: [g++] + flags: [''] include: - - rust: nightly - - rust: beta - - rust: stable - - rust: 1.60.0 - - rust: 1.64.0 - - name: macOS + - name: Cargo on macOS rust: nightly os: macos - - name: Windows (msvc) + - name: Cargo on Windows (msvc) rust: nightly-x86_64-pc-windows-msvc os: windows - flags: /EHsc + - name: Clang + rust: nightly + os: ubuntu + cc: clang++ + flags: -std=c++20 + - name: Clang (no exceptions) + rust: nightly + os: ubuntu + cc: clang++ + flags: -std=c++20 -fno-exceptions + - name: C++14 on Linux + rust: nightly + os: ubuntu + cc: g++ + flags: -std=c++14 + - name: C++14 on macOS + rust: nightly + os: macos + flags: -std=c++14 + - name: C++14 on Windows + rust: nightly-x86_64-pc-windows-msvc + os: windows + flags: /std:c++14 + - name: C++17 on Linux + rust: nightly + os: ubuntu + cc: g++ + flags: -std=c++17 + - name: C++17 on macOS + rust: nightly + os: macos + flags: -std=c++17 + - name: C++17 on Windows + rust: nightly-x86_64-pc-windows-msvc + os: windows + flags: /std:c++17 + - name: C++20 on Linux + rust: nightly + os: ubuntu + cc: g++ + flags: -std=c++20 + - name: C++20 on macOS + rust: nightly + os: macos + flags: -std=c++20 + runs-on: macos-15 + - name: C++20 on Windows + rust: nightly-x86_64-pc-windows-msvc + os: windows + flags: /std:c++20 + - name: Pedantic + rust: nightly + os: ubuntu + cc: clang++ + flags: + -Weverything + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-c++20-compat + -Wno-implicit-int-conversion + -Wno-missing-prototypes + -Wno-padded + -Wno-sign-conversion + -Wno-undefined-func-template + -Wno-unsafe-buffer-usage + -Wno-unused-macros env: - CXXFLAGS: ${{matrix.flags}} + CXX: ${{matrix.cc}} + CXXFLAGS: ${{matrix.flags}} ${{matrix.os == 'windows' && '/EHsc /WX' || '-Werror -Wall -Wpedantic'}} 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@v3 + - uses: actions/checkout@v7 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} + components: rust-src - name: Determine test suite subset # Our Windows and macOS jobs are the longest running, so exclude the # relatively slow compiletest from them to speed up end-to-end CI time, @@ -54,71 +121,214 @@ jobs: # builds. run: | echo RUSTFLAGS=$RUSTFLAGS >> $GITHUB_ENV - echo exclude=--exclude cxx-test-suite ${{matrix.rust == '1.60.0' && '--exclude cxxbridge-cmd' || ''}} >> $GITHUB_OUTPUT + echo exclude=--exclude cxx-test-suite >> $GITHUB_OUTPUT env: - RUSTFLAGS: ${{env.RUSTFLAGS}} ${{matrix.os && github.event_name != 'schedule' && '--cfg skip_ui_tests' || ''}} + RUSTFLAGS: ${{env.RUSTFLAGS}} ${{matrix.os != 'ubuntu' && github.event_name != 'schedule' && '--cfg skip_ui_tests' || ''}} id: testsuite shell: bash + - name: Ignore macOS linker warning + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Alinker_messages >> $GITHUB_ENV + if: matrix.os == 'macos' - run: cargo run --manifest-path demo/Cargo.toml - run: cargo test --workspace ${{steps.testsuite.outputs.exclude}} + if: contains(matrix.flags, '-fno-exceptions') == false - 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}} + - uses: actions/upload-artifact@v7 + if: matrix.os == 'ubuntu' && matrix.rust == 'nightly' && matrix.cc == '' && matrix.flags == '' && always() + with: + name: Cargo.lock + path: Cargo.lock + continue-on-error: true + + wasi: + name: WebAssembly + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@nightly + with: + targets: wasm32-wasip1 + components: rust-src + - uses: dtolnay/install@wasmtime-cli + - run: curl https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-33/wasi-sdk-33.0-x86_64-linux.tar.gz --location --silent --show-error --fail --retry 2 --output ${{runner.temp}}/wasi-sdk-33.0-x86_64-linux.tar.gz + - run: tar xf ${{runner.temp}}/wasi-sdk-33.0-x86_64-linux.tar.gz -C ${{runner.temp}} + - run: cargo build --target=wasm32-wasip1 --manifest-path=demo/Cargo.toml --release + --config='target.wasm32-wasip1.linker="${{runner.temp}}/wasi-sdk-33.0-x86_64-linux/bin/lld"' + --config='target.wasm32-wasip1.rustflags=["-Clink-args=-L${{runner.temp}}/wasi-sdk-33.0-x86_64-linux/share/wasi-sysroot/lib/wasm32-wasip1/eh", "-Clink-args=-lc++abi", "-Clink-args=-lunwind"]' + env: + CXX: ${{runner.temp}}/wasi-sdk-33.0-x86_64-linux/bin/clang++ + CXXFLAGS: --sysroot=${{runner.temp}}/wasi-sdk-33.0-x86_64-linux/share/wasi-sysroot + - run: wasmtime --wasm=exceptions target/wasm32-wasip1/release/demo.wasm - buck: - name: Buck + emscripten: + name: Emscripten + needs: pre_ci + if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest - if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@nightly with: - submodules: true + targets: wasm32-unknown-emscripten + components: rust-src + - uses: emscripten-core/setup-emsdk@v16 + - run: cargo build + --manifest-path=demo/Cargo.toml + --target=wasm32-unknown-emscripten + --release + -Zbuild-std + --config='target.wasm32-unknown-emscripten.linker="em++"' + env: + RUSTFLAGS: -Clink-arg=--emrun ${{env.RUSTFLAGS}} + - name: Create demo.html for demo.js + run: echo '' > target/wasm32-unknown-emscripten/release/demo.html + - name: Install firefox + uses: browser-actions/setup-firefox@v1 + id: setup-firefox + - run: emrun target/wasm32-unknown-emscripten/release/demo.html + --browser=${{steps.setup-firefox.outputs.firefox-path}} + --browser_args=-headless + --safe_firefox_profile + --log_stdout=${{runner.temp}}/demo.log + --timeout=60 + --kill_exit + - run: cat ${{runner.temp}}/demo.log + - run: grep --silent blobid ${{runner.temp}}/demo.log + + reindeer: + name: Reindeer + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 - uses: dtolnay/rust-toolchain@stable + with: + components: rust-src - uses: dtolnay/install@reindeer - - uses: dtolnay/install@buck2 - - name: Install lld - run: sudo apt-get install lld - - run: cargo vendor --versioned-dirs --locked - working-directory: third-party - run: reindeer buckify 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 + name: Bazel on ${{matrix.os == 'ubuntu' && 'Linux' || matrix.os == 'macos' && 'macOS' || matrix.os == 'windows' && 'Windows' || '???'}} + runs-on: ${{matrix.os}}-latest if: github.event_name != 'pull_request' + strategy: + fail-fast: false + matrix: + os: [ubuntu, macos, windows] timeout-minutes: 45 steps: - - uses: actions/checkout@v3 - - name: Install Bazel - run: | - wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/6.0.0/bazel-6.0.0-installer-linux-x86_64.sh - chmod +x install.sh - ./install.sh --user - echo $HOME/bin >> $GITHUB_PATH + - uses: actions/checkout@v7 + - name: Disable initramfs update + run: sudo sed -i 's/^update_initramfs=yes$/update_initramfs=no/' /etc/initramfs-tools/update-initramfs.conf + if: matrix.os == 'ubuntu' + - name: Disable man-db update + run: sudo rm -f /var/lib/man-db/auto-update + if: matrix.os == 'ubuntu' - name: Install lld run: sudo apt-get install lld - - run: bazel run demo --verbose_failures --noshow_progress - - run: bazel test ... --verbose_failures --noshow_progress + if: matrix.os == 'ubuntu' + - name: Set bazelrc for Windows + run: echo "startup --output_user_root=D:/bzl" > user.bazelrc + if: matrix.os == 'windows' + - run: bazel --version + - run: bazel run demo --verbose_failures --noshow_progress ${{matrix.os == 'macos' && '--xcode_version_config=tools/bazel:github_actions_xcodes' || ''}} + - run: bazel test ... --verbose_failures --noshow_progress ${{matrix.os == 'macos' && '--xcode_version_config=tools/bazel:github_actions_xcodes' || ''}} + - name: Check MODULE.bazel.lock up to date + run: git diff --exit-code + - run: bazel run //third-party:vendor + if: matrix.os == 'ubuntu' || matrix.os == 'macos' + - name: Check third-party/bazel up to date + run: git diff --exit-code + if: matrix.os == 'ubuntu' || matrix.os == 'macos' + + buildifier: + name: Buildifier + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + - run: go install github.com/bazelbuild/buildtools/buildifier@latest + - run: echo $(go env GOPATH)/bin >> $GITHUB_PATH + - run: git ls-files '*.bzl' '*.bazel' | xargs buildifier + - run: git ls-files ':(glob)**/BUCK' | xargs -n1 buildifier -path BUILD.bazel -lint fix + - name: Check that buildifier wanted no changes + run: git diff --exit-code + + minimal: + name: Minimal versions + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked --workspace + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + - run: cargo docs-rs -p cxx-build + - run: cargo docs-rs -p cxx-gen + - run: cargo docs-rs -p cxxbridge-flags + - run: cargo docs-rs -p cxxbridge-macro + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test --test=cxx_string + env: + MIRIFLAGS: -Zmiri-strict-provenance clippy: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 + env: + RUSTFLAGS: -Dwarnings steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@clippy - - run: cargo clippy --workspace --tests -- -Dclippy::all + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy, rust-src + - run: cargo clippy --workspace --tests --exclude demo -- -Dclippy::all -Dclippy::pedantic + - run: cargo clippy --manifest-path demo/Cargo.toml -- -Dclippy::all clang-tidy: name: Clang Tidy @@ -126,11 +336,27 @@ jobs: if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v7 + - name: Disable initramfs update + run: sudo sed -i 's/^update_initramfs=yes$/update_initramfs=no/' /etc/initramfs-tools/update-initramfs.conf + - name: Disable man-db update + run: sudo rm -f /var/lib/man-db/auto-update - name: Install clang-tidy - run: sudo apt-get install clang-tidy-11 + run: sudo apt-get update && sudo apt-get install clang-tidy-20 - name: Run clang-tidy - run: clang-tidy-11 src/cxx.cc --warnings-as-errors=* + run: clang-tidy-20 src/cxx.cc --warnings-as-errors=* + + eslint: + name: ESLint + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + - run: npm install + working-directory: book + - run: npx eslint + working-directory: book outdated: name: Outdated @@ -138,6 +364,7 @@ jobs: if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@stable - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml new file mode 100644 index 000000000..025fe23c4 --- /dev/null +++ b/.github/workflows/install.yml @@ -0,0 +1,18 @@ +name: Install + +on: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + push: {tags: ['*']} + +permissions: {} + +env: + RUSTFLAGS: -Dwarnings + +jobs: + install: + name: Install + uses: dtolnay/.github/.github/workflows/check_install.yml@master + with: + crate: cxxbridge-cmd diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..06305bafc --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,24 @@ +name: Release + +on: + release: + types: [released] + +permissions: + attestations: write + contents: write + id-token: write + +jobs: + upload: + uses: dtolnay/.github/.github/workflows/release_tgz.yml@master + + publish-to-bcr: + needs: upload + uses: bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@92ae43f10e552721931f98b61fe5506bbdf32ce6 + with: + tag_name: ${{github.event.release.tag_name}} + registry_fork: dtolnay-contrib/bazel-central-registry + attest: false + secrets: + publish_token: ${{secrets.PUBLISH_TOKEN}} diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index 09382b791..78d046805 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -7,6 +7,7 @@ on: paths: - book/** - .github/workflows/site.yml + workflow_dispatch: jobs: deploy: @@ -16,15 +17,9 @@ jobs: contents: write timeout-minutes: 30 steps: - - uses: actions/checkout@v3 - - - name: Get mdBook - run: | - export MDBOOK_VERSION="dtolnay" - export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz" - export MDBOOK_URL="https://github.com/dtolnay/mdBook/releases/download/cxx/${MDBOOK_TARBALL}" - curl -Lf "${MDBOOK_URL}" | tar -xzC book - book/mdbook --version + - uses: actions/checkout@v7 + - uses: dtolnay/install@mdbook + - run: mdbook --version - name: Build run: book/build.sh diff --git a/.gitignore b/.gitignore index b036b6fb9..3dfe7323e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,13 @@ +/.buckconfig.d/ +/.buckconfig.local /.buckd /bazel-bin /bazel-cxx /bazel-out /bazel-testlogs +/user.bazelrc /buck-out /expand.cc /expand.rs -Cargo.lock -target +/target/ +/Cargo.lock diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 208a58a9a..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "tools/buck/prelude"] - path = tools/buck/prelude - url = https://github.com/facebookincubator/buck2-prelude diff --git a/.watchmanconfig b/.watchmanconfig index d93f3088a..935c1863f 100644 --- a/.watchmanconfig +++ b/.watchmanconfig @@ -1,3 +1,3 @@ { - "ignore_dirs": ["buck-out"] + "ignore_dirs": ["buck-out"] } diff --git a/BUCK b/BUCK index 6fcf7fa82..1466d12cc 100644 --- a/BUCK +++ b/BUCK @@ -1,7 +1,14 @@ +load(":Cargo.toml", cargo_toml = "value") + +CARGO_PKG_VERSION_PATCH = cargo_toml["package"]["version"].split(".")[2] + rust_library( name = "cxx", srcs = glob(["src/**/*.rs"]), - edition = "2018", + doc_deps = [ + ":cxx-build", + ], + edition = "2024", features = [ "alloc", "std", @@ -9,22 +16,34 @@ rust_library( visibility = ["PUBLIC"], deps = [ ":core", - ":macro", + ":cxxbridge-macro", + "//third-party:foldhash", ], ) -rust_binary( +alias( name = "codegen", - srcs = glob(["gen/cmd/src/**/*.rs"]) + [ - "gen/cmd/src/gen", - "gen/cmd/src/syntax", - ], - crate = "cxxbridge", - edition = "2018", + actual = ":cxxbridge", visibility = ["PUBLIC"], +) + +rust_binary( + name = "cxxbridge", + srcs = glob([ + "bridge/cmd/src/**/*.rs", + "bridge/src/builtin/*.h", + ]) + [ + "bridge/cmd/src/bridge", + "bridge/cmd/src/syntax", + ], + edition = "2024", + env = { + "CARGO_PKG_VERSION_PATCH": CARGO_PKG_VERSION_PATCH, + }, deps = [ "//third-party:clap", "//third-party:codespan-reporting", + "//third-party:indexmap", "//third-party:proc-macro2", "//third-party:quote", "//third-party:syn", @@ -37,36 +56,47 @@ cxx_library( exported_headers = { "cxx.h": "include/cxx.h", }, - exported_linker_flags = ["-lstdc++"], header_namespace = "rust", + preferred_linkage = "static", visibility = ["PUBLIC"], ) rust_library( - name = "macro", + name = "cxxbridge-macro", srcs = glob(["macro/src/**/*.rs"]) + ["macro/src/syntax"], - crate = "cxxbridge_macro", - edition = "2018", + doctests = False, + edition = "2024", + env = { + "CARGO_PKG_VERSION_PATCH": CARGO_PKG_VERSION_PATCH, + }, proc_macro = True, deps = [ + "//third-party:indexmap", "//third-party:proc-macro2", "//third-party:quote", + "//third-party:rustversion", "//third-party:syn", ], ) rust_library( - name = "build", - srcs = glob(["gen/build/src/**/*.rs"]) + [ - "gen/build/src/gen", - "gen/build/src/syntax", + name = "cxx-build", + srcs = glob([ + "bridge/build/src/**/*.rs", + "bridge/src/builtin/*.h", + ]) + [ + "bridge/build/src/bridge", + "bridge/build/src/syntax", ], - edition = "2018", - visibility = ["PUBLIC"], + doctests = False, + edition = "2024", + env = { + "CARGO_PKG_VERSION_PATCH": CARGO_PKG_VERSION_PATCH, + }, deps = [ "//third-party:cc", "//third-party:codespan-reporting", - "//third-party:once_cell", + "//third-party:indexmap", "//third-party:proc-macro2", "//third-party:quote", "//third-party:scratch", @@ -75,16 +105,23 @@ rust_library( ) rust_library( - name = "lib", - srcs = glob(["gen/lib/src/**/*.rs"]) + [ - "gen/lib/src/gen", - "gen/lib/src/syntax", + name = "cxx-gen", + srcs = glob([ + "bridge/lib/src/**/*.rs", + "bridge/src/builtin/*.h", + ]) + [ + "bridge/lib/src/bridge", + "bridge/lib/src/syntax", ], - edition = "2018", + edition = "2024", + env = { + "CARGO_PKG_VERSION_PATCH": CARGO_PKG_VERSION_PATCH, + }, visibility = ["PUBLIC"], deps = [ "//third-party:cc", "//third-party:codespan-reporting", + "//third-party:indexmap", "//third-party:proc-macro2", "//third-party:quote", "//third-party:syn", diff --git a/BUILD b/BUILD deleted file mode 100644 index c88eb2494..000000000 --- a/BUILD +++ /dev/null @@ -1,89 +0,0 @@ -load("@rules_cc//cc:defs.bzl", "cc_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", - ], - visibility = ["//visibility:public"], - deps = [":core-lib"], -) - -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", - "//third-party:codespan-reporting", - "//third-party:proc-macro2", - "//third-party:quote", - "//third-party:syn", - ], -) - -cc_library( - name = "core", - hdrs = ["include/cxx.h"], - include_prefix = "rust", - strip_include_prefix = "include", - visibility = ["//visibility:public"], -) - -cc_library( - name = "core-lib", - srcs = ["src/cxx.cc"], - hdrs = ["include/cxx.h"], -) - -rust_proc_macro( - name = "cxxbridge-macro", - srcs = glob(["macro/src/**/*.rs"]), - edition = "2018", - deps = [ - "//third-party:proc-macro2", - "//third-party:quote", - "//third-party:syn", - ], -) - -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:once_cell", - "//third-party:proc-macro2", - "//third-party:quote", - "//third-party:scratch", - "//third-party:syn", - ], -) - -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", - "//third-party:codespan-reporting", - "//third-party:proc-macro2", - "//third-party:quote", - "//third-party:syn", - ], -) diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 000000000..2cac67cf6 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,110 @@ +load("@rules_cc//cc:defs.bzl", "cc_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 = "2024", + link_deps = [ + ":core-lib", + ], + proc_macro_deps = [ + ":cxxbridge-macro", + ], + version = module_version(), + visibility = ["//visibility:public"], + deps = [ + "@crates.io//:foldhash", + ], +) + +alias( + name = "codegen", + actual = ":cxxbridge", + visibility = ["//visibility:public"], +) + +rust_binary( + name = "cxxbridge", + srcs = glob(["bridge/cmd/src/**/*.rs"]), + compile_data = glob(["bridge/cmd/src/bridge/**/*.h"]), + edition = "2024", + version = module_version(), + deps = [ + "@crates.io//:clap", + "@crates.io//:codespan-reporting", + "@crates.io//:indexmap", + "@crates.io//:proc-macro2", + "@crates.io//:quote", + "@crates.io//:syn", + ], +) + +cc_library( + name = "core", + hdrs = ["include/cxx.h"], + include_prefix = "rust", + strip_include_prefix = "include", + visibility = ["//visibility:public"], +) + +cc_library( + name = "core-lib", + srcs = ["src/cxx.cc"], + hdrs = ["include/cxx.h"], + linkstatic = True, +) + +rust_proc_macro( + name = "cxxbridge-macro", + srcs = glob(["macro/src/**/*.rs"]), + edition = "2024", + proc_macro_deps = [ + "@crates.io//:rustversion", + ], + version = module_version(), + deps = [ + "@crates.io//:indexmap", + "@crates.io//:proc-macro2", + "@crates.io//:quote", + "@crates.io//:syn", + ], +) + +rust_library( + name = "cxx-build", + srcs = glob(["bridge/build/src/**/*.rs"]), + compile_data = glob(["bridge/build/src/bridge/**/*.h"]), + edition = "2024", + version = module_version(), + deps = [ + "@crates.io//:cc", + "@crates.io//:codespan-reporting", + "@crates.io//:indexmap", + "@crates.io//:proc-macro2", + "@crates.io//:quote", + "@crates.io//:scratch", + "@crates.io//:syn", + ], +) + +rust_library( + name = "cxx-gen", + srcs = glob(["bridge/lib/src/**/*.rs"]), + compile_data = glob(["bridge/lib/src/bridge/**/*.h"]), + edition = "2024", + version = module_version(), + visibility = ["//visibility:public"], + deps = [ + "@crates.io//:cc", + "@crates.io//:codespan-reporting", + "@crates.io//:indexmap", + "@crates.io//:proc-macro2", + "@crates.io//:quote", + "@crates.io//:syn", + ], +) diff --git a/Cargo.toml b/Cargo.toml index 5ed5809c3..102793097 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "cxx" -version = "1.0.91" # remember to update html_root_url +version = "1.0.199" authors = ["David Tolnay "] categories = ["development-tools::ffi", "api-bindings", "no-std"] description = "Safe interop between Rust and C++" documentation = "https://docs.rs/cxx" -edition = "2018" -exclude = ["/demo", "/gen", "/syntax", "/third-party", "/tools/buck/prelude"] +edition = "2024" +exclude = ["/bridge", "/demo", "/syntax", "/third-party", "/tools/buck/prelude"] homepage = "https://cxx.rs" keywords = ["ffi", "c++"] license = "MIT OR Apache-2.0" links = "cxxbridge1" repository = "https://github.com/dtolnay/cxx" -rust-version = "1.60" +rust-version = "1.88" [features] default = ["std", "cxxbridge-flags/default"] # c++11 @@ -20,33 +20,67 @@ default = ["std", "cxxbridge-flags/default"] # c++11 "c++17" = ["cxxbridge-flags/c++17"] "c++20" = ["cxxbridge-flags/c++20"] alloc = [] -std = ["alloc"] +std = ["alloc", "foldhash/std"] [dependencies] -cxxbridge-macro = { version = "=1.0.91", path = "macro" } -link-cplusplus = "1.0" +cxxbridge-macro = { version = "=1.0.199", path = "macro" } +foldhash = { version = "0.2", default-features = false } +link-cplusplus = "1.0.11" [build-dependencies] -cc = "1.0.49" -cxxbridge-flags = { version = "=1.0.91", path = "flags", default-features = false } +cc = "1.0.101" +cxxbridge-flags = { version = "=1.0.199", path = "flags", default-features = false } [dev-dependencies] -cxx-build = { version = "=1.0.91", path = "gen/build" } -cxx-gen = { version = "0.7", path = "gen/lib" } +cc = "1.0.101" +cxx-build = { version = "1", path = "bridge/build" } +cxx-gen = { version = "=0.7.199", path = "bridge/lib" } cxx-test-suite = { version = "0", path = "tests/ffi" } -rustversion = "1.0" -trybuild = { version = "1.0.66", features = ["diff"] } +indoc = "2" +proc-macro2 = "1.0.95" +quote = "1.0.40" +rustversion = "1.0.13" +scratch = "1" +target-triple = "1" +tempfile = "3.8" +trybuild = { version = "1.0.108", features = ["diff"] } -[lib] -doc-scrape-examples = false +# Disallow incompatible version appearing in the same lockfile. +[target.'cfg(any())'.build-dependencies] +cxx-build = { version = "=1.0.199", path = "bridge/build" } +cxxbridge-cmd = { version = "=1.0.199", path = "bridge/cmd" } [workspace] -members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"] +members = ["demo", "flags", "bridge/build", "bridge/cmd", "bridge/lib", "macro", "tests/ffi"] [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = ["--cfg", "doc_cfg"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] + +[package.metadata.bazel] +additive_build_file_content = """ +load("@rules_cc//cc:defs.bzl", "cc_library") +cc_library( + name = "cxx_cc", + srcs = ["src/cxx.cc"], + hdrs = ["include/cxx.h"], + include_prefix = "rust", + includes = ["include"], + linkstatic = True, + strip_include_prefix = "include", + visibility = ["//visibility:public"], +) +""" +extra_aliased_targets = { cxx_cc = "cxx_cc" } +gen_build_script = false +link_deps = [":cxx_cc"] [patch.crates-io] cxx = { path = "." } -cxx-build = { path = "gen/build" } +cxx-build = { path = "bridge/build" } diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 000000000..079c06cf5 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,21 @@ +module( + name = "cxx.rs", + version = "0.0.0", + bazel_compatibility = [">=8.0.0"], +) + +bazel_dep(name = "apple_support", version = "2.1.0") +bazel_dep(name = "bazel_features", version = "1.50.0") +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "platforms", version = "1.1.0") +bazel_dep(name = "rules_cc", version = "0.2.17") +bazel_dep(name = "rules_rust", version = "0.73.0") + +rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") +rust.toolchain(versions = ["1.97.1"]) +use_repo(rust, "rust_toolchains") + +register_toolchains("@rust_toolchains//:all") + +crate_repositories = use_extension("//tools/bazel:extension.bzl", "crate_repositories") +use_repo(crate_repositories, "crates.io", "vendor") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock new file mode 100644 index 000000000..dcf0ca74d --- /dev/null +++ b/MODULE.bazel.lock @@ -0,0 +1,458 @@ +{ + "lockFileVersion": 28, + "registryFileHashes": { + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1", + "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215", + "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2", + "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c", + "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", + "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", + "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e", + "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1", + "https://bcr.bazel.build/modules/apple_support/1.24.1/MODULE.bazel": "f46e8ddad60aef170ee92b2f3d00ef66c147ceafea68b6877cb45bd91737f5f8", + "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4", + "https://bcr.bazel.build/modules/apple_support/2.1.0/MODULE.bazel": "b15c125dabed01b6803c129cd384de4997759f02f8ec90dc5136bcf6dfc5086a", + "https://bcr.bazel.build/modules/apple_support/2.1.0/source.json": "78064cfefe18dee4faaf51893661e0d403784f3efe88671d727cdcdc67ed8fb3", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", + "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", + "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", + "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", + "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", + "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", + "https://bcr.bazel.build/modules/bazel_features/1.50.0/MODULE.bazel": "2083ef9c7a469f520890483ccf8e0189d6e71e2117e7752e15e6554433d5ae3e", + "https://bcr.bazel.build/modules/bazel_features/1.50.0/source.json": "e0ee3debde2789ff56e4452e612d126925ba9ab64d4bde79c67f099d2902df9b", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", + "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f", + "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", + "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", + "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", + "https://bcr.bazel.build/modules/package_metadata/0.0.3/MODULE.bazel": "77890552ecea9e284b5424c9de827a58099348763a4359e975c359a83d4faa83", + "https://bcr.bazel.build/modules/package_metadata/0.0.3/source.json": "742075a428ad12a3fa18a69014c2f57f01af910c6d9d18646c990200853e641a", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", + "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", + "https://bcr.bazel.build/modules/platforms/1.1.0/MODULE.bazel": "1c0c09f5bdcf4b3f924720d2478a3711cb39f4977019ca5988685e5b7e18b3d2", + "https://bcr.bazel.build/modules/platforms/1.1.0/source.json": "fcf351c47596c939140ab0d333dfdd08ed1ea6ce33c2fe70c12493a301cf1344", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", + "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d", + "https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42", + "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", + "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", + "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", + "https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68", + "https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", + "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0", + "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", + "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", + "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", + "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", + "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", + "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", + "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", + "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d", + "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96", + "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", + "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", + "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", + "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", + "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", + "https://bcr.bazel.build/modules/rules_rust/0.73.0/MODULE.bazel": "25e3b077128612754c4add1b4c90d20a6be06566b623dee6e32038d0e8f93062", + "https://bcr.bazel.build/modules/rules_rust/0.73.0/source.json": "8eeb3d9ba7c57916b63887a651e8f84c2f68b7243af9e712d728c2a0b7882255", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c", + "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", + "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", + "https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd", + "https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400", + "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", + "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" + }, + "selectedYankedVersions": {}, + "moduleExtensions": { + "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { + "general": { + "bzlTransitiveDigest": "+Kp6j204mBZ3mxlIDDR0gBoP45BZ4jYRhRAcB8sU0qc=", + "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", + "recordedInputs": [ + "REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools" + ], + "generatedRepoSpecs": { + "com_github_jetbrains_kotlin_git": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", + "attributes": { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" + ], + "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" + } + }, + "com_github_jetbrains_kotlin": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository", + "attributes": { + "git_repository_name": "com_github_jetbrains_kotlin_git", + "compiler_version": "1.9.23" + } + }, + "com_github_google_ksp": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository", + "attributes": { + "urls": [ + "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" + ], + "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", + "strip_version": "1.9.23-1.0.20" + } + }, + "com_github_pinterest_ktlint": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", + "urls": [ + "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" + ], + "executable": true + } + }, + "rules_android": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + "strip_prefix": "rules_android-0.1.1", + "urls": [ + "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" + ] + } + } + } + } + }, + "@@rules_python+//python/extensions:config.bzl%config": { + "general": { + "bzlTransitiveDigest": "dzD8Q2YmrP3fz8saWLHPmlwPLO91ImtTmP/c9JKTStM=", + "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=", + "recordedInputs": [ + "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_python+,pypi__build rules_python++config+pypi__build", + "REPO_MAPPING:rules_python+,pypi__click rules_python++config+pypi__click", + "REPO_MAPPING:rules_python+,pypi__colorama rules_python++config+pypi__colorama", + "REPO_MAPPING:rules_python+,pypi__importlib_metadata rules_python++config+pypi__importlib_metadata", + "REPO_MAPPING:rules_python+,pypi__installer rules_python++config+pypi__installer", + "REPO_MAPPING:rules_python+,pypi__more_itertools rules_python++config+pypi__more_itertools", + "REPO_MAPPING:rules_python+,pypi__packaging rules_python++config+pypi__packaging", + "REPO_MAPPING:rules_python+,pypi__pep517 rules_python++config+pypi__pep517", + "REPO_MAPPING:rules_python+,pypi__pip rules_python++config+pypi__pip", + "REPO_MAPPING:rules_python+,pypi__pip_tools rules_python++config+pypi__pip_tools", + "REPO_MAPPING:rules_python+,pypi__pyproject_hooks rules_python++config+pypi__pyproject_hooks", + "REPO_MAPPING:rules_python+,pypi__setuptools rules_python++config+pypi__setuptools", + "REPO_MAPPING:rules_python+,pypi__tomli rules_python++config+pypi__tomli", + "REPO_MAPPING:rules_python+,pypi__wheel rules_python++config+pypi__wheel", + "REPO_MAPPING:rules_python+,pypi__zipp rules_python++config+pypi__zipp" + ], + "generatedRepoSpecs": { + "rules_python_internal": { + "repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo", + "attributes": { + "transition_setting_generators": {}, + "transition_settings": [] + } + }, + "pypi__build": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl", + "sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__click": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", + "sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__colorama": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", + "sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__importlib_metadata": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl", + "sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__installer": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl", + "sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__more_itertools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl", + "sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__packaging": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", + "sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pep517": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl", + "sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl", + "sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip_tools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl", + "sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pyproject_hooks": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl", + "sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__setuptools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl", + "sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__tomli": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", + "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__wheel": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl", + "sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__zipp": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl", + "sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + } + } + } + }, + "@@rules_python+//python/uv:uv.bzl%uv": { + "general": { + "bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=", + "usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=", + "recordedInputs": [ + "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_python+,platforms platforms" + ], + "generatedRepoSpecs": { + "uv": { + "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo", + "attributes": { + "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'", + "toolchain_names": [ + "none" + ], + "toolchain_implementations": { + "none": "'@@rules_python+//python:none'" + }, + "toolchain_compatible_with": { + "none": [ + "@platforms//:incompatible" + ] + }, + "toolchain_target_settings": {} + } + } + } + } + } + }, + "facts": {}, + "factsVersions": {} +} diff --git a/README.md b/README.md index 883cfe533..9603afdf6 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ cxx = "1.0" cxx-build = "1.0" ``` -*Compiler support: requires rustc 1.60+ and c++11 or newer*
+*Compiler support: requires rustc 1.88+ and c++11 or newer*
*[Release notes](https://github.com/dtolnay/cxx/releases)*
@@ -136,7 +136,7 @@ generators: $ cargo expand --manifest-path demo/Cargo.toml # run C++ code generator and print to stdout -$ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs +$ cargo run --manifest-path bridge/cmd/Cargo.toml -- demo/src/main.rs ```
@@ -244,10 +244,9 @@ cxx-build = "1.0" fn main() { cxx_build::bridge("src/main.rs") // returns a cc::Build .file("src/demo.cc") - .flag_if_supported("-std=c++11") + .std("c++11") .compile("cxxbridge-demo"); - println!("cargo:rerun-if-changed=src/main.rs"); println!("cargo:rerun-if-changed=src/demo.cc"); println!("cargo:rerun-if-changed=include/demo.h"); } @@ -260,7 +259,7 @@ fn main() { For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate way of invoking the C++ code generator as a standalone command line tool. The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be built from the -*gen/cmd* directory of this repo. +*bridge/cmd* directory of this repo. ```bash $ cargo install cxxbridge-cmd diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index 7707436a1..000000000 --- a/WORKSPACE +++ /dev/null @@ -1,25 +0,0 @@ -workspace(name = "cxx.rs") - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "rules_rust", - sha256 = "2466e5b2514772e84f9009010797b9cd4b51c1e6445bbd5b5e24848d90e6fb2e", - urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.18.0/rules_rust-v0.18.0.tar.gz"], -) - -load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") - -rules_rust_dependencies() - -rust_register_toolchains( - versions = ["1.67.0"], -) - -load("@rules_rust//crate_universe:repositories.bzl", "crate_universe_dependencies") - -crate_universe_dependencies() - -load("//third-party/bazel:defs.bzl", "crate_repositories") - -crate_repositories() diff --git a/book/.gitignore b/book/.gitignore index 727750711..3c7d18740 100644 --- a/book/.gitignore +++ b/book/.gitignore @@ -1,3 +1,3 @@ -/build +/build/ /mdbook -/node_modules +/node_modules/ diff --git a/book/book.toml b/book/book.toml index 066f3a627..cd691d95b 100644 --- a/book/book.toml +++ b/book/book.toml @@ -1,10 +1,10 @@ [book] #title = "Rust ♡ C++" authors = ["David Tolnay"] -description = "CXX — safe interop between Rust and C++" +description = "CXX — safe interop between Rust and C++ by David Tolnay. This library provides a safe mechanism for calling C++ code from Rust and Rust code from C++." [rust] -edition = "2018" +edition = "2024" [build] build-dir = "build" diff --git a/book/build.js b/book/build.js index 2cda5860c..db428c02f 100755 --- a/book/build.js +++ b/book/build.js @@ -2,9 +2,8 @@ const fs = require('fs'); const cheerio = require('cheerio'); +const entities = require('html-entities'); const hljs = require('./build/highlight.js'); -const Entities = require('html-entities').AllHtmlEntities; -const entities = new Entities(); const githublink = `\
  • \ @@ -23,16 +22,24 @@ const opengraph = `\ \ `; -const htmljs = `\ -var html = document.querySelector('html'); -html.classList.remove('no-js'); +const themejs = `\ +var theme; +try { theme = localStorage.getItem('mdbook-theme'); } catch(e) {} +if (theme === null || theme === undefined) { theme = default_theme; } +const html = document.documentElement; +html.classList.remove('light') +html.classList.add(theme); +html.classList.add("js");`; + +const themejsReplacement = `\ +const html = document.documentElement; html.classList.add('js');`; const dirs = ['build']; while (dirs.length) { const dir = dirs.pop(); fs.readdirSync(dir).forEach((entry) => { - path = dir + '/' + entry; + const path = dir + '/' + entry; const stat = fs.statSync(path); if (stat.isDirectory()) { dirs.push(path); @@ -44,10 +51,12 @@ while (dirs.length) { } const index = fs.readFileSync(path, 'utf8'); - const $ = cheerio.load(index, { decodeEntities: false }); + const $ = cheerio.load(index, { + decodeEntities: false, + xml: { xmlMode: false }, + }); $('head').append(opengraph); - $('script:nth-of-type(3)').text(htmljs); $('nav#sidebar ol.chapter').append(githublink); $('head link[href="tomorrow-night.css"]').attr('disabled', true); $('head link[href="ayu-highlight.css"]').attr('disabled', true); @@ -59,15 +68,14 @@ while (dirs.length) { return; } const lang = langClass.replace('language-', ''); - const lines = node.html().split('\n'); - const boring = lines.map((line) => - line.includes('') + const originalLines = node.html().split('\n'); + const boring = originalLines.map((line) => + line.includes(''), ); - const ellipsis = lines.map((line) => line.includes('// ...')); + const ellipsis = originalLines.map((line) => line.includes('// ...')); const target = entities.decode(node.text()); - const highlighted = hljs.highlight(lang, target).value; - const result = highlighted - .split('\n') + const highlightedLines = hljs.highlight(lang, target).value.split('\n'); + const result = highlightedLines .map(function (line, i) { if (boring[i]) { line = '' + line; @@ -77,6 +85,9 @@ while (dirs.length) { if (i > 0 && (boring[i - 1] || ellipsis[i - 1])) { line = '' + line; } + if (i + 1 === highlightedLines.length && (boring[i] || ellipsis[i])) { + line = line + ''; + } return line; }) .join('\n'); @@ -91,6 +102,23 @@ while (dirs.length) { $(this).addClass('hljs'); }); + var foundScript = false; + $('body script').each(function () { + const node = $(this); + if (node.text().replace(/\s/g, '') === themejs.replace(/\s/g, '')) { + node.text(themejsReplacement); + foundScript = true; + } + }); + const pathsWithoutScript = [ + 'build/toc.html', + 'build/build/index.html', + 'build/binding/index.html', + ]; + if (!foundScript && !pathsWithoutScript.includes(path)) { + throw new Error(`theme script not found in ${path}`); + } + const out = $.html(); fs.writeFileSync(path, out); }); @@ -100,5 +128,10 @@ fs.copyFileSync('build/highlight.css', 'build/tomorrow-night.css'); fs.copyFileSync('build/highlight.css', 'build/ayu-highlight.css'); var bookjs = fs.readFileSync('build/book.js', 'utf8'); -bookjs = bookjs.replace('set_theme(theme, false);', ''); +bookjs = bookjs + .replace('set_theme(theme, false);', '') + .replace( + 'document.querySelectorAll("code.hljs")', + 'document.querySelectorAll("code.hidelines")', + ); fs.writeFileSync('build/book.js', bookjs); diff --git a/book/css/cxx.css b/book/css/cxx.css index 647f4f716..68d32db53 100644 --- a/book/css/cxx.css +++ b/book/css/cxx.css @@ -42,3 +42,8 @@ nav.sidebar li.part-title i.fa-github { .sidebar .sidebar-scrollbox { padding: 10px 0 10px 10px; } + +pre > .buttons { + visibility: visible; + opacity: 0.3; +} diff --git a/book/diagram/.gitignore b/book/diagram/.gitignore index 27572bd3b..001728175 100644 --- a/book/diagram/.gitignore +++ b/book/diagram/.gitignore @@ -1,7 +1,7 @@ -*.aux -*.fdb_latexmk -*.fls -*.log -*.pdf -*.png -*.svg +/*.aux +/*.fdb_latexmk +/*.fls +/*.log +/*.pdf +/*.png +/*.svg diff --git a/book/eslint.config.mjs b/book/eslint.config.mjs new file mode 100644 index 000000000..6ad9c6c87 --- /dev/null +++ b/book/eslint.config.mjs @@ -0,0 +1,8 @@ +import pluginJs from '@eslint/js'; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { ignores: ['build/*'] }, + { files: ['**/*.js'], languageOptions: { sourceType: 'commonjs' } }, + pluginJs.configs.recommended, +]; diff --git a/book/package-lock.json b/book/package-lock.json index dec26ad16..e470ebff9 100644 --- a/book/package-lock.json +++ b/book/package-lock.json @@ -1,207 +1,1416 @@ { "name": "cxx-book-build", "version": "0.0.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "boolbase": { + "packages": { + "": { + "name": "cxx-book-build", + "version": "0.0.0", + "dependencies": { + "cheerio": "^1.0.0", + "html-entities": "^2.5.2" + }, + "devDependencies": { + "@eslint/js": "^9.19.0", + "eslint": "^9.19.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" - }, - "cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - } - }, - "css-select": { + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" - }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "html-entities": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", - "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==" - }, - "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" - }, - "lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" }, - "lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } }, - "lodash.foreach": { + "node_modules/entities": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" }, - "lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, - "lodash.merge": { + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } }, - "lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, - "lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/undici": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/book/package.json b/book/package.json index 092cea218..bbed76523 100644 --- a/book/package.json +++ b/book/package.json @@ -3,8 +3,12 @@ "version": "0.0.0", "main": "build.js", "dependencies": { - "cheerio": "^0.22.0", - "html-entities": "^1.3.1" + "cheerio": "^1.0.0", + "html-entities": "^2.5.2" + }, + "devDependencies": { + "@eslint/js": "^9.19.0", + "eslint": "^9.19.0" }, "prettier": { "singleQuote": true diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index a8f89bfc8..2d2502ee7 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -10,7 +10,7 @@ - [Multi-language build system options](building.md) - [Cargo](build/cargo.md) - - [Bazel](build/bazel.md) + - [Bazel or Buck2](build/bazel.md) - [CMake](build/cmake.md) - [More...](build/other.md) diff --git a/book/src/async.md b/book/src/async.md index b4c696a36..ee4defee7 100644 --- a/book/src/async.md +++ b/book/src/async.md @@ -14,7 +14,7 @@ mod ffi { } ``` -```cpp,hidelines +```cpp rust::Future doThing(Arg arg) { auto v1 = co_await f(); auto v2 = co_await g(arg); @@ -28,7 +28,7 @@ For now the recommended approach is to handle the return codepath over a oneshot channel (such as [`futures::channel::oneshot`]) represented in an opaque Rust type on the FFI. -[`futures::channel::oneshot`]: https://docs.rs/futures/0.3.8/futures/channel/oneshot/index.html +[`futures::channel::oneshot`]: https://docs.rs/futures/0.3.31/futures/channel/oneshot/index.html ```rust,noplayground // bridge.rs @@ -84,3 +84,14 @@ void shim_doThing( }); } ``` + +## Streams + +Through a multishot channel such as [`futures::channel::mpsc::unbounded`] in +place of the `futures::channel::oneshot` from above, C++ can send a stream of +values that become a `futures::Stream` in Rust. + +[`futures::channel::mpsc::unbounded`]: https://docs.rs/futures/0.3.31/futures/channel/mpsc/fn.unbounded.html + +In this case the callback function will take the channel sender by reference, +not as a Box. `rust::Fn` diff --git a/book/src/attributes.md b/book/src/attributes.md index 9c33b7771..0342c640d 100644 --- a/book/src/attributes.md +++ b/book/src/attributes.md @@ -73,3 +73,30 @@ Either of the two attributes may be used on extern "Rust" as well as extern The same attribute works for renaming functions, opaque types, shared structs and enums, and enum variants. + +## Self + +Indicates the name of the type in which to place a [Rust associated function] or +[C++ static member function]. + +[Rust associated function]: extern-rust.md#associated-functions +[C++ static member function]: extern-c++.md#functions-and-member-functions + +```rust,noplayground +#[cxx::bridge] +mod ffi { + extern "Rust" { + type RustType; + + #[Self = "RustType"] + fn member(); // callable from C++ as `RustType::member()` + } + + unsafe extern "C++" { + type CppType; + + #[Self = "CppType"] + fn member(); // callable from Rust as `CppType::member()` + } +} +``` diff --git a/book/src/binding/box.md b/book/src/binding/box.md index 7df195974..abd40d672 100644 --- a/book/src/binding/box.md +++ b/book/src/binding/box.md @@ -3,12 +3,12 @@ ### Public API: -```cpp,hidelines +```cpp,hidelines=... // rust/cxx.h -# -# #include -# -# namespace rust { +... +...#include +... +...namespace rust { template class Box final { @@ -24,7 +24,7 @@ public: explicit Box(const T &); explicit Box(T &&); - Box &operator=(Box &&) noexcept; + Box &operator=(Box &&) & noexcept; const T *operator->() const noexcept; const T &operator*() const noexcept; @@ -42,8 +42,8 @@ public: T *into_raw() noexcept; }; -# -# } // namespace rust +... +...} // namespace rust ``` ### Restrictions: diff --git a/book/src/binding/cxxstring.md b/book/src/binding/cxxstring.md index cfe707f21..dc2619ce9 100644 --- a/book/src/binding/cxxstring.md +++ b/book/src/binding/cxxstring.md @@ -134,7 +134,7 @@ std::unique_ptr load_config() { std::in_place_type, std::initializer_list>{ {"name", "cxx-example"}, - {"edition", 2018.}, + {"edition", 2021.}, {"repository", json::null}}); } ``` diff --git a/book/src/binding/fn.md b/book/src/binding/fn.md index 2934b0695..a32ad52a9 100644 --- a/book/src/binding/fn.md +++ b/book/src/binding/fn.md @@ -3,10 +3,10 @@ ### Public API: -```cpp,hidelines +```cpp,hidelines=... // rust/cxx.h -# -# namespace rust { +... +...namespace rust { template class Fn; @@ -17,8 +17,8 @@ public: Ret operator()(Args... args) const noexcept; Fn operator*() const noexcept; }; -# -# } // namespace rust +... +...} // namespace rust ``` ### Restrictions: diff --git a/book/src/binding/result.md b/book/src/binding/result.md index e49dcf4de..2a475313a 100644 --- a/book/src/binding/result.md +++ b/book/src/binding/result.md @@ -55,10 +55,10 @@ The exception that gets thrown by CXX on the C++ side is always of type `rust::Error` and has the following C++ public API. The `what()` member function gives the error message according to the Rust error's std::fmt::Display impl. -```cpp,hidelines +```cpp,hidelines=... // rust/cxx.h -# -# namespace rust { +... +...namespace rust { class Error final : public std::exception { public: @@ -66,13 +66,13 @@ public: Error(Error &&) noexcept; ~Error() noexcept; - Error &operator=(const Error &); - Error &operator=(Error &&) noexcept; + Error &operator=(const Error &) &; + Error &operator=(Error &&) & noexcept; const char *what() const noexcept override; }; -# -# } // namespace rust +... +...} // namespace rust ``` ## Returning Result from C++ to Rust @@ -114,7 +114,7 @@ headers `include!`'d by your cxx::bridge. The template signature is required to be: -```cpp,hidelines +```cpp namespace rust { namespace behavior { @@ -130,19 +130,19 @@ following. You must follow the same pattern: invoke `func` with no arguments, catch whatever exception(s) you want, and invoke `fail` with the error message you'd like for the Rust error to have. -```cpp,hidelines -# #include -# -# namespace rust { -# namespace behavior { -# +```cpp,hidelines=... +...#include +... +...namespace rust { +...namespace behavior { +... template static void trycatch(Try &&func, Fail &&fail) noexcept try { func(); } catch (const std::exception &e) { fail(e.what()); } -# -# } // namespace behavior -# } // namespace rust +... +...} // namespace behavior +...} // namespace rust ``` diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md index 803277ba9..9fcb51428 100644 --- a/book/src/binding/slice.md +++ b/book/src/binding/slice.md @@ -6,13 +6,13 @@ ### Public API: -```cpp,hidelines +```cpp,hidelines=... // rust/cxx.h -# -# #include -# #include -# -# namespace rust { +... +...#include +...#include +... +...namespace rust { template class Slice final { @@ -23,13 +23,15 @@ public: Slice(const Slice &) noexcept; Slice(T *, size_t count) noexcept; - Slice &operator=(Slice &&) noexcept; - Slice &operator=(const Slice &) noexcept + template + explicit Slice(C &c) : Slice(c.data(), c.size()); + + Slice &operator=(Slice &&) & noexcept; + Slice &operator=(const Slice &) & noexcept requires std::is_const_v; T *data() const noexcept; size_t size() const noexcept; - size_t length() const noexcept; bool empty() const noexcept; T &operator[](size_t n) const noexcept; @@ -43,39 +45,43 @@ public: void swap(Slice &) noexcept; }; -# -# template -# class Slice::iterator final { -# public: -# using iterator_category = std::random_access_iterator_tag; -# using value_type = T; -# using pointer = T *; -# using reference = T &; -# -# T &operator*() const noexcept; -# T *operator->() const noexcept; -# T &operator[](ptrdiff_t) const noexcept; -# -# iterator &operator++() noexcept; -# iterator operator++(int) noexcept; -# iterator &operator--() noexcept; -# iterator operator--(int) noexcept; -# -# iterator &operator+=(ptrdiff_t) noexcept; -# iterator &operator-=(ptrdiff_t) noexcept; -# iterator operator+(ptrdiff_t) const noexcept; -# iterator operator-(ptrdiff_t) const noexcept; -# ptrdiff_t operator-(const iterator &) const noexcept; -# -# bool operator==(const iterator &) const noexcept; -# bool operator!=(const iterator &) const noexcept; -# bool operator<(const iterator &) const noexcept; -# bool operator>(const iterator &) const noexcept; -# bool operator<=(const iterator &) const noexcept; -# bool operator>=(const iterator &) const noexcept; -# }; -# -# } // namespace rust +... +...template +...class Slice::iterator final { +...public: +...#if __cplusplus >= 202002L +... using iterator_category = std::contiguous_iterator_tag; +...#else +... using iterator_category = std::random_access_iterator_tag; +...#endif +... using value_type = T; +... using pointer = T *; +... using reference = T &; +... +... T &operator*() const noexcept; +... T *operator->() const noexcept; +... T &operator[](ptrdiff_t) const noexcept; +... +... iterator &operator++() noexcept; +... iterator operator++(int) noexcept; +... iterator &operator--() noexcept; +... iterator operator--(int) noexcept; +... +... iterator &operator+=(ptrdiff_t) noexcept; +... iterator &operator-=(ptrdiff_t) noexcept; +... iterator operator+(ptrdiff_t) const noexcept; +... iterator operator-(ptrdiff_t) const noexcept; +... ptrdiff_t operator-(const iterator &) const noexcept; +... +... bool operator==(const iterator &) const noexcept; +... bool operator!=(const iterator &) const noexcept; +... bool operator<(const iterator &) const noexcept; +... bool operator>(const iterator &) const noexcept; +... bool operator<=(const iterator &) const noexcept; +... bool operator>=(const iterator &) const noexcept; +...}; +... +...} // namespace rust ``` ### Restrictions: diff --git a/book/src/binding/str.md b/book/src/binding/str.md index 9c1e0a773..abb2c80c4 100644 --- a/book/src/binding/str.md +++ b/book/src/binding/str.md @@ -3,13 +3,13 @@ ### Public API: -```cpp,hidelines +```cpp,hidelines=... // rust/cxx.h -# -# #include -# #include -# -# namespace rust { +... +...#include +...#include +... +...namespace rust { class Str final { public: @@ -22,13 +22,18 @@ public: Str(const char *); Str(const char *, size_t); - Str &operator=(const Str &) noexcept; + Str &operator=(const Str &) & noexcept; explicit operator std::string() const; +#if __cplusplus >= 201703L + explicit operator std::string_view() const; +#endif // Note: no null terminator. const char *data() const noexcept; + // Length in bytes. size_t size() const noexcept; + // Length in bytes, same as size(). size_t length() const noexcept; bool empty() const noexcept; @@ -50,8 +55,8 @@ public: }; std::ostream &operator<<(std::ostream &, const Str &); -# -# } // namespace rust +... +...} // namespace rust ``` ### Notes: diff --git a/book/src/binding/string.md b/book/src/binding/string.md index 1e4827812..5116e6556 100644 --- a/book/src/binding/string.md +++ b/book/src/binding/string.md @@ -3,13 +3,13 @@ ### Public API: -```cpp,hidelines +```cpp,hidelines=... // rust/cxx.h -# -# #include -# #include -# -# namespace rust { +... +...#include +...#include +... +...namespace rust { class String final { public: @@ -22,6 +22,8 @@ public: String(const std::string &); String(const char *); String(const char *, size_t); + String(const char8_t *); + String(const char8_t *, size_t); // Replaces invalid UTF-8 data with the replacement character (U+FFFD). static String lossy(const std::string &) noexcept; @@ -36,14 +38,16 @@ public: 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; + String &operator=(const String &) & noexcept; + String &operator=(String &&) & noexcept; explicit operator std::string() const; // Note: no null terminator. const char *data() const noexcept; + // Length in bytes. size_t size() const noexcept; + // Length in bytes, same as size(). size_t length() const noexcept; bool empty() const noexcept; @@ -73,8 +77,8 @@ public: }; std::ostream &operator<<(std::ostream &, const String &); -# -# } // namespace rust +... +...} // namespace rust ``` ### Restrictions: diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md index 4d6587ab1..3e883a21d 100644 --- a/book/src/binding/vec.md +++ b/book/src/binding/vec.md @@ -3,14 +3,14 @@ ### Public API: -```cpp,hidelines +```cpp,hidelines=... // rust/cxx.h -# -# #include -# #include -# #include -# -# namespace rust { +... +...#include +...#include +...#include +... +...namespace rust { template class Vec final { @@ -23,8 +23,8 @@ public: Vec(Vec &&) noexcept; ~Vec() noexcept; - Vec &operator=(Vec &&) noexcept; - Vec &operator=(const Vec &); + Vec &operator=(Vec &&) & noexcept; + Vec &operator=(const Vec &) &; size_t size() const noexcept; bool empty() const noexcept; @@ -62,70 +62,78 @@ public: void swap(Vec &) noexcept; }; -# -# template -# class Vec::iterator final { -# public: -# using iterator_category = std::random_access_iterator_tag; -# using value_type = T; -# using pointer = T *; -# using reference = T &; -# -# T &operator*() const noexcept; -# T *operator->() const noexcept; -# T &operator[](ptrdiff_t) const noexcept; -# -# iterator &operator++() noexcept; -# iterator operator++(int) noexcept; -# iterator &operator--() noexcept; -# iterator operator--(int) noexcept; -# -# iterator &operator+=(ptrdiff_t) noexcept; -# iterator &operator-=(ptrdiff_t) noexcept; -# iterator operator+(ptrdiff_t) const noexcept; -# iterator operator-(ptrdiff_t) const noexcept; -# ptrdiff_t operator-(const iterator &) const noexcept; -# -# bool operator==(const iterator &) const noexcept; -# bool operator!=(const iterator &) const noexcept; -# bool operator<(const iterator &) const noexcept; -# bool operator<=(const iterator &) const noexcept; -# bool operator>(const iterator &) const noexcept; -# bool operator>=(const iterator &) const noexcept; -# }; -# -# template -# class Vec::const_iterator final { -# public: -# using iterator_category = std::random_access_iterator_tag; -# using value_type = const T; -# using pointer = const T *; -# using reference = const T &; -# -# const T &operator*() const noexcept; -# const T *operator->() const noexcept; -# const T &operator[](ptrdiff_t) const noexcept; -# -# const_iterator &operator++() noexcept; -# const_iterator operator++(int) noexcept; -# const_iterator &operator--() noexcept; -# const_iterator operator--(int) noexcept; -# -# const_iterator &operator+=(ptrdiff_t) noexcept; -# const_iterator &operator-=(ptrdiff_t) noexcept; -# const_iterator operator+(ptrdiff_t) const noexcept; -# const_iterator operator-(ptrdiff_t) const noexcept; -# ptrdiff_t operator-(const const_iterator &) const noexcept; -# -# bool operator==(const const_iterator &) const noexcept; -# bool operator!=(const const_iterator &) const noexcept; -# bool operator<(const const_iterator &) const noexcept; -# bool operator<=(const const_iterator &) const noexcept; -# bool operator>(const const_iterator &) const noexcept; -# bool operator>=(const const_iterator &) const noexcept; -# }; -# -# } // namespace rust +... +...template +...class Vec::iterator final { +...public: +...#if __cplusplus >= 202002L +... using iterator_category = std::contiguous_iterator_tag; +...#else +... using iterator_category = std::random_access_iterator_tag; +...#endif +... using value_type = T; +... using pointer = T *; +... using reference = T &; +... +... T &operator*() const noexcept; +... T *operator->() const noexcept; +... T &operator[](ptrdiff_t) const noexcept; +... +... iterator &operator++() noexcept; +... iterator operator++(int) noexcept; +... iterator &operator--() noexcept; +... iterator operator--(int) noexcept; +... +... iterator &operator+=(ptrdiff_t) noexcept; +... iterator &operator-=(ptrdiff_t) noexcept; +... iterator operator+(ptrdiff_t) const noexcept; +... iterator operator-(ptrdiff_t) const noexcept; +... ptrdiff_t operator-(const iterator &) const noexcept; +... +... bool operator==(const iterator &) const noexcept; +... bool operator!=(const iterator &) const noexcept; +... bool operator<(const iterator &) const noexcept; +... bool operator<=(const iterator &) const noexcept; +... bool operator>(const iterator &) const noexcept; +... bool operator>=(const iterator &) const noexcept; +...}; +... +...template +...class Vec::const_iterator final { +...public: +...#if __cplusplus >= 202002L +... using iterator_category = std::contiguous_iterator_tag; +...#else +... using iterator_category = std::random_access_iterator_tag; +...#endif +... using value_type = const T; +... using pointer = const T *; +... using reference = const T &; +... +... const T &operator*() const noexcept; +... const T *operator->() const noexcept; +... const T &operator[](ptrdiff_t) const noexcept; +... +... const_iterator &operator++() noexcept; +... const_iterator operator++(int) noexcept; +... const_iterator &operator--() noexcept; +... const_iterator operator--(int) noexcept; +... +... const_iterator &operator+=(ptrdiff_t) noexcept; +... const_iterator &operator-=(ptrdiff_t) noexcept; +... const_iterator operator+(ptrdiff_t) const noexcept; +... const_iterator operator-(ptrdiff_t) const noexcept; +... ptrdiff_t operator-(const const_iterator &) const noexcept; +... +... bool operator==(const const_iterator &) const noexcept; +... bool operator!=(const const_iterator &) const noexcept; +... bool operator<(const const_iterator &) const noexcept; +... bool operator<=(const const_iterator &) const noexcept; +... bool operator>(const const_iterator &) const noexcept; +... bool operator>=(const const_iterator &) const noexcept; +...}; +... +...} // namespace rust ``` ### Restrictions: diff --git a/book/src/build/bazel.md b/book/src/build/bazel.md index 6a2c82b00..d3534c5cd 100644 --- a/book/src/build/bazel.md +++ b/book/src/build/bazel.md @@ -1,12 +1,12 @@ -{{#title Bazel, Buck — Rust ♡ C++}} -## Bazel, Buck, potentially other similar environments +{{#title Bazel, Buck2 — Rust ♡ C++}} +## Bazel, Buck2, potentially other similar environments Starlark-based build systems with the ability to compile a code generator and invoke it as a `genrule` will run CXX's C++ code generator via its `cxxbridge` command line interface. The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be built -from the *gen/cmd/* directory of the CXX GitHub repo. +from the *bridge/cmd/* directory of the CXX GitHub repo. ```console $ cargo install cxxbridge-cmd @@ -15,10 +15,22 @@ $ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h $ cxxbridge src/bridge.rs > path/to/bridge.rs.cc ``` -The CXX repo maintains working Bazel `BUILD` and Buck `BUCK` targets for the -complete blobstore tutorial (chapter 3) for your reference, tested in CI. These -aren't meant to be directly what you use in your codebase, but serve as an -illustration of one possible working pattern. +
    + +**Important:** The version number of `cxxbridge-cmd` used for the C++ side of +the binding must always be identical to the version number of `cxx` used for the +Rust side. You must use some form of lockfile or version pinning to ensure that +this is the case. + +
    + +The CXX repo maintains working [Bazel] `BUILD.bazel` and [Buck2] `BUCK` targets +for the complete blobstore tutorial (chapter 3) for your reference, tested in +CI. These aren't meant to be directly what you use in your codebase, but serve +as an illustration of one possible working pattern. + +[Bazel]: https://bazel.build +[Buck2]: https://buck2.build ```python # tools/bazel/rust_cxx_bridge.bzl @@ -67,7 +79,7 @@ def rust_cxx_bridge(name, src, deps = []): ``` ```python -# demo/BUILD +# demo/BUILD.bazel load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_rust//rust:defs.bzl", "rust_binary") diff --git a/book/src/build/cargo.md b/book/src/build/cargo.md index 82ccfb500..7a572b4c0 100644 --- a/book/src/build/cargo.md +++ b/book/src/build/cargo.md @@ -12,12 +12,12 @@ CXX's integration with Cargo is handled through the [cxx-build] crate. [cxx-build]: https://docs.rs/cxx-build -```toml,hidelines -## Cargo.toml -# [package] -# name = "..." -# version = "..." -# edition = "2018" +```toml,hidelines=... +# Cargo.toml +...[package] +...name = "..." +...version = "..." +...edition = "2024" [dependencies] cxx = "1.0" @@ -38,10 +38,9 @@ set up any additional source files and compiler flags as normal. fn main() { cxx_build::bridge("src/main.rs") // returns a cc::Build .file("src/demo.cc") - .flag_if_supported("-std=c++11") + .std("c++11") .compile("cxxbridge-demo"); - println!("cargo:rerun-if-changed=src/main.rs"); println!("cargo:rerun-if-changed=src/demo.cc"); println!("cargo:rerun-if-changed=include/demo.h"); } diff --git a/book/src/build/other.md b/book/src/build/other.md index af835e658..e531d3968 100644 --- a/book/src/build/other.md +++ b/book/src/build/other.md @@ -8,7 +8,7 @@ You will need to achieve at least these three things: - Link the resulting objects together with your other C++ and Rust objects. *Not all build systems are created equal. If you're hoping to use a build system -from the '90s, especially if you're hoping to overlaying the limitations of 2 or +from the '90s, especially if you're hoping to overlay the limitations of 2 or more build systems (like automake+cargo) and expect to solve them simultaneously, then be mindful that your expectations are set accordingly and seek sympathy from those who have imposed the same approach on themselves.* @@ -31,11 +31,21 @@ But the C++ side of the bindings needs to be generated. Your options are: ``` It's packaged as the `cxxbridge-cmd` crate on crates.io or can be built from - the *gen/cmd/* directory of the CXX GitHub repo. + the *bridge/cmd/* directory of the CXX GitHub repo. - Or, build your own code generator frontend on top of the [cxx-gen] crate. This is currently unofficial and unsupported. +
    + +**Important:** The Rust side and C++ side of a binding must always be created +using the same release of CXX. If using `cxxbridge-cmd` for the C++ side, the +version number of `cxxbridge-cmd` must be identical to the version number of +`cxx` used for the Rust side. If using `cxx-gen` for the C++ side, its patch +number must be identical to the patch number of `cxx`. + +
    + [cxx-gen]: https://docs.rs/cxx-gen ### Compiling C++ @@ -48,6 +58,12 @@ When linking a binary which contains mixed Rust and C++ code, you will have to choose between using the Rust toolchain (`rustc`) or the C++ toolchain which you may already have extensively tuned. +The generated C++ code and the Rust code generated by the procedural macro both +depend on each other. Simple examples may only require one or the other, but in +general your linking will need to handle both directions. For some linkers, such +as LLD, this is not a problem at all. For others, such as GNU ld, flags like +`--start-lib`/`--end-lib` may help. + Rust does not generate simple standalone `.o` files, so you can't just throw the Rust-generated code into your existing C++ toolchain linker. Instead you need to choose one of these options: diff --git a/book/src/extern-c++.md b/book/src/extern-c++.md index 11ed7b54e..4fda537a3 100644 --- a/book/src/extern-c++.md +++ b/book/src/extern-c++.md @@ -81,7 +81,9 @@ member function trigger a data race on the `blobs` map. This largely follows the same principles as ***[extern "Rust"](extern-rust.md)*** functions and methods. In particular, any signature with a `self` parameter is interpreted as a C++ non-static member function and -exposed to Rust as a method. +exposed to Rust as a method; any signature with a `#[Self = "…"]` attribute is +interpreted as a C++ static member function and exposed to Rust as an associated +function. The programmer **does not** need to promise that the signatures they have typed in are accurate; that would be unreasonable. CXX performs static assertions that diff --git a/book/src/extern-rust.md b/book/src/extern-rust.md index 40f223759..397c4f057 100644 --- a/book/src/extern-rust.md +++ b/book/src/extern-rust.md @@ -143,6 +143,37 @@ multiple extern blocks. # } ``` +## Associated functions + +A function with a `Self` attribute is interpreted as a Rust associated function +and exposed to C++ as a static member function. These must not have a `self` +argument. + +In the following example, the `builder` associated function is callable as +`MyType::builder()` from both Rust and C++. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + extern "Rust" { + type MyType; + type MyTypeBuilder; + + #[Self = "MyType"] + fn builder() -> Box; + } +} + +pub struct MyType; +pub struct MyTypeBuilder; + +impl MyType { + pub fn builder() -> Box { + ... + } +} +``` + ## Functions with explicit lifetimes An extern Rust function signature is allowed to contain explicit lifetimes but diff --git a/book/src/shared.md b/book/src/shared.md index 4043db124..bec087e9e 100644 --- a/book/src/shared.md +++ b/book/src/shared.md @@ -215,6 +215,9 @@ bridge module. - `Ord` - `PartialEq` - `PartialOrd` +- `BitAnd` (enums only) +- `BitOr` (enums only) +- `BitXor` (enums only) Note that shared enums automatically always come with impls of `Copy`, `Clone`, `Eq`, and `PartialEq`, so you're free to omit those derives on an enum. @@ -242,5 +245,28 @@ C++ data type: - `Hash` gives you a specialization of [`template <> struct std::hash`][hash] in C++ - `PartialEq` produces `operator==` and `operator!=` - `PartialOrd` produces `operator<`, `operator<=`, `operator>`, `operator>=` +- `BitAnd` produces `operator&` +- `BitOr` produces `operator|` +- `BitXor` produces `operator^` [hash]: https://en.cppreference.com/w/cpp/utility/hash + +## Alignment + +The attribute `repr(align(…))` sets a minimum required alignment for a shared +struct. The alignment value must be a power of two in the range 20 to +213. + +This turns into an [`alignas`] specifier in C++. + +[`alignas`]: https://en.cppreference.com/w/cpp/language/alignas.html + +```rust,noplayground +#[cxx::bridge] +mod ffi { + #[repr(align(4))] + struct ExampleStruct { + b: [u8; 4], + } +} +``` diff --git a/book/src/tutorial.md b/book/src/tutorial.md index 2467282fb..de9b90516 100644 --- a/book/src/tutorial.md +++ b/book/src/tutorial.md @@ -23,12 +23,12 @@ Create a blank Cargo project: `mkdir cxx-demo`; `cd cxx-demo`; `cargo init`. Edit the Cargo.toml to add a dependency on the `cxx` crate: -```toml,hidelines -## Cargo.toml -# [package] -# name = "cxx-demo" -# version = "0.1.0" -# edition = "2018" +```toml,hidelines=... +# Cargo.toml +...[package] +...name = "cxx-demo" +...version = "0.1.0" +...edition = "2024" [dependencies] cxx = "1.0" @@ -159,8 +159,8 @@ std::unique_ptr new_blobstore_client() { } ``` -Using `std::make_unique` would work too, as long as you pass `-std=c++14` to the -C++ compiler as described later on. +Using `std::make_unique` would work too, as long as you pass `std("c++14")` to +the C++ compiler as described later on. The placement in *include/* and *src/* is not significant; you can place C++ code anywhere else in the crate as long as you use the right paths throughout @@ -177,12 +177,12 @@ Cargo has a [build scripts] feature suitable for compiling non-Rust code. We need to introduce a new build-time dependency on CXX's C++ code generator in Cargo.toml: -```toml,hidelines -## Cargo.toml -# [package] -# name = "cxx-demo" -# version = "0.1.0" -# edition = "2018" +```toml,hidelines=... +# Cargo.toml +...[package] +...name = "cxx-demo" +...version = "0.1.0" +...edition = "2024" [dependencies] cxx = "1.0" @@ -204,6 +204,9 @@ fn main() { cxx_build::bridge("src/main.rs") .file("src/blobstore.cc") .compile("cxx-demo"); + + println!("cargo:rerun-if-changed=src/blobstore.cc"); + println!("cargo:rerun-if-changed=include/blobstore.h"); } ``` @@ -218,7 +221,7 @@ integration. # fn main() { cxx_build::bridge("src/main.rs") .file("src/blobstore.cc") - .flag_if_supported("-std=c++14") + .std("c++14") .compile("cxx-demo"); # } ``` @@ -328,12 +331,12 @@ pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { # } ``` -```cpp,hidelines +```cpp,hidelines=... // include/blobstore.h -# #pragma once -# #include -# +...#pragma once +...#include +... struct MultiBuf; class BlobstoreClient { @@ -341,8 +344,8 @@ public: BlobstoreClient(); uint64_t put(MultiBuf &buf) const; }; -# -#std::unique_ptr new_blobstore_client(); +... +...std::unique_ptr new_blobstore_client(); ``` In blobstore.cc we're able to call the Rust `next_chunk` function, exposed to @@ -350,19 +353,19 @@ C++ by a header `main.rs.h` generated by the CXX code generator. In CXX's Cargo integration this generated header has a path containing the crate name, the relative path of the Rust source file within the crate, and a `.rs.h` extension. -```cpp,hidelines +```cpp,hidelines=... // src/blobstore.cc -##include "cxx-demo/include/blobstore.h" -##include "cxx-demo/src/main.rs.h" -##include -##include -# -# BlobstoreClient::BlobstoreClient() {} -# -# std::unique_ptr new_blobstore_client() { -# return std::make_unique(); -# } +#include "cxx-demo/include/blobstore.h" +#include "cxx-demo/src/main.rs.h" +#include +#include +... +...BlobstoreClient::BlobstoreClient() {} +... +...std::unique_ptr new_blobstore_client() { +... return std::make_unique(); +...} // Upload a new blob and return a blobid that serves as a handle to the blob. uint64_t BlobstoreClient::put(MultiBuf &buf) const { @@ -422,7 +425,7 @@ fn main() { let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; let mut buf = MultiBuf { chunks, pos: 0 }; let blobid = client.put(&mut buf); - println!("blobid = {}", blobid); + println!("blobid = {blobid}"); } ``` @@ -548,7 +551,7 @@ fn main() { let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; let mut buf = MultiBuf { chunks, pos: 0 }; let blobid = client.put(&mut buf); - println!("blobid = {}", blobid); + println!("blobid = {blobid}"); // Add a tag. client.tag(blobid, "rust"); @@ -559,12 +562,12 @@ fn main() { } ``` -```cpp,hidelines +```cpp,hidelines=... // include/blobstore.h -##pragma once -##include "rust/cxx.h" -# #include +#pragma once +#include "rust/cxx.h" +...#include struct MultiBuf; struct BlobMetadata; @@ -580,20 +583,20 @@ private: class impl; std::shared_ptr impl; }; -# -# std::unique_ptr new_blobstore_client(); +... +...std::unique_ptr new_blobstore_client(); ``` -```cpp,hidelines +```cpp,hidelines=... // src/blobstore.cc -##include "cxx-demo/include/blobstore.h" -##include "cxx-demo/src/main.rs.h" -##include -##include -##include -##include -##include +#include "cxx-demo/include/blobstore.h" +#include "cxx-demo/src/main.rs.h" +#include +#include +#include +#include +#include // Toy implementation of an in-memory blobstore. // @@ -609,24 +612,24 @@ class BlobstoreClient::impl { }; BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {} -# -# // Upload a new blob and return a blobid that serves as a handle to the blob. -# uint64_t BlobstoreClient::put(MultiBuf &buf) const { -# // Traverse the caller's chunk iterator. -# std::string contents; -# while (true) { -# auto chunk = next_chunk(buf); -# if (chunk.size() == 0) { -# break; -# } -# contents.append(reinterpret_cast(chunk.data()), chunk.size()); -# } -# -# // Insert into map and provide caller the handle. -# auto blobid = std::hash{}(contents); -# impl->blobs[blobid] = {std::move(contents), {}}; -# return blobid; -# } +... +...// Upload a new blob and return a blobid that serves as a handle to the blob. +...uint64_t BlobstoreClient::put(MultiBuf &buf) const { +... // Traverse the caller's chunk iterator. +... std::string contents; +... while (true) { +... auto chunk = next_chunk(buf); +... if (chunk.size() == 0) { +... break; +... } +... contents.append(reinterpret_cast(chunk.data()), chunk.size()); +... } +... +... // Insert into map and provide caller the handle. +... auto blobid = std::hash{}(contents); +... impl->blobs[blobid] = {std::move(contents), {}}; +... return blobid; +...} // Add tag to an existing blob. void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const { @@ -644,10 +647,10 @@ BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const { } return metadata; } -# -# std::unique_ptr new_blobstore_client() { -# return std::make_unique(); -# } +... +...std::unique_ptr new_blobstore_client() { +... return std::make_unique(); +...} ``` ```console diff --git a/book/theme/head.hbs b/book/theme/head.hbs index 4210276b0..d6b32cb98 100644 --- a/book/theme/head.hbs +++ b/book/theme/head.hbs @@ -1,7 +1,7 @@ - - + + diff --git a/gen/README.md b/bridge/README.md similarity index 100% rename from gen/README.md rename to bridge/README.md diff --git a/gen/build/Cargo.toml b/bridge/build/Cargo.toml similarity index 51% rename from gen/build/Cargo.toml rename to bridge/build/Cargo.toml index 08c4a4d53..3f1e79c35 100644 --- a/gen/build/Cargo.toml +++ b/bridge/build/Cargo.toml @@ -1,39 +1,41 @@ [package] name = "cxx-build" -version = "1.0.91" +version = "1.0.199" authors = ["David Tolnay "] categories = ["development-tools::build-utils", "development-tools::ffi"] description = "C++ code generator for integrating `cxx` crate into a Cargo build." documentation = "https://docs.rs/cxx-build" -edition = "2018" +edition = "2024" exclude = ["build.rs"] homepage = "https://cxx.rs" keywords = ["ffi", "build-dependencies"] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/cxx" -rust-version = "1.60" +rust-version = "1.88" [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.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.95", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] } +cc = "1.0.101" +codespan-reporting = "0.13.1" +indexmap = "2.9.0" +proc-macro2 = { version = "1.0.74", default-features = false, features = ["span-locations"] } +quote = { version = "1.0.35", default-features = false } +scratch = "1.0.5" +syn = { version = "3", default-features = false, features = ["clone-impls", "full", "parsing", "printing"] } [dev-dependencies] cxx = { version = "1.0", path = "../.." } cxx-gen = { version = "0.7", path = "../lib" } -pkg-config = "0.3" - -[lib] -doc-scrape-examples = false +pkg-config = "0.3.27" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] diff --git a/gen/build/LICENSE-APACHE b/bridge/build/LICENSE-APACHE similarity index 100% rename from gen/build/LICENSE-APACHE rename to bridge/build/LICENSE-APACHE diff --git a/gen/build/LICENSE-MIT b/bridge/build/LICENSE-MIT similarity index 100% rename from gen/build/LICENSE-MIT rename to bridge/build/LICENSE-MIT diff --git a/gen/build/build.rs b/bridge/build/build.rs similarity index 100% rename from gen/build/build.rs rename to bridge/build/build.rs diff --git a/gen/build/src/gen b/bridge/build/src/bridge similarity index 100% rename from gen/build/src/gen rename to bridge/build/src/bridge diff --git a/gen/build/src/cargo.rs b/bridge/build/src/cargo.rs similarity index 90% rename from gen/build/src/cargo.rs rename to bridge/build/src/cargo.rs index cbaa58a44..4be6b1e1d 100644 --- a/gen/build/src/cargo.rs +++ b/bridge/build/src/cargo.rs @@ -1,11 +1,12 @@ -use crate::gen::{CfgEvaluator, CfgResult}; -use once_cell::sync::OnceCell; +use crate::bridge::{CfgEvaluator, CfgResult}; use std::borrow::Borrow; use std::cmp::Ordering; use std::collections::{BTreeMap as Map, BTreeSet as Set}; use std::env; +use std::ptr; +use std::sync::OnceLock; -static ENV: OnceCell = OnceCell::new(); +static ENV: OnceLock = OnceLock::new(); struct CargoEnv { features: Set, @@ -51,13 +52,11 @@ impl CargoEnv { 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 Some(k) = k.to_str() else { + continue; }; - let v = match v.into_string() { - Ok(v) => v, - Err(_) => continue, + let Ok(v) = v.into_string() else { + continue; }; if let Some(feature_name) = k.strip_prefix(CARGO_FEATURE_PREFIX) { let feature_name = Name(feature_name.to_owned()); @@ -98,7 +97,7 @@ struct Lookup(str); impl Lookup { fn new(name: &str) -> &Self { - unsafe { &*(name as *const str as *const Self) } + unsafe { &*(ptr::from_ref::(name) as *const Self) } } } diff --git a/gen/build/src/cfg.rs b/bridge/build/src/cfg.rs similarity index 97% rename from gen/build/src/cfg.rs rename to bridge/build/src/cfg.rs index 69eb6945d..f826fa1ae 100644 --- a/gen/build/src/cfg.rs +++ b/bridge/build/src/cfg.rs @@ -341,15 +341,14 @@ pub use self::r#impl::Cfg::CFG; #[cfg(not(doc))] mod r#impl { - use crate::intern::{intern, InternedString}; + use crate::intern::{InternedString, intern}; use crate::syntax::map::UnorderedMap as Map; use crate::vec::{self, InternedVec as _}; - use once_cell::sync::Lazy; use std::cell::RefCell; use std::fmt::{self, Debug}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; - use std::sync::{PoisonError, RwLock}; + use std::sync::{OnceLock, PoisonError, RwLock}; struct CurrentCfg { include_prefix: InternedString, @@ -378,7 +377,10 @@ mod r#impl { } } - static CURRENT: Lazy> = Lazy::new(|| RwLock::new(CurrentCfg::default())); + fn current() -> &'static RwLock { + static CURRENT: OnceLock> = OnceLock::new(); + CURRENT.get_or_init(|| RwLock::new(CurrentCfg::default())) + } thread_local! { // FIXME: If https://github.com/rust-lang/rust/issues/77425 is resolved, @@ -401,7 +403,7 @@ mod r#impl { impl<'a> Cfg<'a> { fn current() -> super::Cfg<'a> { - let current = CURRENT.read().unwrap_or_else(PoisonError::into_inner); + let current = current().read().unwrap_or_else(PoisonError::into_inner); let include_prefix = current.include_prefix.str(); let exported_header_dirs = current.exported_header_dirs.vec(); let exported_header_prefixes = current.exported_header_prefixes.vec(); @@ -447,7 +449,7 @@ mod r#impl { cfg } else { let cfg = CONST_DEREFS.with(|derefs| -> *mut super::Cfg { - &mut **derefs + &raw mut **derefs .borrow_mut() .entry(self.handle()) .or_insert_with(|| Box::new(Cfg::current())) @@ -481,7 +483,7 @@ mod r#impl { doxygen, marker: _, } = cfg; - let mut current = CURRENT.write().unwrap_or_else(PoisonError::into_inner); + let mut current = current().write().unwrap_or_else(PoisonError::into_inner); current.include_prefix = intern(include_prefix); current.exported_header_dirs = vec::intern(exported_header_dirs); current.exported_header_prefixes = vec::intern(exported_header_prefixes); diff --git a/gen/build/src/deps.rs b/bridge/build/src/deps.rs similarity index 95% rename from gen/build/src/deps.rs rename to bridge/build/src/deps.rs index fb80072c8..36f2066a4 100644 --- a/gen/build/src/deps.rs +++ b/bridge/build/src/deps.rs @@ -4,19 +4,19 @@ use std::ffi::OsString; use std::path::PathBuf; #[derive(Default)] -pub struct Crate { +pub(crate) struct Crate { pub include_prefix: Option, pub links: Option, pub header_dirs: Vec, } -pub struct HeaderDir { +pub(crate) struct HeaderDir { pub exported: bool, pub path: PathBuf, } impl Crate { - pub fn print_to_cargo(&self) { + pub(crate) fn print_to_cargo(&self) { if let Some(include_prefix) = &self.include_prefix { println!( "cargo:CXXBRIDGE_PREFIX={}", @@ -38,7 +38,7 @@ impl Crate { } } -pub fn direct_dependencies() -> Vec { +pub(crate) fn direct_dependencies() -> Vec { let mut crates: BTreeMap = BTreeMap::new(); let mut exported_header_dirs: BTreeMap> = BTreeMap::new(); diff --git a/gen/build/src/error.rs b/bridge/build/src/error.rs similarity index 96% rename from gen/build/src/error.rs rename to bridge/build/src/error.rs index 99d7a30bf..fd0e59fdb 100644 --- a/gen/build/src/error.rs +++ b/bridge/build/src/error.rs @@ -1,5 +1,5 @@ +use crate::bridge::fs; use crate::cfg::CFG; -use crate::gen::fs; use std::error::Error as StdError; use std::ffi::OsString; use std::fmt::{self, Display}; @@ -39,9 +39,9 @@ impl Display for Error { Error::Fs(err) => err.fmt(f), Error::ExportedDirNotAbsolute(path) => write!( f, - "element of {} must be absolute path, but was: {:?}", + "element of {} must be absolute path, but was: `{}`", expr!(CFG.exported_header_dirs), - path, + path.display(), ), Error::ExportedEmptyPrefix => write!( f, diff --git a/gen/build/src/intern.rs b/bridge/build/src/intern.rs similarity index 65% rename from gen/build/src/intern.rs rename to bridge/build/src/intern.rs index c8b57d89c..0423ea105 100644 --- a/gen/build/src/intern.rs +++ b/bridge/build/src/intern.rs @@ -1,18 +1,17 @@ use crate::syntax::set::UnorderedSet as Set; -use once_cell::sync::OnceCell; -use std::sync::{Mutex, PoisonError}; +use std::sync::{Mutex, OnceLock, PoisonError}; #[derive(Copy, Clone, Default)] -pub struct InternedString(&'static str); +pub(crate) struct InternedString(&'static str); impl InternedString { - pub fn str(self) -> &'static str { + pub(crate) fn str(self) -> &'static str { self.0 } } -pub fn intern(s: &str) -> InternedString { - static INTERN: OnceCell>> = OnceCell::new(); +pub(crate) fn intern(s: &str) -> InternedString { + static INTERN: OnceLock>> = OnceLock::new(); let mut set = INTERN .get_or_init(|| Mutex::new(Set::new())) diff --git a/gen/build/src/lib.rs b/bridge/build/src/lib.rs similarity index 89% rename from gen/build/src/lib.rs rename to bridge/build/src/lib.rs index 3176a283e..b807396e4 100644 --- a/gen/build/src/lib.rs +++ b/bridge/build/src/lib.rs @@ -16,10 +16,9 @@ //! fn main() { //! cxx_build::bridge("src/main.rs") //! .file("src/demo.cc") -//! .flag_if_supported("-std=c++11") +//! .std("c++11") //! .compile("cxxbridge-demo"); //! -//! println!("cargo:rerun-if-changed=src/main.rs"); //! println!("cargo:rerun-if-changed=src/demo.cc"); //! println!("cargo:rerun-if-changed=include/demo.h"); //! } @@ -45,46 +44,47 @@ //! $ cxxbridge src/main.rs > path/to/mybridge.cc //! ``` +#![doc(html_root_url = "https://docs.rs/cxx-build/1.0.199")] +#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] #![allow( + clippy::assert_is_empty, clippy::cast_sign_loss, clippy::default_trait_access, - clippy::derive_partial_eq_without_eq, clippy::doc_markdown, - clippy::drop_copy, + clippy::elidable_lifetime_names, clippy::enum_glob_use, + clippy::expl_impl_clone_on_copy, // https://github.com/rust-lang/rust-clippy/issues/15842 clippy::explicit_auto_deref, - clippy::if_same_then_else, clippy::inherent_to_string, clippy::items_after_statements, clippy::match_bool, - clippy::match_on_vec_items, + clippy::match_like_matches_macro, clippy::match_same_arms, - clippy::module_name_repetitions, + clippy::needless_continue, clippy::needless_doctest_main, + clippy::needless_lifetimes, clippy::needless_pass_by_value, - clippy::new_without_default, clippy::nonminimal_bool, - clippy::option_if_let_else, - clippy::or_fun_call, + clippy::precedence, clippy::redundant_else, - clippy::shadow_unrelated, - clippy::significant_drop_in_scrutinee, + clippy::ref_option, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, + clippy::struct_field_names, clippy::too_many_arguments, clippy::too_many_lines, clippy::toplevel_ref_arg, - clippy::upper_case_acronyms, - // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983 - clippy::wrong_self_convention + clippy::uninlined_format_args, + clippy::upper_case_acronyms )] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] +mod bridge; mod cargo; mod cfg; mod deps; mod error; -mod gen; mod intern; mod out; mod paths; @@ -92,11 +92,11 @@ mod syntax; mod target; mod vec; +use crate::bridge::Opt; +use crate::bridge::error::report; use crate::cargo::CargoEnvCfgEvaluator; use crate::deps::{Crate, HeaderDir}; use crate::error::{Error, Result}; -use crate::gen::error::report; -use crate::gen::Opt; use crate::paths::PathExt; use crate::syntax::map::{Entry, UnorderedMap}; use crate::target::TargetDir; @@ -109,13 +109,13 @@ use std::iter; use std::path::{Path, PathBuf}; use std::process; -pub use crate::cfg::{Cfg, CFG}; +pub use crate::cfg::{CFG, Cfg}; /// This returns a [`cc::Build`] on which you should continue to set up any /// additional source files or compiler flags, and lastly call its [`compile`] /// method to execute the C++ build. /// -/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile +/// [`compile`]: cc::Build::compile #[must_use] pub fn bridge(rust_source_file: impl AsRef) -> Build { bridges(iter::once(rust_source_file)) @@ -128,7 +128,7 @@ pub fn bridge(rust_source_file: impl AsRef) -> Build { /// let source_files = vec!["src/main.rs", "src/path/to/other.rs"]; /// cxx_build::bridges(source_files) /// .file("src/demo.cc") -/// .flag_if_supported("-std=c++11") +/// .std("c++11") /// .compile("cxxbridge-demo"); /// ``` #[must_use] @@ -368,7 +368,7 @@ fn make_crate_dir(prj: &Project) -> PathBuf { let crate_dir = prj.out_dir.join("cxxbridge").join("crate"); let ref link = crate_dir.join(&prj.include_prefix); let ref manifest_dir = prj.manifest_dir; - if out::symlink_dir(manifest_dir, link).is_err() && cfg!(not(unix)) { + if out::relative_symlink_dir(manifest_dir, link).is_err() && cfg!(not(unix)) { let cachedir_tag = "\ Signature: 8a477f597d28d172789f06886806bc55\n\ # This file is a cache directory tag created by cxx.\n\ @@ -385,11 +385,11 @@ fn make_include_dir(prj: &Project) -> Result { let cxx_h = include_dir.join("rust").join("cxx.h"); let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h"); if let Some(ref original) = env::var_os("DEP_CXXBRIDGE1_HEADER") { - out::symlink_file(original, cxx_h)?; - out::symlink_file(original, shared_cxx_h)?; + out::absolute_symlink_file(original, cxx_h)?; + out::absolute_symlink_file(original, shared_cxx_h)?; } else { - out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?; - out::symlink_file(shared_cxx_h, cxx_h)?; + out::write(shared_cxx_h, bridge::include::HEADER.as_bytes())?; + out::relative_symlink_file(shared_cxx_h, cxx_h)?; } Ok(include_dir) } @@ -401,7 +401,10 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> doxygen: CFG.doxygen, ..Opt::default() }; - let generated = gen::generate_from_path(rust_source_file, &opt); + if !rust_source_file.starts_with(&prj.out_dir) { + println!("cargo:rerun-if-changed={}", rust_source_file.display()); + } + let generated = bridge::generate_from_path(rust_source_file, &opt); let ref rel_path = paths::local_relative_path(rust_source_file); let cxxbridge = prj.out_dir.join("cxxbridge"); @@ -413,7 +416,7 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> out::write(header_path, &generated.header)?; let ref link_path = include_dir.join(rel_path); - let _ = out::symlink_file(header_path, link_path); + let _ = out::relative_symlink_file(header_path, link_path); let ref rel_path_cc = rel_path.with_appended_extension(".cc"); let ref implementation_path = sources_dir.join(rel_path_cc); @@ -422,19 +425,18 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> let shared_h = prj.shared_dir.join(&prj.include_prefix).join(rel_path_h); let shared_cc = prj.shared_dir.join(&prj.include_prefix).join(rel_path_cc); - let _ = out::symlink_file(header_path, shared_h); - let _ = out::symlink_file(implementation_path, shared_cc); + let _ = out::relative_symlink_file(header_path, shared_h); + let _ = out::relative_symlink_file(implementation_path, shared_cc); Ok(()) } fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) { - // Not using crate::gen::fs because we aren't reporting the errors. + // Not using crate::bridge::fs because we aren't reporting the errors. use std::fs; let mut dst_created = false; - let mut entries = match fs::read_dir(src) { - Ok(entries) => entries, - Err(_) => return, + let Ok(mut entries) = fs::read_dir(src) else { + return; }; while let Some(Ok(entry)) = entries.next() { @@ -454,7 +456,7 @@ fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) { Ok(file_type) if file_type.is_file() => { let src = entry.path(); match src.extension().and_then(OsStr::to_str) { - Some("h") | Some("hh") | Some("hpp") => {} + Some("h" | "hh" | "hpp") => {} _ => continue, } if !dst_created && fs::create_dir_all(dst).is_err() { diff --git a/bridge/build/src/out.rs b/bridge/build/src/out.rs new file mode 100644 index 000000000..0b46c16a1 --- /dev/null +++ b/bridge/build/src/out.rs @@ -0,0 +1,304 @@ +use crate::bridge::fs; +use crate::error::{Error, Result}; +use crate::paths; +use std::path::{Component, Path, PathBuf}; +use std::{env, io}; + +pub(crate) fn write(path: impl AsRef, content: &[u8]) -> Result<()> { + let path = path.as_ref(); + + let mut create_dir_error = None; + if fs::exists(path) { + if let Ok(existing) = fs::read(path) + && existing == content + { + // Avoid bumping modified time with unchanged contents. + return Ok(()); + } + best_effort_remove(path); + } else { + let parent = path.parent().unwrap(); + create_dir_error = fs::create_dir_all(parent).err(); + } + + match fs::write(path, content) { + // As long as write succeeded, ignore any create_dir_all error. + Ok(()) => Ok(()), + // If create_dir_all and write both failed, prefer the first error. + Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))), + } +} + +pub(crate) fn relative_symlink_file( + original: impl AsRef, + link: impl AsRef, +) -> Result<()> { + let original = original.as_ref(); + let link = link.as_ref(); + + let parent_directory_error = prepare_parent_directory_for_symlink(link).err(); + let relativized = best_effort_relativize_symlink(original, link); + + symlink_file(&relativized, original, link, parent_directory_error) +} + +pub(crate) fn absolute_symlink_file( + original: impl AsRef, + link: impl AsRef, +) -> Result<()> { + let original = original.as_ref(); + let link = link.as_ref(); + + let parent_directory_error = prepare_parent_directory_for_symlink(link).err(); + + symlink_file(original, original, link, parent_directory_error) +} + +pub(crate) fn relative_symlink_dir( + original: impl AsRef, + link: impl AsRef, +) -> Result<()> { + let original = original.as_ref(); + let link = link.as_ref(); + + let parent_directory_error = prepare_parent_directory_for_symlink(link).err(); + let relativized = best_effort_relativize_symlink(original, link); + + symlink_dir(&relativized, link, parent_directory_error) +} + +fn prepare_parent_directory_for_symlink(link: &Path) -> fs::Result<()> { + if fs::exists(link) { + best_effort_remove(link); + Ok(()) + } else { + let parent = link.parent().unwrap(); + fs::create_dir_all(parent) + } +} + +fn symlink_file( + path_for_symlink: &Path, + path_for_copy: &Path, + link: &Path, + parent_directory_error: Option, +) -> Result<()> { + match paths::symlink_or_copy(path_for_symlink, path_for_copy, link) { + // As long as symlink_or_copy succeeded, ignore any create_dir_all error. + Ok(()) => Ok(()), + 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(parent_directory_error.unwrap_or(err))) + } + } + } +} + +fn symlink_dir( + path_for_symlink: &Path, + link: &Path, + parent_directory_error: Option, +) -> Result<()> { + match fs::symlink_dir(path_for_symlink, link) { + // As long as symlink_dir succeeded, ignore any create_dir_all error. + Ok(()) => Ok(()), + // If create_dir_all and symlink_dir both failed, prefer the first error. + Err(err) => Err(Error::Fs(parent_directory_error.unwrap_or(err))), + } +} + +fn best_effort_remove(path: &Path) { + use std::fs; + + 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". + 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. + if let Ok(metadata) = fs::symlink_metadata(path) { + if metadata.is_dir() { + let _ = fs::remove_dir_all(path); + } else { + let _ = fs::remove_file(path); + } + } + } +} + +fn best_effort_relativize_symlink(original: impl AsRef, link: impl AsRef) -> PathBuf { + let original = original.as_ref(); + let link = link.as_ref(); + + let Some(relative_path) = abstractly_relativize_symlink(original, link) else { + return original.to_path_buf(); + }; + + // Sometimes "a/b/../c" refers to a different canonical location than "a/c". + // This can happen if 'b' is a symlink. The '..' canonicalizes to the parent + // directory of the symlink's target, not back to 'a'. In cxx-build's case + // someone could be using `--target-dir` with a location containing such + // symlinks. + if let Ok(original_canonical) = original.canonicalize() + && let Ok(relative_canonical) = link.parent().unwrap().join(&relative_path).canonicalize() + && original_canonical == relative_canonical + { + return relative_path; + } + + original.to_path_buf() +} + +fn abstractly_relativize_symlink( + original: impl AsRef, + link: impl AsRef, +) -> Option { + let original = original.as_ref(); + let link = link.as_ref(); + + // Relativization only makes sense if there is a semantically meaningful + // base directory shared between the two paths. + // + // For example /Volumes/code/library/src/lib.rs + // and /Volumes/code/library/target/path/to/something.a + // have a meaningful shared base of /Volumes/code/library. The target and + // source directory only likely ever get relocated as one unit. + // + // On the other hand, /Volumes/code/library/src/lib.rs + // and /Volumes/shared_target + // do not, since upon moving library to a different location it should + // continue referring to the original location of that shared Cargo target + // directory. + let likely_no_semantic_prefix = env::var_os("CARGO_TARGET_DIR").is_some(); + + if likely_no_semantic_prefix + || original.is_relative() + || link.is_relative() + || path_contains_intermediate_components(original) + || path_contains_intermediate_components(link) + { + return None; + } + + let (common_prefix, rest_of_original, rest_of_link) = split_after_common_prefix(original, link); + + if common_prefix == Path::new("") { + return None; + } + + let mut rest_of_link = rest_of_link.components(); + rest_of_link + .next_back() + .expect("original can't be a subdirectory of link"); + + let mut path_to_common_prefix = PathBuf::new(); + while rest_of_link.next_back().is_some() { + path_to_common_prefix.push(Component::ParentDir); + } + + Some(path_to_common_prefix.join(rest_of_original)) +} + +fn path_contains_intermediate_components(path: impl AsRef) -> bool { + path.as_ref() + .components() + .any(|component| component == Component::ParentDir) +} + +fn split_after_common_prefix<'first, 'second>( + first: &'first Path, + second: &'second Path, +) -> (&'first Path, &'first Path, &'second Path) { + let entire_first = first; + let mut first = first.components(); + let mut second = second.components(); + loop { + let rest_of_first = first.as_path(); + let rest_of_second = second.as_path(); + match (first.next(), second.next()) { + (Some(first_component), Some(second_component)) + if first_component == second_component => {} + _ => { + let mut common_prefix = entire_first; + for _ in rest_of_first.components().rev() { + if let Some(parent) = common_prefix.parent() { + common_prefix = parent; + } else { + common_prefix = Path::new(""); + break; + } + } + return (common_prefix, rest_of_first, rest_of_second); + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::out::abstractly_relativize_symlink; + use std::path::Path; + + #[cfg(not(windows))] + #[test] + fn test_relativize_symlink_unix() { + assert_eq!( + abstractly_relativize_symlink("/foo/bar/baz", "/foo/spam/eggs").as_deref(), + Some(Path::new("../bar/baz")), + ); + assert_eq!( + abstractly_relativize_symlink("/foo/bar/../baz", "/foo/spam/eggs"), + None, + ); + assert_eq!( + abstractly_relativize_symlink("/foo/bar/baz", "/foo/spam/./eggs").as_deref(), + Some(Path::new("../bar/baz")), + ); + } + + #[cfg(windows)] + #[test] + fn test_relativize_symlink_windows() { + use std::path::PathBuf; + + let windows_target = PathBuf::from_iter(["c:\\", "windows", "foo"]); + let windows_link = PathBuf::from_iter(["c:\\", "users", "link"]); + let windows_different_volume_link = PathBuf::from_iter(["d:\\", "users", "link"]); + + assert_eq!( + abstractly_relativize_symlink(&windows_target, windows_link).as_deref(), + Some(Path::new("..\\windows\\foo")), + ); + assert_eq!( + abstractly_relativize_symlink(&windows_target, windows_different_volume_link), + None, + ); + } +} diff --git a/gen/build/src/paths.rs b/bridge/build/src/paths.rs similarity index 74% rename from gen/build/src/paths.rs rename to bridge/build/src/paths.rs index c514a5702..dfa0447fc 100644 --- a/gen/build/src/paths.rs +++ b/bridge/build/src/paths.rs @@ -1,5 +1,5 @@ +use crate::bridge::fs; use crate::error::Result; -use crate::gen::fs; use std::ffi::OsStr; use std::path::{Component, Path, PathBuf}; @@ -40,28 +40,37 @@ impl PathExt for Path { } #[cfg(unix)] -pub(crate) use self::fs::symlink_file as symlink_or_copy; +pub(crate) fn symlink_or_copy( + path_for_symlink: impl AsRef, + _path_for_copy: impl AsRef, + link: impl AsRef, +) -> fs::Result<()> { + fs::symlink_file(path_for_symlink, link) +} #[cfg(windows)] pub(crate) fn symlink_or_copy( - original: impl AsRef, + path_for_symlink: impl AsRef, + path_for_copy: impl AsRef, link: impl AsRef, ) -> fs::Result<()> { // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they // require Developer Mode. If it fails, fall back to copying the file. - let original = original.as_ref(); + let path_for_symlink = path_for_symlink.as_ref(); let link = link.as_ref(); - if fs::symlink_file(original, link).is_err() { - fs::copy(original, link)?; + if fs::symlink_file(path_for_symlink, link).is_err() { + let path_for_copy = path_for_copy.as_ref(); + fs::copy(path_for_copy, link)?; } Ok(()) } #[cfg(not(any(unix, windows)))] pub(crate) fn symlink_or_copy( - original: impl AsRef, + _path_for_symlink: impl AsRef, + path_for_copy: impl AsRef, copy: impl AsRef, ) -> fs::Result<()> { - fs::copy(original, copy)?; + fs::copy(path_for_copy, copy)?; Ok(()) } diff --git a/gen/build/src/syntax b/bridge/build/src/syntax similarity index 100% rename from gen/build/src/syntax rename to bridge/build/src/syntax diff --git a/gen/build/src/target.rs b/bridge/build/src/target.rs similarity index 71% rename from gen/build/src/target.rs rename to bridge/build/src/target.rs index 4c9a9f3d5..df2d3e959 100644 --- a/gen/build/src/target.rs +++ b/bridge/build/src/target.rs @@ -10,10 +10,10 @@ pub(crate) enum TargetDir { pub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir { if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") { let target_dir = PathBuf::from(target_dir); - if target_dir.is_absolute() { - return TargetDir::Path(target_dir); + return if target_dir.is_absolute() { + TargetDir::Path(target_dir) } else { - return TargetDir::Unknown; + TargetDir::Unknown }; } @@ -30,19 +30,17 @@ pub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir { || dir.file_name() == Some(OsStr::new("target")) && dir .parent() - .map_or(false, |parent| parent.join("Cargo.toml").exists()) + .is_some_and(|parent| parent.join("Cargo.toml").exists()) { return TargetDir::Path(dir); } if dir.pop() { continue; } - if also_try_canonical { - if let Ok(canonical_dir) = out_dir.canonicalize() { - dir = canonical_dir; - also_try_canonical = false; - continue; - } + if also_try_canonical && let Ok(canonical_dir) = out_dir.canonicalize() { + dir = canonical_dir; + also_try_canonical = false; + continue; } return TargetDir::Unknown; } diff --git a/gen/build/src/vec.rs b/bridge/build/src/vec.rs similarity index 88% rename from gen/build/src/vec.rs rename to bridge/build/src/vec.rs index ac9235ec7..ccc989557 100644 --- a/gen/build/src/vec.rs +++ b/bridge/build/src/vec.rs @@ -1,7 +1,7 @@ use crate::intern::{self, InternedString}; use std::path::Path; -pub trait InternedVec +pub(crate) trait InternedVec where T: ?Sized, { @@ -17,14 +17,14 @@ where } } -pub fn intern(elements: &[&T]) -> Vec +pub(crate) fn intern(elements: &[&T]) -> Vec where T: ?Sized + Element, { elements.iter().copied().map(Element::intern).collect() } -pub trait Element { +pub(crate) trait Element { fn intern(&self) -> InternedString; fn unintern(_: InternedString) -> &'static Self; } diff --git a/bridge/cmd/Cargo.toml b/bridge/cmd/Cargo.toml new file mode 100644 index 000000000..9f4fb5d57 --- /dev/null +++ b/bridge/cmd/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "cxxbridge-cmd" +version = "1.0.199" +authors = ["David Tolnay "] +categories = ["development-tools::build-utils", "development-tools::ffi"] +description = "C++ code generator for integrating `cxx` crate into a non-Cargo build." +edition = "2024" +exclude = ["build.rs"] +homepage = "https://cxx.rs" +keywords = ["ffi"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/cxx" +rust-version = "1.88" + +[[bin]] +name = "cxxbridge" +path = "src/main.rs" + +[dependencies] +clap = { version = "4.3.11", default-features = false, features = ["error-context", "help", "std", "suggestions", "usage"] } +codespan-reporting = "0.13.1" +indexmap = "2.9.0" +proc-macro2 = { version = "1.0.74", default-features = false, features = ["span-locations"] } +quote = { version = "1.0.35", default-features = false } +syn = { version = "3", default-features = false, features = ["clone-impls", "full", "parsing", "printing"] } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/gen/cmd/LICENSE-APACHE b/bridge/cmd/LICENSE-APACHE similarity index 100% rename from gen/cmd/LICENSE-APACHE rename to bridge/cmd/LICENSE-APACHE diff --git a/gen/cmd/LICENSE-MIT b/bridge/cmd/LICENSE-MIT similarity index 100% rename from gen/cmd/LICENSE-MIT rename to bridge/cmd/LICENSE-MIT diff --git a/gen/cmd/build.rs b/bridge/cmd/build.rs similarity index 100% rename from gen/cmd/build.rs rename to bridge/cmd/build.rs diff --git a/gen/cmd/src/app.rs b/bridge/cmd/src/app.rs similarity index 94% rename from gen/cmd/src/app.rs rename to bridge/cmd/src/app.rs index bfad85626..549e71fd4 100644 --- a/gen/cmd/src/app.rs +++ b/bridge/cmd/src/app.rs @@ -3,8 +3,8 @@ mod test; use super::{Opt, Output}; +use crate::bridge::include::Include; use crate::cfg::{self, CfgValue}; -use crate::gen::include::Include; use crate::syntax::IncludeKind; use clap::builder::{ArgAction, ValueParser}; use clap::{Arg, Command}; @@ -84,7 +84,7 @@ pub(super) fn from_args() -> Opt { } } else { Include { - path: include.to_owned(), + path: include.clone(), kind: IncludeKind::Quoted, } } @@ -122,7 +122,7 @@ pub(super) fn from_args() -> Opt { fn arg_input() -> Arg { Arg::new(INPUT) .help("Input Rust source file containing #[cxx::bridge].") - .required_unless_present_any(&[HEADER, HELP]) + .required_unless_present_any([HEADER, HELP]) .value_parser(ValueParser::path_buf()) } @@ -140,10 +140,10 @@ the Rust side of the bridge."; 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)); - } + if let Some(&prev) = bool_cfgs.get(&name) + && prev != value + { + return Err(format!("cannot have both {0}=false and {0}=true", name)); } bool_cfgs.insert(name, value); Ok(arg.to_owned()) diff --git a/gen/cmd/src/gen b/bridge/cmd/src/bridge similarity index 100% rename from gen/cmd/src/gen rename to bridge/cmd/src/bridge diff --git a/gen/cmd/src/cfg.rs b/bridge/cmd/src/cfg.rs similarity index 91% rename from gen/cmd/src/cfg.rs rename to bridge/cmd/src/cfg.rs index 29f0b9bcb..7a3d89270 100644 --- a/gen/cmd/src/cfg.rs +++ b/bridge/cmd/src/cfg.rs @@ -1,11 +1,11 @@ -use crate::gen::{CfgEvaluator, CfgResult}; +use crate::bridge::{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 { +pub(crate) enum CfgValue { Bool(bool), Str(String), } @@ -15,12 +15,12 @@ impl CfgValue { const TRUE: Self = CfgValue::Bool(true); } -pub struct FlagsCfgEvaluator { +pub(crate) struct FlagsCfgEvaluator { map: Map>, } impl FlagsCfgEvaluator { - pub fn new(map: Map>) -> Self { + pub(crate) fn new(map: Map>) -> Self { FlagsCfgEvaluator { map } } } @@ -73,7 +73,7 @@ impl Debug for CfgValue { } } -pub fn parse(input: ParseStream) -> syn::Result<(String, CfgValue)> { +pub(crate) fn parse(input: ParseStream) -> syn::Result<(String, CfgValue)> { let ident: Ident = input.parse()?; let name = ident.to_string(); if input.is_empty() { diff --git a/gen/cmd/src/main.rs b/bridge/cmd/src/main.rs similarity index 78% rename from gen/cmd/src/main.rs rename to bridge/cmd/src/main.rs index 4d5edfd15..1346452e1 100644 --- a/gen/cmd/src/main.rs +++ b/bridge/cmd/src/main.rs @@ -1,44 +1,45 @@ +#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] #![allow( + clippy::assert_is_empty, clippy::cast_sign_loss, - clippy::cognitive_complexity, clippy::default_trait_access, - clippy::derive_partial_eq_without_eq, + clippy::elidable_lifetime_names, clippy::enum_glob_use, - clippy::if_same_then_else, + clippy::expl_impl_clone_on_copy, // https://github.com/rust-lang/rust-clippy/issues/15842 clippy::inherent_to_string, clippy::items_after_statements, - clippy::large_enum_variant, + clippy::map_clone, clippy::match_bool, - clippy::match_on_vec_items, + clippy::match_like_matches_macro, clippy::match_same_arms, - clippy::module_name_repetitions, + clippy::needless_continue, + clippy::needless_lifetimes, clippy::needless_pass_by_value, - clippy::new_without_default, clippy::nonminimal_bool, - clippy::option_if_let_else, - clippy::or_fun_call, + clippy::precedence, clippy::redundant_else, - clippy::shadow_unrelated, + clippy::ref_option, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, + clippy::struct_field_names, clippy::too_many_arguments, clippy::too_many_lines, clippy::toplevel_ref_arg, - // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983 - clippy::wrong_self_convention + clippy::uninlined_format_args )] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] mod app; +mod bridge; mod cfg; -mod gen; mod output; mod syntax; +use crate::bridge::error::{Result, report}; +use crate::bridge::fs; +use crate::bridge::include::{self, Include}; 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}; @@ -91,7 +92,7 @@ fn try_main() -> Result<()> { outputs.push((output, kind)); } - let gen = gen::Opt { + let bridge = bridge::Opt { include: opt.include, cxx_impl_annotations: opt.cxx_impl_annotations, gen_header, @@ -101,7 +102,7 @@ fn try_main() -> Result<()> { }; let generated_code = if let Some(input) = opt.input { - gen::generate_from_path(&input, &gen) + bridge::generate_from_path(&input, &bridge) } else { Default::default() }; diff --git a/gen/cmd/src/output.rs b/bridge/cmd/src/output.rs similarity index 100% rename from gen/cmd/src/output.rs rename to bridge/cmd/src/output.rs diff --git a/gen/cmd/src/syntax b/bridge/cmd/src/syntax similarity index 100% rename from gen/cmd/src/syntax rename to bridge/cmd/src/syntax diff --git a/gen/cmd/src/test.rs b/bridge/cmd/src/test.rs similarity index 100% rename from gen/cmd/src/test.rs rename to bridge/cmd/src/test.rs diff --git a/bridge/lib/Cargo.toml b/bridge/lib/Cargo.toml new file mode 100644 index 000000000..7c6b982ae --- /dev/null +++ b/bridge/lib/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "cxx-gen" +version = "0.7.199" +authors = ["Adrian Taylor "] +categories = ["development-tools::ffi"] +description = "C++ code generator for integrating `cxx` crate into higher level tools." +documentation = "https://docs.rs/cxx-gen" +edition = "2024" +exclude = ["build.rs"] +keywords = ["ffi"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/cxx" +rust-version = "1.88" + +[dependencies] +codespan-reporting = "0.13.1" +indexmap = "2.9.0" +proc-macro2 = { version = "1.0.74", default-features = false, features = ["span-locations"] } +quote = { version = "1.0.35", default-features = false } +syn = { version = "3", default-features = false, features = ["clone-impls", "full", "parsing", "printing"] } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] diff --git a/gen/lib/LICENSE-APACHE b/bridge/lib/LICENSE-APACHE similarity index 100% rename from gen/lib/LICENSE-APACHE rename to bridge/lib/LICENSE-APACHE diff --git a/gen/lib/LICENSE-MIT b/bridge/lib/LICENSE-MIT similarity index 100% rename from gen/lib/LICENSE-MIT rename to bridge/lib/LICENSE-MIT diff --git a/gen/lib/build.rs b/bridge/lib/build.rs similarity index 100% rename from gen/lib/build.rs rename to bridge/lib/build.rs diff --git a/gen/lib/src/gen b/bridge/lib/src/bridge similarity index 100% rename from gen/lib/src/gen rename to bridge/lib/src/bridge diff --git a/bridge/lib/src/error.rs b/bridge/lib/src/error.rs new file mode 100644 index 000000000..c456dcd2e --- /dev/null +++ b/bridge/lib/src/error.rs @@ -0,0 +1,75 @@ +// We can expose more detail on the error as the need arises, but start with an +// opaque error type for now. + +use std::error::Error as StdError; +use std::fmt::{self, Debug, Display}; +use std::iter; + +#[allow(missing_docs)] +pub struct Error { + pub(crate) err: crate::bridge::Error, +} + +impl Error { + /// Returns the span of the error, if available. + pub fn span(&self) -> Option { + match &self.err { + crate::bridge::Error::Syn(err) => Some(err.span()), + _ => None, + } + } +} + +impl From for Error { + fn from(err: crate::bridge::Error) -> Self { + Error { err } + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.err, f) + } +} + +impl Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.err, f) + } +} + +impl StdError for Error { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.err.source() + } +} + +impl IntoIterator for Error { + type Item = Error; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + match self.err { + crate::bridge::Error::Syn(err) => IntoIter::Syn(err.into_iter()), + _ => IntoIter::Other(iter::once(self)), + } + } +} + +pub enum IntoIter { + Syn(::IntoIter), + Other(iter::Once), +} + +impl Iterator for IntoIter { + type Item = Error; + + fn next(&mut self) -> Option { + match self { + IntoIter::Syn(iter) => iter + .next() + .map(|syn_err| Error::from(crate::bridge::Error::Syn(syn_err))), + IntoIter::Other(iter) => iter.next(), + } + } +} diff --git a/gen/lib/src/lib.rs b/bridge/lib/src/lib.rs similarity index 62% rename from gen/lib/src/lib.rs rename to bridge/lib/src/lib.rs index 47cfa18d6..b8553ae07 100644 --- a/gen/lib/src/lib.rs +++ b/bridge/lib/src/lib.rs @@ -7,45 +7,49 @@ //! [dtolnay/cxx#235]: https://github.com/dtolnay/cxx/issues/235 //! [https://github.com/google/autocxx]: https://github.com/google/autocxx +#![doc(html_root_url = "https://docs.rs/cxx-gen/0.7.199")] #![deny(missing_docs)] -#![allow(dead_code)] +#![expect(dead_code)] +#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] #![allow( + clippy::assert_is_empty, clippy::cast_sign_loss, clippy::default_trait_access, - clippy::derive_partial_eq_without_eq, + clippy::elidable_lifetime_names, clippy::enum_glob_use, - clippy::if_same_then_else, + clippy::expl_impl_clone_on_copy, // https://github.com/rust-lang/rust-clippy/issues/15842 clippy::inherent_to_string, clippy::items_after_statements, clippy::match_bool, - clippy::match_on_vec_items, + clippy::match_like_matches_macro, clippy::match_same_arms, clippy::missing_errors_doc, - clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_continue, + clippy::needless_lifetimes, clippy::needless_pass_by_value, - clippy::new_without_default, clippy::nonminimal_bool, - clippy::option_if_let_else, - clippy::or_fun_call, + clippy::precedence, clippy::redundant_else, - clippy::shadow_unrelated, + clippy::ref_option, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, + clippy::struct_field_names, clippy::too_many_arguments, clippy::too_many_lines, clippy::toplevel_ref_arg, - // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983 - clippy::wrong_self_convention + clippy::uninlined_format_args )] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] +mod bridge; mod error; -mod gen; mod syntax; +pub use crate::bridge::include::{HEADER, Include}; +pub use crate::bridge::{CfgEvaluator, CfgResult, GeneratedCode, Opt}; pub use crate::error::Error; -pub use crate::gen::include::{Include, HEADER}; -pub use crate::gen::{GeneratedCode, Opt}; pub use crate::syntax::IncludeKind; use proc_macro2::TokenStream; @@ -53,7 +57,7 @@ use proc_macro2::TokenStream; /// token stream which somewhere contains a `#[cxx::bridge] mod {}`. pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result { let syntax = syn::parse2(rust_source) - .map_err(crate::gen::Error::from) + .map_err(crate::bridge::Error::from) .map_err(Error::from)?; - gen::generate(syntax, opt).map_err(Error::from) + bridge::generate(syntax, opt).map_err(Error::from) } diff --git a/gen/lib/src/syntax b/bridge/lib/src/syntax similarity index 100% rename from gen/lib/src/syntax rename to bridge/lib/src/syntax diff --git a/gen/lib/tests/test.rs b/bridge/lib/tests/test.rs similarity index 84% rename from gen/lib/tests/test.rs rename to bridge/lib/tests/test.rs index d035b5225..eb796a93a 100644 --- a/gen/lib/tests/test.rs +++ b/bridge/lib/tests/test.rs @@ -1,3 +1,5 @@ +#![allow(clippy::assert_is_empty)] + use cxx_gen::Opt; use quote::quote; @@ -24,5 +26,5 @@ fn test_positive() { fn test_negative() { let rs = quote! {}; let opt = Opt::default(); - assert!(cxx_gen::generate_header_and_cc(rs, &opt).is_err()) + assert!(cxx_gen::generate_header_and_cc(rs, &opt).is_err()); } diff --git a/gen/src/block.rs b/bridge/src/block.rs similarity index 84% rename from gen/src/block.rs rename to bridge/src/block.rs index 96a9a6ee0..9bdb5c0dd 100644 --- a/gen/src/block.rs +++ b/bridge/src/block.rs @@ -1,16 +1,16 @@ use proc_macro2::Ident; #[derive(Copy, Clone, PartialEq, Debug)] -pub enum Block<'a> { +pub(crate) enum Block<'a> { AnonymousNamespace, - Namespace(&'static str), + Namespace(&'a str), UserDefinedNamespace(&'a Ident), - InlineNamespace(&'static str), + InlineNamespace(&'a str), ExternC, } impl<'a> Block<'a> { - pub fn write_begin(self, out: &mut String) { + pub(crate) fn write_begin(self, out: &mut String) { if let Block::InlineNamespace(_) = self { out.push_str("inline "); } @@ -18,7 +18,7 @@ impl<'a> Block<'a> { out.push_str(" {\n"); } - pub fn write_end(self, out: &mut String) { + pub(crate) fn write_end(self, out: &mut String) { out.push_str("} // "); self.write_common(out); out.push('\n'); diff --git a/gen/src/builtin.rs b/bridge/src/builtin.rs similarity index 54% rename from gen/src/builtin.rs rename to bridge/src/builtin.rs index 277c64f8d..6775ad0ef 100644 --- a/gen/src/builtin.rs +++ b/bridge/src/builtin.rs @@ -1,9 +1,11 @@ -use crate::gen::block::Block; -use crate::gen::ifndef; -use crate::gen::out::{Content, OutFile}; +use crate::bridge::block::Block; +use crate::bridge::ifndef; +use crate::bridge::include::Includes; +use crate::bridge::out::{Content, OutFile}; +use crate::bridge::pragma::Pragma; #[derive(Default, PartialEq)] -pub struct Builtins<'a> { +pub(crate) struct Builtins<'a> { pub panic: bool, pub rust_string: bool, pub rust_str: bool, @@ -32,11 +34,14 @@ pub struct Builtins<'a> { pub is_complete: bool, pub destroy: bool, pub deleter_if: bool, + pub shared_ptr: bool, + pub vector: bool, + pub alignmax: bool, pub content: Content<'a>, } impl<'a> Builtins<'a> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Builtins::default() } } @@ -47,6 +52,7 @@ pub(super) fn write(out: &mut OutFile) { } let include = &mut out.include; + let pragma = &mut out.pragma; let builtin = &mut out.builtin; let out = &mut builtin.content; @@ -60,6 +66,7 @@ pub(super) fn write(out: &mut OutFile) { include.array = true; include.cstdint = true; include.string = true; + include.string_view = true; builtin.friend_impl = true; } @@ -86,6 +93,7 @@ pub(super) fn write(out: &mut OutFile) { include.cstddef = true; include.cstdint = true; include.iterator = true; + include.ranges = true; include.stdexcept = true; include.type_traits = true; builtin.friend_impl = true; @@ -128,6 +136,12 @@ pub(super) fn write(out: &mut OutFile) { builtin.is_complete = true; } + if builtin.shared_ptr { + include.memory = true; + include.type_traits = true; + builtin.is_complete = true; + } + if builtin.is_complete { include.cstddef = true; include.type_traits = true; @@ -194,112 +208,61 @@ pub(super) fn write(out: &mut OutFile) { ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE"); } + out.end_block(Block::InlineNamespace("cxxbridge1")); + out.end_block(Block::Namespace("rust")); + + macro_rules! write_builtin { + ($path:literal) => { + write_builtin(out, include, pragma, include_str!($path)); + }; + } + + // namespace rust::cxxbridge1 + if builtin.rust_str_new_unchecked { - out.next_section(); - writeln!(out, "class Str::uninit {{}};"); - writeln!(out, "inline Str::Str(uninit) noexcept {{}}"); + write_builtin!("builtin/rust_str_uninit.h"); } if builtin.rust_slice_new { - out.next_section(); - writeln!(out, "template "); - writeln!(out, "class Slice::uninit {{}};"); - writeln!(out, "template "); - writeln!(out, "inline Slice::Slice(uninit) noexcept {{}}"); + write_builtin!("builtin/rust_slice_uninit.h"); } - out.begin_block(Block::Namespace("repr")); + // namespace rust::cxxbridge1::repr if builtin.repr_fat { - include.array = true; - include.cstdint = true; - out.next_section(); - writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;"); + write_builtin!("builtin/repr_fat.h"); } 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, "}};"); + write_builtin!("builtin/ptr_len.h"); } - out.end_block(Block::Namespace("repr")); + if builtin.alignmax { + write_builtin!("builtin/alignmax.h"); + } - out.begin_block(Block::Namespace("detail")); + // namespace rust::cxxbridge1::detail if builtin.maybe_uninit { - include.cstddef = true; - include.new = true; - out.next_section(); - writeln!(out, "template "); - writeln!(out, "struct operator_new {{"); - writeln!( - out, - " void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}", - ); - writeln!(out, "}};"); - out.next_section(); - writeln!(out, "template "); - writeln!( - out, - "struct operator_new {{", - ); - writeln!( - out, - " void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}", - ); - writeln!(out, "}};"); + write_builtin!("builtin/maybe_uninit_detail.h"); } 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, "}};"); + write_builtin!("builtin/trycatch_detail.h"); } - out.end_block(Block::Namespace("detail")); + // namespace rust::cxxbridge1 if builtin.manually_drop { - out.next_section(); - include.utility = true; - writeln!(out, "template "); - writeln!(out, "union ManuallyDrop {{"); - writeln!(out, " T value;"); - writeln!( - out, - " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}", - ); - writeln!(out, " ~ManuallyDrop() {{}}"); - writeln!(out, "}};"); + write_builtin!("builtin/manually_drop.h"); } if builtin.maybe_uninit { - include.cstddef = true; - out.next_section(); - writeln!(out, "template "); - writeln!(out, "union MaybeUninit {{"); - writeln!(out, " T value;"); - writeln!( - out, - " void *operator new(::std::size_t sz) {{ return detail::operator_new{{}}(sz); }}", - ); - writeln!(out, " MaybeUninit() {{}}"); - writeln!(out, " ~MaybeUninit() {{}}"); - writeln!(out, "}};"); + write_builtin!("builtin/maybe_uninit.h"); } + out.begin_block(Block::Namespace("rust")); + out.begin_block(Block::InlineNamespace("cxxbridge1")); out.begin_block(Block::AnonymousNamespace); if builtin.rust_str_new_unchecked || builtin.rust_str_repr { @@ -345,78 +308,164 @@ pub(super) fn write(out: &mut OutFile) { writeln!(out, "}};"); } + out.end_block(Block::AnonymousNamespace); + out.end_block(Block::InlineNamespace("cxxbridge1")); + out.end_block(Block::Namespace("rust")); + + // namespace rust::cxxbridge1::(anonymous) + if builtin.rust_error { - out.next_section(); - writeln!(out, "template <>"); - writeln!(out, "class impl final {{"); - writeln!(out, "public:"); - writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{"); - writeln!(out, " Error error;"); - writeln!(out, " error.msg = static_cast(repr.ptr);"); - writeln!(out, " error.len = repr.len;"); - writeln!(out, " return error;"); - writeln!(out, " }}"); - writeln!(out, "}};"); + write_builtin!("builtin/rust_error.h"); } if builtin.destroy { - out.next_section(); - writeln!(out, "template "); - writeln!(out, "void destroy(T *ptr) {{"); - writeln!(out, " ptr->~T();"); - writeln!(out, "}}"); + write_builtin!("builtin/destroy.h"); } if builtin.deleter_if { - out.next_section(); - writeln!(out, "template struct deleter_if {{"); - writeln!(out, " template void operator()(T *) {{}}"); - writeln!(out, "}};"); - out.next_section(); - writeln!(out, "template <> struct deleter_if {{"); - writeln!( - out, - " template void operator()(T *ptr) {{ ptr->~T(); }}", - ); - writeln!(out, "}};"); + write_builtin!("builtin/deleter_if.h"); + } + + if builtin.shared_ptr { + write_builtin!("builtin/shared_ptr.h"); + } + + if builtin.vector { + write_builtin!("builtin/vector.h"); } if builtin.relocatable_or_array { - out.next_section(); - writeln!(out, "template "); - writeln!(out, "struct IsRelocatableOrArray : IsRelocatable {{}};"); - writeln!(out, "template "); - writeln!( - out, - "struct IsRelocatableOrArray : IsRelocatableOrArray {{}};", - ); + write_builtin!("builtin/relocatable_or_array.h"); } - out.end_block(Block::AnonymousNamespace); - out.end_block(Block::InlineNamespace("cxxbridge1")); + // namespace rust::behavior if builtin.trycatch { - out.begin_block(Block::Namespace("behavior")); - include.exception = true; - include.type_traits = true; - include.utility = true; - writeln!(out, "class missing {{}};"); - writeln!(out, "missing trycatch(...);"); - writeln!(out); - writeln!(out, "template "); - writeln!(out, "static typename ::std::enable_if<"); - writeln!( - out, - " ::std::is_same(), ::std::declval())),", - ); - writeln!(out, " missing>::value>::type"); - writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{"); - writeln!(out, " func();"); - writeln!(out, "}} catch (::std::exception const &e) {{"); - writeln!(out, " fail(e.what());"); - writeln!(out, "}}"); - out.end_block(Block::Namespace("behavior")); + write_builtin!("builtin/trycatch.h"); } +} - out.end_block(Block::Namespace("rust")); +fn write_builtin<'a>( + out: &mut Content<'a>, + include: &mut Includes, + pragma: &mut Pragma<'a>, + src: &'a str, +) { + let mut namespace = Vec::new(); + let mut ready = false; + + for line in src.lines() { + if line == "#pragma once" || line.starts_with("#include \".") { + continue; + } else if let Some(rest) = line.strip_prefix("#include <") { + let Includes { + custom: _, + algorithm, + array, + cassert, + cstddef, + cstdint, + cstring, + exception, + functional, + initializer_list, + iterator, + limits, + memory, + new, + ranges, + stdexcept, + string, + string_view, + type_traits, + utility, + vector, + basetsd: _, + sys_types: _, + content: _, + } = include; + match rest.strip_suffix(">").unwrap() { + "algorithm" => *algorithm = true, + "array" => *array = true, + "cassert" => *cassert = true, + "cstddef" => *cstddef = true, + "cstdint" => *cstdint = true, + "cstring" => *cstring = true, + "exception" => *exception = true, + "functional" => *functional = true, + "initializer_list" => *initializer_list = true, + "iterator" => *iterator = true, + "limits" => *limits = true, + "memory" => *memory = true, + "new" => *new = true, + "ranges" => *ranges = true, + "stdexcept" => *stdexcept = true, + "string" => *string = true, + "string_view" => *string_view = true, + "type_traits" => *type_traits = true, + "utility" => *utility = true, + "vector" => *vector = true, + _ => unimplemented!("{}", line), + } + } else if let Some(rest) = line.strip_prefix("#pragma GCC diagnostic ignored \"") { + let diagnostic = rest.strip_suffix('"').unwrap(); + pragma.gnu_diagnostic_ignore.insert(diagnostic); + ready = false; + } else if let Some(rest) = line.strip_prefix("#pragma clang diagnostic ignored \"") { + let diagnostic = rest.strip_suffix('"').unwrap(); + pragma.clang_diagnostic_ignore.insert(diagnostic); + ready = false; + } else if line == "namespace {" { + namespace.push(Block::AnonymousNamespace); + out.begin_block(Block::AnonymousNamespace); + } else if let Some(rest) = line.strip_prefix("namespace ") { + let name = rest.strip_suffix(" {").unwrap(); + namespace.push(Block::Namespace(name)); + out.begin_block(Block::Namespace(name)); + } else if let Some(rest) = line.strip_prefix("inline namespace ") { + let name = rest.strip_suffix(" {").unwrap(); + namespace.push(Block::InlineNamespace(name)); + out.begin_block(Block::InlineNamespace(name)); + } else if line.starts_with("} // namespace") { + out.end_block(namespace.pop().unwrap()); + } else if line.is_empty() && !ready { + out.next_section(); + ready = true; + } else if !line.trim_start_matches(' ').starts_with("//") { + assert!(ready); + writeln!(out, "{}", line); + } + } + + assert!(namespace.is_empty()); + assert!(ready); +} + +#[cfg(test)] +mod tests { + use crate::bridge::include::Includes; + use crate::bridge::out::Content; + use crate::bridge::pragma::Pragma; + use std::fs; + + #[test] + fn test_write_builtin() { + let mut builtin_src = Vec::new(); + + for entry in fs::read_dir("src/bridge/builtin").unwrap() { + let path = entry.unwrap().path(); + let src = fs::read_to_string(path).unwrap(); + builtin_src.push(src); + } + + assert_ne!(builtin_src.len(), 0); + builtin_src.sort(); + + let mut content = Content::new(); + let mut include = Includes::new(); + let mut pragma = Pragma::new(); + for src in &builtin_src { + super::write_builtin(&mut content, &mut include, &mut pragma, src); + } + } } diff --git a/bridge/src/builtin/alignmax.h b/bridge/src/builtin/alignmax.h new file mode 100644 index 000000000..f84fbdfad --- /dev/null +++ b/bridge/src/builtin/alignmax.h @@ -0,0 +1,31 @@ +#pragma once +#include + +namespace rust { +inline namespace cxxbridge1 { +namespace repr { +#ifndef CXXBRIDGE_ALIGNMAX +#define CXXBRIDGE_ALIGNMAX +// This would be cleaner as the following, but GCC does not implement that +// correctly. +// +// template <::std::size_t... N> +// class alignas(N...) alignmax {}; +// +// Next, it could be this, but MSVC does not implement this correctly. +// +// template <::std::size_t... N> +// class alignmax { alignas(N...) union {} members; }; +// +template <::std::size_t N> +class alignas(N) aligned {}; +// +template +class alignmax_t { alignas(T...) union {} members; }; +// +template <::std::size_t... N> +using alignmax = alignmax_t...>; +#endif // CXXBRIDGE_ALIGNMAX +} // namespace repr +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/deleter_if.h b/bridge/src/builtin/deleter_if.h new file mode 100644 index 000000000..4c6526cf8 --- /dev/null +++ b/bridge/src/builtin/deleter_if.h @@ -0,0 +1,15 @@ +#pragma once + +namespace rust { +inline namespace cxxbridge1 { +namespace { +template struct deleter_if { + template void operator()(T *) {} +}; +// +template <> struct deleter_if { + template void operator()(T *ptr) { ptr->~T(); } +}; +} // namespace +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/destroy.h b/bridge/src/builtin/destroy.h new file mode 100644 index 000000000..cd4721164 --- /dev/null +++ b/bridge/src/builtin/destroy.h @@ -0,0 +1,12 @@ +#pragma once + +namespace rust { +inline namespace cxxbridge1 { +namespace { +template +void destroy(T *ptr) { + ptr->~T(); +} +} // namespace +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/friend_impl.h b/bridge/src/builtin/friend_impl.h new file mode 100644 index 000000000..d1f87ad12 --- /dev/null +++ b/bridge/src/builtin/friend_impl.h @@ -0,0 +1,10 @@ +#pragma once + +namespace rust { +inline namespace cxxbridge1 { +namespace { +template +class impl; +} // namespace +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/manually_drop.h b/bridge/src/builtin/manually_drop.h new file mode 100644 index 000000000..65a5484a2 --- /dev/null +++ b/bridge/src/builtin/manually_drop.h @@ -0,0 +1,15 @@ +#pragma once +#include + +#pragma GCC diagnostic ignored "-Wshadow" + +namespace rust { +inline namespace cxxbridge1 { +template +union ManuallyDrop { + T value; + ManuallyDrop(T &&value) : value(::std::move(value)) {} + ~ManuallyDrop() {} +}; +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/maybe_uninit.h b/bridge/src/builtin/maybe_uninit.h new file mode 100644 index 000000000..84610f01e --- /dev/null +++ b/bridge/src/builtin/maybe_uninit.h @@ -0,0 +1,15 @@ +#pragma once +#include "./maybe_uninit_detail.h" +#include + +namespace rust { +inline namespace cxxbridge1 { +template +union MaybeUninit { + T value; + void *operator new(::std::size_t sz) { return detail::operator_new{}(sz); } + MaybeUninit() {} + ~MaybeUninit() {} +}; +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/maybe_uninit_detail.h b/bridge/src/builtin/maybe_uninit_detail.h new file mode 100644 index 000000000..c6141aafa --- /dev/null +++ b/bridge/src/builtin/maybe_uninit_detail.h @@ -0,0 +1,19 @@ +#pragma once +#include +#include + +namespace rust { +inline namespace cxxbridge1 { +namespace detail { +template +struct operator_new { + void *operator()(::std::size_t sz) { return ::operator new(sz); } +}; + +template +struct operator_new { + void *operator()(::std::size_t sz) { return T::operator new(sz); } +}; +} // namespace detail +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/ptr_len.h b/bridge/src/builtin/ptr_len.h new file mode 100644 index 000000000..5685337b1 --- /dev/null +++ b/bridge/src/builtin/ptr_len.h @@ -0,0 +1,13 @@ +#pragma once +#include + +namespace rust { +inline namespace cxxbridge1 { +namespace repr { +struct PtrLen final { + void *ptr; + ::std::size_t len; +}; +} // namespace repr +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/relocatable_or_array.h b/bridge/src/builtin/relocatable_or_array.h new file mode 100644 index 000000000..f03c12c28 --- /dev/null +++ b/bridge/src/builtin/relocatable_or_array.h @@ -0,0 +1,15 @@ +#pragma once +#include "../../../include/cxx.h" +#include + +namespace rust { +inline namespace cxxbridge1 { +namespace { +template +struct IsRelocatableOrArray : IsRelocatable {}; +// +template +struct IsRelocatableOrArray : IsRelocatableOrArray {}; +} // namespace +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/repr_fat.h b/bridge/src/builtin/repr_fat.h new file mode 100644 index 000000000..5059a609e --- /dev/null +++ b/bridge/src/builtin/repr_fat.h @@ -0,0 +1,11 @@ +#pragma once +#include +#include + +namespace rust { +inline namespace cxxbridge1 { +namespace repr { +using Fat = ::std::array<::std::uintptr_t, 2>; +} // namespace repr +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/rust_error.h b/bridge/src/builtin/rust_error.h new file mode 100644 index 000000000..fb3a01e96 --- /dev/null +++ b/bridge/src/builtin/rust_error.h @@ -0,0 +1,21 @@ +#pragma once +#include "../../../include/cxx.h" +#include "./friend_impl.h" +#include "./ptr_len.h" + +namespace rust { +inline namespace cxxbridge1 { +namespace { +template <> +class impl final { +public: + static Error error(repr::PtrLen repr) noexcept { + Error error; + error.msg = static_cast(repr.ptr); + error.len = repr.len; + return error; + } +}; +} // namespace +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/rust_slice_uninit.h b/bridge/src/builtin/rust_slice_uninit.h new file mode 100644 index 000000000..b6c3ded98 --- /dev/null +++ b/bridge/src/builtin/rust_slice_uninit.h @@ -0,0 +1,12 @@ +#pragma once +#include "../../../include/cxx.h" + +namespace rust { +inline namespace cxxbridge1 { +template +class Slice::uninit {}; +// +template +inline Slice::Slice(uninit) noexcept {} +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/rust_str_uninit.h b/bridge/src/builtin/rust_str_uninit.h new file mode 100644 index 000000000..68fcb1bc8 --- /dev/null +++ b/bridge/src/builtin/rust_str_uninit.h @@ -0,0 +1,10 @@ +#pragma once +#include "../../../include/cxx.h" + +namespace rust { +inline namespace cxxbridge1 { +class Str::uninit {}; +// +inline Str::Str(uninit) noexcept {} +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/shared_ptr.h b/bridge/src/builtin/shared_ptr.h new file mode 100644 index 000000000..4132f5d71 --- /dev/null +++ b/bridge/src/builtin/shared_ptr.h @@ -0,0 +1,28 @@ +#pragma once +#include "../../../include/cxx.h" +#include + +namespace rust { +inline namespace cxxbridge1 { +namespace { +template ::value> +struct is_destructible : ::std::false_type {}; +// +template +struct is_destructible : ::std::is_destructible {}; +// +template +struct is_destructible : is_destructible {}; +// +template ::value> +struct shared_ptr_if_destructible { + explicit shared_ptr_if_destructible(typename ::std::shared_ptr::element_type *) {} +}; +// +template +struct shared_ptr_if_destructible : ::std::shared_ptr { + using ::std::shared_ptr::shared_ptr; +}; +} // namespace +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/trycatch.h b/bridge/src/builtin/trycatch.h new file mode 100644 index 000000000..825299023 --- /dev/null +++ b/bridge/src/builtin/trycatch.h @@ -0,0 +1,22 @@ +#pragma once +#include "./trycatch_detail.h" +#include +#include +#include + +namespace rust { +namespace behavior { +class missing {}; +missing trycatch(...); + +template +static typename ::std::enable_if<::std::is_same< + decltype(trycatch(::std::declval(), ::std::declval())), + missing>::value>::type +trycatch(Try &&func, Fail &&fail) noexcept try { + func(); +} catch (::std::exception const &e) { + fail(e.what()); +} +} // namespace behavior +} // namespace rust diff --git a/bridge/src/builtin/trycatch_detail.h b/bridge/src/builtin/trycatch_detail.h new file mode 100644 index 000000000..849538f8c --- /dev/null +++ b/bridge/src/builtin/trycatch_detail.h @@ -0,0 +1,21 @@ +#pragma once +#include "./ptr_len.h" +#include + +#pragma GCC diagnostic ignored "-Wshadow" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +namespace rust { +inline namespace cxxbridge1 { +namespace detail { +class Fail final { + ::rust::repr::PtrLen &throw$; + // +public: + Fail(::rust::repr::PtrLen &throw$) noexcept : throw$(throw$) {} + void operator()(char const *) noexcept; + void operator()(std::string const &) noexcept; +}; +} // namespace detail +} // namespace cxxbridge1 +} // namespace rust diff --git a/bridge/src/builtin/vector.h b/bridge/src/builtin/vector.h new file mode 100644 index 000000000..9a7967aeb --- /dev/null +++ b/bridge/src/builtin/vector.h @@ -0,0 +1,25 @@ +#pragma once +#include "../../../include/cxx.h" +#include +#include + +namespace rust { +inline namespace cxxbridge1 { +namespace { +template ::value> +struct if_move_constructible { + static bool reserve(::std::vector &, ::std::size_t) noexcept { + return false; + } +}; +// +template +struct if_move_constructible { + static bool reserve(::std::vector &vec, ::std::size_t new_cap) { + vec.reserve(new_cap); + return true; + } +}; +} // namespace +} // namespace cxxbridge1 +} // namespace rust diff --git a/gen/src/cfg.rs b/bridge/src/cfg.rs similarity index 76% rename from gen/src/cfg.rs rename to bridge/src/cfg.rs index da589085b..66b06d521 100644 --- a/gen/src/cfg.rs +++ b/bridge/src/cfg.rs @@ -1,10 +1,11 @@ -use crate::gen::{CfgEvaluator, CfgResult}; +use crate::bridge::{CfgEvaluator, CfgResult}; +use crate::syntax::Api; 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; +use std::mem; +use syn::{Error, LitStr}; pub(super) struct UnsupportedCfgEvaluator; @@ -23,15 +24,25 @@ pub(super) fn strip( cfg_evaluator: &dyn CfgEvaluator, apis: &mut Vec, ) { - apis.retain(|api| eval(cx, cfg_errors, cfg_evaluator, api.cfg())); + let mut eval = |cfg: &mut CfgExpr| { + let cfg = mem::replace(cfg, CfgExpr::Unconditional); + self::eval(cx, cfg_errors, cfg_evaluator, &cfg) + }; + apis.retain_mut(|api| { + eval(match api { + Api::Include(include) => &mut include.cfg, + Api::Struct(strct) => &mut strct.cfg, + Api::Enum(enm) => &mut enm.cfg, + Api::CxxType(ety) | Api::RustType(ety) => &mut ety.cfg, + Api::CxxFunction(efn) | Api::RustFunction(efn) => &mut efn.cfg, + Api::TypeAlias(alias) => &mut alias.cfg, + Api::Impl(imp) => &mut imp.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)), + Api::Struct(strct) => strct.fields.retain_mut(|field| eval(&mut field.cfg)), + Api::Enum(enm) => enm.variants.retain_mut(|variant| eval(&mut variant.cfg)), _ => {} } } @@ -61,7 +72,7 @@ fn try_eval(cfg_evaluator: &dyn CfgEvaluator, expr: &CfgExpr) -> Result Ok(true), CfgExpr::Eq(ident, string) => { let key = ident.to_string(); - let value = string.as_ref().map(|string| string.value()); + let value = string.as_ref().map(LitStr::value); match cfg_evaluator.eval(&key, value.as_deref()) { CfgResult::True => Ok(true), CfgResult::False => Ok(false), @@ -108,20 +119,6 @@ fn try_eval(cfg_evaluator: &dyn CfgEvaluator, expr: &CfgExpr) -> Result &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 for CfgResult { fn from(value: bool) -> Self { if value { diff --git a/gen/src/check.rs b/bridge/src/check.rs similarity index 77% rename from gen/src/check.rs rename to bridge/src/check.rs index 15add20aa..084e0bc16 100644 --- a/gen/src/check.rs +++ b/bridge/src/check.rs @@ -1,10 +1,10 @@ -use crate::gen::Opt; +use crate::bridge::Opt; use crate::syntax::report::Errors; -use crate::syntax::{error, Api}; +use crate::syntax::{Api, error}; use quote::{quote, quote_spanned}; use std::path::{Component, Path}; -pub(super) use crate::syntax::check::{typecheck, Generator}; +pub(super) use crate::syntax::check::{Generator, typecheck}; pub(super) fn precheck(cx: &mut Errors, apis: &[Api], opt: &Opt) { if !opt.allow_dot_includes { @@ -16,7 +16,7 @@ fn check_dot_includes(cx: &mut Errors, apis: &[Api]) { for api in apis { if let Api::Include(include) = api { let first_component = Path::new(&include.path).components().next(); - if let Some(Component::CurDir) | Some(Component::ParentDir) = first_component { + if let Some(Component::CurDir | Component::ParentDir) = first_component { let begin = quote_spanned!(include.begin_span=> .); let end = quote_spanned!(include.end_span=> .); let span = quote!(#begin #end); diff --git a/gen/src/error.rs b/bridge/src/error.rs similarity index 94% rename from gen/src/error.rs rename to bridge/src/error.rs index 3672e26ec..d6c2d901e 100644 --- a/gen/src/error.rs +++ b/bridge/src/error.rs @@ -1,9 +1,9 @@ -use crate::gen::fs; +use crate::bridge::fs; use crate::syntax; use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::files::SimpleFiles; -use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor}; -use codespan_reporting::term::{self, Config}; +use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; +use codespan_reporting::term::{self, Config, WriteStyle}; use std::borrow::Cow; use std::error::Error as StdError; use std::fmt::{self, Display}; @@ -40,7 +40,7 @@ impl StdError for Error { Error::Fs(err) => err.source(), Error::Utf8(_, err) => Some(err), Error::Syn(err) => err.source(), - _ => None, + Error::NoBridgeMod => None, } } } @@ -111,7 +111,7 @@ fn sort_syn_errors(error: syn::Error) -> Vec { errors } -fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, error: syn::Error) { +fn display_syn_error(stderr: &mut dyn WriteStyle, path: &Path, source: &str, error: syn::Error) { let span = error.span(); let start = span.start(); let end = span.end(); @@ -152,7 +152,7 @@ fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, err let diagnostic = diagnose(file, start_offset..end_offset, error); let config = Config::default(); - let _ = term::emit(stderr, &config, &files, &diagnostic); + let _ = term::emit_to_write_style(stderr, &config, &files, &diagnostic); } fn diagnose(file: usize, range: Range, error: syn::Error) -> Diagnostic { diff --git a/gen/src/file.rs b/bridge/src/file.rs similarity index 90% rename from gen/src/file.rs rename to bridge/src/file.rs index 46616fbda..b14c5eca0 100644 --- a/gen/src/file.rs +++ b/bridge/src/file.rs @@ -2,28 +2,29 @@ use crate::syntax::file::Module; use crate::syntax::namespace::Namespace; use syn::parse::discouraged::Speculative; use syn::parse::{Error, Parse, ParseStream, Result}; -use syn::{braced, Attribute, Ident, Item, Token, Visibility}; +use syn::{Attribute, Ident, Item, Meta, Token, Visibility, braced}; -pub struct File { +pub(crate) struct File { pub modules: Vec, } impl Parse for File { fn parse(input: ParseStream) -> Result { let mut modules = Vec::new(); - input.call(Attribute::parse_inner)?; parse(input, &mut modules)?; Ok(File { modules }) } } fn parse(input: ParseStream, modules: &mut Vec) -> Result<()> { + input.call(Attribute::parse_inner)?; + while !input.is_empty() { let mut cxx_bridge = false; let mut namespace = Namespace::ROOT; let mut attrs = input.call(Attribute::parse_outer)?; for attr in &attrs { - let path = &attr.path.segments; + let path = &attr.path().segments; if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" { cxx_bridge = true; namespace = parse_args(attr)?; @@ -60,11 +61,12 @@ fn parse(input: ParseStream, modules: &mut Vec) -> Result<()> { } } } + Ok(()) } fn parse_args(attr: &Attribute) -> Result { - if attr.tokens.is_empty() { + if let Meta::Path(_) = attr.meta { Ok(Namespace::ROOT) } else { attr.parse_args_with(Namespace::parse_bridge_attr_namespace) diff --git a/gen/src/fs.rs b/bridge/src/fs.rs similarity index 98% rename from gen/src/fs.rs rename to bridge/src/fs.rs index 7bc3bbcba..a96b551f7 100644 --- a/gen/src/fs.rs +++ b/bridge/src/fs.rs @@ -14,7 +14,7 @@ pub(crate) struct Error { } impl Error { - pub fn kind(&self) -> io::ErrorKind { + pub(crate) fn kind(&self) -> io::ErrorKind { match &self.source { Some(io_error) => io_error.kind(), None => io::ErrorKind::Other, diff --git a/bridge/src/guard.rs b/bridge/src/guard.rs new file mode 100644 index 000000000..f683434e8 --- /dev/null +++ b/bridge/src/guard.rs @@ -0,0 +1,23 @@ +use crate::bridge::out::OutFile; +use crate::syntax::Pair; +use crate::syntax::symbol::Symbol; +use std::fmt::{self, Display}; + +pub(crate) struct Guard { + kind: &'static str, + symbol: Symbol, +} + +impl Guard { + pub fn new(out: &mut OutFile, kind: &'static str, name: &Pair) -> Self { + let symbol = name.to_symbol(); + out.pragma.dollar_in_identifier |= symbol.contains('$'); + Guard { kind, symbol } + } +} + +impl Display for Guard { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "{}_{}", self.kind, self.symbol) + } +} diff --git a/gen/src/ifndef.rs b/bridge/src/ifndef.rs similarity index 95% rename from gen/src/ifndef.rs rename to bridge/src/ifndef.rs index b436266e1..e0ef4598b 100644 --- a/gen/src/ifndef.rs +++ b/bridge/src/ifndef.rs @@ -1,5 +1,5 @@ -use crate::gen::include::HEADER; -use crate::gen::out::Content; +use crate::bridge::include::HEADER; +use crate::bridge::out::Content; pub(super) fn write(out: &mut Content, needed: bool, guard: &str) { let ifndef = format!("#ifndef {}", guard); diff --git a/gen/src/include b/bridge/src/include similarity index 100% rename from gen/src/include rename to bridge/src/include diff --git a/gen/src/include.rs b/bridge/src/include.rs similarity index 85% rename from gen/src/include.rs rename to bridge/src/include.rs index 62c92320f..7940540d8 100644 --- a/gen/src/include.rs +++ b/bridge/src/include.rs @@ -1,4 +1,4 @@ -use crate::gen::out::{Content, OutFile}; +use crate::bridge::out::{Content, OutFile}; use crate::syntax::{self, IncludeKind}; use std::ops::{Deref, DerefMut}; @@ -19,7 +19,7 @@ pub struct Include { } #[derive(Default, PartialEq)] -pub struct Includes<'a> { +pub(crate) struct Includes<'a> { pub custom: Vec, pub algorithm: bool, pub array: bool, @@ -31,10 +31,13 @@ pub struct Includes<'a> { pub functional: bool, pub initializer_list: bool, pub iterator: bool, + pub limits: bool, pub memory: bool, pub new: bool, + pub ranges: bool, pub stdexcept: bool, pub string: bool, + pub string_view: bool, pub type_traits: bool, pub utility: bool, pub vector: bool, @@ -44,15 +47,15 @@ pub struct Includes<'a> { } impl<'a> Includes<'a> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Includes::default() } - pub fn insert(&mut self, include: impl Into) { + pub(crate) fn insert(&mut self, include: impl Into) { self.custom.push(include.into()); } - pub fn has_cxx_header(&self) -> bool { + pub(crate) fn has_cxx_header(&self) -> bool { self.custom .iter() .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h") @@ -92,10 +95,13 @@ pub(super) fn write(out: &mut OutFile) { functional, initializer_list, iterator, + limits, memory, new, + ranges, stdexcept, string, + string_view, type_traits, utility, vector, @@ -134,6 +140,9 @@ pub(super) fn write(out: &mut OutFile) { if iterator && !cxx_header { writeln!(out, "#include "); } + if limits { + writeln!(out, "#include "); + } if memory { writeln!(out, "#include "); } @@ -172,6 +181,16 @@ pub(super) fn write(out: &mut OutFile) { if (basetsd || sys_types) && !cxx_header { writeln!(out, "#endif"); } + if string_view && !cxx_header { + writeln!(out, "#if __cplusplus >= 201703L"); + writeln!(out, "#include "); + writeln!(out, "#endif"); + } + if ranges && !cxx_header { + writeln!(out, "#if __cplusplus >= 202002L"); + writeln!(out, "#include "); + writeln!(out, "#endif"); + } } impl<'i, 'a> Extend<&'i Include> for Includes<'a> { @@ -180,7 +199,7 @@ impl<'i, 'a> Extend<&'i Include> for Includes<'a> { } } -impl<'i> From<&'i syntax::Include> for Include { +impl From<&syntax::Include> for Include { fn from(include: &syntax::Include) -> Self { Include { path: include.path.clone(), diff --git a/gen/src/mod.rs b/bridge/src/mod.rs similarity index 84% rename from gen/src/mod.rs rename to bridge/src/mod.rs index f24846a7e..4741f41d1 100644 --- a/gen/src/mod.rs +++ b/bridge/src/mod.rs @@ -8,21 +8,23 @@ mod check; pub(super) mod error; mod file; pub(super) mod fs; +mod guard; mod ifndef; pub(super) mod include; mod names; mod namespace; mod nested; pub(super) mod out; +mod pragma; mod write; use self::cfg::UnsupportedCfgEvaluator; -use self::error::{format_err, Result}; +use self::error::{Result, format_err}; use self::file::File; use self::include::Include; use crate::syntax::cfg::CfgExpr; use crate::syntax::report::Errors; -use crate::syntax::{self, attrs, Types}; +use crate::syntax::{self, Types, attrs}; use std::collections::BTreeSet as Set; use std::path::Path; @@ -54,22 +56,34 @@ pub struct Opt { /// Rust code from one shared object or executable depends on these C++ /// functions in another. pub cxx_impl_annotations: Option, + /// Impl for handling conditional compilation attributes. + pub cfg_evaluator: Box, pub(super) gen_header: bool, pub(super) gen_implementation: bool, pub(super) allow_dot_includes: bool, - pub(super) cfg_evaluator: Box, pub(super) doxygen: bool, } -pub(super) trait CfgEvaluator { +/// Logic to decide whether a conditional compilation attribute is enabled or +/// disabled. +pub trait CfgEvaluator { + /// A name-only attribute such as `cfg(ident)` is passed with a `value` of + /// None, while `cfg(key = "value")` is passed with the "value" in `value`. fn eval(&self, name: &str, value: Option<&str>) -> CfgResult; } -pub(super) enum CfgResult { +/// Result of a [`CfgEvaluator`] evaluation. +pub enum CfgResult { + /// Cfg option is enabled. True, + /// Cfg option is disabled. False, - Undetermined { msg: String }, + /// Cfg option is neither enabled nor disabled. + Undetermined { + /// Message explaining why the cfg option is undetermined. + msg: String, + }, } /// Results of code generation. @@ -124,7 +138,6 @@ fn generate_from_string(source: &str, opt: &Opt) -> Result { let shebang_end = source.find('\n').unwrap_or(source.len()); source = &source[shebang_end..]; } - proc_macro2::fallback::force(); let syntax: File = syn::parse_str(source)?; generate(syntax, opt) } @@ -139,7 +152,7 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result { let ref mut cfg_errors = Set::new(); for bridge in syntax.modules { let mut cfg = CfgExpr::Unconditional; - attrs::parse( + let _ = attrs::parse( errors, bridge.attrs, attrs::Parser { @@ -176,10 +189,10 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result { // one or the other. let (mut header, mut implementation) = Default::default(); if opt.gen_header { - header = write::gen(apis, types, opt, true); + header = write::generate(apis, types, opt, true); } if opt.gen_implementation { - implementation = write::gen(apis, types, opt, false); + implementation = write::generate(apis, types, opt, false); } Ok(GeneratedCode { header, diff --git a/gen/src/names.rs b/bridge/src/names.rs similarity index 85% rename from gen/src/names.rs rename to bridge/src/names.rs index 834424bb6..620aaa85f 100644 --- a/gen/src/names.rs +++ b/bridge/src/names.rs @@ -1,7 +1,7 @@ use crate::syntax::Pair; impl Pair { - pub fn to_fully_qualified(&self) -> String { + pub(crate) fn to_fully_qualified(&self) -> String { let mut fully_qualified = String::new(); for segment in &self.namespace { fully_qualified += "::"; diff --git a/gen/src/namespace.rs b/bridge/src/namespace.rs similarity index 90% rename from gen/src/namespace.rs rename to bridge/src/namespace.rs index b79c38f90..f24bfeb8f 100644 --- a/gen/src/namespace.rs +++ b/bridge/src/namespace.rs @@ -1,8 +1,8 @@ -use crate::syntax::namespace::Namespace; use crate::syntax::Api; +use crate::syntax::namespace::Namespace; impl Api { - pub fn namespace(&self) -> &Namespace { + pub(crate) fn namespace(&self) -> &Namespace { match self { Api::CxxFunction(efn) | Api::RustFunction(efn) => &efn.name.namespace, Api::CxxType(ety) | Api::RustType(ety) => &ety.name.namespace, diff --git a/gen/src/nested.rs b/bridge/src/nested.rs similarity index 93% rename from gen/src/nested.rs rename to bridge/src/nested.rs index 32cc5f152..8476f519b 100644 --- a/gen/src/nested.rs +++ b/bridge/src/nested.rs @@ -1,22 +1,24 @@ -use crate::syntax::map::UnorderedMap as Map; use crate::syntax::Api; +use crate::syntax::map::UnorderedMap as Map; use proc_macro2::Ident; -pub struct NamespaceEntries<'a> { +pub(crate) struct NamespaceEntries<'a> { direct: Vec<&'a Api>, nested: Vec<(&'a Ident, NamespaceEntries<'a>)>, } impl<'a> NamespaceEntries<'a> { - pub fn new(apis: Vec<&'a Api>) -> Self { + pub(crate) fn new(apis: Vec<&'a Api>) -> Self { sort_by_inner_namespace(apis, 0) } - pub fn direct_content(&self) -> &[&'a Api] { + pub(crate) fn direct_content(&self) -> &[&'a Api] { &self.direct } - pub fn nested_content(&self) -> impl Iterator)> { + pub(crate) fn nested_content( + &self, + ) -> impl Iterator)> { self.nested.iter().map(|(k, entries)| (*k, entries)) } } @@ -56,9 +58,8 @@ mod tests { use crate::syntax::namespace::Namespace; use crate::syntax::{Api, Doc, ExternType, ForeignName, Lang, Lifetimes, Pair}; use proc_macro2::{Ident, Span}; - use std::iter::FromIterator; - use syn::punctuated::Punctuated; use syn::Token; + use syn::punctuated::Punctuated; #[test] fn test_ns_entries_sort() { @@ -133,7 +134,7 @@ mod tests { lang: Lang::Rust, doc: Doc::new(), derives: Vec::new(), - attrs: OtherAttrs::none(), + attrs: OtherAttrs::new(), visibility: Token![pub](Span::call_site()), type_token: Token![type](Span::call_site()), name: Pair { diff --git a/gen/src/out.rs b/bridge/src/out.rs similarity index 68% rename from gen/src/out.rs rename to bridge/src/out.rs index 3b4d7392f..b7c656d3b 100644 --- a/gen/src/out.rs +++ b/bridge/src/out.rs @@ -1,9 +1,10 @@ -use crate::gen::block::Block; -use crate::gen::builtin::Builtins; -use crate::gen::include::Includes; -use crate::gen::Opt; -use crate::syntax::namespace::Namespace; +use crate::bridge::Opt; +use crate::bridge::block::Block; +use crate::bridge::builtin::Builtins; +use crate::bridge::include::Includes; +use crate::bridge::pragma::Pragma; use crate::syntax::Types; +use crate::syntax::namespace::Namespace; use std::cell::RefCell; use std::fmt::{self, Arguments, Write}; @@ -12,15 +13,17 @@ pub(crate) struct OutFile<'a> { pub opt: &'a Opt, pub types: &'a Types<'a>, pub include: Includes<'a>, + pub pragma: Pragma<'a>, pub builtin: Builtins<'a>, content: RefCell>, } #[derive(Default)] -pub struct Content<'a> { +pub(crate) struct Content<'a> { bytes: String, namespace: &'a Namespace, blocks: Vec>, + suppress_next_section: bool, section_pending: bool, blocks_pending: usize, } @@ -32,47 +35,54 @@ enum BlockBoundary<'a> { } impl<'a> OutFile<'a> { - pub fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self { + pub(crate) fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self { OutFile { header, opt, types, include: Includes::new(), + pragma: Pragma::new(), builtin: Builtins::new(), content: RefCell::new(Content::new()), } } // Write a blank line if the preceding section had any contents. - pub fn next_section(&mut self) { + pub(crate) fn next_section(&mut self) { self.content.get_mut().next_section(); } - pub fn begin_block(&mut self, block: Block<'a>) { + pub(crate) fn suppress_next_section(&mut self) { + self.content.get_mut().suppress_next_section(); + } + + pub(crate) fn begin_block(&mut self, block: Block<'a>) { self.content.get_mut().begin_block(block); } - pub fn end_block(&mut self, block: Block<'a>) { + pub(crate) fn end_block(&mut self, block: Block<'a>) { self.content.get_mut().end_block(block); } - pub fn set_namespace(&mut self, namespace: &'a Namespace) { + pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) { self.content.get_mut().set_namespace(namespace); } - pub fn write_fmt(&self, args: Arguments) { - let content = &mut *self.content.borrow_mut(); - Write::write_fmt(content, args).unwrap(); - } - - pub fn content(&mut self) -> Vec { + pub(crate) fn content(&mut self) -> Vec { self.flush(); + let include = &self.include.content.bytes; + let pragma_begin = &self.pragma.begin.bytes; let builtin = &self.builtin.content.bytes; let content = &self.content.get_mut().bytes; - let len = include.len() + builtin.len() + content.len() + 2; - let mut out = String::with_capacity(len); + let pragma_end = &self.pragma.end.bytes; + + let mut out = String::new(); out.push_str(include); + if !out.is_empty() && !pragma_begin.is_empty() { + out.push('\n'); + } + out.push_str(pragma_begin); if !out.is_empty() && !builtin.is_empty() { out.push('\n'); } @@ -81,6 +91,10 @@ impl<'a> OutFile<'a> { out.push('\n'); } out.push_str(content); + if !out.is_empty() && !pragma_end.is_empty() { + out.push('\n'); + } + out.push_str(pragma_end); if out.is_empty() { out.push_str("// empty\n"); } @@ -89,8 +103,10 @@ impl<'a> OutFile<'a> { fn flush(&mut self) { self.include.content.flush(); + self.pragma.begin.flush(); self.builtin.content.flush(); self.content.get_mut().flush(); + self.pragma.end.flush(); } } @@ -108,23 +124,27 @@ impl<'a> PartialEq for Content<'a> { } impl<'a> Content<'a> { - fn new() -> Self { + pub(crate) fn new() -> Self { Content::default() } - pub fn next_section(&mut self) { - self.section_pending = true; + pub(crate) fn next_section(&mut self) { + self.section_pending = !self.suppress_next_section; + } + + pub(crate) fn suppress_next_section(&mut self) { + self.suppress_next_section = true; } - pub fn begin_block(&mut self, block: Block<'a>) { + pub(crate) fn begin_block(&mut self, block: Block<'a>) { self.push_block_boundary(BlockBoundary::Begin(block)); } - pub fn end_block(&mut self, block: Block<'a>) { + pub(crate) fn end_block(&mut self, block: Block<'a>) { self.push_block_boundary(BlockBoundary::End(block)); } - pub fn set_namespace(&mut self, namespace: &'a Namespace) { + pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) { for name in self.namespace.iter().rev() { self.end_block(Block::UserDefinedNamespace(name)); } @@ -134,7 +154,7 @@ impl<'a> Content<'a> { self.namespace = namespace; } - pub fn write_fmt(&mut self, args: Arguments) { + pub(crate) fn write_fmt(&mut self, args: Arguments) { Write::write_fmt(self, args).unwrap(); } @@ -147,6 +167,7 @@ impl<'a> Content<'a> { self.bytes.push('\n'); } self.bytes.push_str(b); + self.suppress_next_section = false; self.section_pending = false; self.blocks_pending = 0; } @@ -208,3 +229,25 @@ impl<'a> BlockBoundary<'a> { } } } + +pub(crate) trait InfallibleWrite { + fn write_fmt(&mut self, args: Arguments); +} + +impl InfallibleWrite for String { + fn write_fmt(&mut self, args: Arguments) { + Write::write_fmt(self, args).unwrap(); + } +} + +impl<'a> InfallibleWrite for Content<'a> { + fn write_fmt(&mut self, args: Arguments) { + Write::write_fmt(self, args).unwrap(); + } +} + +impl<'a> InfallibleWrite for OutFile<'a> { + fn write_fmt(&mut self, args: Arguments) { + InfallibleWrite::write_fmt(self.content.get_mut(), args); + } +} diff --git a/bridge/src/pragma.rs b/bridge/src/pragma.rs new file mode 100644 index 000000000..d468f2060 --- /dev/null +++ b/bridge/src/pragma.rs @@ -0,0 +1,83 @@ +use crate::bridge::out::{Content, OutFile}; +use std::collections::BTreeSet; + +#[derive(Default)] +pub(crate) struct Pragma<'a> { + pub gnu_diagnostic_ignore: BTreeSet<&'a str>, + pub clang_diagnostic_ignore: BTreeSet<&'a str>, + pub dollar_in_identifier: bool, + pub mismatched_new_delete: bool, + pub missing_declarations: bool, + pub return_type_c_linkage: bool, + pub begin: Content<'a>, + pub end: Content<'a>, +} + +impl<'a> Pragma<'a> { + pub fn new() -> Self { + Pragma::default() + } +} + +pub(super) fn write(out: &mut OutFile) { + let Pragma { + ref mut gnu_diagnostic_ignore, + ref mut clang_diagnostic_ignore, + dollar_in_identifier, + mismatched_new_delete, + missing_declarations, + return_type_c_linkage, + ref mut begin, + ref mut end, + } = out.pragma; + + if dollar_in_identifier { + clang_diagnostic_ignore.insert("-Wdollar-in-identifier-extension"); + } + if mismatched_new_delete { + gnu_diagnostic_ignore.insert("-Wmismatched-new-delete"); + } + if missing_declarations { + gnu_diagnostic_ignore.insert("-Wmissing-declarations"); + } + if return_type_c_linkage { + clang_diagnostic_ignore.insert("-Wreturn-type-c-linkage"); + } + let gnu_diagnostic_ignore = &*gnu_diagnostic_ignore; + let clang_diagnostic_ignore = &*clang_diagnostic_ignore; + + if !gnu_diagnostic_ignore.is_empty() { + writeln!(begin, "#ifdef __GNUC__"); + if out.header { + writeln!(begin, "#pragma GCC diagnostic push"); + } + for diag in gnu_diagnostic_ignore { + writeln!(begin, "#pragma GCC diagnostic ignored \"{diag}\""); + } + } + if !clang_diagnostic_ignore.is_empty() { + writeln!(begin, "#ifdef __clang__"); + if out.header && gnu_diagnostic_ignore.is_empty() { + writeln!(begin, "#pragma clang diagnostic push"); + } + for diag in clang_diagnostic_ignore { + writeln!(begin, "#pragma clang diagnostic ignored \"{diag}\""); + } + writeln!(begin, "#endif // __clang__"); + } + if !gnu_diagnostic_ignore.is_empty() { + writeln!(begin, "#endif // __GNUC__"); + } + + if out.header { + if !gnu_diagnostic_ignore.is_empty() { + writeln!(end, "#ifdef __GNUC__"); + writeln!(end, "#pragma GCC diagnostic pop"); + writeln!(end, "#endif // __GNUC__"); + } else if !clang_diagnostic_ignore.is_empty() { + writeln!(end, "#ifdef __clang__"); + writeln!(end, "#pragma clang diagnostic pop"); + writeln!(end, "#endif // __clang__"); + } + } +} diff --git a/gen/src/write.rs b/bridge/src/write.rs similarity index 73% rename from gen/src/write.rs rename to bridge/src/write.rs index 6f535ccb9..22b036f67 100644 --- a/gen/src/write.rs +++ b/bridge/src/write.rs @@ -1,37 +1,64 @@ -use crate::gen::block::Block; -use crate::gen::nested::NamespaceEntries; -use crate::gen::out::OutFile; -use crate::gen::{builtin, include, Opt}; +use crate::bridge::block::Block; +use crate::bridge::guard::Guard; +use crate::bridge::nested::NamespaceEntries; +use crate::bridge::out::{InfallibleWrite, OutFile}; +use crate::bridge::{Opt, builtin, include, pragma}; use crate::syntax::atom::Atom::{self, *}; +use crate::syntax::discriminant::{Discriminant, Limits}; use crate::syntax::instantiate::{ImplKey, NamedImplKey}; use crate::syntax::map::UnorderedMap as Map; +use crate::syntax::namespace::Namespace; +use crate::syntax::primitive::{self, PrimitiveKind}; use crate::syntax::set::UnorderedSet; -use crate::syntax::symbol::{self, Symbol}; +use crate::syntax::symbol::Symbol; use crate::syntax::trivial::{self, TrivialReason}; use crate::syntax::{ - derive, mangle, Api, Doc, Enum, EnumRepr, ExternFn, ExternType, Pair, Signature, Struct, Trait, - Type, TypeAlias, Types, Var, + Api, Doc, Enum, ExternFn, ExternType, FnKind, Lang, Pair, Signature, Struct, Trait, Type, + TypeAlias, Types, Var, derive, mangle, }; -use proc_macro2::Ident; -pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec { +pub(super) fn generate(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec { let mut out_file = OutFile::new(header, opt, types); let out = &mut out_file; pick_includes_and_builtins(out, apis); out.include.extend(&opt.include); + write_macros(out, apis); write_forward_declarations(out, apis); write_data_structures(out, apis); write_functions(out, apis); write_generic_instantiations(out); builtin::write(out); + pragma::write(out); include::write(out); out_file.content() } +fn write_macros(out: &mut OutFile, apis: &[Api]) { + let mut needs_default_value = false; + for api in apis { + if let Api::Struct(strct) = api + && !out.types.cxx.contains(&strct.name.rust) + { + for field in &strct.fields { + needs_default_value |= primitive::kind(&field.ty).is_some(); + } + } + } + + if needs_default_value { + out.next_section(); + writeln!(out, "#if __cplusplus >= 201402L"); + writeln!(out, "#define CXX_DEFAULT_VALUE(value) = value"); + writeln!(out, "#else"); + writeln!(out, "#define CXX_DEFAULT_VALUE(value)"); + writeln!(out, "#endif"); + } +} + fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) { let needs_forward_declaration = |api: &&Api| match api { Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true, @@ -42,6 +69,7 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) { let apis_by_namespace = NamespaceEntries::new(apis.iter().filter(needs_forward_declaration).collect()); + out.next_section(); write(out, &apis_by_namespace, 0); fn write(out: &mut OutFile, ns_entries: &NamespaceEntries, indent: usize) { @@ -69,13 +97,13 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) { fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) { let mut methods_for_type = Map::new(); for api in apis { - if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api { - if let Some(receiver) = &efn.sig.receiver { - methods_for_type - .entry(&receiver.ty.rust) - .or_insert_with(Vec::new) - .push(efn); - } + if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api + && let Some(self_type) = efn.self_type() + { + methods_for_type + .entry(self_type) + .or_insert_with(Vec::new) + .push(efn); } } @@ -85,10 +113,10 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) { match api { Api::Struct(strct) if !structs_written.contains(&strct.name.rust) => { for next in &mut toposorted_structs { - if !out.types.cxx.contains(&strct.name.rust) { + if !out.types.cxx.contains(&next.name.rust) { out.next_section(); let methods = methods_for_type - .get(&strct.name.rust) + .get(&next.name.rust) .map(Vec::as_slice) .unwrap_or_default(); write_struct(out, next, methods); @@ -101,10 +129,10 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) { } Api::Enum(enm) => { out.next_section(); - if !out.types.cxx.contains(&enm.name.rust) { - write_enum(out, enm); - } else if !enm.variants_from_header { + if out.types.cxx.contains(&enm.name.rust) { check_enum(out, enm); + } else { + write_enum(out, enm); } } Api::RustType(ety) => { @@ -127,10 +155,10 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) { out.next_section(); for api in apis { - if let Api::TypeAlias(ety) = api { - if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) { - check_trivial_extern_type(out, ety, reasons) - } + if let Api::TypeAlias(ety) = api + && let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) + { + check_trivial_extern_type(out, ety, reasons); } } } @@ -168,27 +196,28 @@ fn write_std_specializations(out: &mut OutFile, apis: &[Api]) { out.begin_block(Block::Namespace("std")); for api in apis { - if let Api::Struct(strct) = api { - if derive::contains(&strct.derives, Trait::Hash) { - out.next_section(); - out.include.cstddef = true; - out.include.functional = true; - let qualified = strct.name.to_fully_qualified(); - writeln!(out, "template <> struct hash<{}> {{", qualified); - writeln!( - out, - " ::std::size_t operator()({} const &self) const noexcept {{", - qualified, - ); - let link_name = mangle::operator(&strct.name, "hash"); - write!(out, " return ::"); - for name in &strct.name.namespace { - write!(out, "{}::", name); - } - writeln!(out, "{}(self);", link_name); - writeln!(out, " }}"); - writeln!(out, "}};"); + if let Api::Struct(strct) = api + && derive::contains(&strct.derives, Trait::Hash) + { + out.next_section(); + out.include.cstddef = true; + out.include.functional = true; + out.pragma.dollar_in_identifier = true; + let qualified = strct.name.to_fully_qualified(); + writeln!(out, "template <> struct hash<{}> {{", qualified); + writeln!( + out, + " ::std::size_t operator()({} const &self) const noexcept {{", + qualified, + ); + let link_name = mangle::operator(&strct.name, "hash"); + write!(out, " return ::"); + for name in &strct.name.namespace { + write!(out, "{}::", name); } + writeln!(out, "{}(self);", link_name); + writeln!(out, " }}"); + writeln!(out, "}};"); } } @@ -205,13 +234,12 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) { for ty in out.types { match ty { Type::Ident(ident) => match Atom::from(&ident.rust) { - Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32) - | Some(I64) => out.include.cstdint = true, + Some(U8 | U16 | U32 | U64 | I8 | I16 | I32 | I64) => out.include.cstdint = true, Some(Usize) => out.include.cstddef = true, Some(Isize) => out.builtin.rust_isize = true, Some(CxxString) => out.include.string = true, Some(RustString) => out.builtin.rust_string = true, - Some(Bool) | Some(Char) | Some(F32) | Some(F64) | None => {} + Some(Bool | Char | F32 | F64) | None => {} }, Type::RustBox(_) => out.builtin.rust_box = true, Type::RustVec(_) => out.builtin.rust_vec = true, @@ -251,17 +279,42 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern let operator_ord = derive::contains(&strct.derives, Trait::PartialOrd); out.set_namespace(&strct.name.namespace); - let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol()); + let guard = Guard::new(out, "CXXBRIDGE1_STRUCT", &strct.name); writeln!(out, "#ifndef {}", guard); writeln!(out, "#define {}", guard); write_doc(out, "", &strct.doc); - writeln!(out, "struct {} final {{", strct.name.cxx); + write!(out, "struct"); + if let Some(align) = &strct.align { + out.builtin.alignmax = true; + writeln!(out, " alignas(::rust::repr::alignmax<"); + writeln!(out, " {},", align.base10_parse::().unwrap()); + for (i, field) in strct.fields.iter().enumerate() { + write!(out, " alignof("); + write_type(out, &field.ty); + write!(out, ")"); + if i + 1 != strct.fields.len() { + write!(out, ","); + } + writeln!(out); + } + write!(out, ">)"); + } + writeln!(out, " {} final {{", strct.name.cxx); for field in &strct.fields { write_doc(out, " ", &field.doc); write!(out, " "); write_type_space(out, &field.ty); - writeln!(out, "{};", field.name.cxx); + write!(out, "{}", field.name.cxx); + if let Some(primitive) = primitive::kind(&field.ty) { + let default_value = match primitive { + PrimitiveKind::Boolean => "false", + PrimitiveKind::Number => "0", + PrimitiveKind::Pointer => "nullptr", + }; + write!(out, " CXX_DEFAULT_VALUE({})", default_value); + } + writeln!(out, ";"); } out.next_section(); @@ -272,10 +325,12 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern } write_doc(out, " ", &method.doc); write!(out, " "); - let sig = &method.sig; let local_name = method.name.cxx.to_string(); + let sig = &method.sig; + let in_class = true; let indirect_call = false; - write_rust_function_shim_decl(out, &local_name, sig, indirect_call); + let main = false; + write_rust_function_shim_decl(out, &local_name, sig, in_class, indirect_call, main); writeln!(out, ";"); if !method.doc.is_empty() { out.next_section(); @@ -330,13 +385,8 @@ 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, - }; write!(out, "enum class {} : ", enm.name.cxx); - write_atom(out, repr); + write_atom(out, enm.repr.atom); writeln!(out, ";"); } @@ -346,7 +396,7 @@ fn write_struct_using(out: &mut OutFile, ident: &Pair) { fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[&ExternFn]) { out.set_namespace(&ety.name.namespace); - let guard = format!("CXXBRIDGE1_STRUCT_{}", ety.name.to_symbol()); + let guard = Guard::new(out, "CXXBRIDGE1_STRUCT", &ety.name); writeln!(out, "#ifndef {}", guard); writeln!(out, "#define {}", guard); write_doc(out, "", &ety.doc); @@ -364,10 +414,12 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[ } write_doc(out, " ", &method.doc); write!(out, " "); - let sig = &method.sig; let local_name = method.name.cxx.to_string(); + let sig = &method.sig; + let in_class = true; let indirect_call = false; - write_rust_function_shim_decl(out, &local_name, sig, indirect_call); + let main = false; + write_rust_function_shim_decl(out, &local_name, sig, in_class, indirect_call, main); writeln!(out, ";"); if !method.doc.is_empty() { out.next_section(); @@ -390,33 +442,31 @@ 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, - }; out.set_namespace(&enm.name.namespace); - let guard = format!("CXXBRIDGE1_ENUM_{}", enm.name.to_symbol()); + let guard = Guard::new(out, "CXXBRIDGE1_ENUM", &enm.name); writeln!(out, "#ifndef {}", guard); writeln!(out, "#define {}", guard); + write_doc(out, "", &enm.doc); write!(out, "enum class {} : ", enm.name.cxx); - write_atom(out, repr); + write_atom(out, enm.repr.atom); writeln!(out, " {{"); for variant in &enm.variants { write_doc(out, " ", &variant.doc); - writeln!(out, " {} = {},", variant.name.cxx, variant.discriminant); + write!(out, " {} = ", variant.name.cxx); + write_discriminant(out, enm.repr.atom, variant.discriminant); + writeln!(out, ","); } writeln!(out, "}};"); + + if out.header { + write_enum_operators(out, enm); + } + writeln!(out, "#endif // {}", guard); } 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, - }; out.set_namespace(&enm.name.namespace); out.include.type_traits = true; writeln!( @@ -425,16 +475,71 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) { enm.name.cxx, ); write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx); - write_atom(out, repr); + write_atom(out, enm.repr.atom); writeln!(out, "), \"incorrect size\");"); for variant in &enm.variants { write!(out, "static_assert(static_cast<"); + write_atom(out, enm.repr.atom); + write!(out, ">({}::{}) == ", enm.name.cxx, variant.name.cxx); + write_discriminant(out, enm.repr.atom, variant.discriminant); + writeln!(out, ", \"disagrees with the value in #[cxx::bridge]\");"); + } + + if out.header + && (derive::contains(&enm.derives, Trait::BitAnd) + || derive::contains(&enm.derives, Trait::BitOr) + || derive::contains(&enm.derives, Trait::BitXor)) + { + out.next_section(); + let guard = Guard::new(out, "CXXBRIDGE1_ENUM", &enm.name); + writeln!(out, "#ifndef {}", guard); + writeln!(out, "#define {}", guard); + out.suppress_next_section(); + write_enum_operators(out, enm); + writeln!(out, "#endif // {}", guard); + } +} + +fn write_discriminant(out: &mut OutFile, repr: Atom, discriminant: Discriminant) { + let limits = Limits::of(repr).unwrap(); + if discriminant == limits.min && limits.min < Discriminant::zero() { + out.include.limits = true; + write!(out, "::std::numeric_limits<"); write_atom(out, repr); - writeln!( - out, - ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");", - enm.name.cxx, variant.name.cxx, variant.discriminant, - ); + write!(out, ">::min()"); + } else { + write!(out, "{}", discriminant); + } +} + +fn write_binary_bitwise_op(out: &mut OutFile, op: &str, enm: &Enum) { + let enum_name = &enm.name.cxx; + writeln!( + out, + "inline {enum_name} operator{op}({enum_name} lhs, {enum_name} rhs) {{", + ); + write!(out, " return static_cast<{enum_name}>(static_cast<"); + write_atom(out, enm.repr.atom); + write!(out, ">(lhs) {op} static_cast<"); + write_atom(out, enm.repr.atom); + writeln!(out, ">(rhs));"); + writeln!(out, "}}"); +} + +fn write_enum_operators(out: &mut OutFile, enm: &Enum) { + if derive::contains(&enm.derives, Trait::BitAnd) { + out.next_section(); + write_binary_bitwise_op(out, "&", enm); + } + + if derive::contains(&enm.derives, Trait::BitOr) { + out.next_section(); + write_binary_bitwise_op(out, "|", enm); + } + + if derive::contains(&enm.derives, Trait::BitXor) { + out.next_section(); + write_binary_bitwise_op(out, "^", enm); } } @@ -474,11 +579,20 @@ 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("); - if reasons - .iter() - .all(|r| matches!(r, TrivialReason::StructField(_) | TrivialReason::VecElement)) - { + + let mut rust_type_ok = true; + let mut array_ok = true; + for reason in reasons { + // Allow extern type that inherits from ::rust::Opaque in positions + // where an opaque Rust type would be allowed. + rust_type_ok &= match reason { + TrivialReason::BoxTarget { .. } + | TrivialReason::VecElement { .. } + | TrivialReason::SliceElement { .. } => true, + TrivialReason::StructField(_) + | TrivialReason::FunctionArgument(_) + | TrivialReason::FunctionReturn(_) => false, + }; // 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. @@ -489,10 +603,27 @@ fn check_trivial_extern_type(out: &mut OutFile, alias: &TypeAlias, reasons: &[Tr // --- means something totally different: // void f(char buf[N]); // + array_ok &= match reason { + TrivialReason::StructField(_) | TrivialReason::VecElement { .. } => true, + TrivialReason::FunctionArgument(_) + | TrivialReason::FunctionReturn(_) + | TrivialReason::BoxTarget { .. } + | TrivialReason::SliceElement { .. } => false, + }; + } + + writeln!(out, "static_assert("); + write!(out, " "); + if rust_type_ok { + out.include.type_traits = true; + out.builtin.opaque = true; + write!(out, "::std::is_base_of<::rust::Opaque, {}>::value || ", id); + } + if array_ok { out.builtin.relocatable_or_array = true; - writeln!(out, " ::rust::IsRelocatableOrArray<{}>::value,", id); + writeln!(out, "::rust::IsRelocatableOrArray<{}>::value,", id); } else { - writeln!(out, " ::rust::IsRelocatable<{}>::value,", id); + writeln!(out, "::rust::IsRelocatable<{}>::value,", id); } writeln!( out, @@ -507,6 +638,8 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { out.begin_block(Block::ExternC); if derive::contains(&strct.derives, Trait::PartialEq) { + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; let link_name = mangle::operator(&strct.name, "eq"); writeln!( out, @@ -525,6 +658,8 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { } if derive::contains(&strct.derives, Trait::PartialOrd) { + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; let link_name = mangle::operator(&strct.name, "lt"); writeln!( out, @@ -558,6 +693,8 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { if derive::contains(&strct.derives, Trait::Hash) { out.include.cstddef = true; + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; let link_name = mangle::operator(&strct.name, "hash"); writeln!( out, @@ -577,6 +714,8 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { out.set_namespace(&strct.name.namespace); if derive::contains(&strct.derives, Trait::PartialEq) { + out.pragma.dollar_in_identifier = true; + out.next_section(); writeln!( out, @@ -603,6 +742,8 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { } if derive::contains(&strct.derives, Trait::PartialOrd) { + out.pragma.dollar_in_identifier = true; + out.next_section(); writeln!( out, @@ -656,6 +797,8 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) { fn write_opaque_type_layout_decls<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) { out.set_namespace(&ety.name.namespace); out.begin_block(Block::ExternC); + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; let link_name = mangle::operator(&ety.name, "sizeof"); writeln!(out, "::std::size_t {}() noexcept;", link_name); @@ -672,6 +815,7 @@ fn write_opaque_type_layout<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) { } out.set_namespace(&ety.name.namespace); + out.pragma.dollar_in_identifier = true; out.next_section(); let link_name = mangle::operator(&ety.name, "sizeof"); @@ -701,6 +845,8 @@ fn begin_function_definition(out: &mut OutFile) { } fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; out.next_section(); out.set_namespace(&efn.name.namespace); out.begin_block(Block::ExternC); @@ -709,11 +855,11 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { out.builtin.ptr_len = true; write!(out, "::rust::repr::PtrLen "); } else { - write_extern_return_type_space(out, &efn.ret); + write_extern_return_type_space(out, efn, efn.lang); } let mangled = mangle::extern_fn(efn, out.types); write!(out, "{}(", mangled); - if let Some(receiver) = &efn.receiver { + if let FnKind::Method(receiver) = &efn.kind { write!( out, "{}", @@ -725,7 +871,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { write!(out, " &self"); } for (i, arg) in efn.args.iter().enumerate() { - if i > 0 || efn.receiver.is_some() { + if i > 0 || matches!(efn.kind, FnKind::Method(_)) { write!(out, ", "); } if arg.ty == RustString { @@ -738,18 +884,24 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { write_extern_arg(out, arg); } } - let indirect_return = indirect_return(efn, out.types); + let indirect_return = indirect_return(efn, out.types, efn.lang); if indirect_return { - if !efn.args.is_empty() || efn.receiver.is_some() { + if !efn.args.is_empty() || matches!(efn.kind, FnKind::Method(_)) { write!(out, ", "); } write_indirect_return_type_space(out, efn.ret.as_ref().unwrap()); write!(out, "*return$"); } - writeln!(out, ") noexcept {{"); + write!(out, ")"); + match efn.lang { + Lang::Cxx => write!(out, " noexcept"), + Lang::CxxUnwind => {} + Lang::Rust => unreachable!(), + } + writeln!(out, " {{"); write!(out, " "); write_return_type(out, &efn.ret); - match &efn.receiver { + match efn.receiver() { None => write!(out, "(*{}$)(", efn.name.rust), Some(receiver) => write!( out, @@ -765,18 +917,18 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { write_type(out, &arg.ty); } write!(out, ")"); - if let Some(receiver) = &efn.receiver { - if !receiver.mutable { - write!(out, " const"); - } + if let Some(receiver) = efn.receiver() + && !receiver.mutable + { + write!(out, " const"); } write!(out, " = "); - match &efn.receiver { + match efn.self_type() { None => write!(out, "{}", efn.name.to_fully_qualified()), - Some(receiver) => write!( + Some(self_type) => write!( out, "&{}::{}", - out.types.resolve(&receiver.ty).name.to_fully_qualified(), + out.types.resolve(self_type).name.to_fully_qualified(), efn.name.cxx, ), } @@ -812,7 +964,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { } _ => {} } - match &efn.receiver { + match efn.receiver() { None => write!(out, "{}$(", efn.name.rust), Some(_) => write!(out, "(self.*{}$)(", efn.name.rust), } @@ -848,7 +1000,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { match &efn.ret { Some(Type::RustBox(_)) => write!(out, ".into_raw()"), Some(Type::UniquePtr(_)) => write!(out, ".release()"), - Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"), + Some(Type::Str(_) | Type::SliceRef(_)) if !indirect_return => write!(out, ")"), _ => {} } if indirect_return { @@ -872,6 +1024,8 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { } fn write_function_pointer_trampoline(out: &mut OutFile, efn: &ExternFn, var: &Pair, f: &Signature) { + out.pragma.return_type_c_linkage = true; + let r_trampoline = mangle::r_trampoline(efn, var, out.types); let indirect_call = true; write_rust_function_decl_impl(out, &r_trampoline, f, indirect_call); @@ -879,7 +1033,16 @@ fn write_function_pointer_trampoline(out: &mut OutFile, efn: &ExternFn, var: &Pa out.next_section(); let c_trampoline = mangle::c_trampoline(efn, var, out.types).to_string(); let doc = Doc::new(); - write_rust_function_shim_impl(out, &c_trampoline, f, &doc, &r_trampoline, indirect_call); + let main = false; + write_rust_function_shim_impl( + out, + &c_trampoline, + f, + &doc, + &r_trampoline, + indirect_call, + main, + ); } fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { @@ -898,15 +1061,16 @@ fn write_rust_function_decl_impl( indirect_call: bool, ) { out.next_section(); + out.pragma.dollar_in_identifier = true; if sig.throws { out.builtin.ptr_len = true; write!(out, "::rust::repr::PtrLen "); } else { - write_extern_return_type_space(out, &sig.ret); + write_extern_return_type_space(out, sig, Lang::Rust); } write!(out, "{}(", link_name); let mut needs_comma = false; - if let Some(receiver) = &sig.receiver { + if let FnKind::Method(receiver) = &sig.kind { write!( out, "{}", @@ -925,7 +1089,7 @@ fn write_rust_function_decl_impl( write_extern_arg(out, arg); needs_comma = true; } - if indirect_return(sig, out.types) { + if indirect_return(sig, out.types, Lang::Rust) { if needs_comma { write!(out, ", "); } @@ -953,28 +1117,44 @@ fn write_rust_function_decl_impl( fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { out.set_namespace(&efn.name.namespace); - let local_name = match &efn.sig.receiver { + let local_name = match efn.self_type() { None => efn.name.cxx.to_string(), - Some(receiver) => format!( + Some(self_type) => format!( "{}::{}", - out.types.resolve(&receiver.ty).name.cxx, + out.types.resolve(self_type).name.cxx, efn.name.cxx, ), }; let doc = &efn.doc; let invoke = mangle::extern_fn(efn, out.types); let indirect_call = false; - write_rust_function_shim_impl(out, &local_name, efn, doc, &invoke, indirect_call); + let main = efn.name.cxx == *"main" + && efn.name.namespace == Namespace::ROOT + && efn.sig.asyncness.is_none() + && matches!(efn.kind, FnKind::Free) + && efn.sig.args.is_empty() + && efn.sig.ret.is_none() + && !efn.sig.throws; + write_rust_function_shim_impl(out, &local_name, efn, doc, &invoke, indirect_call, main); } fn write_rust_function_shim_decl( out: &mut OutFile, local_name: &str, sig: &Signature, + in_class: bool, indirect_call: bool, + main: bool, ) { begin_function_definition(out); - write_return_type(out, &sig.ret); + if matches!(sig.kind, FnKind::Assoc(_)) && in_class { + write!(out, "static "); + } + if main { + write!(out, "int "); + } else { + write_return_type(out, &sig.ret); + } write!(out, "{}(", local_name); for (i, arg) in sig.args.iter().enumerate() { if i > 0 { @@ -990,10 +1170,10 @@ fn write_rust_function_shim_decl( write!(out, "void *extern$"); } write!(out, ")"); - if let Some(receiver) = &sig.receiver { - if !receiver.mutable { - write!(out, " const"); - } + if let FnKind::Method(receiver) = &sig.kind + && !receiver.mutable + { + write!(out, " const"); } if !sig.throws { write!(out, " noexcept"); @@ -1007,16 +1187,22 @@ fn write_rust_function_shim_impl( doc: &Doc, invoke: &Symbol, indirect_call: bool, + main: bool, ) { - if out.header && sig.receiver.is_some() { + if match sig.kind { + FnKind::Free => false, + FnKind::Method(_) | FnKind::Assoc(_) => out.header, + } { // We've already defined this inside the struct. return; } - if sig.receiver.is_none() { + out.pragma.dollar_in_identifier = true; + if matches!(sig.kind, FnKind::Free) { // Member functions already documented at their declaration. write_doc(out, "", doc); } - write_rust_function_shim_decl(out, local_name, sig, indirect_call); + let in_class = false; + write_rust_function_shim_decl(out, local_name, sig, in_class, indirect_call, main); if out.header { writeln!(out, ";"); return; @@ -1032,7 +1218,7 @@ fn write_rust_function_shim_impl( } } write!(out, " "); - let indirect_return = indirect_return(sig, out.types); + let indirect_return = indirect_return(sig, out.types, Lang::Rust); if indirect_return { out.builtin.maybe_uninit = true; write!(out, "::rust::MaybeUninit<"); @@ -1079,7 +1265,7 @@ fn write_rust_function_shim_impl( } write!(out, "{}(", invoke); let mut needs_comma = false; - if sig.receiver.is_some() { + if matches!(sig.kind, FnKind::Method(_)) { write!(out, "*this"); needs_comma = true; } @@ -1113,12 +1299,11 @@ fn write_rust_function_shim_impl( write!(out, "extern$"); } write!(out, ")"); - if !indirect_return { - if let Some(ret) = &sig.ret { - if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_) = ret { - write!(out, ")"); - } - } + if !indirect_return + && let Some(Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_)) = + &sig.ret + { + write!(out, ")"); } writeln!(out, ";"); if sig.throws { @@ -1148,10 +1333,15 @@ fn write_return_type(out: &mut OutFile, ty: &Option) { } } -fn indirect_return(sig: &Signature, types: &Types) -> bool { - sig.ret - .as_ref() - .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret)) +fn indirect_return(sig: &Signature, types: &Types, lang: Lang) -> bool { + sig.ret.as_ref().is_some_and(|ret| { + sig.throws + || types.needs_indirect_abi(ret) + || match lang { + Lang::Cxx | Lang::CxxUnwind => types.contains_elided_lifetime(ret), + Lang::Rust => false, + } + }) } fn write_indirect_return_type(out: &mut OutFile, ty: &Type) { @@ -1180,9 +1370,10 @@ fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) { } } -fn write_extern_return_type_space(out: &mut OutFile, ty: &Option) { - match ty { - Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => { +fn write_extern_return_type_space(out: &mut OutFile, sig: &Signature, lang: Lang) { + match &sig.ret { + Some(_) if indirect_return(sig, out.types, lang) => write!(out, "void "), + Some(Type::RustBox(ty) | Type::UniquePtr(ty)) => { write_type_space(out, &ty.inner); write!(out, "*"); } @@ -1193,12 +1384,11 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option) { } write!(out, "*"); } - Some(Type::Str(_)) | Some(Type::SliceRef(_)) => { + Some(Type::Str(_) | Type::SliceRef(_)) => { out.builtin.repr_fat = true; write!(out, "::rust::repr::Fat "); } - Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "), - _ => write_return_type(out, ty), + ty => write_return_type(out, ty), } } @@ -1217,54 +1407,60 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) { } fn write_type(out: &mut OutFile, ty: &Type) { + write_type_to_generic_writer(out, ty, out.types); +} + +fn stringify_type(ty: &Type, types: &Types) -> String { + let mut s = String::new(); + write_type_to_generic_writer(&mut s, ty, types); + s +} + +fn write_type_to_generic_writer(out: &mut impl InfallibleWrite, ty: &Type, types: &Types) { match ty { Type::Ident(ident) => match Atom::from(&ident.rust) { Some(atom) => write_atom(out, atom), - None => write!( - out, - "{}", - out.types.resolve(ident).name.to_fully_qualified(), - ), + None => write!(out, "{}", types.resolve(ident).name.to_fully_qualified()), }, Type::RustBox(ty) => { write!(out, "::rust::Box<"); - write_type(out, &ty.inner); + write_type_to_generic_writer(out, &ty.inner, types); write!(out, ">"); } Type::RustVec(ty) => { write!(out, "::rust::Vec<"); - write_type(out, &ty.inner); + write_type_to_generic_writer(out, &ty.inner, types); write!(out, ">"); } Type::UniquePtr(ptr) => { write!(out, "::std::unique_ptr<"); - write_type(out, &ptr.inner); + write_type_to_generic_writer(out, &ptr.inner, types); write!(out, ">"); } Type::SharedPtr(ptr) => { write!(out, "::std::shared_ptr<"); - write_type(out, &ptr.inner); + write_type_to_generic_writer(out, &ptr.inner, types); write!(out, ">"); } Type::WeakPtr(ptr) => { write!(out, "::std::weak_ptr<"); - write_type(out, &ptr.inner); + write_type_to_generic_writer(out, &ptr.inner, types); write!(out, ">"); } Type::CxxVector(ty) => { write!(out, "::std::vector<"); - write_type(out, &ty.inner); + write_type_to_generic_writer(out, &ty.inner, types); write!(out, ">"); } Type::Ref(r) => { - write_type_space(out, &r.inner); + write_type_space_to_generic_writer(out, &r.inner, types); if !r.mutable { write!(out, "const "); } write!(out, "&"); } Type::Ptr(p) => { - write_type_space(out, &p.inner); + write_type_space_to_generic_writer(out, &p.inner, types); if !p.mutable { write!(out, "const "); } @@ -1275,7 +1471,7 @@ fn write_type(out: &mut OutFile, ty: &Type) { } Type::SliceRef(slice) => { write!(out, "::rust::Slice<"); - write_type_space(out, &slice.inner); + write_type_space_to_generic_writer(out, &slice.inner, types); if slice.mutability.is_none() { write!(out, "const"); } @@ -1284,7 +1480,7 @@ fn write_type(out: &mut OutFile, ty: &Type) { Type::Fn(f) => { write!(out, "::rust::Fn<"); match &f.ret { - Some(ret) => write_type(out, ret), + Some(ret) => write_type_to_generic_writer(out, ret, types), None => write!(out, "void"), } write!(out, "("); @@ -1292,20 +1488,20 @@ fn write_type(out: &mut OutFile, ty: &Type) { if i > 0 { write!(out, ", "); } - write_type(out, &arg.ty); + write_type_to_generic_writer(out, &arg.ty, types); } write!(out, ")>"); } Type::Array(a) => { write!(out, "::std::array<"); - write_type(out, &a.inner); - write!(out, ", {}>", &a.len); + write_type_to_generic_writer(out, &a.inner, types); + write!(out, ", {}>", a.len); } Type::Void(_) => unreachable!(), } } -fn write_atom(out: &mut OutFile, atom: Atom) { +fn write_atom(out: &mut impl InfallibleWrite, atom: Atom) { match atom { Bool => write!(out, "bool"), Char => write!(out, "char"), @@ -1327,11 +1523,15 @@ fn write_atom(out: &mut OutFile, atom: Atom) { } fn write_type_space(out: &mut OutFile, ty: &Type) { - write_type(out, ty); + write_type_space_to_generic_writer(out, ty, out.types); +} + +fn write_type_space_to_generic_writer(out: &mut impl InfallibleWrite, ty: &Type, types: &Types) { + write_type_to_generic_writer(out, ty, types); write_space_after_type(out, ty); } -fn write_space_after_type(out: &mut OutFile, ty: &Type) { +fn write_space_after_type(out: &mut impl InfallibleWrite, ty: &Type) { match ty { Type::Ident(_) | Type::RustBox(_) @@ -1349,54 +1549,6 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) { } } -#[derive(Copy, Clone)] -enum UniquePtr<'a> { - Ident(&'a Ident), - CxxVector(&'a Ident), -} - -trait ToTypename { - fn to_typename(&self, types: &Types) -> String; -} - -impl ToTypename for Ident { - fn to_typename(&self, types: &Types) -> String { - types.resolve(self).name.to_fully_qualified() - } -} - -impl<'a> ToTypename for UniquePtr<'a> { - fn to_typename(&self, types: &Types) -> String { - match self { - UniquePtr::Ident(ident) => ident.to_typename(types), - UniquePtr::CxxVector(element) => { - format!("::std::vector<{}>", element.to_typename(types)) - } - } - } -} - -trait ToMangled { - fn to_mangled(&self, types: &Types) -> Symbol; -} - -impl ToMangled for Ident { - fn to_mangled(&self, types: &Types) -> Symbol { - types.resolve(self).name.to_symbol() - } -} - -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) => { - symbol::join(&[&"std", &"vector", &element.to_mangled(types)]) - } - } - } -} - fn write_generic_instantiations(out: &mut OutFile) { if out.header { return; @@ -1407,7 +1559,7 @@ fn write_generic_instantiations(out: &mut OutFile) { out.begin_block(Block::ExternC); for impl_key in out.types.impls.keys() { out.next_section(); - match *impl_key { + match impl_key { ImplKey::RustBox(ident) => write_rust_box_extern(out, ident), ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident), ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident), @@ -1421,7 +1573,7 @@ fn write_generic_instantiations(out: &mut OutFile) { out.begin_block(Block::Namespace("rust")); out.begin_block(Block::InlineNamespace("cxxbridge1")); for impl_key in out.types.impls.keys() { - match *impl_key { + match impl_key { ImplKey::RustBox(ident) => write_rust_box_impl(out, ident), ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident), _ => {} @@ -1431,10 +1583,11 @@ fn write_generic_instantiations(out: &mut OutFile) { out.end_block(Block::Namespace("rust")); } -fn write_rust_box_extern(out: &mut OutFile, key: NamedImplKey) { - let resolve = out.types.resolve(&key); - let inner = resolve.name.to_fully_qualified(); - let instance = resolve.name.to_symbol(); +fn write_rust_box_extern(out: &mut OutFile, key: &NamedImplKey) { + let inner = stringify_type(key.inner, out.types); + let instance = &key.symbol; + + out.pragma.dollar_in_identifier = true; writeln!( out, @@ -1453,12 +1606,12 @@ fn write_rust_box_extern(out: &mut OutFile, key: NamedImplKey) { ); } -fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) { - let element = key.rust; - let inner = element.to_typename(out.types); - let instance = element.to_mangled(out.types); +fn write_rust_vec_extern(out: &mut OutFile, key: &NamedImplKey) { + let inner = stringify_type(key.inner, out.types); + let instance = &key.symbol; out.include.cstddef = true; + out.pragma.dollar_in_identifier = true; writeln!( out, @@ -1502,10 +1655,11 @@ fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) { ); } -fn write_rust_box_impl(out: &mut OutFile, key: NamedImplKey) { - let resolve = out.types.resolve(&key); - let inner = resolve.name.to_fully_qualified(); - let instance = resolve.name.to_symbol(); +fn write_rust_box_impl(out: &mut OutFile, key: &NamedImplKey) { + let inner = stringify_type(key.inner, out.types); + let instance = &key.symbol; + + out.pragma.dollar_in_identifier = true; writeln!(out, "template <>"); begin_function_definition(out); @@ -1534,12 +1688,12 @@ fn write_rust_box_impl(out: &mut OutFile, key: NamedImplKey) { writeln!(out, "}}"); } -fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) { - let element = key.rust; - let inner = element.to_typename(out.types); - let instance = element.to_mangled(out.types); +fn write_rust_vec_impl(out: &mut OutFile, key: &NamedImplKey) { + let inner = stringify_type(key.inner, out.types); + let instance = &key.symbol; out.include.cstddef = true; + out.pragma.dollar_in_identifier = true; writeln!(out, "template <>"); begin_function_definition(out); @@ -1613,7 +1767,7 @@ fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) { writeln!(out, "template <>"); begin_function_definition(out); - writeln!(out, "void Vec<{}>::truncate(::std::size_t len) {{", inner,); + writeln!(out, "void Vec<{}>::truncate(::std::size_t len) {{", inner); writeln!( out, " return cxxbridge1$rust_vec${}$truncate(this, len);", @@ -1622,46 +1776,33 @@ fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) { writeln!(out, "}}"); } -fn write_unique_ptr(out: &mut OutFile, key: NamedImplKey) { - let ty = UniquePtr::Ident(key.rust); - write_unique_ptr_common(out, ty); +fn write_unique_ptr(out: &mut OutFile, key: &NamedImplKey) { + write_unique_ptr_common(out, key.inner); } // Shared by UniquePtr and UniquePtr>. -fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) { +fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) { out.include.new = true; out.include.utility = true; - let inner = ty.to_typename(out.types); - let instance = ty.to_mangled(out.types); - - let can_construct_from_value = match ty { - // Some aliases are to opaque types; some are to trivial types. We can't - // know at code generation time, so we generate both C++ and Rust side - // bindings for a "new" method anyway. But the Rust code can't be called - // for Opaque types because the 'new' method is not implemented. - UniquePtr::Ident(ident) => out.types.is_maybe_trivial(ident), - UniquePtr::CxxVector(_) => false, - }; + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; - let conditional_delete = match ty { - UniquePtr::Ident(ident) => { - !out.types.structs.contains_key(ident) && !out.types.enums.contains_key(ident) - } - UniquePtr::CxxVector(_) => false, - }; + let inner = stringify_type(ty, out.types); + let instance = mangle::typename(ty, &out.types.resolutions) + .expect("unexpected UniquePtr generic parameter allowed through by syntax/check.rs"); - if conditional_delete { - out.builtin.is_complete = true; - let definition = match ty { - UniquePtr::Ident(ty) => &out.types.resolve(ty).name.cxx, - UniquePtr::CxxVector(_) => unreachable!(), - }; - writeln!( - out, - "static_assert(::rust::detail::is_complete<{}>::value, \"definition of {} is required\");", - inner, definition, - ); - } + // Some aliases are to opaque types; some are to trivial types. We can't + // know at code generation time, so we generate both C++ and Rust side + // bindings for a "new" method anyway. But the Rust code can't be called for + // Opaque types because the 'new' method is not implemented. + let can_construct_from_value = out.types.is_maybe_trivial(ty); + + out.builtin.is_complete = true; + writeln!( + out, + "static_assert(::rust::detail::is_complete<::std::remove_extent<{}>::type>::value, \"definition of `{}` is required\");", + inner, inner, + ); writeln!( out, "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");", @@ -1672,6 +1813,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, @@ -1680,8 +1822,10 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) { ); writeln!(out, " ::new (ptr) ::std::unique_ptr<{}>();", inner); writeln!(out, "}}"); + if can_construct_from_value { out.builtin.maybe_uninit = true; + out.pragma.mismatched_new_delete = true; begin_function_definition(out); writeln!( out, @@ -1697,63 +1841,63 @@ 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 {{", + "void cxxbridge1$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, ::std::unique_ptr<{}>::pointer raw) noexcept {{", instance, inner, inner, ); writeln!(out, " ::new (ptr) ::std::unique_ptr<{}>(raw);", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, - "{} const *cxxbridge1$unique_ptr${}$get(::std::unique_ptr<{}> const &ptr) noexcept {{", + "::std::unique_ptr<{}>::element_type 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 {{", + "::std::unique_ptr<{}>::pointer 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 {{", instance, inner, ); - if conditional_delete { - out.builtin.deleter_if = true; - writeln!( - out, - " ::rust::deleter_if<::rust::detail::is_complete<{}>::value>{{}}(ptr);", - inner, - ); - } else { - writeln!(out, " ptr->~unique_ptr();"); - } + out.builtin.deleter_if = true; + writeln!( + out, + " ::rust::deleter_if<::rust::detail::is_complete<{}>::value>{{}}(ptr);", + inner, + ); writeln!(out, "}}"); } -fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) { - let ident = key.rust; - let resolve = out.types.resolve(ident); - let inner = resolve.name.to_fully_qualified(); - let instance = resolve.name.to_symbol(); +fn write_shared_ptr(out: &mut OutFile, key: &NamedImplKey) { + let inner = stringify_type(key.inner, out.types); + let instance = &key.symbol; out.include.new = true; out.include.utility = true; + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; // Some aliases are to opaque types; some are to trivial types. We can't // know at code generation time, so we generate both C++ and Rust side // bindings for a "new" method anyway. But the Rust code can't be called for // Opaque types because the 'new' method is not implemented. - let can_construct_from_value = out.types.is_maybe_trivial(ident); + let can_construct_from_value = out.types.is_maybe_trivial(key.inner); writeln!( out, @@ -1765,6 +1909,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, @@ -1773,8 +1918,10 @@ fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) { ); writeln!(out, " ::new (ptr) ::std::shared_ptr<{}>();", inner); writeln!(out, "}}"); + if can_construct_from_value { out.builtin.maybe_uninit = true; + out.pragma.mismatched_new_delete = true; begin_function_definition(out); writeln!( out, @@ -1790,6 +1937,22 @@ fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) { writeln!(out, " return uninit;"); writeln!(out, "}}"); } + + out.builtin.shared_ptr = true; + begin_function_definition(out); + writeln!( + out, + "bool cxxbridge1$shared_ptr${}$raw(::std::shared_ptr<{}> *ptr, ::std::shared_ptr<{}>::element_type *raw) noexcept {{", + instance, inner, inner, + ); + writeln!( + out, + " ::new (ptr) ::rust::shared_ptr_if_destructible<{}>(raw);", + inner, + ); + writeln!(out, " return ::rust::is_destructible<{}>::value;", inner); + writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, @@ -1798,14 +1961,16 @@ fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) { ); writeln!(out, " ::new (ptr) ::std::shared_ptr<{}>(self);", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, - "{} const *cxxbridge1$shared_ptr${}$get(::std::shared_ptr<{}> const &self) noexcept {{", + "::std::shared_ptr<{}>::element_type 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, @@ -1816,13 +1981,14 @@ fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) { writeln!(out, "}}"); } -fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) { - let resolve = out.types.resolve(&key); - let inner = resolve.name.to_fully_qualified(); - let instance = resolve.name.to_symbol(); +fn write_weak_ptr(out: &mut OutFile, key: &NamedImplKey) { + let inner = stringify_type(key.inner, out.types); + let instance = &key.symbol; out.include.new = true; out.include.utility = true; + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; writeln!( out, @@ -1834,6 +2000,8 @@ fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) { "static_assert(alignof(::std::weak_ptr<{}>) == alignof(void *), \"\");", inner, ); + + begin_function_definition(out); writeln!( out, "void cxxbridge1$weak_ptr${}$null(::std::weak_ptr<{}> *ptr) noexcept {{", @@ -1841,6 +2009,7 @@ 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, @@ -1849,6 +2018,7 @@ fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) { ); writeln!(out, " ::new (ptr) ::std::weak_ptr<{}>(self);", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, @@ -1857,6 +2027,7 @@ fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) { ); writeln!(out, " ::new (weak) ::std::weak_ptr<{}>(shared);", inner); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, @@ -1869,6 +2040,7 @@ fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) { inner, ); writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, @@ -1879,15 +2051,27 @@ fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) { writeln!(out, "}}"); } -fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) { - let element = key.rust; - let inner = element.to_typename(out.types); - let instance = element.to_mangled(out.types); +fn write_cxx_vector(out: &mut OutFile, key: &NamedImplKey) { + let inner = stringify_type(key.inner, out.types); + let instance = &key.symbol; out.include.cstddef = true; out.include.utility = true; out.builtin.destroy = true; + out.builtin.vector = true; + out.pragma.dollar_in_identifier = true; + out.pragma.missing_declarations = true; + begin_function_definition(out); + writeln!( + out, + "::std::vector<{}> *cxxbridge1$std$vector${}$new() noexcept {{", + inner, instance, + ); + writeln!(out, " return new ::std::vector<{}>();", inner); + writeln!(out, "}}"); + + begin_function_definition(out); writeln!( out, "::std::size_t cxxbridge1$std$vector${}$size(::std::vector<{}> const &s) noexcept {{", @@ -1896,6 +2080,15 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) { writeln!(out, " return s.size();"); writeln!(out, "}}"); + begin_function_definition(out); + writeln!( + out, + "::std::size_t cxxbridge1$std$vector${}$capacity(::std::vector<{}> const &s) noexcept {{", + instance, inner, + ); + writeln!(out, " return s.capacity();"); + writeln!(out, "}}"); + begin_function_definition(out); writeln!( out, @@ -1905,7 +2098,20 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) { writeln!(out, " return &(*s)[pos];"); writeln!(out, "}}"); - if out.types.is_maybe_trivial(element) { + begin_function_definition(out); + writeln!( + out, + "bool cxxbridge1$std$vector${}$reserve(::std::vector<{}> *s, ::std::size_t new_cap) noexcept {{", + instance, inner, + ); + writeln!( + out, + " return ::rust::if_move_constructible<{}>::reserve(*s, new_cap);", + inner, + ); + writeln!(out, "}}"); + + if out.types.is_maybe_trivial(key.inner) { begin_function_definition(out); writeln!( out, @@ -1928,5 +2134,5 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) { } out.include.memory = true; - write_unique_ptr_common(out, UniquePtr::CxxVector(element)); + write_unique_ptr_common(out, key.outer); } diff --git a/build.rs b/build.rs index 9158b1c84..8b395eddc 100644 --- a/build.rs +++ b/build.rs @@ -1,13 +1,18 @@ +#![expect(unexpected_cfgs)] + use std::env; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::Command; fn main() { + let manifest_dir_opt = env::var_os("CARGO_MANIFEST_DIR").map(PathBuf::from); + let manifest_dir = manifest_dir_opt.as_deref().unwrap_or(Path::new("")); + cc::Build::new() - .file("src/cxx.cc") + .file(manifest_dir.join("src/cxx.cc")) .cpp(true) .cpp_link_stdlib(None) // linked via link-cplusplus crate - .flag_if_supported(cxxbridge_flags::STD) + .std(cxxbridge_flags::STD) .warnings_into_errors(cfg!(deny_warnings)) .compile("cxxbridge1"); @@ -15,19 +20,35 @@ fn main() { println!("cargo:rerun-if-changed=include/cxx.h"); println!("cargo:rustc-cfg=built_with_cargo"); - if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") { - let cxx_h = Path::new(&manifest_dir).join("include").join("cxx.h"); + if let Some(manifest_dir) = &manifest_dir_opt { + let cxx_h = manifest_dir.join("include").join("cxx.h"); println!("cargo:HEADER={}", cxx_h.to_string_lossy()); } - if let Some(rustc) = rustc_version() { - if rustc.minor < 60 { - println!("cargo:warning=The cxx crate requires a rustc version 1.60.0 or newer."); - println!( - "cargo:warning=You appear to be building with: {}", - rustc.version, - ); - } + println!("cargo:rustc-check-cfg=cfg(built_with_cargo)"); + println!("cargo:rustc-check-cfg=cfg(compile_error_if_alloc)"); + println!("cargo:rustc-check-cfg=cfg(compile_error_if_std)"); + println!("cargo:rustc-check-cfg=cfg(cxx_experimental_no_alloc)"); + println!("cargo:rustc-check-cfg=cfg(skip_ui_tests)"); + + if let Some(rustc) = rustc_version() + && rustc.minor < 88 + { + println!("cargo:warning=The cxx crate requires a rustc version 1.88.0 or newer."); + println!( + "cargo:warning=You appear to be building with: {}", + rustc.version, + ); + } + + if let (Some(manifest_links), Some(pkg_version_major)) = ( + env::var_os("CARGO_MANIFEST_LINKS"), + env::var_os("CARGO_PKG_VERSION_MAJOR"), + ) { + assert_eq!( + manifest_links, + *format!("cxxbridge{}", pkg_version_major.to_str().unwrap()), + ); } } diff --git a/compile_flags.txt b/compile_flags.txt index c24e3b5e5..e23b2aef6 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1 +1 @@ --std=c++11 +-std=c++20 diff --git a/demo/BUCK b/demo/BUCK index 8b3990ce9..86dd001db 100644 --- a/demo/BUCK +++ b/demo/BUCK @@ -3,7 +3,7 @@ load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_binary( name = "demo", srcs = glob(["src/**/*.rs"]), - edition = "2018", + edition = "2024", deps = [ ":blobstore-sys", ":bridge", @@ -20,7 +20,7 @@ rust_cxx_bridge( cxx_library( name = "blobstore-sys", srcs = ["src/blobstore.cc"], - compiler_flags = ["-std=c++14"], + preferred_linkage = "static", deps = [ ":blobstore-include", ":bridge/include", diff --git a/demo/BUILD b/demo/BUILD.bazel similarity index 90% rename from demo/BUILD rename to demo/BUILD.bazel index 3f598fe25..6ef48f90d 100644 --- a/demo/BUILD +++ b/demo/BUILD.bazel @@ -5,10 +5,12 @@ load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_binary( name = "demo", srcs = glob(["src/**/*.rs"]), - edition = "2018", - deps = [ + edition = "2024", + link_deps = [ ":blobstore-sys", ":bridge", + ], + deps = [ "//:cxx", ], ) @@ -22,7 +24,7 @@ rust_cxx_bridge( cc_library( name = "blobstore-sys", srcs = ["src/blobstore.cc"], - copts = ["-std=c++14"], + linkstatic = True, deps = [ ":blobstore-include", ":bridge/include", diff --git a/demo/Cargo.toml b/demo/Cargo.toml index cee0bc2c9..5b178cfa4 100644 --- a/demo/Cargo.toml +++ b/demo/Cargo.toml @@ -3,7 +3,7 @@ name = "demo" version = "0.0.0" authors = ["David Tolnay "] description = "Toy project from https://github.com/dtolnay/cxx" -edition = "2018" +edition = "2024" license = "MIT OR Apache-2.0" publish = false repository = "https://github.com/dtolnay/cxx" diff --git a/demo/build.rs b/demo/build.rs index c1b55cc2b..95990497b 100644 --- a/demo/build.rs +++ b/demo/build.rs @@ -1,10 +1,9 @@ fn main() { cxx_build::bridge("src/main.rs") .file("src/blobstore.cc") - .flag_if_supported("-std=c++14") + .std("c++14") .compile("cxxbridge-demo"); - println!("cargo:rerun-if-changed=src/main.rs"); println!("cargo:rerun-if-changed=src/blobstore.cc"); println!("cargo:rerun-if-changed=include/blobstore.h"); } diff --git a/demo/src/main.rs b/demo/src/main.rs index 458f1f211..e43f15621 100644 --- a/demo/src/main.rs +++ b/demo/src/main.rs @@ -48,7 +48,7 @@ fn main() { let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; let mut buf = MultiBuf { chunks, pos: 0 }; let blobid = client.put(&mut buf); - println!("blobid = {}", blobid); + println!("blobid = {blobid}"); // Add a tag. client.tag(blobid, "rust"); diff --git a/flags/Cargo.toml b/flags/Cargo.toml index 1f3822949..97d67e370 100644 --- a/flags/Cargo.toml +++ b/flags/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "cxxbridge-flags" -version = "1.0.91" +version = "1.0.199" authors = ["David Tolnay "] categories = ["development-tools::ffi", "compilers"] description = "Compiler configuration of the `cxx` crate (implementation detail)" -edition = "2018" +edition = "2024" license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/cxx" -rust-version = "1.60" +rust-version = "1.88" [features] default = [] # c++11 @@ -17,3 +17,10 @@ default = [] # c++11 [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] diff --git a/flags/src/impl.rs b/flags/src/impl.rs index 4f7b8fb4b..4cf0713ed 100644 --- a/flags/src/impl.rs +++ b/flags/src/impl.rs @@ -1,20 +1,15 @@ #[allow(unused_assignments, unused_mut, unused_variables)] pub const STD: &str = { - let mut flags = ["-std=c++11", "/std:c++11"]; + let mut flag = "c++11"; #[cfg(feature = "c++14")] - (flags = ["-std=c++14", "/std:c++14"]); + (flag = "c++14"); #[cfg(feature = "c++17")] - (flags = ["-std=c++17", "/std:c++17"]); + (flag = "c++17"); #[cfg(feature = "c++20")] - (flags = ["-std=c++20", "/std:c++20"]); - - let [mut flag, msvc_flag] = flags; - - #[cfg(target_env = "msvc")] - (flag = msvc_flag); + (flag = "c++20"); flag }; diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs deleted file mode 100644 index a52aab258..000000000 --- a/gen/build/src/out.rs +++ /dev/null @@ -1,119 +0,0 @@ -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, content: &[u8]) -> Result<()> { - let path = path.as_ref(); - - let mut create_dir_error = None; - if fs::exists(path) { - if let Ok(existing) = fs::read(path) { - if existing == content { - // Avoid bumping modified time with unchanged contents. - return Ok(()); - } - } - best_effort_remove(path); - } else { - let parent = path.parent().unwrap(); - create_dir_error = fs::create_dir_all(parent).err(); - } - - match fs::write(path, content) { - // As long as write succeeded, ignore any create_dir_all error. - Ok(()) => Ok(()), - // If create_dir_all and write both failed, prefer the first error. - Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))), - } -} - -pub(crate) fn symlink_file(original: impl AsRef, link: impl AsRef) -> Result<()> { - let original = original.as_ref(); - let link = link.as_ref(); - - let mut create_dir_error = None; - if fs::exists(link) { - best_effort_remove(link); - } else { - let parent = link.parent().unwrap(); - create_dir_error = fs::create_dir_all(parent).err(); - } - - match paths::symlink_or_copy(original, link) { - // As long as symlink_or_copy succeeded, ignore any create_dir_all error. - Ok(()) => Ok(()), - 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))) - } - } - } -} - -pub(crate) fn symlink_dir(original: impl AsRef, link: impl AsRef) -> Result<()> { - let original = original.as_ref(); - let link = link.as_ref(); - - let mut create_dir_error = None; - if fs::exists(link) { - best_effort_remove(link); - } else { - let parent = link.parent().unwrap(); - create_dir_error = fs::create_dir_all(parent).err(); - } - - match fs::symlink_dir(original, link) { - // As long as symlink_dir succeeded, ignore any create_dir_all error. - Ok(()) => Ok(()), - // If create_dir_all and symlink_dir both failed, prefer the first error. - Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))), - } -} - -fn best_effort_remove(path: &Path) { - use std::fs; - - 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". - 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. - 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/Cargo.toml b/gen/cmd/Cargo.toml deleted file mode 100644 index 677aa326c..000000000 --- a/gen/cmd/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "cxxbridge-cmd" -version = "1.0.91" -authors = ["David Tolnay "] -categories = ["development-tools::build-utils", "development-tools::ffi"] -description = "C++ code generator for integrating `cxx` crate into a non-Cargo build." -edition = "2018" -exclude = ["build.rs"] -homepage = "https://cxx.rs" -keywords = ["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 = { version = "4", default-features = false, features = ["error-context", "help", "std", "suggestions", "usage"] } -codespan-reporting = "0.11" -proc-macro2 = { version = "1.0.39", default-features = false, features = ["span-locations"] } -quote = { version = "1.0", default-features = false } -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/lib.rs b/gen/cmd/src/lib.rs deleted file mode 100644 index 8b1a39374..000000000 --- a/gen/cmd/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -// empty diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml deleted file mode 100644 index 01b5876f9..000000000 --- a/gen/lib/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "cxx-gen" -version = "0.7.91" -authors = ["Adrian Taylor "] -categories = ["development-tools::ffi"] -description = "C++ code generator for integrating `cxx` crate into higher level tools." -edition = "2018" -exclude = ["build.rs"] -keywords = ["ffi"] -license = "MIT OR Apache-2.0" -repository = "https://github.com/dtolnay/cxx" -rust-version = "1.60" - -[dependencies] -codespan-reporting = "0.11" -proc-macro2 = { version = "1.0.39", default-features = false, features = ["span-locations"] } -quote = { version = "1.0", default-features = false } -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 deleted file mode 100644 index bb53a7fc2..000000000 --- a/gen/lib/src/error.rs +++ /dev/null @@ -1,34 +0,0 @@ -// We can expose more detail on the error as the need arises, but start with an -// opaque error type for now. - -use std::error::Error as StdError; -use std::fmt::{self, Debug, Display}; - -#[allow(missing_docs)] -pub struct Error { - pub(crate) err: crate::gen::Error, -} - -impl From for Error { - fn from(err: crate::gen::Error) -> Self { - Error { err } - } -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(&self.err, f) - } -} - -impl Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Debug::fmt(&self.err, f) - } -} - -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - self.err.source() - } -} diff --git a/include/cxx.h b/include/cxx.h index 907ee829f..4e261a355 100644 --- a/include/cxx.h +++ b/include/cxx.h @@ -20,6 +20,14 @@ #include #endif +#if __cplusplus >= 201703L +#include +#endif + +#if __cplusplus >= 202002L +#include +#endif + namespace rust { inline namespace cxxbridge1 { @@ -45,6 +53,10 @@ class String final { String(const char *, std::size_t); String(const char16_t *); String(const char16_t *, std::size_t); +#ifdef __cpp_char8_t + String(const char8_t *s); + String(const char8_t *s, std::size_t len); +#endif // Replace invalid Unicode data with the replacement character (U+FFFD). static String lossy(const std::string &) noexcept; @@ -53,8 +65,8 @@ class String final { 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; + String &operator=(const String &) & noexcept; + String &operator=(String &&) & noexcept; explicit operator std::string() const; @@ -113,9 +125,12 @@ class Str final { Str(const char *); Str(const char *, std::size_t); - Str &operator=(const Str &) &noexcept = default; + Str &operator=(const Str &) & noexcept = default; explicit operator std::string() const; +#if __cplusplus >= 201703L + explicit operator std::string_view() const; +#endif // Note: no null terminator. const char *data() const noexcept; @@ -161,8 +176,8 @@ template <> struct copy_assignable_if { copy_assignable_if() noexcept = default; copy_assignable_if(const copy_assignable_if &) noexcept = default; - copy_assignable_if &operator=(const copy_assignable_if &) &noexcept = delete; - copy_assignable_if &operator=(copy_assignable_if &&) &noexcept = default; + copy_assignable_if &operator=(const copy_assignable_if &) & noexcept = delete; + copy_assignable_if &operator=(copy_assignable_if &&) & noexcept = default; }; } // namespace detail @@ -176,8 +191,11 @@ class Slice final Slice() noexcept; Slice(T *, std::size_t count) noexcept; - Slice &operator=(const Slice &) &noexcept = default; - Slice &operator=(Slice &&) &noexcept = default; + template + explicit Slice(C &c) : Slice(c.data(), c.size()) {} + + Slice &operator=(const Slice &) & noexcept = default; + Slice &operator=(Slice &&) & noexcept = default; T *data() const noexcept; std::size_t size() const noexcept; @@ -210,10 +228,20 @@ class Slice final std::array repr; }; +#ifdef __cpp_deduction_guides +template +explicit Slice(C &c) + -> Slice().data())>>; +#endif // __cpp_deduction_guides + template class Slice::iterator final { public: +#if __cplusplus >= 202002L + using iterator_category = std::contiguous_iterator_tag; +#else using iterator_category = std::random_access_iterator_tag; +#endif using value_type = T; using difference_type = std::ptrdiff_t; using pointer = typename std::add_pointer::type; @@ -231,6 +259,9 @@ class Slice::iterator final { iterator &operator+=(difference_type) noexcept; iterator &operator-=(difference_type) noexcept; iterator operator+(difference_type) const noexcept; + friend inline iterator operator+(difference_type lhs, iterator rhs) noexcept { + return rhs + lhs; + } iterator operator-(difference_type) const noexcept; difference_type operator-(const iterator &) const noexcept; @@ -246,6 +277,12 @@ class Slice::iterator final { void *pos; std::size_t stride; }; + +#if __cplusplus >= 202002L +static_assert(std::ranges::contiguous_range>); +static_assert(std::contiguous_iterator::iterator>); +#endif + #endif // CXXBRIDGE1_RUST_SLICE #ifndef CXXBRIDGE1_RUST_BOX @@ -265,7 +302,7 @@ class Box final { explicit Box(const T &); explicit Box(T &&); - Box &operator=(Box &&) &noexcept; + Box &operator=(Box &&) & noexcept; const T *operator->() const noexcept; const T &operator*() const noexcept; @@ -310,7 +347,7 @@ class Vec final { Vec(Vec &&) noexcept; ~Vec() noexcept; - Vec &operator=(Vec &&) &noexcept; + Vec &operator=(Vec &&) & noexcept; Vec &operator=(const Vec &) &; std::size_t size() const noexcept; @@ -391,7 +428,7 @@ class Error final : public std::exception { ~Error() noexcept override; Error &operator=(const Error &) &; - Error &operator=(Error &&) &noexcept; + Error &operator=(Error &&) & noexcept; const char *what() const noexcept override; @@ -659,7 +696,8 @@ typename Slice::iterator::difference_type Slice::iterator::operator-(const iterator &other) const noexcept { auto diff = std::distance(static_cast(other.pos), static_cast(this->pos)); - return diff / this->stride; + return diff / static_cast::iterator::difference_type>( + this->stride); } template @@ -762,7 +800,7 @@ Box::~Box() noexcept { } template -Box &Box::operator=(Box &&other) &noexcept { +Box &Box::operator=(Box &&other) & noexcept { if (this->ptr) { this->drop(); } @@ -850,7 +888,7 @@ Vec::~Vec() noexcept { } template -Vec &Vec::operator=(Vec &&other) &noexcept { +Vec &Vec::operator=(Vec &&other) & noexcept { this->drop(); this->repr = other.repr; new (&other) Vec(); diff --git a/macro/Cargo.toml b/macro/Cargo.toml index 988c848be..0be4f3290 100644 --- a/macro/Cargo.toml +++ b/macro/Cargo.toml @@ -1,39 +1,37 @@ [package] name = "cxxbridge-macro" -version = "1.0.91" +version = "1.0.199" authors = ["David Tolnay "] categories = ["development-tools::ffi"] description = "Implementation detail of the `cxx` crate." -edition = "2018" +edition = "2024" exclude = ["build.rs", "README.md"] homepage = "https://cxx.rs" keywords = ["ffi"] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/cxx" -rust-version = "1.60" +rust-version = "1.88" [lib] proc-macro = true -[features] -# 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.39" -quote = "1.0.4" -syn = { version = "1.0.95", features = ["full"] } - -# optional dependencies: -clang-ast = { version = "0.1", optional = true } -flate2 = { version = "1.0", optional = true } -memmap = { version = "0.7", optional = true } -serde = { version = "1.0", optional = true, features = ["derive"] } -serde_json = { version = "1.0", optional = true } +indexmap = "2.9.0" +proc-macro2 = "1.0.74" +quote = "1.0.35" +syn = { version = "3", features = ["full"] } [dev-dependencies] cxx = { version = "1.0", path = ".." } +prettyplease = "0.3" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", +] diff --git a/macro/src/attrs.rs b/macro/src/attrs.rs new file mode 100644 index 000000000..2880e63c6 --- /dev/null +++ b/macro/src/attrs.rs @@ -0,0 +1,68 @@ +use crate::syntax::attrs::OtherAttrs; +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::Attribute; + +impl OtherAttrs { + pub(crate) fn all(&self) -> PrintOtherAttrs { + PrintOtherAttrs { + attrs: self, + cfg: true, + lint: true, + passthrough: true, + } + } + + pub(crate) fn cfg(&self) -> PrintOtherAttrs { + PrintOtherAttrs { + attrs: self, + cfg: true, + lint: false, + passthrough: false, + } + } + + pub(crate) fn cfg_and_lint(&self) -> PrintOtherAttrs { + PrintOtherAttrs { + attrs: self, + cfg: true, + lint: true, + passthrough: false, + } + } +} + +pub(crate) struct PrintOtherAttrs<'a> { + attrs: &'a OtherAttrs, + cfg: bool, + lint: bool, + passthrough: bool, +} + +impl<'a> ToTokens for PrintOtherAttrs<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { + if self.cfg { + print_attrs_as_outer(&self.attrs.cfg, tokens); + } + if self.lint { + print_attrs_as_outer(&self.attrs.lint, tokens); + } + if self.passthrough { + print_attrs_as_outer(&self.attrs.passthrough, tokens); + } + } +} + +fn print_attrs_as_outer(attrs: &[Attribute], tokens: &mut TokenStream) { + for attr in attrs { + let Attribute { + pound_token, + style, + bracket_token, + meta, + } = attr; + pound_token.to_tokens(tokens); + let _ = style; // ignore; render outer and inner attrs both as outer + bracket_token.surround(tokens, |tokens| meta.to_tokens(tokens)); + } +} diff --git a/macro/src/cfg.rs b/macro/src/cfg.rs new file mode 100644 index 000000000..4ce93b833 --- /dev/null +++ b/macro/src/cfg.rs @@ -0,0 +1,95 @@ +use crate::syntax::cfg::{CfgExpr, ComputedCfg}; +use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream}; +use quote::{ToTokens, TokenStreamExt as _}; +use syn::{AttrStyle, Attribute, MacroDelimiter, Meta, MetaList, Path, Token, token}; + +impl<'a> ComputedCfg<'a> { + pub(crate) fn into_attr(&self) -> Option { + if let ComputedCfg::Leaf(CfgExpr::Unconditional) = self { + None + } else { + let span = Span::call_site(); + Some(Attribute { + pound_token: Token![#](span), + style: AttrStyle::Outer, + bracket_token: token::Bracket(span), + meta: Meta::List(MetaList { + path: Path::from(Ident::new("cfg", span)), + delimiter: MacroDelimiter::Paren(token::Paren(span)), + tokens: self.as_meta().into_token_stream(), + }), + }) + } + } + + pub(crate) fn as_meta(&self) -> impl ToTokens + '_ { + Print { + cfg: self, + span: Span::call_site(), + } + } +} + +struct Print<'a, Cfg> { + cfg: &'a Cfg, + span: Span, +} + +impl<'a> ToTokens for Print<'a, CfgExpr> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let span = self.span; + let print = |cfg| Print { cfg, span }; + match self.cfg { + CfgExpr::Unconditional => unreachable!(), + CfgExpr::Eq(ident, value) => { + ident.to_tokens(tokens); + if let Some(value) = value { + Token![=](span).to_tokens(tokens); + value.to_tokens(tokens); + } + } + CfgExpr::All(inner) => { + tokens.append(Ident::new("all", span)); + let mut group = TokenStream::new(); + group.append_separated(inner.iter().map(print), Token![,](span)); + tokens.append(Group::new(Delimiter::Parenthesis, group)); + } + CfgExpr::Any(inner) => { + tokens.append(Ident::new("any", span)); + let mut group = TokenStream::new(); + group.append_separated(inner.iter().map(print), Token![,](span)); + tokens.append(Group::new(Delimiter::Parenthesis, group)); + } + CfgExpr::Not(inner) => { + tokens.append(Ident::new("not", span)); + let group = print(inner).into_token_stream(); + tokens.append(Group::new(Delimiter::Parenthesis, group)); + } + } + } +} + +impl<'a> ToTokens for Print<'a, ComputedCfg<'a>> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let span = self.span; + match *self.cfg { + ComputedCfg::Leaf(cfg) => Print { cfg, span }.to_tokens(tokens), + ComputedCfg::All(ref inner) => { + tokens.append(Ident::new("all", span)); + let mut group = TokenStream::new(); + group.append_separated( + inner.iter().map(|&cfg| Print { cfg, span }), + Token![,](span), + ); + tokens.append(Group::new(Delimiter::Parenthesis, group)); + } + ComputedCfg::Any(ref inner) => { + tokens.append(Ident::new("any", span)); + let mut group = TokenStream::new(); + group + .append_separated(inner.iter().map(|cfg| Print { cfg, span }), Token![,](span)); + tokens.append(Group::new(Delimiter::Parenthesis, group)); + } + } + } +} diff --git a/macro/src/clang.rs b/macro/src/clang.rs deleted file mode 100644 index 381e5086d..000000000 --- a/macro/src/clang.rs +++ /dev/null @@ -1,51 +0,0 @@ -use serde::{Deserialize, Serialize}; - -pub type Node = clang_ast::Node; - -#[derive(Deserialize, Serialize)] -pub enum Clang { - NamespaceDecl(NamespaceDecl), - EnumDecl(EnumDecl), - EnumConstantDecl(EnumConstantDecl), - ImplicitCastExpr, - ConstantExpr(ConstantExpr), - Unknown, -} - -#[derive(Deserialize, Serialize)] -pub struct NamespaceDecl { - #[serde(skip_serializing_if = "Option::is_none")] - pub name: Option>, -} - -#[derive(Deserialize, Serialize)] -pub struct EnumDecl { - #[serde(skip_serializing_if = "Option::is_none")] - pub name: Option>, - #[serde( - rename = "fixedUnderlyingType", - skip_serializing_if = "Option::is_none" - )] - pub fixed_underlying_type: Option, -} - -#[derive(Deserialize, Serialize)] -pub struct EnumConstantDecl { - pub name: Box, -} - -#[derive(Deserialize, Serialize)] -pub struct ConstantExpr { - pub value: Box, -} - -#[derive(Deserialize, Serialize)] -pub struct Type { - #[serde(rename = "qualType")] - pub qual_type: Box, - #[serde(rename = "desugaredQualType", skip_serializing_if = "Option::is_none")] - pub desugared_qual_type: Option>, -} - -#[cfg(all(test, target_pointer_width = "64"))] -const _: [(); core::mem::size_of::()] = [(); 88]; diff --git a/macro/src/derive.rs b/macro/src/derive.rs index e1d8d69e7..b4b0087ba 100644 --- a/macro/src/derive.rs +++ b/macro/src/derive.rs @@ -1,16 +1,22 @@ -use crate::syntax::{derive, Enum, Struct, Trait}; +use crate::syntax::{Enum, Struct, derive}; use proc_macro2::{Ident, Span, TokenStream}; -use quote::{quote, quote_spanned, ToTokens}; +use quote::{ToTokens, quote, quote_spanned}; -pub use crate::syntax::derive::*; +pub(crate) use crate::syntax::derive::*; -pub fn expand_struct(strct: &Struct, actual_derives: &mut Option) -> TokenStream { +pub(crate) fn expand_struct( + strct: &Struct, + actual_derives: &mut Option, +) -> TokenStream { let mut expanded = TokenStream::new(); let mut traits = Vec::new(); for derive in &strct.derives { let span = derive.span; match derive.what { + Trait::BitAnd => unreachable!(), + Trait::BitOr => unreachable!(), + Trait::BitXor => unreachable!(), Trait::Copy => expanded.extend(struct_copy(strct, span)), Trait::Clone => expanded.extend(struct_clone(strct, span)), Trait::Debug => expanded.extend(struct_debug(strct, span)), @@ -35,7 +41,7 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option) - expanded } -pub fn expand_enum(enm: &Enum, actual_derives: &mut Option) -> TokenStream { +pub(crate) fn expand_enum(enm: &Enum, actual_derives: &mut Option) -> TokenStream { let mut expanded = TokenStream::new(); let mut traits = Vec::new(); let mut has_copy = false; @@ -46,6 +52,9 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option) -> Toke for derive in &enm.derives { let span = derive.span; match derive.what { + Trait::BitAnd => expanded.extend(enum_bitand(enm, span)), + Trait::BitOr => expanded.extend(enum_bitor(enm, span)), + Trait::BitXor => expanded.extend(enum_bitxor(enm, span)), Trait::Copy => { expanded.extend(enum_copy(enm, span)); has_copy = true; @@ -55,7 +64,7 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option) -> Toke has_clone = true; } Trait::Debug => expanded.extend(enum_debug(enm, span)), - Trait::Default => unreachable!(), + Trait::Default => expanded.extend(enum_default(enm, span)), Trait::Eq => { traits.push(quote_spanned!(span=> ::cxx::core::cmp::Eq)); has_eq = true; @@ -97,8 +106,11 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option) -> Toke fn struct_copy(strct: &Struct, span: Span) -> TokenStream { let ident = &strct.name.rust; let generics = &strct.generics; + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] impl #generics ::cxx::core::marker::Copy for #ident #generics {} } } @@ -106,6 +118,7 @@ fn struct_copy(strct: &Struct, span: Span) -> TokenStream { fn struct_clone(strct: &Struct, span: Span) -> TokenStream { let ident = &strct.name.rust; let generics = &strct.generics; + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); let body = if derive::contains(&strct.derives, Trait::Copy) { quote!(*self) @@ -123,7 +136,9 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream { }; quote_spanned! {span=> - #[allow(clippy::expl_impl_clone_on_copy)] + #cfg_and_lint_attrs + #[automatically_derived] + #[allow(clippy::clone_on_copy, clippy::expl_impl_clone_on_copy)] impl #generics ::cxx::core::clone::Clone for #ident #generics { fn clone(&self) -> Self { #body @@ -135,11 +150,14 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream { fn struct_debug(strct: &Struct, span: Span) -> TokenStream { let ident = &strct.name.rust; let generics = &strct.generics; + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); let struct_name = ident.to_string(); let fields = strct.fields.iter().map(|field| &field.name.rust); let field_names = fields.clone().map(Ident::to_string); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] 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) @@ -153,9 +171,12 @@ fn struct_debug(strct: &Struct, span: Span) -> TokenStream { fn struct_default(strct: &Struct, span: Span) -> TokenStream { let ident = &strct.name.rust; let generics = &strct.generics; + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); let fields = strct.fields.iter().map(|field| &field.name.rust); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] #[allow(clippy::derivable_impls)] // different spans than the derived impl impl #generics ::cxx::core::default::Default for #ident #generics { fn default() -> Self { @@ -172,9 +193,12 @@ fn struct_default(strct: &Struct, span: Span) -> TokenStream { fn struct_ord(strct: &Struct, span: Span) -> TokenStream { let ident = &strct.name.rust; let generics = &strct.generics; + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); let fields = strct.fields.iter().map(|field| &field.name.rust); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] impl #generics ::cxx::core::cmp::Ord for #ident #generics { fn cmp(&self, other: &Self) -> ::cxx::core::cmp::Ordering { #( @@ -192,6 +216,7 @@ fn struct_ord(strct: &Struct, span: Span) -> TokenStream { fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream { let ident = &strct.name.rust; let generics = &strct.generics; + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); let body = if derive::contains(&strct.derives, Trait::Ord) { quote! { @@ -211,7 +236,10 @@ fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream { }; quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] impl #generics ::cxx::core::cmp::PartialOrd for #ident #generics { + #[allow(clippy::non_canonical_partial_ord_impl)] fn partial_cmp(&self, other: &Self) -> ::cxx::core::option::Option<::cxx::core::cmp::Ordering> { #body } @@ -219,18 +247,78 @@ fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream { } } +fn enum_bitand(enm: &Enum, span: Span) -> TokenStream { + let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); + + quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] + impl ::cxx::core::ops::BitAnd for #ident { + type Output = #ident; + fn bitand(self, rhs: Self) -> Self::Output { + #ident { + repr: self.repr & rhs.repr, + } + } + } + } +} + +fn enum_bitor(enm: &Enum, span: Span) -> TokenStream { + let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); + + quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] + impl ::cxx::core::ops::BitOr for #ident { + type Output = #ident; + fn bitor(self, rhs: Self) -> Self::Output { + #ident { + repr: self.repr | rhs.repr, + } + } + } + } +} + +fn enum_bitxor(enm: &Enum, span: Span) -> TokenStream { + let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); + + quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] + impl ::cxx::core::ops::BitXor for #ident { + type Output = #ident; + fn bitxor(self, rhs: Self) -> Self::Output { + #ident { + repr: self.repr ^ rhs.repr, + } + } + } + } +} + fn enum_copy(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] impl ::cxx::core::marker::Copy for #ident {} } } fn enum_clone(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] #[allow(clippy::expl_impl_clone_on_copy)] impl ::cxx::core::clone::Clone for #ident { fn clone(&self) -> Self { @@ -242,6 +330,7 @@ fn enum_clone(enm: &Enum, span: Span) -> TokenStream { fn enum_debug(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); let variants = enm.variants.iter().map(|variant| { let variant = &variant.name.rust; let name = variant.to_string(); @@ -252,6 +341,8 @@ fn enum_debug(enm: &Enum, span: Span) -> TokenStream { let fallback = format!("{}({{}})", ident); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] impl ::cxx::core::fmt::Debug for #ident { fn fmt(&self, formatter: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { match *self { @@ -263,10 +354,35 @@ fn enum_debug(enm: &Enum, span: Span) -> TokenStream { } } +fn enum_default(enm: &Enum, span: Span) -> TokenStream { + let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); + + for variant in &enm.variants { + if variant.default { + let variant = &variant.name.rust; + return quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] + impl ::cxx::core::default::Default for #ident { + fn default() -> Self { + #ident::#variant + } + } + }; + } + } + + unreachable!("no #[default] variant"); +} + fn enum_ord(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] 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) @@ -277,9 +393,13 @@ fn enum_ord(enm: &Enum, span: Span) -> TokenStream { fn enum_partial_ord(enm: &Enum, span: Span) -> TokenStream { let ident = &enm.name.rust; + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] impl ::cxx::core::cmp::PartialOrd for #ident { + #[allow(clippy::non_canonical_partial_ord_impl)] 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 ea5af66a4..b4a60d35d 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -1,23 +1,31 @@ use crate::syntax::atom::Atom::*; use crate::syntax::attrs::{self, OtherAttrs}; -use crate::syntax::cfg::CfgExpr; +use crate::syntax::cfg::{CfgExpr, ComputedCfg}; use crate::syntax::file::Module; use crate::syntax::instantiate::{ImplKey, NamedImplKey}; +use crate::syntax::map::OrderedMap; +use crate::syntax::message::Message; +use crate::syntax::namespace::Namespace; use crate::syntax::qualified::QualifiedName; use crate::syntax::report::Errors; +use crate::syntax::set::UnorderedSet; use crate::syntax::symbol::Symbol; +use crate::syntax::trivial::TrivialReason; +use crate::syntax::types::ConditionalImpl; +use crate::syntax::unpin::UnpinReason; use crate::syntax::{ - self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature, - Struct, Trait, Type, TypeAlias, Types, + self, Api, Doc, Enum, ExternFn, ExternType, FnKind, Lang, Pair, Signature, Struct, Trait, Type, + TypeAlias, Types, check, mangle, }; use crate::type_id::Crate; use crate::{derive, generics}; use proc_macro2::{Ident, Span, TokenStream}; -use quote::{format_ident, quote, quote_spanned, ToTokens}; +use quote::{ToTokens, format_ident, quote, quote_spanned}; +use std::fmt::{self, Display}; use std::mem; -use syn::{parse_quote, punctuated, Generics, Lifetime, Result, Token}; +use syn::{GenericParam, Generics, Lifetime, Result, Token, Visibility, parse_quote}; -pub fn bridge(mut ffi: Module) -> Result { +pub(crate) fn bridge(mut ffi: Module) -> Result { let ref mut errors = Errors::new(); let mut cfg = CfgExpr::Unconditional; @@ -36,8 +44,6 @@ pub fn bridge(mut ffi: Module) -> Result { let trusted = ffi.unsafety.is_some(); let namespace = &ffi.namespace; let ref mut apis = syntax::parse_items(errors, content, trusted, namespace); - #[cfg(feature = "experimental-enum-variants-from-header")] - crate::load::load(errors, apis); let ref types = Types::collect(errors, apis); errors.propagate()?; @@ -65,51 +71,60 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) Api::Include(_) | Api::Impl(_) => {} Api::Struct(strct) => { expanded.extend(expand_struct(strct)); + expanded.extend(expand_associated_functions(&strct.name.rust, types)); + hidden.extend(expand_struct_nonempty(strct)); hidden.extend(expand_struct_operators(strct)); forbid.extend(expand_struct_forbid_drop(strct)); } Api::Enum(enm) => expanded.extend(expand_enum(enm)), Api::CxxType(ety) => { let ident = &ety.name.rust; - if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) { + if types.structs.contains_key(ident) { + hidden.extend(expand_extern_shared_struct(ety, &ffi)); + } else if !types.enums.contains_key(ident) { expanded.extend(expand_cxx_type(ety)); + expanded.extend(expand_associated_functions(&ety.name.rust, types)); hidden.extend(expand_cxx_type_assert_pinned(ety, types)); } } Api::CxxFunction(efn) => { - expanded.extend(expand_cxx_function_shim(efn, types)); + if efn.self_type().is_none() { + expanded.extend(expand_cxx_function_shim(efn, types)); + } } Api::RustType(ety) => { expanded.extend(expand_rust_type_impl(ety)); + expanded.extend(expand_associated_functions(&ety.name.rust, types)); hidden.extend(expand_rust_type_layout(ety, types)); } Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)), Api::TypeAlias(alias) => { expanded.extend(expand_type_alias(alias)); + expanded.extend(expand_associated_functions(&alias.name.rust, types)); hidden.extend(expand_type_alias_verify(alias, types)); } } } - for (impl_key, &explicit_impl) in &types.impls { - match *impl_key { + for (impl_key, conditional_impl) in &types.impls { + match impl_key { ImplKey::RustBox(ident) => { - hidden.extend(expand_rust_box(ident, types, explicit_impl)); + hidden.extend(expand_rust_box(ident, types, conditional_impl)); } ImplKey::RustVec(ident) => { - hidden.extend(expand_rust_vec(ident, types, explicit_impl)); + hidden.extend(expand_rust_vec(ident, types, conditional_impl)); } ImplKey::UniquePtr(ident) => { - expanded.extend(expand_unique_ptr(ident, types, explicit_impl)); + expanded.extend(expand_unique_ptr(ident, types, conditional_impl)); } ImplKey::SharedPtr(ident) => { - expanded.extend(expand_shared_ptr(ident, types, explicit_impl)); + expanded.extend(expand_shared_ptr(ident, types, conditional_impl)); } ImplKey::WeakPtr(ident) => { - expanded.extend(expand_weak_ptr(ident, types, explicit_impl)); + expanded.extend(expand_weak_ptr(ident, types, conditional_impl)); } ImplKey::CxxVector(ident) => { - expanded.extend(expand_cxx_vector(ident, explicit_impl, types)); + expanded.extend(expand_cxx_vector(ident, conditional_impl, types)); } } } @@ -128,6 +143,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) }); } + let all_attrs = attrs.all(); let vis = &ffi.vis; let mod_token = &ffi.mod_token; let ident = &ffi.ident; @@ -136,14 +152,16 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) quote! { #doc - #attrs + #all_attrs #[deny(improper_ctypes, improper_ctypes_definitions)] - #[allow(clippy::unknown_clippy_lints)] + #[allow(clippy::unknown_lints)] #[allow( non_camel_case_types, non_snake_case, clippy::extra_unused_type_parameters, - clippy::ptr_as_ptr, + clippy::items_after_statements, + clippy::no_effect_underscore_binding, + clippy::unsafe_derive_deserialize, clippy::upper_case_acronyms, clippy::use_self, )] @@ -154,16 +172,17 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) fn expand_struct(strct: &Struct) -> TokenStream { let ident = &strct.name.rust; let doc = &strct.doc; - let attrs = &strct.attrs; + let all_attrs = strct.attrs.all(); + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); let generics = &strct.generics; let type_id = type_id(&strct.name); let fields = strct.fields.iter().map(|field| { let doc = &field.doc; - let attrs = &field.attrs; + let all_attrs = field.attrs.all(); // This span on the pub makes "private type in public interface" errors // appear in the right place. let vis = field.visibility; - quote!(#doc #attrs #vis #field) + quote!(#doc #all_attrs #vis #field) }); let mut derives = None; let derived_traits = derive::expand_struct(strct, &mut derives); @@ -177,13 +196,17 @@ fn expand_struct(strct: &Struct) -> TokenStream { } }; + let align = strct.align.as_ref().map(|align| quote!(, align(#align))); + quote! { #doc #derives - #attrs - #[repr(C)] + #all_attrs + #[repr(C #align)] #struct_def + #cfg_and_lint_attrs + #[automatically_derived] unsafe impl #generics ::cxx::ExternType for #ident #generics { #[allow(unused_attributes)] // incorrect lint #[doc(hidden)] @@ -195,9 +218,37 @@ fn expand_struct(strct: &Struct) -> TokenStream { } } +fn expand_struct_nonempty(strct: &Struct) -> TokenStream { + let has_unconditional_field = strct + .fields + .iter() + .any(|field| matches!(field.cfg, CfgExpr::Unconditional)); + if has_unconditional_field { + return TokenStream::new(); + } + + let mut fields = strct.fields.iter(); + let mut cfg = ComputedCfg::from(&fields.next().unwrap().cfg); + fields.for_each(|field| cfg.merge_or(&field.cfg)); + + if let ComputedCfg::Leaf(CfgExpr::Unconditional) = cfg { + // At least one field is unconditional, nothing to check. + TokenStream::new() + } else { + let meta = cfg.as_meta(); + let msg = "structs without any fields are not supported"; + let error = syn::Error::new_spanned(strct, msg).into_compile_error(); + quote! { + #[cfg(not(#meta))] + #error + } + } +} + fn expand_struct_operators(strct: &Struct) -> TokenStream { let ident = &strct.name.rust; let generics = &strct.generics; + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); let mut operators = TokenStream::new(); for derive in &strct.derives { @@ -208,10 +259,11 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { 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=> + #cfg_and_lint_attrs #[doc(hidden)] - #[export_name = #link_name] - extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { - let __fn = concat!("<", module_path!(), #prevent_unwind_label); + #[unsafe(export_name = #link_name)] + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> ::cxx::core::primitive::bool { + let __fn = ::cxx::core::concat!("<", ::cxx::core::module_path!(), #prevent_unwind_label); ::cxx::private::prevent_unwind(__fn, || *lhs == *rhs) } }); @@ -221,10 +273,11 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { 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=> + #cfg_and_lint_attrs #[doc(hidden)] - #[export_name = #link_name] - extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { - let __fn = concat!("<", module_path!(), #prevent_unwind_label); + #[unsafe(export_name = #link_name)] + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> ::cxx::core::primitive::bool { + let __fn = ::cxx::core::concat!("<", ::cxx::core::module_path!(), #prevent_unwind_label); ::cxx::private::prevent_unwind(__fn, || *lhs != *rhs) } }); @@ -235,10 +288,11 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { 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=> + #cfg_and_lint_attrs #[doc(hidden)] - #[export_name = #link_name] - extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { - let __fn = concat!("<", module_path!(), #prevent_unwind_label); + #[unsafe(export_name = #link_name)] + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> ::cxx::core::primitive::bool { + let __fn = ::cxx::core::concat!("<", ::cxx::core::module_path!(), #prevent_unwind_label); ::cxx::private::prevent_unwind(__fn, || *lhs < *rhs) } }); @@ -247,10 +301,11 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { 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=> + #cfg_and_lint_attrs #[doc(hidden)] - #[export_name = #link_name] - extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { - let __fn = concat!("<", module_path!(), #prevent_unwind_label); + #[unsafe(export_name = #link_name)] + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> ::cxx::core::primitive::bool { + let __fn = ::cxx::core::concat!("<", ::cxx::core::module_path!(), #prevent_unwind_label); ::cxx::private::prevent_unwind(__fn, || *lhs <= *rhs) } }); @@ -260,10 +315,11 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { 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=> + #cfg_and_lint_attrs #[doc(hidden)] - #[export_name = #link_name] - extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { - let __fn = concat!("<", module_path!(), #prevent_unwind_label); + #[unsafe(export_name = #link_name)] + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> ::cxx::core::primitive::bool { + let __fn = ::cxx::core::concat!("<", ::cxx::core::module_path!(), #prevent_unwind_label); ::cxx::private::prevent_unwind(__fn, || *lhs > *rhs) } }); @@ -272,10 +328,11 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { 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=> + #cfg_and_lint_attrs #[doc(hidden)] - #[export_name = #link_name] - extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool { - let __fn = concat!("<", module_path!(), #prevent_unwind_label); + #[unsafe(export_name = #link_name)] + extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> ::cxx::core::primitive::bool { + let __fn = ::cxx::core::concat!("<", ::cxx::core::module_path!(), #prevent_unwind_label); ::cxx::private::prevent_unwind(__fn, || *lhs >= *rhs) } }); @@ -286,11 +343,12 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { 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=> + #cfg_and_lint_attrs #[doc(hidden)] - #[export_name = #link_name] + #[unsafe(export_name = #link_name)] #[allow(clippy::cast_possible_truncation)] - extern "C" fn #local_name #generics(this: &#ident #generics) -> usize { - let __fn = concat!("<", module_path!(), #prevent_unwind_label); + extern "C" fn #local_name #generics(this: &#ident #generics) -> ::cxx::core::primitive::usize { + let __fn = ::cxx::core::concat!("<", ::cxx::core::module_path!(), #prevent_unwind_label); ::cxx::private::prevent_unwind(__fn, || ::cxx::private::hash(this)) } }); @@ -305,10 +363,13 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream { fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream { let ident = &strct.name.rust; let generics = &strct.generics; + let cfg_and_lint_attrs = strct.attrs.cfg_and_lint(); let span = ident.span(); let impl_token = Token![impl](strct.visibility.span); quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] #impl_token #generics self::Drop for super::#ident #generics {} } } @@ -316,18 +377,19 @@ fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream { fn expand_enum(enm: &Enum) -> TokenStream { let ident = &enm.name.rust; let doc = &enm.doc; - let attrs = &enm.attrs; + let all_attrs = enm.attrs.all(); + let cfg_and_lint_attrs = enm.attrs.cfg_and_lint(); let repr = &enm.repr; let type_id = type_id(&enm.name); let variants = enm.variants.iter().map(|variant| { let doc = &variant.doc; - let attrs = &variant.attrs; + let all_attrs = variant.attrs.all(); let variant_ident = &variant.name.rust; let discriminant = &variant.discriminant; let span = variant_ident.span(); Some(quote_spanned! {span=> #doc - #attrs + #all_attrs #[allow(dead_code)] pub const #variant_ident: Self = #ident { repr: #discriminant }; }) @@ -351,15 +413,18 @@ fn expand_enum(enm: &Enum) -> TokenStream { quote! { #doc #derives - #attrs + #all_attrs #[repr(transparent)] #enum_def + #cfg_and_lint_attrs #[allow(non_upper_case_globals)] impl #ident { #(#variants)* } + #cfg_and_lint_attrs + #[automatically_derived] unsafe impl ::cxx::ExternType for #ident { #[allow(unused_attributes)] // incorrect lint #[doc(hidden)] @@ -374,7 +439,8 @@ fn expand_enum(enm: &Enum) -> TokenStream { fn expand_cxx_type(ety: &ExternType) -> TokenStream { let ident = &ety.name.rust; let doc = &ety.doc; - let attrs = &ety.attrs; + let all_attrs = ety.attrs.all(); + let cfg_and_lint_attrs = ety.attrs.cfg_and_lint(); let generics = &ety.generics; let type_id = type_id(&ety.name); @@ -398,10 +464,12 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream { quote! { #doc - #attrs + #all_attrs #[repr(C)] #extern_type_def + #cfg_and_lint_attrs + #[automatically_derived] unsafe impl #generics ::cxx::ExternType for #ident #generics { #[allow(unused_attributes)] // incorrect lint #[doc(hidden)] @@ -413,18 +481,21 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream { fn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream { let ident = &ety.name.rust; + let cfg_and_lint_attrs = ety.attrs.cfg_and_lint(); let infer = Token![_](ident.span()); let resolve = types.resolve(ident); let lifetimes = resolve.generics.to_underscore_lifetimes(); quote! { + #cfg_and_lint_attrs let _: fn() = { // Derived from https://github.com/nvzqz/static-assertions-rs. trait __AmbiguousIfImpl { fn infer() {} } + #[automatically_derived] impl __AmbiguousIfImpl<()> for T where T: ?::cxx::core::marker::Sized @@ -433,6 +504,7 @@ fn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream #[allow(dead_code)] struct __Invalid; + #[automatically_derived] impl __AmbiguousIfImpl<__Invalid> for T where T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin, @@ -447,11 +519,169 @@ fn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream } } +fn expand_extern_shared_struct(ety: &ExternType, ffi: &Module) -> TokenStream { + let module = &ffi.ident; + let name = &ety.name.rust; + let namespaced_name = display_namespaced(&ety.name); + let cfg_and_lint_attrs = ety.attrs.cfg_and_lint(); + + let visibility = match &ffi.vis { + Visibility::Public(_) => "pub ".to_owned(), + Visibility::Restricted(vis) => { + format!( + "pub(in {}) ", + vis.path + .segments + .iter() + .map(|segment| segment.ident.to_string()) + .collect::>() + .join("::"), + ) + } + Visibility::Inherited => String::new(), + }; + + let namespace_attr = if ety.name.namespace == Namespace::ROOT { + String::new() + } else { + format!( + "#[namespace = \"{}\"]\n ", + ety.name + .namespace + .iter() + .map(Ident::to_string) + .collect::>() + .join("::"), + ) + }; + + let message = format!( + "\ + \nShared struct redeclared as an unsafe extern C++ type is deprecated.\ + \nIf this is intended to be a shared struct, remove this `type {name}`.\ + \nIf this is intended to be an extern type, change it to:\ + \n\ + \n use cxx::ExternType;\ + \n \ + \n #[repr(C)]\ + \n {visibility}struct {name} {{\ + \n ...\ + \n }}\ + \n \ + \n unsafe impl ExternType for {name} {{\ + \n type Id = cxx::type_id!(\"{namespaced_name}\");\ + \n type Kind = cxx::kind::Trivial;\ + \n }}\ + \n \ + \n {visibility}mod {module} {{\ + \n {namespace_attr}extern \"C++\" {{\ + \n type {name} = crate::{name};\ + \n }}\ + \n ...\ + \n }}", + ); + + quote! { + #cfg_and_lint_attrs + #[deprecated = #message] + struct #name {} + + #cfg_and_lint_attrs + let _ = #name {}; + } +} + +fn expand_associated_functions(self_type: &Ident, types: &Types) -> TokenStream { + let Some(functions) = types.associated_fn.get(self_type) else { + return TokenStream::new(); + }; + + let resolve = types.resolve(self_type); + let self_type_cfg_attrs = resolve.attrs.cfg(); + let elided_lifetime = Lifetime::new("'_", Span::call_site()); + let mut group_by_lifetimes = OrderedMap::new(); + let mut tokens = TokenStream::new(); + + for efn in functions { + match efn.lang { + Lang::Cxx | Lang::CxxUnwind => {} + Lang::Rust => continue, + } + let mut impl_lifetimes = Vec::new(); + let mut self_type_lifetimes = Vec::new(); + let self_lt_token; + let self_gt_token; + match &efn.kind { + FnKind::Method(receiver) if receiver.ty.generics.lt_token.is_some() => { + for lifetime in &receiver.ty.generics.lifetimes { + if lifetime.ident != "_" + && efn + .generics + .lifetimes() + .any(|param| param.lifetime == *lifetime) + { + impl_lifetimes.push(lifetime); + } + self_type_lifetimes.push(lifetime); + } + self_lt_token = receiver.ty.generics.lt_token; + self_gt_token = receiver.ty.generics.gt_token; + } + _ => { + self_type_lifetimes.resize(resolve.generics.lifetimes.len(), &elided_lifetime); + self_lt_token = resolve.generics.lt_token; + self_gt_token = resolve.generics.gt_token; + } + } + if efn.undeclared_lifetimes().is_empty() + && self_type_lifetimes.len() == resolve.generics.lifetimes.len() + { + group_by_lifetimes + .entry((impl_lifetimes, self_type_lifetimes)) + .or_insert_with(Vec::new) + .push(efn); + } else { + let impl_token = Token![impl](efn.name.rust.span()); + let impl_lt_token = efn.generics.lt_token; + let impl_gt_token = efn.generics.gt_token; + let self_type = efn.self_type().unwrap(); + let function = expand_cxx_function_shim(efn, types); + tokens.extend(quote! { + #self_type_cfg_attrs + #impl_token #impl_lt_token #(#impl_lifetimes),* #impl_gt_token #self_type #self_lt_token #(#self_type_lifetimes),* #self_gt_token { + #function + } + }); + } + } + + for ((impl_lifetimes, self_type_lifetimes), functions) in &group_by_lifetimes { + let functions = functions + .iter() + .map(|efn| expand_cxx_function_shim(efn, types)); + tokens.extend(quote! { + #self_type_cfg_attrs + impl <#(#impl_lifetimes),*> #self_type <#(#self_type_lifetimes),*> { + #(#functions)* + } + }); + } + + tokens +} + fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream { - let generics = &efn.generics; - let receiver = efn.receiver.iter().map(|receiver| { - let receiver_type = receiver.ty(); - quote!(_: #receiver_type) + let receiver = efn.receiver().into_iter().map(|receiver| { + if types.is_considered_improper_ctype(&receiver.ty) { + if receiver.mutable { + quote!(_: *mut ::cxx::core::ffi::c_void) + } else { + quote!(_: *const ::cxx::core::ffi::c_void) + } + } else { + let receiver_type = receiver.ty(); + quote!(_: #receiver_type) + } }); let args = efn.args.iter().map(|arg| { let var = &arg.name.rust; @@ -473,26 +703,30 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream { let ret = if efn.throws { quote!(-> ::cxx::private::Result) } else { - expand_extern_return_type(&efn.ret, types, true) + expand_extern_return_type(efn, types, true, efn.lang) }; let mut outparam = None; - if indirect_return(efn, types) { + if indirect_return(efn, types, efn.lang) { let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true); outparam = Some(quote!(__return: *mut #ret)); } let link_name = mangle::extern_fn(efn, types); let local_name = format_ident!("__{}", efn.name.rust); + let lt_token = efn.generics.lt_token.unwrap_or_default(); + let undeclared_lifetimes = efn.undeclared_lifetimes().into_iter(); + let declared_lifetimes = &efn.generics.params; + let gt_token = efn.generics.gt_token.unwrap_or_default(); quote! { #[link_name = #link_name] - fn #local_name #generics(#(#all_args,)* #outparam) #ret; + fn #local_name #lt_token #(#undeclared_lifetimes,)* #declared_lifetimes #gt_token(#(#all_args,)* #outparam) #ret; } } fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { let doc = &efn.doc; - let attrs = &efn.attrs; + let all_attrs = efn.attrs.all(); let decl = expand_cxx_function_decl(efn, types); - let receiver = efn.receiver.iter().map(|receiver| { + let receiver = efn.receiver().into_iter().map(|receiver| { let var = receiver.var; if receiver.pinned { let colon = receiver.colon_token; @@ -516,17 +750,30 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { } else { expand_return_type(&efn.ret) }; - let indirect_return = indirect_return(efn, types); - let receiver_var = efn - .receiver - .iter() - .map(|receiver| receiver.var.to_token_stream()); + let indirect_return = indirect_return(efn, types, efn.lang); + let receiver_var = efn.receiver().into_iter().map(|receiver| { + if types.is_considered_improper_ctype(&receiver.ty) { + let var = receiver.var; + let ty = &receiver.ty.rust; + let resolve = types.resolve(ty); + let lifetimes = resolve.generics.to_underscore_lifetimes(); + if receiver.pinned { + quote!(::cxx::core::ptr::from_mut::<#ty #lifetimes>(::cxx::core::pin::Pin::into_inner_unchecked(#var)).cast::<::cxx::core::ffi::c_void>()) + } else if receiver.mutable { + quote!(::cxx::core::ptr::from_mut::<#ty #lifetimes>(#var).cast::<::cxx::core::ffi::c_void>()) + } else { + quote!(::cxx::core::ptr::from_ref::<#ty #lifetimes>(#var).cast::<::cxx::core::ffi::c_void>()) + } + } else { + receiver.var.to_token_stream() + } + }); let arg_vars = efn.args.iter().map(|arg| { let var = &arg.name.rust; let span = var.span(); match &arg.ty { Type::Ident(ident) if ident.rust == RustString => { - quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustString) + quote_spanned!(span=> #var.as_mut_ptr().cast::<::cxx::private::RustString>().cast_const()) } Type::RustBox(ty) => { if types.is_considered_improper_ctype(&ty.inner) { @@ -542,16 +789,12 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var)) } } - Type::RustVec(_) => quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustVec<_>), + Type::RustVec(_) => quote_spanned!(span=> #var.as_mut_ptr().cast::<::cxx::private::RustVec<_>>().cast_const()), Type::Ref(ty) => match &ty.inner { Type::Ident(ident) if ident.rust == RustString => match ty.mutable { false => quote_spanned!(span=> ::cxx::private::RustString::from_ref(#var)), true => quote_spanned!(span=> ::cxx::private::RustString::from_mut(#var)), }, - Type::RustVec(vec) if vec.inner == RustString => match ty.mutable { - false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string(#var)), - true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string(#var)), - }, Type::RustVec(_) => match ty.mutable { false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref(#var)), true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut(#var)), @@ -563,9 +806,9 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { }; match ty.mutable { false => { - quote_spanned!(span=> #var as *const #inner as *const ::cxx::core::ffi::c_void) + quote_spanned!(span=> ::cxx::core::ptr::from_ref::<#inner>(#var).cast::<::cxx::core::ffi::c_void>()) } - true => quote_spanned!(span=> #var as *mut #inner as *mut ::cxx::core::ffi::c_void), + true => quote_spanned!(span=> ::cxx::core::ptr::from_mut::<#inner>(#var).cast::<::cxx::core::ffi::c_void>()), } } _ => quote!(#var), @@ -640,138 +883,109 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { } }; let mut expr; - if efn.throws && efn.sig.ret.is_none() { - expr = call; - } else { - expr = match &efn.ret { - None => call, - Some(ret) => match ret { - Type::Ident(ident) if ident.rust == RustString => { - quote_spanned!(span=> #call.into_string()) - } - Type::RustBox(ty) => { - if types.is_considered_improper_ctype(&ty.inner) { - quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call.cast())) - } else { - quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call)) - } - } - Type::RustVec(vec) => { - if vec.inner == RustString { - quote_spanned!(span=> #call.into_vec_string()) - } else { - quote_spanned!(span=> #call.into_vec()) - } + if let Some(ret) = &efn.ret { + expr = match ret { + Type::Ident(ident) if ident.rust == RustString => { + quote_spanned!(span=> #call.into_string()) + } + Type::RustBox(ty) => { + if types.is_considered_improper_ctype(&ty.inner) { + quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call.cast())) + } else { + quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call)) } - Type::UniquePtr(ty) => { - if types.is_considered_improper_ctype(&ty.inner) { - quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call.cast())) - } else { - quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call)) - } + } + Type::RustVec(_) => { + quote_spanned!(span=> #call.into_vec()) + } + Type::UniquePtr(ty) => { + if types.is_considered_improper_ctype(&ty.inner) { + quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call.cast())) + } else { + quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call)) } - Type::Ref(ty) => match &ty.inner { - Type::Ident(ident) if ident.rust == RustString => match ty.mutable { - false => quote_spanned!(span=> #call.as_string()), - true => quote_spanned!(span=> #call.as_mut_string()), - }, - Type::RustVec(vec) if vec.inner == RustString => match ty.mutable { - false => quote_spanned!(span=> #call.as_vec_string()), - true => quote_spanned!(span=> #call.as_mut_vec_string()), - }, - Type::RustVec(_) => match ty.mutable { - false => quote_spanned!(span=> #call.as_vec()), - true => quote_spanned!(span=> #call.as_mut_vec()), - }, - inner if types.is_considered_improper_ctype(inner) => { - let mutability = ty.mutability; - let deref_mut = quote_spanned!(span=> &#mutability *#call.cast()); - match ty.pinned { - false => deref_mut, - true => { - quote_spanned!(span=> ::cxx::core::pin::Pin::new_unchecked(#deref_mut)) - } - } - } - _ => call, + } + Type::Ref(ty) => match &ty.inner { + Type::Ident(ident) if ident.rust == RustString => match ty.mutable { + false => quote_spanned!(span=> #call.as_string()), + true => quote_spanned!(span=> #call.as_mut_string()), }, - Type::Ptr(ty) => { - if types.is_considered_improper_ctype(&ty.inner) { - quote_spanned!(span=> #call.cast()) - } else { - call - } - } - Type::Str(_) => quote_spanned!(span=> #call.as_str()), - Type::SliceRef(slice) => { - let inner = &slice.inner; - match slice.mutable { - false => quote_spanned!(span=> #call.as_slice::<#inner>()), - true => quote_spanned!(span=> #call.as_mut_slice::<#inner>()), + Type::RustVec(_) => match ty.mutable { + false => quote_spanned!(span=> #call.as_vec()), + true => quote_spanned!(span=> #call.as_mut_vec()), + }, + inner if types.is_considered_improper_ctype(inner) => { + let mutability = ty.mutability; + let deref_mut = quote_spanned!(span=> &#mutability *#call.cast()); + match ty.pinned { + false => deref_mut, + true => { + quote_spanned!(span=> ::cxx::core::pin::Pin::new_unchecked(#deref_mut)) + } } } _ => call, }, + Type::Ptr(ty) => { + if types.is_considered_improper_ctype(&ty.inner) { + quote_spanned!(span=> #call.cast()) + } else { + call + } + } + Type::Str(_) => quote_spanned!(span=> #call.as_str()), + Type::SliceRef(slice) => { + let inner = &slice.inner; + match slice.mutable { + false => quote_spanned!(span=> #call.as_slice::<#inner>()), + true => quote_spanned!(span=> #call.as_mut_slice::<#inner>()), + } + } + _ => call, }; if efn.throws { expr = quote_spanned!(span=> ::cxx::core::result::Result::Ok(#expr)); } - }; - let mut dispatch = quote!(#setup #expr); - let visibility = efn.visibility; - let unsafety = &efn.sig.unsafety; - if unsafety.is_none() { - dispatch = quote_spanned!(span=> unsafe { #dispatch }); + } else if efn.throws { + expr = call; + } else { + expr = quote! { #call; }; } - let fn_token = efn.sig.fn_token; + let dispatch = quote_spanned!(span=> unsafe { #setup #expr }); + let visibility = efn.visibility; + let unsafety = &efn.unsafety; + let fn_token = efn.fn_token; let ident = &efn.name.rust; - let generics = &efn.generics; - let arg_list = quote_spanned!(efn.sig.paren_token.span=> (#(#all_args,)*)); - let fn_body = quote_spanned!(span=> { - extern "C" { - #decl - } - #trampolines - #dispatch - }); - match &efn.receiver { - None => { - quote! { - #doc - #attrs - #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body - } + let lt_token = efn.generics.lt_token; + let lifetimes = { + let mut self_type_lifetimes = UnorderedSet::new(); + if let FnKind::Method(receiver) = &efn.kind { + self_type_lifetimes.extend(&receiver.ty.generics.lifetimes); } - Some(receiver) => { - let elided_generics; - let receiver_ident = &receiver.ty.rust; - let resolve = types.resolve(&receiver.ty); - let receiver_generics = if receiver.ty.generics.lt_token.is_some() { - &receiver.ty.generics - } else { - elided_generics = Lifetimes { - lt_token: resolve.generics.lt_token, - lifetimes: resolve - .generics - .lifetimes - .pairs() - .map(|pair| { - let lifetime = Lifetime::new("'_", pair.value().apostrophe); - let punct = pair.punct().map(|&&comma| comma); - punctuated::Pair::new(lifetime, punct) - }) - .collect(), - gt_token: resolve.generics.gt_token, - }; - &elided_generics - }; - quote_spanned! {ident.span()=> - impl #generics #receiver_ident #receiver_generics { - #doc - #attrs - #visibility #unsafety #fn_token #ident #arg_list #ret #fn_body - } + efn.generics + .params + .pairs() + .filter(move |param| match param.value() { + GenericParam::Lifetime(param) => !self_type_lifetimes.contains(¶m.lifetime), + GenericParam::Type(_) | GenericParam::Const(_) => unreachable!(), + }) + }; + let gt_token = efn.generics.gt_token; + let arg_list = quote_spanned!(efn.paren_token.span=> (#(#all_args,)*)); + let calling_conv = match efn.lang { + Lang::Cxx => quote_spanned!(span=> "C"), + Lang::CxxUnwind => quote_spanned!(span=> "C-unwind"), + Lang::Rust => unreachable!(), + }; + quote_spanned! {span=> + #doc + #all_attrs + #visibility #unsafety #fn_token #ident #lt_token #(#lifetimes)* #gt_token #arg_list #ret { + unsafe extern #calling_conv { + #decl } + #trampolines + #dispatch } } } @@ -798,28 +1012,35 @@ fn expand_function_pointer_trampoline( &efn.attrs, body_span, ); + let calling_conv = match efn.lang { + Lang::Cxx => "C", + Lang::CxxUnwind => "C-unwind", + Lang::Rust => unreachable!(), + }; let var = &var.rust; quote! { let #var = ::cxx::private::FatFunction { trampoline: { - extern "C" { + unsafe extern #calling_conv { #[link_name = #c_trampoline] fn trampoline(); } #shim - trampoline as usize as *const ::cxx::core::ffi::c_void + trampoline as ::cxx::core::primitive::usize as *const ::cxx::core::ffi::c_void }, - ptr: #var as usize as *const ::cxx::core::ffi::c_void, + ptr: #var as ::cxx::core::primitive::usize as *const ::cxx::core::ffi::c_void, }; } } fn expand_rust_type_import(ety: &ExternType) -> TokenStream { let ident = &ety.name.rust; + let all_attrs = ety.attrs.all(); let span = ident.span(); quote_spanned! {span=> + #all_attrs use super::#ident; } } @@ -827,10 +1048,13 @@ fn expand_rust_type_import(ety: &ExternType) -> TokenStream { fn expand_rust_type_impl(ety: &ExternType) -> TokenStream { let ident = &ety.name.rust; let generics = &ety.generics; + let cfg_and_lint_attrs = ety.attrs.cfg_and_lint(); let span = ident.span(); let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl); let mut impls = quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] #[doc(hidden)] #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {} }; @@ -840,6 +1064,8 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream { let type_id = type_id(&ety.name); let span = derive.span; impls.extend(quote_spanned! {span=> + #cfg_and_lint_attrs + #[automatically_derived] unsafe impl #generics ::cxx::ExternType for #ident #generics { #[allow(unused_attributes)] // incorrect lint #[doc(hidden)] @@ -855,19 +1081,14 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream { 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 cxx::core::marker::Unpin - }; + let cfg_and_lint_attrs = ety.attrs.cfg_and_lint(); let resolve = types.resolve(ident); let lifetimes = resolve.generics.to_underscore_lifetimes(); quote_spanned! {ident.span()=> - let _ = { - fn __AssertUnpin() {} - __AssertUnpin::<#ident #lifetimes> - }; + #cfg_and_lint_attrs + const _: fn() = ::cxx::private::require_unpin::<#ident #lifetimes>; } } @@ -881,6 +1102,7 @@ fn expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStream { // required by this bound in `__AssertSized` let ident = &ety.name.rust; + let cfg_and_lint_attrs = ety.attrs.cfg_and_lint(); let begin_span = Token![::](ety.type_token.span); let sized = quote_spanned! {ety.semi_token.span=> #begin_span cxx::core::marker::Sized @@ -896,19 +1118,21 @@ fn expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStream { let lifetimes = resolve.generics.to_underscore_lifetimes(); quote_spanned! {ident.span()=> + #cfg_and_lint_attrs { #[doc(hidden)] + #[allow(clippy::needless_maybe_sized)] fn __AssertSized() -> ::cxx::core::alloc::Layout { ::cxx::core::alloc::Layout::new::() } #[doc(hidden)] - #[export_name = #link_sizeof] - extern "C" fn #local_sizeof() -> usize { + #[unsafe(export_name = #link_sizeof)] + extern "C" fn #local_sizeof() -> ::cxx::core::primitive::usize { __AssertSized::<#ident #lifetimes>().size() } #[doc(hidden)] - #[export_name = #link_alignof] - extern "C" fn #local_alignof() -> usize { + #[unsafe(export_name = #link_alignof)] + extern "C" fn #local_alignof() -> ::cxx::core::primitive::usize { __AssertSized::<#ident #lifetimes>().align() } } @@ -919,6 +1143,7 @@ fn expand_forbid(impls: TokenStream) -> TokenStream { quote! { mod forbid { pub trait Drop {} + #[automatically_derived] #[allow(drop_bounds)] impl self::Drop for T {} #impls @@ -928,13 +1153,13 @@ fn expand_forbid(impls: TokenStream) -> TokenStream { fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { let link_name = mangle::extern_fn(efn, types); - let local_name = match &efn.receiver { + let local_name = match efn.self_type() { None => format_ident!("__{}", efn.name.rust), - Some(receiver) => format_ident!("__{}__{}", receiver.ty.rust, efn.name.rust), + Some(self_type) => format_ident!("__{}__{}", self_type, efn.name.rust), }; - let prevent_unwind_label = match &efn.receiver { + let prevent_unwind_label = match efn.self_type() { None => format!("::{}", efn.name.rust), - Some(receiver) => format!("::{}::{}", receiver.ty.rust, efn.name.rust), + Some(self_type) => format!("::{}::{}", self_type, efn.name.rust), }; let invoke = Some(&efn.name.rust); let body_span = efn.semi_token.span; @@ -962,12 +1187,12 @@ fn expand_rust_function_shim_impl( attrs: &OtherAttrs, body_span: Span, ) -> TokenStream { + let all_attrs = attrs.all(); let generics = outer_generics.unwrap_or(&sig.generics); let receiver_var = sig - .receiver - .as_ref() + .receiver() .map(|receiver| quote_spanned!(receiver.var.span=> __self)); - let receiver = sig.receiver.as_ref().map(|receiver| { + let receiver = sig.receiver().map(|receiver| { let colon = receiver.colon_token; let receiver_type = receiver.ty(); quote!(#receiver_var #colon #receiver_type) @@ -984,39 +1209,44 @@ fn expand_rust_function_shim_impl( }); let all_args = receiver.into_iter().chain(args); + let mut requires_unsafe = false; let arg_vars = sig.args.iter().map(|arg| { let var = &arg.name.rust; let span = var.span(); match &arg.ty { Type::Ident(i) if i.rust == RustString => { + requires_unsafe = true; quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_string())) } - Type::RustBox(_) => quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#var)), - Type::RustVec(vec) => { - if vec.inner == RustString { - quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec_string())) - } else { - quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec())) - } + Type::RustBox(_) => { + requires_unsafe = true; + quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#var)) + } + Type::RustVec(_) => { + requires_unsafe = true; + quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec())) + } + Type::UniquePtr(_) => { + requires_unsafe = true; + quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#var)) } - Type::UniquePtr(_) => quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#var)), Type::Ref(ty) => match &ty.inner { Type::Ident(i) if i.rust == RustString => match ty.mutable { false => quote_spanned!(span=> #var.as_string()), true => quote_spanned!(span=> #var.as_mut_string()), }, - Type::RustVec(vec) if vec.inner == RustString => match ty.mutable { - false => quote_spanned!(span=> #var.as_vec_string()), - true => quote_spanned!(span=> #var.as_mut_vec_string()), - }, Type::RustVec(_) => match ty.mutable { false => quote_spanned!(span=> #var.as_vec()), true => quote_spanned!(span=> #var.as_mut_vec()), }, _ => quote!(#var), }, - Type::Str(_) => quote_spanned!(span=> #var.as_str()), + Type::Str(_) => { + requires_unsafe = true; + quote_spanned!(span=> #var.as_str()) + } Type::SliceRef(slice) => { + requires_unsafe = true; let inner = &slice.inner; match slice.mutable { false => quote_spanned!(span=> #var.as_slice::<#inner>()), @@ -1024,6 +1254,7 @@ fn expand_rust_function_shim_impl( } } ty if types.needs_indirect_abi(ty) => { + requires_unsafe = true; quote_spanned!(span=> ::cxx::core::ptr::read(#var)) } _ => quote!(#var), @@ -1031,8 +1262,6 @@ fn expand_rust_function_shim_impl( }); let vars: Vec<_> = receiver_var.into_iter().chain(arg_vars).collect(); - let wrap_super = invoke.map(|invoke| expand_rust_function_shim_super(sig, &local_name, invoke)); - let mut requires_closure; let mut call = match invoke { Some(_) => { @@ -1041,35 +1270,33 @@ fn expand_rust_function_shim_impl( } None => { requires_closure = true; + requires_unsafe = true; quote!(::cxx::core::mem::transmute::<*const (), #sig>(__extern)) } }; requires_closure |= !vars.is_empty(); call.extend(quote! { (#(#vars),*) }); + let wrap_super = invoke.map(|invoke| { + // If the wrapper function is being passed directly to prevent_unwind, + // it must implement `FnOnce() -> R` and cannot be an unsafe fn. + let unsafety = sig.unsafety.filter(|_| requires_closure); + expand_rust_function_shim_super(sig, &local_name, invoke, unsafety) + }); + let span = body_span; let conversion = sig.ret.as_ref().and_then(|ret| match ret { Type::Ident(ident) if ident.rust == RustString => { Some(quote_spanned!(span=> ::cxx::private::RustString::from)) } 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)) - } else { - Some(quote_spanned!(span=> ::cxx::private::RustVec::from)) - } - } + Type::RustVec(_) => Some(quote_spanned!(span=> ::cxx::private::RustVec::from)), Type::UniquePtr(_) => Some(quote_spanned!(span=> ::cxx::UniquePtr::into_raw)), Type::Ref(ty) => match &ty.inner { Type::Ident(ident) if ident.rust == RustString => match ty.mutable { false => Some(quote_spanned!(span=> ::cxx::private::RustString::from_ref)), true => Some(quote_spanned!(span=> ::cxx::private::RustString::from_mut)), }, - Type::RustVec(vec) if vec.inner == RustString => match ty.mutable { - false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string)), - true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string)), - }, Type::RustVec(_) => match ty.mutable { false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref)), true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut)), @@ -1097,7 +1324,7 @@ fn expand_rust_function_shim_impl( }; let mut outparam = None; - let indirect_return = indirect_return(sig, types); + let indirect_return = indirect_return(sig, types, Lang::Rust); if indirect_return { let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types, false); outparam = Some(quote_spanned!(span=> __return: *mut #ret,)); @@ -1108,12 +1335,18 @@ fn expand_rust_function_shim_impl( None => quote_spanned!(span=> &mut ()), }; requires_closure = true; + requires_unsafe = true; expr = quote_spanned!(span=> ::cxx::private::r#try(#out, #expr)); } else if indirect_return { requires_closure = true; + requires_unsafe = true; expr = quote_spanned!(span=> ::cxx::core::ptr::write(__return, #expr)); } + if requires_unsafe { + expr = quote_spanned!(span=> unsafe { #expr }); + } + let closure = if requires_closure { quote_spanned!(span=> move || #expr) } else { @@ -1125,7 +1358,7 @@ fn expand_rust_function_shim_impl( let ret = if sig.throws { quote!(-> ::cxx::private::Result) } else { - expand_extern_return_type(&sig.ret, types, false) + expand_extern_return_type(sig, types, false, Lang::Rust) }; let pointer = match invoke { @@ -1134,11 +1367,11 @@ fn expand_rust_function_shim_impl( }; quote_spanned! {span=> - #attrs + #all_attrs #[doc(hidden)] - #[export_name = #link_name] + #[unsafe(export_name = #link_name)] unsafe extern "C" fn #local_name #generics(#(#all_args,)* #outparam #pointer) #ret { - let __fn = ::cxx::private::concat!(::cxx::private::module_path!(), #prevent_unwind_label); + let __fn = ::cxx::core::concat!(::cxx::core::module_path!(), #prevent_unwind_label); #wrap_super #expr } @@ -1151,15 +1384,14 @@ fn expand_rust_function_shim_super( sig: &Signature, local_name: &Ident, invoke: &Ident, + unsafety: Option, ) -> TokenStream { - let unsafety = sig.unsafety; let generics = &sig.generics; let receiver_var = sig - .receiver - .as_ref() + .receiver() .map(|receiver| Ident::new("__self", receiver.var.span)); - let receiver = sig.receiver.iter().map(|receiver| { + let receiver = sig.receiver().into_iter().map(|receiver| { let receiver_type = receiver.ty(); quote!(#receiver_var: #receiver_type) }); @@ -1174,7 +1406,7 @@ 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=> ::cxx::core::result::Result<#ok, impl); - let result_end = quote_spanned!(rangle.span=> ::cxx::core::fmt::Display>); + let result_end = quote_spanned!(rangle.span=> ::cxx::core::fmt::Display + use<>>); quote!(-> #result_begin #result_end) } else { expand_return_type(&sig.ret) @@ -1184,24 +1416,29 @@ fn expand_rust_function_shim_super( let vars = receiver_var.iter().chain(arg_vars); let span = invoke.span(); - let call = match &sig.receiver { + let call = match sig.self_type() { None => quote_spanned!(span=> super::#invoke), - Some(receiver) => { - let receiver_type = &receiver.ty.rust; - quote_spanned!(span=> #receiver_type::#invoke) - } + Some(self_type) => quote_spanned!(span=> #self_type::#invoke), }; + let mut body = quote_spanned!(span=> #call(#(#vars,)*)); + let mut allow_unused_unsafe = None; + if sig.unsafety.is_some() { + body = quote_spanned!(span=> unsafe { #body }); + allow_unused_unsafe = Some(quote_spanned!(span=> #[allow(unused_unsafe)])); + } + quote_spanned! {span=> + #allow_unused_unsafe #unsafety fn #local_name #generics(#(#all_args,)*) #ret { - #call(#(#vars,)*) + #body } } } fn expand_type_alias(alias: &TypeAlias) -> TokenStream { let doc = &alias.doc; - let attrs = &alias.attrs; + let all_attrs = alias.attrs.all(); let visibility = alias.visibility; let type_token = alias.type_token; let ident = &alias.name.rust; @@ -1212,12 +1449,13 @@ fn expand_type_alias(alias: &TypeAlias) -> TokenStream { quote! { #doc - #attrs + #all_attrs #visibility #type_token #ident #generics #eq_token #ty #semi_token } } fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream { + let cfg_and_lint_attrs = alias.attrs.cfg_and_lint(); let ident = &alias.name.rust; let type_id = type_id(&alias.name); let begin_span = alias.type_token.span; @@ -1225,14 +1463,177 @@ fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream { let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_type::<); let end = quote_spanned!(end_span=> >); + let resolve = types.resolve(ident); + let lifetimes = resolve.generics.to_underscore_lifetimes(); + let mut verify = quote! { - const _: fn() = #begin #ident, #type_id #end; + #cfg_and_lint_attrs + const _: fn() = #begin #ident #lifetimes, #type_id #end; }; - if types.required_trivial.contains_key(&alias.name.rust) { + let mut require_unpin = false; + let mut require_box = false; + let mut require_vec = false; + let mut require_extern_type_trivial = false; + let mut require_rust_type_or_trivial = None; + if let Some(reasons) = types.required_trivial.get(&alias.name.rust) { + for reason in reasons { + match reason { + TrivialReason::BoxTarget { local: true } + | TrivialReason::VecElement { local: true } => require_unpin = true, + TrivialReason::BoxTarget { local: false } => require_box = true, + TrivialReason::VecElement { local: false } => require_vec = true, + TrivialReason::StructField(_) + | TrivialReason::FunctionArgument(_) + | TrivialReason::FunctionReturn(_) => require_extern_type_trivial = true, + TrivialReason::SliceElement(slice) => require_rust_type_or_trivial = Some(slice), + } + } + } + + 'unpin: { + if let Some(reason) = types.required_unpin.get(ident) { + let ampersand; + let reference_lifetime; + let mutability; + let mut inner; + let generics; + let shorthand; + match reason { + UnpinReason::Receiver(receiver) => { + ampersand = &receiver.ampersand; + reference_lifetime = &receiver.lifetime; + mutability = &receiver.mutability; + inner = receiver.ty.rust.clone(); + generics = &receiver.ty.generics; + shorthand = receiver.shorthand; + if receiver.shorthand { + inner.set_span(receiver.var.span); + } + } + UnpinReason::Ref(mutable_reference) => { + ampersand = &mutable_reference.ampersand; + reference_lifetime = &mutable_reference.lifetime; + mutability = &mutable_reference.mutability; + let Type::Ident(inner_type) = &mutable_reference.inner else { + unreachable!(); + }; + inner = inner_type.rust.clone(); + generics = &inner_type.generics; + shorthand = false; + } + UnpinReason::Slice(mutable_slice) => { + ampersand = &mutable_slice.ampersand; + mutability = &mutable_slice.mutability; + let inner = quote_spanned!(mutable_slice.bracket.span=> [#ident #lifetimes]); + let trait_name = format_ident!("SliceOfUnpin_{ident}"); + let label = format!("requires `{ident}: Unpin`"); + verify.extend(quote! { + #cfg_and_lint_attrs + let _ = { + #[diagnostic::on_unimplemented( + message = "mutable slice of pinned type is not supported", + label = #label, + )] + trait #trait_name { + fn check_unpin() {} + } + #[diagnostic::do_not_recommend] + impl<'a, T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin> #trait_name for &'a #mutability T {} + <#ampersand #mutability #inner as #trait_name>::check_unpin + }; + }); + require_unpin = false; + break 'unpin; + } + } + let trait_name = format_ident!("ReferenceToUnpin_{ident}"); + let message = + format!("mutable reference to C++ type requires a pin -- use Pin<&mut {ident}>"); + let label = { + let mut label = Message::new(); + write!(label, "use `"); + if shorthand { + write!(label, "self: "); + } + write!(label, "Pin<&"); + if let Some(reference_lifetime) = reference_lifetime { + write!(label, "{reference_lifetime} "); + } + write!(label, "mut {ident}"); + if !generics.lifetimes.is_empty() { + write!(label, "<"); + for (i, lifetime) in generics.lifetimes.iter().enumerate() { + if i > 0 { + write!(label, ", "); + } + write!(label, "{lifetime}"); + } + write!(label, ">"); + } else if shorthand && !alias.generics.lifetimes.is_empty() { + write!(label, "<"); + for i in 0..alias.generics.lifetimes.len() { + if i > 0 { + write!(label, ", "); + } + write!(label, "'_"); + } + write!(label, ">"); + } + write!(label, ">`"); + label + }; + let lifetimes = generics.to_underscore_lifetimes(); + verify.extend(quote! { + #cfg_and_lint_attrs + let _ = { + #[diagnostic::on_unimplemented(message = #message, label = #label)] + trait #trait_name { + fn check_unpin() {} + } + #[diagnostic::do_not_recommend] + impl<'a, T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin> #trait_name for &'a mut T {} + <#ampersand #mutability #inner #lifetimes as #trait_name>::check_unpin + }; + }); + require_unpin = false; + } + } + + if require_unpin { + verify.extend(quote! { + #cfg_and_lint_attrs + const _: fn() = ::cxx::private::require_unpin::<#ident #lifetimes>; + }); + } + + if require_box { + verify.extend(quote! { + #cfg_and_lint_attrs + const _: fn() = ::cxx::private::require_box::<#ident #lifetimes>; + }); + } + + if require_vec { + verify.extend(quote! { + #cfg_and_lint_attrs + const _: fn() = ::cxx::private::require_vec::<#ident #lifetimes>; + }); + } + + if require_extern_type_trivial { let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<); verify.extend(quote! { - const _: fn() = #begin #ident, ::cxx::kind::Trivial #end; + #cfg_and_lint_attrs + const _: fn() = #begin #ident #lifetimes, ::cxx::kind::Trivial #end; + }); + } else if let Some(slice_type) = require_rust_type_or_trivial { + let ampersand = &slice_type.ampersand; + let mutability = &slice_type.mutability; + let inner = quote_spanned!(slice_type.bracket.span.join()=> [#ident #lifetimes]); + verify.extend(quote! { + #cfg_and_lint_attrs + let _ = || ::cxx::private::with::<#ident #lifetimes>().check_slice::<#ampersand #mutability #inner>(); }); } @@ -1248,58 +1649,67 @@ fn type_id(name: &Pair) -> TokenStream { crate::type_id::expand(Crate::Cxx, qualified) } -fn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream { - let ident = key.rust; - let resolve = types.resolve(ident); - let link_prefix = format!("cxxbridge1$box${}$", resolve.name.to_symbol()); +fn expand_rust_box( + key: &NamedImplKey, + types: &Types, + conditional_impl: &ConditionalImpl, +) -> TokenStream { + let link_prefix = format!("cxxbridge1$box${}$", key.symbol); let link_alloc = format!("{}alloc", link_prefix); let link_dealloc = format!("{}dealloc", link_prefix); let link_drop = format!("{}drop", link_prefix); - let local_prefix = format_ident!("{}__box_", ident); - let local_alloc = format_ident!("{}alloc", local_prefix); - let local_dealloc = format_ident!("{}dealloc", local_prefix); - let local_drop = format_ident!("{}drop", local_prefix); - - let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve); + let (impl_generics, inner_with_generics) = + generics::split_for_impl(key, conditional_impl, types); - 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 cfg = conditional_impl.cfg.into_attr(); + let begin_span = conditional_impl + .explicit_impl + .map_or(key.begin_span, |explicit| explicit.impl_token.span); + let end_span = conditional_impl + .explicit_impl + .map_or(key.end_span, |explicit| explicit.brace_token.span.join()); let unsafe_token = format_ident!("unsafe", span = begin_span); - let prevent_unwind_drop_label = format!("::{} as Drop>::drop", ident); + let prevent_unwind_type_label = generics::format_for_prevent_unwind_label(key.inner); - quote_spanned! {end_span=> + quote_spanned!(end_span=> { + #cfg + #[automatically_derived] #[doc(hidden)] - #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {} + #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #inner_with_generics {} + + #cfg #[doc(hidden)] - #[export_name = #link_alloc] - unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics> { + #[unsafe(export_name = #link_alloc)] + unsafe extern "C" fn __alloc #impl_generics() -> *mut ::cxx::core::mem::MaybeUninit<#inner_with_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())) + ::cxx::alloc::boxed::Box::into_raw(::cxx::alloc::boxed::Box::new_uninit()) } + + #cfg #[doc(hidden)] - #[export_name = #link_dealloc] - unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics>) { + #[unsafe(export_name = #link_dealloc)] + unsafe extern "C" fn __dealloc #impl_generics(ptr: *mut ::cxx::core::mem::MaybeUninit<#inner_with_generics>) { // No prevent_unwind: the global allocator is not allowed to panic. - let _ = ::cxx::alloc::boxed::Box::from_raw(ptr); + let _ = unsafe { ::cxx::alloc::boxed::Box::from_raw(ptr) }; } + + #cfg #[doc(hidden)] - #[export_name = #link_drop] - 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)); + #[unsafe(export_name = #link_drop)] + unsafe extern "C" fn __drop #impl_generics(this: *mut ::cxx::alloc::boxed::Box<#inner_with_generics>) { + let __fn = ::cxx::core::concat!("<", #prevent_unwind_type_label, " as Drop>::drop"); + ::cxx::private::prevent_unwind(__fn, || unsafe { ::cxx::core::ptr::drop_in_place(this) }); } - } + }) } -fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream { - let elem = key.rust; - let resolve = types.resolve(elem); - let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.name.to_symbol()); +fn expand_rust_vec( + key: &NamedImplKey, + types: &Types, + conditional_impl: &ConditionalImpl, +) -> TokenStream { + let link_prefix = format!("cxxbridge1$rust_vec${}$", key.symbol); let link_new = format!("{}new", link_prefix); let link_drop = format!("{}drop", link_prefix); let link_len = format!("{}len", link_prefix); @@ -1309,86 +1719,109 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl 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); - let local_drop = format_ident!("{}drop", local_prefix); - let local_len = format_ident!("{}len", local_prefix); - let local_capacity = format_ident!("{}capacity", local_prefix); - 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 (impl_generics, inner_with_generics) = + generics::split_for_impl(key, conditional_impl, types); - 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 cfg = conditional_impl.cfg.into_attr(); + let begin_span = conditional_impl + .explicit_impl + .map_or(key.begin_span, |explicit| explicit.impl_token.span); + let end_span = conditional_impl + .explicit_impl + .map_or(key.end_span, |explicit| explicit.brace_token.span.join()); let unsafe_token = format_ident!("unsafe", span = begin_span); - let prevent_unwind_drop_label = format!("::{} as Drop>::drop", elem); + let prevent_unwind_type_label = generics::format_for_prevent_unwind_label(key.inner); - quote_spanned! {end_span=> + quote_spanned!(end_span=> { + #cfg + #[automatically_derived] #[doc(hidden)] - #unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {} + #unsafe_token impl #impl_generics ::cxx::private::ImplVec for #inner_with_generics {} + + #cfg #[doc(hidden)] - #[export_name = #link_new] - unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) { + #[unsafe(export_name = #link_new)] + unsafe extern "C" fn __new #impl_generics(this: *mut ::cxx::private::RustVec<#inner_with_generics>) { // No prevent_unwind: cannot panic. - ::cxx::core::ptr::write(this, ::cxx::private::RustVec::new()); + unsafe { + ::cxx::core::ptr::write(this, ::cxx::private::RustVec::new()); + } } + + #cfg #[doc(hidden)] - #[export_name = #link_drop] - unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) { - let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label); - ::cxx::private::prevent_unwind(__fn, || ::cxx::core::ptr::drop_in_place(this)); + #[unsafe(export_name = #link_drop)] + unsafe extern "C" fn __drop #impl_generics(this: *mut ::cxx::private::RustVec<#inner_with_generics>) { + let __fn = ::cxx::core::concat!("<", #prevent_unwind_type_label, " as Drop>::drop"); + ::cxx::private::prevent_unwind( + __fn, + || unsafe { ::cxx::core::ptr::drop_in_place(this) }, + ); } + + #cfg #[doc(hidden)] - #[export_name = #link_len] - unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize { + #[unsafe(export_name = #link_len)] + unsafe extern "C" fn __len #impl_generics(this: *const ::cxx::private::RustVec<#inner_with_generics>) -> ::cxx::core::primitive::usize { // No prevent_unwind: cannot panic. - (*this).len() + unsafe { (*this).len() } } + + #cfg #[doc(hidden)] - #[export_name = #link_capacity] - unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize { + #[unsafe(export_name = #link_capacity)] + unsafe extern "C" fn __capacity #impl_generics(this: *const ::cxx::private::RustVec<#inner_with_generics>) -> ::cxx::core::primitive::usize { // No prevent_unwind: cannot panic. - (*this).capacity() + unsafe { (*this).capacity() } } + + #cfg #[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 { + #[unsafe(export_name = #link_data)] + unsafe extern "C" fn __data #impl_generics(this: *const ::cxx::private::RustVec<#inner_with_generics>) -> *const #inner_with_generics { // No prevent_unwind: cannot panic. - (*this).as_ptr() + unsafe { (*this).as_ptr() } } + + #cfg #[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) { + #[unsafe(export_name = #link_reserve_total)] + unsafe extern "C" fn __reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#inner_with_generics>, new_cap: ::cxx::core::primitive::usize) { // No prevent_unwind: the global allocator is not allowed to panic. - (*this).reserve_total(new_cap); + unsafe { + (*this).reserve_total(new_cap); + } } + + #cfg #[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) { + #[unsafe(export_name = #link_set_len)] + unsafe extern "C" fn __set_len #impl_generics(this: *mut ::cxx::private::RustVec<#inner_with_generics>, len: ::cxx::core::primitive::usize) { // No prevent_unwind: cannot panic. - (*this).set_len(len); + unsafe { + (*this).set_len(len); + } } + + #cfg #[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)); + #[unsafe(export_name = #link_truncate)] + unsafe extern "C" fn __truncate #impl_generics(this: *mut ::cxx::private::RustVec<#inner_with_generics>, len: ::cxx::core::primitive::usize) { + let __fn = ::cxx::core::concat!("<", #prevent_unwind_type_label, " as Drop>::drop"); + ::cxx::private::prevent_unwind( + __fn, + || unsafe { (*this).truncate(len) }, + ); } - } + }) } fn expand_unique_ptr( - key: NamedImplKey, + key: &NamedImplKey, types: &Types, - explicit_impl: Option<&Impl>, + conditional_impl: &ConditionalImpl, ) -> TokenStream { - let ident = key.rust; - let name = ident.to_string(); - let resolve = types.resolve(ident); - let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.name.to_symbol()); + let prefix = format!("cxxbridge1$unique_ptr${}$", key.symbol); let link_null = format!("{}null", prefix); let link_uninit = format!("{}uninit", prefix); let link_raw = format!("{}raw", prefix); @@ -1396,18 +1829,22 @@ fn expand_unique_ptr( let link_release = format!("{}release", prefix); let link_drop = format!("{}drop", prefix); - let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve); + let name = generics::concise_rust_name(key.inner); + let (impl_generics, inner_with_generics) = + generics::split_for_impl(key, conditional_impl, types); - let can_construct_from_value = types.is_maybe_trivial(ident); + let can_construct_from_value = types.is_maybe_trivial(key.inner); let new_method = if can_construct_from_value { Some(quote! { fn __new(value: Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { - extern "C" { + unsafe extern "C" { #[link_name = #link_uninit] fn __uninit(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void; } let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); - unsafe { __uninit(&mut repr).cast::<#ident #ty_generics>().write(value) } + unsafe { + __uninit(&raw mut repr).cast::<#inner_with_generics>().write(value); + } repr } }) @@ -1415,318 +1852,434 @@ fn expand_unique_ptr( None }; - 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 cfg = conditional_impl.cfg.into_attr(); + let begin_span = conditional_impl + .explicit_impl + .map_or(key.begin_span, |explicit| explicit.impl_token.span); + let end_span = conditional_impl + .explicit_impl + .map_or(key.end_span, |explicit| explicit.brace_token.span.join()); let unsafe_token = format_ident!("unsafe", span = begin_span); quote_spanned! {end_span=> - #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics { + #cfg + #[automatically_derived] + #unsafe_token impl #impl_generics ::cxx::memory::UniquePtrTarget for #inner_with_generics { fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { f.write_str(#name) } fn __null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { - extern "C" { + unsafe extern "C" { #[link_name = #link_null] fn __null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>); } let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); - unsafe { __null(&mut repr) } + unsafe { + __null(&raw mut repr); + } repr } #new_method unsafe fn __raw(raw: *mut Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { - extern "C" { + unsafe extern "C" { #[link_name = #link_raw] fn __raw(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::core::ffi::c_void); } let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); - __raw(&mut repr, raw.cast()); + unsafe { + __raw(&raw mut repr, raw.cast()); + } repr } unsafe fn __get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const Self { - extern "C" { + unsafe extern "C" { #[link_name = #link_get] fn __get(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::core::ffi::c_void; } - __get(&repr).cast() + unsafe { __get(&raw const repr).cast() } } unsafe fn __release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut Self { - extern "C" { + unsafe extern "C" { #[link_name = #link_release] fn __release(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void; } - __release(&mut repr).cast() + unsafe { __release(&raw mut repr).cast() } } unsafe fn __drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) { - extern "C" { + unsafe extern "C" { #[link_name = #link_drop] fn __drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>); } - __drop(&mut repr); + unsafe { + __drop(&raw mut repr); + } } } } } fn expand_shared_ptr( - key: NamedImplKey, + key: &NamedImplKey, types: &Types, - explicit_impl: Option<&Impl>, + conditional_impl: &ConditionalImpl, ) -> TokenStream { - let ident = key.rust; - let name = ident.to_string(); - let resolve = types.resolve(ident); - let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol()); + let prefix = format!("cxxbridge1$shared_ptr${}$", key.symbol); let link_null = format!("{}null", prefix); let link_uninit = format!("{}uninit", prefix); + let link_raw = format!("{}raw", prefix); let link_clone = format!("{}clone", prefix); let link_get = format!("{}get", prefix); let link_drop = format!("{}drop", prefix); - let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve); + let name = generics::concise_rust_name(key.inner); + let (impl_generics, inner_with_generics) = + generics::split_for_impl(key, conditional_impl, types); - let can_construct_from_value = types.is_maybe_trivial(ident); + let can_construct_from_value = types.is_maybe_trivial(key.inner); let new_method = if can_construct_from_value { Some(quote! { unsafe fn __new(value: Self, new: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_uninit] fn __uninit(new: *mut ::cxx::core::ffi::c_void) -> *mut ::cxx::core::ffi::c_void; } - __uninit(new).cast::<#ident #ty_generics>().write(value); + unsafe { + __uninit(new).cast::<#inner_with_generics>().write(value); + } } }) } else { None }; - 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 cfg = conditional_impl.cfg.into_attr(); + let begin_span = conditional_impl + .explicit_impl + .map_or(key.begin_span, |explicit| explicit.impl_token.span); + let end_span = conditional_impl + .explicit_impl + .map_or(key.end_span, |explicit| explicit.brace_token.span.join()); let unsafe_token = format_ident!("unsafe", span = begin_span); + let not_destructible_err = format!( + "{} is not destructible", + generics::concise_cxx_name(key.inner, types), + ); + quote_spanned! {end_span=> - #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics { + #cfg + #[automatically_derived] + #unsafe_token impl #impl_generics ::cxx::memory::SharedPtrTarget for #inner_with_generics { fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { f.write_str(#name) } unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_null] fn __null(new: *mut ::cxx::core::ffi::c_void); } - __null(new); + unsafe { + __null(new); + } } #new_method + #[track_caller] + unsafe fn __raw(new: *mut ::cxx::core::ffi::c_void, raw: *mut Self) { + unsafe extern "C" { + #[link_name = #link_raw] + fn __raw(new: *const ::cxx::core::ffi::c_void, raw: *mut ::cxx::core::ffi::c_void) -> ::cxx::core::primitive::bool; + } + if !unsafe { __raw(new, raw.cast::<::cxx::core::ffi::c_void>()) } { + ::cxx::core::panic!(#not_destructible_err); + } + } unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_clone] fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void); } - __clone(this, new); + unsafe { + __clone(this, new); + } } unsafe fn __get(this: *const ::cxx::core::ffi::c_void) -> *const Self { - extern "C" { + unsafe extern "C" { #[link_name = #link_get] fn __get(this: *const ::cxx::core::ffi::c_void) -> *const ::cxx::core::ffi::c_void; } - __get(this).cast() + unsafe { __get(this).cast() } } unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_drop] fn __drop(this: *mut ::cxx::core::ffi::c_void); } - __drop(this); + unsafe { + __drop(this); + } } } } } -fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream { - let ident = key.rust; - let name = ident.to_string(); - let resolve = types.resolve(ident); - let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.name.to_symbol()); +fn expand_weak_ptr( + key: &NamedImplKey, + types: &Types, + conditional_impl: &ConditionalImpl, +) -> TokenStream { + let prefix = format!("cxxbridge1$weak_ptr${}$", key.symbol); let link_null = format!("{}null", prefix); let link_clone = format!("{}clone", prefix); let link_downgrade = format!("{}downgrade", prefix); let link_upgrade = format!("{}upgrade", prefix); let link_drop = format!("{}drop", 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 name = generics::concise_rust_name(key.inner); + let (impl_generics, inner_with_generics) = + generics::split_for_impl(key, conditional_impl, types); + + let cfg = conditional_impl.cfg.into_attr(); + let begin_span = conditional_impl + .explicit_impl + .map_or(key.begin_span, |explicit| explicit.impl_token.span); + let end_span = conditional_impl + .explicit_impl + .map_or(key.end_span, |explicit| explicit.brace_token.span.join()); let unsafe_token = format_ident!("unsafe", span = begin_span); quote_spanned! {end_span=> - #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics { + #cfg + #[automatically_derived] + #unsafe_token impl #impl_generics ::cxx::memory::WeakPtrTarget for #inner_with_generics { fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { f.write_str(#name) } unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_null] fn __null(new: *mut ::cxx::core::ffi::c_void); } - __null(new); + unsafe { + __null(new); + } } unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_clone] fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void); } - __clone(this, new); + unsafe { + __clone(this, new); + } } unsafe fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_downgrade] fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void); } - __downgrade(shared, weak); + unsafe { + __downgrade(shared, weak); + } } unsafe fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_upgrade] fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void); } - __upgrade(weak, shared); + unsafe { + __upgrade(weak, shared); + } } unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) { - extern "C" { + unsafe extern "C" { #[link_name = #link_drop] fn __drop(this: *mut ::cxx::core::ffi::c_void); } - __drop(this); + unsafe { + __drop(this); + } } } } } fn expand_cxx_vector( - key: NamedImplKey, - explicit_impl: Option<&Impl>, + key: &NamedImplKey, + conditional_impl: &ConditionalImpl, types: &Types, ) -> TokenStream { - let elem = key.rust; - let name = elem.to_string(); - let resolve = types.resolve(elem); - let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol()); + let prefix = format!("cxxbridge1$std$vector${}$", key.symbol); + let link_new = format!("{}new", prefix); let link_size = format!("{}size", prefix); + let link_capacity = format!("{}capacity", prefix); let link_get_unchecked = format!("{}get_unchecked", prefix); + let link_reserve = format!("{}reserve", prefix); let link_push_back = format!("{}push_back", prefix); let link_pop_back = format!("{}pop_back", prefix); - let unique_ptr_prefix = format!( - "cxxbridge1$unique_ptr$std$vector${}$", - resolve.name.to_symbol(), - ); + let unique_ptr_prefix = format!("cxxbridge1$unique_ptr$std$vector${}$", key.symbol); let link_unique_ptr_null = format!("{}null", unique_ptr_prefix); let link_unique_ptr_raw = format!("{}raw", unique_ptr_prefix); let link_unique_ptr_get = format!("{}get", unique_ptr_prefix); let link_unique_ptr_release = format!("{}release", unique_ptr_prefix); let link_unique_ptr_drop = format!("{}drop", unique_ptr_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 name = generics::concise_rust_name(key.inner); + let (impl_generics, inner_with_generics) = + generics::split_for_impl(key, conditional_impl, types); + + let cfg = conditional_impl.cfg.into_attr(); + let begin_span = conditional_impl + .explicit_impl + .map_or(key.begin_span, |explicit| explicit.impl_token.span); + let end_span = conditional_impl + .explicit_impl + .map_or(key.end_span, |explicit| explicit.brace_token.span.join()); let unsafe_token = format_ident!("unsafe", span = begin_span); - let can_pass_element_by_value = types.is_maybe_trivial(elem); + let can_pass_element_by_value = types.is_maybe_trivial(key.inner); let by_value_methods = if can_pass_element_by_value { Some(quote_spanned! {end_span=> unsafe fn __push_back( this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector>, value: &mut ::cxx::core::mem::ManuallyDrop, ) { - extern "C" { + unsafe extern "C" { #[link_name = #link_push_back] fn __push_back #impl_generics( - this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>, + this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#inner_with_generics>>, value: *mut ::cxx::core::ffi::c_void, ); } - __push_back(this, value as *mut ::cxx::core::mem::ManuallyDrop as *mut ::cxx::core::ffi::c_void); + unsafe { + __push_back( + this, + ::cxx::core::ptr::from_mut::<::cxx::core::mem::ManuallyDrop>(value).cast::<::cxx::core::ffi::c_void>(), + ); + } } unsafe fn __pop_back( this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector>, out: &mut ::cxx::core::mem::MaybeUninit, ) { - extern "C" { + unsafe extern "C" { #[link_name = #link_pop_back] fn __pop_back #impl_generics( - this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>, + this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#inner_with_generics>>, out: *mut ::cxx::core::ffi::c_void, ); } - __pop_back(this, out as *mut ::cxx::core::mem::MaybeUninit as *mut ::cxx::core::ffi::c_void); + unsafe { + __pop_back( + this, + ::cxx::core::ptr::from_mut::<::cxx::core::mem::MaybeUninit>(out).cast::<::cxx::core::ffi::c_void>(), + ); + } } }) } else { None }; + let not_move_constructible_err = format!( + "{} is not move constructible", + generics::concise_cxx_name(key.inner, types), + ); + quote_spanned! {end_span=> - #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics { + #cfg + #[automatically_derived] + #unsafe_token impl #impl_generics ::cxx::vector::VectorElement for #inner_with_generics { fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result { f.write_str(#name) } - fn __vector_size(v: &::cxx::CxxVector) -> usize { - extern "C" { + fn __vector_new() -> *mut ::cxx::CxxVector { + unsafe extern "C" { + #[link_name = #link_new] + fn __vector_new #impl_generics() -> *mut ::cxx::CxxVector<#inner_with_generics>; + } + unsafe { __vector_new() } + } + fn __vector_size(v: &::cxx::CxxVector) -> ::cxx::core::primitive::usize { + unsafe extern "C" { #[link_name = #link_size] - fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize; + fn __vector_size #impl_generics(_: &::cxx::CxxVector<#inner_with_generics>) -> ::cxx::core::primitive::usize; } unsafe { __vector_size(v) } } - unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector, pos: usize) -> *mut Self { - extern "C" { + fn __vector_capacity(v: &::cxx::CxxVector) -> ::cxx::core::primitive::usize { + unsafe extern "C" { + #[link_name = #link_capacity] + fn __vector_capacity #impl_generics(_: &::cxx::CxxVector<#inner_with_generics>) -> ::cxx::core::primitive::usize; + } + unsafe { __vector_capacity(v) } + } + unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector, pos: ::cxx::core::primitive::usize) -> *mut Self { + unsafe extern "C" { #[link_name = #link_get_unchecked] fn __get_unchecked #impl_generics( - v: *mut ::cxx::CxxVector<#elem #ty_generics>, - pos: usize, + v: *mut ::cxx::CxxVector<#inner_with_generics>, + pos: ::cxx::core::primitive::usize, ) -> *mut ::cxx::core::ffi::c_void; } - __get_unchecked(v, pos) as *mut Self + unsafe { __get_unchecked(v, pos).cast::() } + } + unsafe fn __reserve(v: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector>, new_cap: ::cxx::core::primitive::usize) { + unsafe extern "C" { + #[link_name = #link_reserve] + fn __reserve #impl_generics( + v: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#inner_with_generics>>, + new_cap: ::cxx::core::primitive::usize, + ) -> ::cxx::core::primitive::bool; + } + if !unsafe { __reserve(v, new_cap) } { + ::cxx::core::panic!(#not_move_constructible_err); + } } #by_value_methods fn __unique_ptr_null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { - extern "C" { + unsafe extern "C" { #[link_name = #link_unique_ptr_null] fn __unique_ptr_null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>); } let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); - unsafe { __unique_ptr_null(&mut repr) } + unsafe { + __unique_ptr_null(&raw mut repr); + } repr } unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> { - extern "C" { + unsafe extern "C" { #[link_name = #link_unique_ptr_raw] - 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>); + fn __unique_ptr_raw #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::CxxVector<#inner_with_generics>); } let mut repr = ::cxx::core::mem::MaybeUninit::uninit(); - __unique_ptr_raw(&mut repr, raw); + unsafe { + __unique_ptr_raw(&raw mut repr, raw); + } repr } unsafe fn __unique_ptr_get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector { - extern "C" { + unsafe extern "C" { #[link_name = #link_unique_ptr_get] - fn __unique_ptr_get #impl_generics(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::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<#inner_with_generics>; } - __unique_ptr_get(&repr) + unsafe { __unique_ptr_get(&raw const repr) } } unsafe fn __unique_ptr_release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector { - extern "C" { + unsafe extern "C" { #[link_name = #link_unique_ptr_release] - fn __unique_ptr_release #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::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<#inner_with_generics>; } - __unique_ptr_release(&mut repr) + unsafe { __unique_ptr_release(&raw mut repr) } } unsafe fn __unique_ptr_drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) { - extern "C" { + unsafe extern "C" { #[link_name = #link_unique_ptr_drop] fn __unique_ptr_drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>); } - __unique_ptr_drop(&mut repr); + unsafe { + __unique_ptr_drop(&raw mut repr); + } } } } @@ -1739,10 +2292,15 @@ fn expand_return_type(ret: &Option) -> TokenStream { } } -fn indirect_return(sig: &Signature, types: &Types) -> bool { - sig.ret - .as_ref() - .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret)) +fn indirect_return(sig: &Signature, types: &Types, lang: Lang) -> bool { + sig.ret.as_ref().is_some_and(|ret| { + sig.throws + || types.needs_indirect_abi(ret) + || match lang { + Lang::Cxx | Lang::CxxUnwind => types.contains_elided_lifetime(ret), + Lang::Rust => false, + } + }) } fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream { @@ -1761,9 +2319,13 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream { } } Type::RustVec(ty) => { + // Replace Vec with ::cxx::private::RustVec. Both have the + // same layout but only the latter has a predictable ABI. Note that + // the overall size and alignment are independent of the element + // type, but the field order inside of Vec may not be. let span = ty.name.span(); let langle = ty.langle; - let elem = expand_extern_type(&ty.inner, types, proper); + let elem = &ty.inner; let rangle = ty.rangle; quote_spanned!(span=> ::cxx::private::RustVec #langle #elem #rangle) } @@ -1779,7 +2341,7 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream { Type::RustVec(ty) => { let span = ty.name.span(); let langle = ty.langle; - let inner = expand_extern_type(&ty.inner, types, proper); + let inner = &ty.inner; let rangle = ty.rangle; quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustVec #langle #inner #rangle) } @@ -1796,9 +2358,8 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream { Type::Ptr(ty) => { if proper && types.is_considered_improper_ctype(&ty.inner) { let star = ty.star; - let mutability = ty.mutability; - let constness = ty.constness; - quote!(#star #mutability #constness ::cxx::core::ffi::c_void) + let mutability = &ty.mutability; + quote!(#star #mutability ::cxx::core::ffi::c_void) } else { quote!(#ty) } @@ -1810,18 +2371,38 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream { } Type::SliceRef(ty) => { let span = ty.ampersand.span; - let rust_slice = Ident::new("RustSlice", ty.bracket.span); + let rust_slice = Ident::new("RustSlice", ty.bracket.span.join()); quote_spanned!(span=> ::cxx::private::#rust_slice) } _ => quote!(#ty), } } -fn expand_extern_return_type(ret: &Option, types: &Types, proper: bool) -> TokenStream { - let ret = match ret { - Some(ret) if !types.needs_indirect_abi(ret) => ret, +fn expand_extern_return_type( + sig: &Signature, + types: &Types, + proper: bool, + lang: Lang, +) -> TokenStream { + let ret = match &sig.ret { + Some(ret) if !indirect_return(sig, types, lang) => ret, _ => return TokenStream::new(), }; let ty = expand_extern_type(ret, types, proper); quote!(-> #ty) } + +pub(crate) fn display_namespaced(name: &Pair) -> impl Display + '_ { + struct Namespaced<'a>(&'a Pair); + + impl<'a> Display for Namespaced<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + for segment in &self.0.namespace { + write!(formatter, "{segment}::")?; + } + write!(formatter, "{}", self.0.cxx) + } + } + + Namespaced(name) +} diff --git a/macro/src/generics.rs b/macro/src/generics.rs index 7862536d0..0ba0a8e2c 100644 --- a/macro/src/generics.rs +++ b/macro/src/generics.rs @@ -1,73 +1,138 @@ +use crate::expand::display_namespaced; use crate::syntax::instantiate::NamedImplKey; -use crate::syntax::resolve::Resolution; -use crate::syntax::{Impl, Lifetimes}; +use crate::syntax::types::ConditionalImpl; +use crate::syntax::{Lifetimes, Type, Types}; use proc_macro2::TokenStream; -use quote::ToTokens; +use quote::{ToTokens, quote}; use syn::{Lifetime, Token}; -pub struct ImplGenerics<'a> { - explicit_impl: Option<&'a Impl>, - resolve: Resolution<'a>, +pub(crate) struct ResolvedGenericType<'a> { + ty: &'a Type, + explicit_impl: bool, + types: &'a Types<'a>, } -pub struct TyGenerics<'a> { - key: NamedImplKey<'a>, - explicit_impl: Option<&'a Impl>, - resolve: Resolution<'a>, -} - -pub fn split_for_impl<'a>( - key: NamedImplKey<'a>, - explicit_impl: Option<&'a Impl>, - resolve: Resolution<'a>, -) -> (ImplGenerics<'a>, TyGenerics<'a>) { - let impl_generics = ImplGenerics { - explicit_impl, - resolve, +/// Gets `(impl_generics, inner_with_generics)` pair that can be used when +/// generating an `impl` for a generic type: +/// +/// ```ignore +/// quote! { impl #impl_generics SomeTrait for #inner_with_generics } +/// ``` +pub(crate) fn split_for_impl<'a>( + key: &NamedImplKey<'a>, + conditional_impl: &ConditionalImpl<'a>, + types: &'a Types<'a>, +) -> (&'a Lifetimes, ResolvedGenericType<'a>) { + let impl_generics = if let Some(explicit_impl) = conditional_impl.explicit_impl { + &explicit_impl.impl_generics + } else { + get_impl_generics(key.inner, types) }; - let ty_generics = TyGenerics { - key, - explicit_impl, - resolve, + let ty_generics = ResolvedGenericType { + ty: key.inner, + explicit_impl: conditional_impl.explicit_impl.is_some(), + types, }; (impl_generics, ty_generics) } -impl<'a> ToTokens for ImplGenerics<'a> { +impl<'a> ToTokens for ResolvedGenericType<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { - if let Some(imp) = self.explicit_impl { - imp.impl_generics.to_tokens(tokens); - } else { - self.resolve.generics.to_tokens(tokens); + match self.ty { + Type::Ident(named_type) => { + named_type.rust.to_tokens(tokens); + if self.explicit_impl { + named_type.generics.to_tokens(tokens); + } else { + let resolve = self.types.resolve(named_type); + if !resolve.generics.lifetimes.is_empty() { + let span = named_type.rust.span(); + named_type + .generics + .lt_token + .unwrap_or_else(|| Token![<](span)) + .to_tokens(tokens); + resolve.generics.lifetimes.to_tokens(tokens); + named_type + .generics + .gt_token + .unwrap_or_else(|| Token![>](span)) + .to_tokens(tokens); + } + } + } + Type::RustBox(ty1) => { + let inner = ResolvedGenericType { + ty: &ty1.inner, + explicit_impl: self.explicit_impl, + types: self.types, + }; + tokens.extend(quote! { + ::cxx::alloc::boxed::Box<#inner> + }); + } + _ => unreachable!("syntax/check.rs should reject other types"), } } } -impl<'a> ToTokens for TyGenerics<'a> { - fn to_tokens(&self, tokens: &mut TokenStream) { - if let Some(imp) = self.explicit_impl { - imp.ty_generics.to_tokens(tokens); - } else if !self.resolve.generics.lifetimes.is_empty() { - let span = self.key.rust.span(); - self.key - .lt_token - .unwrap_or_else(|| Token![<](span)) - .to_tokens(tokens); - self.resolve.generics.lifetimes.to_tokens(tokens); - self.key - .gt_token - .unwrap_or_else(|| Token![>](span)) - .to_tokens(tokens); +fn get_impl_generics<'a>(ty: &Type, types: &Types<'a>) -> &'a Lifetimes { + match ty { + Type::Ident(named_type) => types.resolve(named_type).generics, + Type::RustBox(ty1) => get_impl_generics(&ty1.inner, types), + _ => unreachable!("syntax/check.rs should reject other types"), + } +} + +pub(crate) fn format_for_prevent_unwind_label(ty: &Type) -> TokenStream { + match ty { + Type::Ident(named_type) => { + let rust_name = named_type.rust.to_string(); + quote! { + ::cxx::core::concat!(::cxx::core::module_path!(), "::", #rust_name) + } + } + Type::RustBox(ty1) => { + let inner = format_for_prevent_unwind_label(&ty1.inner); + quote! { + ::cxx::core::concat!("Box<", #inner, ">") + } + } + _ => unreachable!("syntax/check.rs should reject other types"), + } +} + +pub(crate) fn concise_rust_name(ty: &Type) -> String { + match ty { + Type::Ident(named_type) => named_type.rust.to_string(), + Type::RustBox(ty1) => { + let inner = concise_rust_name(&ty1.inner); + format!("Box<{inner}>") + } + _ => unreachable!("syntax/check.rs should reject other types"), + } +} + +pub(crate) fn concise_cxx_name(ty: &Type, types: &Types) -> String { + match ty { + Type::Ident(named_type) => { + let res = types.resolve(&named_type.rust); + display_namespaced(res.name).to_string() + } + Type::RustBox(ty1) => { + let inner = concise_cxx_name(&ty1.inner, types); + format!("rust::Box<{inner}>") } + _ => unreachable!("syntax/check.rs should reject other types"), } } -pub struct UnderscoreLifetimes<'a> { +pub(crate) struct UnderscoreLifetimes<'a> { generics: &'a Lifetimes, } impl Lifetimes { - pub fn to_underscore_lifetimes(&self) -> UnderscoreLifetimes { + pub(crate) fn to_underscore_lifetimes(&self) -> UnderscoreLifetimes { UnderscoreLifetimes { generics: self } } } diff --git a/macro/src/lib.rs b/macro/src/lib.rs index 138e3a299..4ef66b18a 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -1,48 +1,45 @@ #![allow( + clippy::assert_is_empty, clippy::cast_sign_loss, - clippy::default_trait_access, - clippy::derive_partial_eq_without_eq, clippy::doc_markdown, + clippy::elidable_lifetime_names, clippy::enum_glob_use, - clippy::if_same_then_else, + clippy::expl_impl_clone_on_copy, // https://github.com/rust-lang/rust-clippy/issues/15842 clippy::inherent_to_string, clippy::items_after_statements, - clippy::large_enum_variant, clippy::match_bool, + clippy::match_like_matches_macro, clippy::match_same_arms, - clippy::module_name_repetitions, + clippy::needless_late_init, + clippy::needless_lifetimes, clippy::needless_pass_by_value, - clippy::new_without_default, clippy::nonminimal_bool, - clippy::option_if_let_else, - clippy::or_fun_call, + clippy::precedence, clippy::redundant_else, - clippy::shadow_unrelated, + clippy::ref_option, clippy::similar_names, - clippy::single_match, clippy::single_match_else, + clippy::struct_field_names, clippy::too_many_arguments, clippy::too_many_lines, clippy::toplevel_ref_arg, - clippy::useless_let_if_seq, - // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983 + clippy::uninlined_format_args, clippy::wrong_self_convention )] +#![cfg_attr(test, allow(dead_code, unfulfilled_lint_expectations))] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] -extern crate proc_macro; - +mod attrs; +mod cfg; mod derive; mod expand; mod generics; mod syntax; +#[cfg(test)] +mod tests; mod tokens; mod type_id; -#[cfg(feature = "experimental-enum-variants-from-header")] -mod clang; -#[cfg(feature = "experimental-enum-variants-from-header")] -mod load; - use crate::syntax::file::Module; use crate::syntax::namespace::Namespace; use crate::syntax::qualified::QualifiedName; diff --git a/macro/src/load.rs b/macro/src/load.rs deleted file mode 100644 index dccece44b..000000000 --- a/macro/src/load.rs +++ /dev/null @@ -1,317 +0,0 @@ -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}; -use flate2::write::GzDecoder; -use memmap::Mmap; -use proc_macro2::{Delimiter, Group, Ident, TokenStream}; -use quote::{format_ident, quote, quote_spanned}; -use std::env; -use std::fmt::{self, Display}; -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; -use std::str::FromStr; -use syn::{parse_quote, Path}; - -const CXX_CLANG_AST: &str = "CXX_CLANG_AST"; - -pub fn load(cx: &mut Errors, apis: &mut [Api]) { - let ref mut variants_from_header = Vec::new(); - for api in apis { - if let Api::Enum(enm) = api { - if enm.variants_from_header { - if enm.variants.is_empty() { - variants_from_header.push(enm); - } else { - let span = span_for_enum_error(enm); - cx.error( - span, - "enum with #![variants_from_header] must be written with no explicit variants", - ); - } - } - } - } - - let span = match variants_from_header.get(0) { - None => return, - Some(enm) => enm.variants_from_header_attr.clone().unwrap(), - }; - - let ast_dump_path = match env::var_os(CXX_CLANG_AST) { - Some(ast_dump_path) => PathBuf::from(ast_dump_path), - None => { - let msg = format!( - "environment variable ${} has not been provided", - CXX_CLANG_AST, - ); - return cx.error(span, msg); - } - }; - - let memmap = File::open(&ast_dump_path).and_then(|file| unsafe { Mmap::map(&file) }); - let mut gunzipped; - let ast_dump_bytes = match match memmap { - Ok(ref memmap) => { - 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); - decode_result.map(|_| gunzipped.as_slice()) - } else { - Ok(memmap as &[u8]) - } - } - Err(error) => Err(error), - } { - Ok(bytes) => bytes, - Err(error) => { - let msg = format!("failed to read {}: {}", ast_dump_path.display(), error); - return cx.error(span, msg); - } - }; - - let ref root: Node = match serde_json::from_slice(ast_dump_bytes) { - Ok(root) => root, - Err(error) => { - let msg = format!("failed to read {}: {}", ast_dump_path.display(), error); - return cx.error(span, msg); - } - }; - - let ref mut namespace = Vec::new(); - traverse(cx, root, namespace, variants_from_header, None); - - for enm in variants_from_header { - if enm.variants.is_empty() { - let span = &enm.variants_from_header_attr; - let name = CxxName(&enm.name); - let msg = format!("failed to find any C++ definition of enum {}", name); - cx.error(span, msg); - } - } -} - -fn traverse<'a>( - cx: &mut Errors, - node: &'a Node, - namespace: &mut Vec<&'a str>, - variants_from_header: &mut [&mut Enum], - mut idx: Option, -) { - match &node.kind { - Clang::NamespaceDecl(decl) => { - let name = match &decl.name { - Some(name) => name, - // Can ignore enums inside an anonymous namespace. - None => return, - }; - namespace.push(name); - idx = None; - } - Clang::EnumDecl(decl) => { - let name = match &decl.name { - Some(name) => name, - None => return, - }; - idx = None; - for (i, enm) in variants_from_header.iter_mut().enumerate() { - if enm.name.cxx == **name && enm.name.namespace.iter().eq(&*namespace) { - if !enm.variants.is_empty() { - let span = &enm.variants_from_header_attr; - let qual_name = CxxName(&enm.name); - let msg = format!("found multiple C++ definitions of enum {}", qual_name); - cx.error(span, msg); - return; - } - let fixed_underlying_type = match &decl.fixed_underlying_type { - Some(fixed_underlying_type) => fixed_underlying_type, - None => { - let span = &enm.variants_from_header_attr; - let name = &enm.name.cxx; - let qual_name = CxxName(&enm.name); - let msg = format!( - "implicit implementation-defined repr for enum {} is not supported yet; consider changing its C++ definition to `enum {}: int {{...}}", - qual_name, name, - ); - cx.error(span, msg); - return; - } - }; - let repr = translate_qual_type( - cx, - enm, - fixed_underlying_type - .desugared_qual_type - .as_ref() - .unwrap_or(&fixed_underlying_type.qual_type), - ); - enm.repr = EnumRepr::Foreign { rust_type: repr }; - idx = Some(i); - break; - } - } - if idx.is_none() { - return; - } - } - Clang::EnumConstantDecl(decl) => { - if let Some(idx) = idx { - let enm = &mut *variants_from_header[idx]; - let span = enm - .variants_from_header_attr - .as_ref() - .unwrap() - .path - .get_ident() - .unwrap() - .span(); - let cxx_name = match ForeignName::parse(&decl.name, span) { - Ok(foreign_name) => foreign_name, - Err(_) => { - let span = &enm.variants_from_header_attr; - let msg = format!("unsupported C++ variant name: {}", decl.name); - return cx.error(span, msg); - } - }; - let rust_name: Ident = match syn::parse_str(&decl.name) { - Ok(ident) => ident, - Err(_) => format_ident!("__Variant{}", enm.variants.len()), - }; - let discriminant = match discriminant_value(&node.inner) { - ParsedDiscriminant::Constant(discriminant) => discriminant, - ParsedDiscriminant::Successor => match enm.variants.last() { - None => Discriminant::zero(), - Some(last) => match last.discriminant.checked_succ() { - Some(discriminant) => discriminant, - None => { - let span = &enm.variants_from_header_attr; - let msg = format!( - "overflow processing discriminant value for variant: {}", - decl.name, - ); - return cx.error(span, msg); - } - }, - }, - ParsedDiscriminant::Fail => { - let span = &enm.variants_from_header_attr; - let msg = format!( - "failed to obtain discriminant value for variant: {}", - decl.name, - ); - cx.error(span, msg); - Discriminant::zero() - } - }; - enm.variants.push(Variant { - cfg: CfgExpr::Unconditional, - doc: Doc::new(), - attrs: OtherAttrs::none(), - name: Pair { - namespace: Namespace::ROOT, - cxx: cxx_name, - rust: rust_name, - }, - discriminant, - expr: None, - }); - } - } - _ => {} - } - for inner in &node.inner { - traverse(cx, inner, namespace, variants_from_header, idx); - } - if let Clang::NamespaceDecl(_) = &node.kind { - let _ = namespace.pop().unwrap(); - } -} - -fn translate_qual_type(cx: &mut Errors, enm: &Enum, qual_type: &str) -> Path { - let rust_std_name = match qual_type { - "char" => "c_char", - "int" => "c_int", - "long" => "c_long", - "long long" => "c_longlong", - "signed char" => "c_schar", - "short" => "c_short", - "unsigned char" => "c_uchar", - "unsigned int" => "c_uint", - "unsigned long" => "c_ulong", - "unsigned long long" => "c_ulonglong", - "unsigned short" => "c_ushort", - unsupported => { - let span = &enm.variants_from_header_attr; - let qual_name = CxxName(&enm.name); - let msg = format!( - "unsupported underlying type for {}: {}", - qual_name, unsupported, - ); - cx.error(span, msg); - "c_int" - } - }; - let span = enm - .variants_from_header_attr - .as_ref() - .unwrap() - .path - .get_ident() - .unwrap() - .span(); - let ident = Ident::new(rust_std_name, span); - let path = quote_spanned!(span=> ::cxx::core::ffi::#ident); - parse_quote!(#path) -} - -enum ParsedDiscriminant { - Constant(Discriminant), - Successor, - Fail, -} - -fn discriminant_value(mut clang: &[Node]) -> ParsedDiscriminant { - if clang.is_empty() { - // No discriminant expression provided; use successor of previous - // descriminant. - return ParsedDiscriminant::Successor; - } - - loop { - if clang.len() != 1 { - return ParsedDiscriminant::Fail; - } - - let node = &clang[0]; - match &node.kind { - Clang::ImplicitCastExpr => clang = &node.inner, - Clang::ConstantExpr(expr) => match Discriminant::from_str(&expr.value) { - Ok(discriminant) => return ParsedDiscriminant::Constant(discriminant), - Err(_) => return ParsedDiscriminant::Fail, - }, - _ => return ParsedDiscriminant::Fail, - } - } -} - -fn span_for_enum_error(enm: &Enum) -> TokenStream { - let enum_token = enm.enum_token; - let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new()); - brace_token.set_span(enm.brace_token.span); - quote!(#enum_token #brace_token) -} - -struct CxxName<'a>(&'a Pair); - -impl<'a> Display for CxxName<'a> { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - for namespace in &self.0.namespace { - write!(formatter, "{}::", namespace)?; - } - write!(formatter, "{}", self.0.cxx) - } -} diff --git a/macro/src/tests.rs b/macro/src/tests.rs new file mode 100644 index 000000000..6be44eef3 --- /dev/null +++ b/macro/src/tests.rs @@ -0,0 +1,181 @@ +use crate::expand; +use crate::syntax::file::Module; +use proc_macro2::TokenStream; +use quote::quote; +use syn::File; + +fn bridge(cxx_bridge: TokenStream) -> String { + let module = syn::parse2::(cxx_bridge).unwrap(); + let tokens = expand::bridge(module).unwrap(); + let file = match syn::parse2::(tokens.clone()) { + Ok(file) => file, + Err(err) => { + eprintln!("The code below is syntactically invalid: {err}:"); + eprintln!("{tokens}"); + panic!("`expand::bridge` should generate syntactically valid code"); + } + }; + let pretty = prettyplease::unparse(&file); + eprintln!("{0:/<80}\n{pretty}{0:/<80}", ""); + pretty +} + +#[test] +fn test_unique_ptr_with_elided_lifetime_implicit_impl() { + let rs = bridge(quote! { + mod ffi { + unsafe extern "C++" { + type Borrowed<'a>; + fn borrowed(arg: &i32) -> UniquePtr; + } + } + }); + + // It is okay that the return type elides Borrowed's lifetime parameter. + assert!(rs.contains("pub fn borrowed(arg: &i32) -> ::cxx::UniquePtr")); + + // But in impl blocks, the lifetime parameter needs to be present. + assert!(rs.contains("unsafe impl<'a> ::cxx::ExternType for Borrowed<'a> {")); + assert!(rs.contains("unsafe impl<'a> ::cxx::memory::UniquePtrTarget for Borrowed<'a> {")); + + // Wrong. + assert!(!rs.contains("unsafe impl ::cxx::ExternType for Borrowed {")); + assert!(!rs.contains("unsafe impl ::cxx::memory::UniquePtrTarget for Borrowed {")); + + // Potentially okay, but not what we currently do. + assert!(!rs.contains("unsafe impl ::cxx::ExternType for Borrowed<'_> {")); + assert!(!rs.contains("unsafe impl ::cxx::memory::UniquePtrTarget for Borrowed<'_> {")); +} + +#[test] +fn test_unique_ptr_lifetimes_from_explicit_impl() { + let rs = bridge(quote! { + mod ffi { + unsafe extern "C++" { + type Borrowed<'a>; + } + impl<'b> UniquePtr> {} + } + }); + + // Lifetimes use the name from the extern type. + assert!(rs.contains("unsafe impl<'a> ::cxx::ExternType for Borrowed<'a>")); + + // Lifetimes use the names written in the explicit impl if one is present. + assert!(rs.contains("unsafe impl<'b> ::cxx::memory::UniquePtrTarget for Borrowed<'c>")); +} + +#[test] +fn test_vec_string() { + let rs = bridge(quote! { + mod ffi { + extern "Rust" { + fn foo() -> Vec; + } + } + }); + + // No substitution of String <=> ::cxx::private::RustString. + assert!(rs.contains("__return: *mut ::cxx::private::RustVec<::cxx::alloc::string::String>")); + assert!(rs.contains("fn __foo() -> ::cxx::alloc::vec::Vec<::cxx::alloc::string::String>")); + + let rs = bridge(quote! { + mod ffi { + extern "Rust" { + fn foo(v: &Vec); + } + } + }); + + // No substitution of String <=> ::cxx::private::RustString. + assert!(rs.contains("v: &::cxx::private::RustVec<::cxx::alloc::string::String>")); + assert!(rs.contains("fn __foo(v: &::cxx::alloc::vec::Vec<::cxx::alloc::string::String>)")); +} + +#[test] +fn test_mangling_covers_cpp_namespace_of_vec_elements() { + let rs = bridge(quote! { + mod ffi { + #[namespace = "test_namespace"] + struct Context { x: i32 } + impl Vec {} + } + }); + + // Mangling must include Context's C++ namespace to avoid colliding the + // symbol names for two identically named structs in different namespaces. + assert!(rs.contains("export_name = \"cxxbridge1$rust_vec$test_namespace$Context$set_len\"")); +} + +#[test] +fn test_struct_with_lifetime() { + let rs = bridge(quote! { + mod ffi { + struct StructWithLifetime<'a> { + s: &'a str, + } + extern "Rust" { + fn f(_: UniquePtr>); + } + } + }); + + // Regression test for + // which generated this invalid code: + // + // impl<'a> ::cxx::memory::UniquePtrTarget for StructWithLifetime < > < 'a > { + // + // Invalid syntax in the output code would already have caused the test + // helper `bridge` to panic above. But for completeness this assertion + // verifies the intended code has been generated. + assert!(rs.contains("impl<'a> ::cxx::memory::UniquePtrTarget for StructWithLifetime<'a> {")); + + // Assertions for other places that refer to `StructWithLifetime`. + assert!(rs.contains("pub struct StructWithLifetime<'a> {")); + assert!(rs.contains("cast::>()")); + assert!(rs.contains("fn __f(arg0: ::cxx::UniquePtr) {")); + assert!(rs.contains("impl<'a> self::Drop for super::StructWithLifetime<'a>")); +} + +#[test] +fn test_original_lifetimes_used_in_impls() { + let rs = bridge(quote! { + mod ffi { + struct Context<'sess> { + session: &'sess str, + } + struct Server<'srv> { + ctx: UniquePtr>, + } + struct Client<'clt> { + ctx: UniquePtr>, + } + } + }); + + // Verify which lifetime name ('sess, 'srv, 'clt) gets used for this impl. + assert!(rs.contains("impl<'sess> ::cxx::memory::UniquePtrTarget for Context<'sess> {")); +} + +/// This test covers implicit impl of `Vec>`. +#[test] +fn test_vec_of_box() { + let rs = bridge(quote! { + mod ffi { + extern "Rust" { + type R; + fn foo() -> Vec>; + } + } + }); + + assert!(rs.contains("unsafe impl ::cxx::private::ImplBox for R {}")); + assert!(rs.contains("export_name = \"cxxbridge1$box$R$drop\"")); + + assert!(rs.contains("unsafe impl ::cxx::private::ImplVec for ::cxx::alloc::boxed::Box {}")); + assert!(rs.contains("export_name = \"cxxbridge1$rust_vec$box$R$set_len\"")); + + // Not supposed to be `RustVec<*mut R>` (which happened in an early draft). + assert!(rs.contains("__return: *mut ::cxx::private::RustVec<::cxx::alloc::boxed::Box>")); + assert!(rs.contains("fn __foo() -> ::cxx::alloc::vec::Vec<::cxx::alloc::boxed::Box>")); +} diff --git a/macro/src/tokens.rs b/macro/src/tokens.rs index 805af227b..c48c06f08 100644 --- a/macro/src/tokens.rs +++ b/macro/src/tokens.rs @@ -1,19 +1,19 @@ use crate::syntax::Receiver; use proc_macro2::TokenStream; -use quote::{quote_spanned, ToTokens}; +use quote::{ToTokens, quote_spanned}; use syn::Token; -pub struct ReceiverType<'a>(&'a Receiver); -pub struct ReceiverTypeSelf<'a>(&'a Receiver); +pub(crate) struct ReceiverType<'a>(&'a Receiver); +pub(crate) struct ReceiverTypeSelf<'a>(&'a Receiver); impl Receiver { // &TheType - pub fn ty(&self) -> ReceiverType { + pub(crate) fn ty(&self) -> ReceiverType { ReceiverType(self) } // &Self - pub fn ty_self(&self) -> ReceiverTypeSelf { + pub(crate) fn ty_self(&self) -> ReceiverTypeSelf { ReceiverTypeSelf(self) } } diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs index 7bca67b18..62b9687e9 100644 --- a/macro/src/type_id.rs +++ b/macro/src/type_id.rs @@ -1,9 +1,9 @@ use crate::syntax::qualified::QualifiedName; use proc_macro2::{TokenStream, TokenTree}; -use quote::{format_ident, quote, ToTokens}; +use quote::{ToTokens, format_ident, quote}; use syn::ext::IdentExt; -pub enum Crate { +pub(crate) enum Crate { Cxx, DollarCrate(TokenTree), } @@ -18,7 +18,7 @@ impl ToTokens for Crate { } // "folly::File" => `(f, o, l, l, y, (), F, i, l, e)` -pub fn expand(krate: Crate, arg: QualifiedName) -> TokenStream { +pub(crate) fn expand(krate: Crate, arg: QualifiedName) -> TokenStream { let mut ids = Vec::new(); for word in arg.segments { diff --git a/reindeer.toml b/reindeer.toml new file mode 100644 index 000000000..4fc8abb6a --- /dev/null +++ b/reindeer.toml @@ -0,0 +1 @@ +error = "This is the wrong directory. Run `reindeer buckify` in the third-party directory." diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000..20fe888c3 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +components = ["rust-src"] diff --git a/src/c_char.rs b/src/c_char.rs deleted file mode 100644 index 333d8491c..000000000 --- a/src/c_char.rs +++ /dev/null @@ -1,69 +0,0 @@ -#[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; - } -} diff --git a/src/cxx.cc b/src/cxx.cc index 4958eb08b..6ce5d0bb3 100644 --- a/src/cxx.cc +++ b/src/cxx.cc @@ -1,8 +1,35 @@ #include "../include/cxx.h" +#include #include #include #include +#ifdef __cpp_lib_bit_cast +#include +#endif + +// Most compilers set __cpp_attributes on C++11 and up, and set __cpp_exceptions +// if the flag `-fno-exceptions` is not set. On these compilers we detect +// `-fno-exceptions` this way. +// +// Some compilers never set either one. On these, rely on the user to do +// `-DRUST_CXX_NO_EXCEPTIONS` if they are not using exceptions. +// +// On MSVC, it is possible for exception throwing and catching to be enabled +// without __cpp_exceptions being defined, so do not try to detect anything. +#if !defined(RUST_CXX_NO_EXCEPTIONS) && defined(__cpp_attributes) && \ + !defined(__cpp_exceptions) && (!defined(_MSC_VER) || defined(__llvm__)) +#define RUST_CXX_NO_EXCEPTIONS +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wmissing-declarations" +#pragma GCC diagnostic ignored "-Wshadow" +#endif +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" +#endif + extern "C" { void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr, std::size_t len) noexcept { @@ -76,8 +103,8 @@ inline namespace cxxbridge1 { template void panic [[noreturn]] (const char *msg) { #if defined(RUST_CXX_NO_EXCEPTIONS) - std::cerr << "Error: " << msg << ". Aborting." << std::endl; - std::terminate(); + std::fprintf(stderr, "Error: %s. Aborting.\n", msg); + std::abort(); #else throw Exception(msg); #endif @@ -129,6 +156,13 @@ String::String(const char *s, std::size_t len) { len); } +#ifdef __cpp_char8_t +String::String(const char8_t *s) : String(reinterpret_cast(s)) {} + +String::String(const char8_t *s, std::size_t len) + : String(reinterpret_cast(s), len) {} +#endif + String::String(const char16_t *s) { assert(s != nullptr); assert(is_aligned(s)); @@ -185,7 +219,7 @@ String String::lossy(const char16_t *s, std::size_t len) noexcept { return String(lossy_t{}, s, len); } -String &String::operator=(const String &other) &noexcept { +String &String::operator=(const String &other) & noexcept { if (this != &other) { cxxbridge1$string$drop(this); cxxbridge1$string$clone(this, other); @@ -193,7 +227,7 @@ String &String::operator=(const String &other) &noexcept { return *this; } -String &String::operator=(String &&other) &noexcept { +String &String::operator=(String &&other) & noexcept { cxxbridge1$string$drop(this); this->repr = other.repr; cxxbridge1$string$new(&other); @@ -285,7 +319,7 @@ String::String(unsafe_bitcopy_t, const String &bits) noexcept : repr(bits.repr) {} std::ostream &operator<<(std::ostream &os, const String &s) { - os.write(s.data(), s.size()); + os.write(s.data(), static_cast(s.size())); return os; } @@ -317,6 +351,12 @@ Str::operator std::string() const { return std::string(this->data(), this->size()); } +#if __cplusplus >= 201703L +Str::operator std::string_view() const { + return std::string_view(this->data(), this->size()); +} +#endif + const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); } std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); } @@ -353,7 +393,8 @@ bool Str::operator<=(const Str &rhs) const noexcept { const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(), rend = rhs.end(); while (liter != lend && riter != rend && *liter == *riter) { - ++liter, ++riter; + ++liter; + ++riter; } if (liter == lend) { return true; // equal or *this is a prefix of rhs @@ -374,7 +415,7 @@ void Str::swap(Str &rhs) noexcept { } std::ostream &operator<<(std::ostream &os, const Str &s) { - os.write(s.data(), s.size()); + os.write(s.data(), static_cast(s.size())); return os; } @@ -406,6 +447,19 @@ static_assert(sizeof(rust::isize) == sizeof(std::intptr_t), static_assert(alignof(rust::isize) == alignof(std::intptr_t), "unsupported ssize_t alignment"); +// The C++ standard does not guarantee a particular size, alignment, or bit +// pattern for bool. In practice on all platforms supported by Rust, it is +// compatible with Rust's bool. The libc crate freely uses Rust bool in +// foreign function signatures. +static_assert(sizeof(bool) == 1, "unsupported bool size"); +static_assert(alignof(bool) == 1, "unsupported bool alignment"); +#ifdef __cpp_lib_bit_cast +static_assert(std::bit_cast(false) == 0, + "unsupported bit representation of false"); +static_assert(std::bit_cast(true) == 1, + "unsupported bit representation of true"); +#endif + static_assert(std::is_trivially_copy_constructible::value, "trivial Str(const Str &)"); static_assert(std::is_trivially_copy_assignable::value, @@ -449,8 +503,9 @@ static_assert(!std::is_same::const_iterator, "Vec::const_iterator != Vec::iterator"); static const char *errorCopy(const char *ptr, std::size_t len) { - char *copy = new char[len]; + char *copy = new char[len + 1]; std::memcpy(copy, ptr, len); + copy[len] = '\0'; return copy; } @@ -486,7 +541,7 @@ Error &Error::operator=(const Error &other) & { return *this; } -Error &Error::operator=(Error &&other) &noexcept { +Error &Error::operator=(Error &&other) & noexcept { std::exception::operator=(std::move(other)); delete[] this->msg; this->msg = other.msg; @@ -531,6 +586,11 @@ using isize_if_unique = typename std::conditional::value || std::is_same::value, struct isize_ignore, rust::isize>::type; +// Similarly, on some platforms char may just be an alias for [u]int8_t. +using char_if_unique = + typename std::conditional::value || + std::is_same::value, + struct char_ignore, char>::type; class Fail final { repr::PtrLen &throw$; @@ -592,14 +652,25 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), } // namespace #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \ + std::vector *cxxbridge1$std$vector$##RUST_TYPE##$new() noexcept { \ + return new std::vector(); \ + } \ std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \ const std::vector &s) noexcept { \ return s.size(); \ } \ + std::size_t cxxbridge1$std$vector$##RUST_TYPE##$capacity( \ + const std::vector &s) noexcept { \ + return s.capacity(); \ + } \ CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \ std::vector *s, std::size_t pos) noexcept { \ return &(*s)[pos]; \ } \ + void cxxbridge1$std$vector$##RUST_TYPE##$reserve( \ + std::vector *s, std::size_t new_cap) noexcept { \ + s->reserve(new_cap); \ + } \ void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \ std::unique_ptr> *ptr) noexcept { \ new (ptr) std::unique_ptr>(); \ @@ -695,6 +766,10 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), std::shared_ptr *ptr) noexcept { \ new (ptr) std::shared_ptr(); \ } \ + void cxxbridge1$std$shared_ptr$##RUST_TYPE##$raw( \ + std::shared_ptr *ptr, CXX_TYPE *raw) noexcept { \ + new (ptr) std::shared_ptr(raw); \ + } \ CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \ std::shared_ptr *ptr) noexcept { \ CXX_TYPE *uninit = \ @@ -766,7 +841,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), #define FOR_EACH_RUST_VEC(MACRO) \ FOR_EACH_NUMERIC(MACRO) \ MACRO(bool, bool) \ - MACRO(char, char) \ + MACRO(char, rust::detail::char_if_unique) \ MACRO(usize, rust::detail::usize_if_unique) \ MACRO(isize, rust::detail::isize_if_unique) \ MACRO(string, rust::String) \ diff --git a/src/cxx_string.rs b/src/cxx_string.rs index 9ecbcc647..7d9e34aca 100644 --- a/src/cxx_string.rs +++ b/src/cxx_string.rs @@ -4,16 +4,19 @@ use crate::lossy; use alloc::borrow::Cow; #[cfg(feature = "alloc")] use alloc::string::String; +use core::cell::UnsafeCell; use core::cmp::Ordering; +use core::ffi::{CStr, c_char}; use core::fmt::{self, Debug, Display}; use core::hash::{Hash, Hasher}; use core::marker::{PhantomData, PhantomPinned}; use core::mem::MaybeUninit; +use core::panic::RefUnwindSafe; use core::pin::Pin; use core::slice; use core::str::{self, Utf8Error}; -extern "C" { +unsafe extern "C" { #[link_name = "cxxbridge1$cxx_string$init"] fn string_init(this: &mut MaybeUninit, ptr: *const u8, len: usize); #[link_name = "cxxbridge1$cxx_string$destroy"] @@ -42,7 +45,10 @@ extern "C" { /// or `UniquePtr`. #[repr(C)] pub struct CxxString { + #[cfg(not(all(miri, feature = "alloc")))] _private: [u8; 0], + #[cfg(all(miri, feature = "alloc"))] + _miri: miri::CxxStringRepr, _pinned: PhantomData, } @@ -80,11 +86,13 @@ pub struct CxxString { #[macro_export] macro_rules! let_cxx_string { ($var:ident = $value:expr $(,)?) => { - let mut cxx_stack_string = $crate::private::StackString::new(); + let cxx_stack_string = $crate::private::StackString::new(); #[allow(unused_mut, unused_unsafe)] let mut $var = match $value { let_cxx_string => unsafe { cxx_stack_string.init(let_cxx_string) }, }; + #[allow(unused_unsafe)] + let _cxx_stack_string_drop_guard = unsafe { cxx_stack_string.drop_guard() }; }; } @@ -129,12 +137,28 @@ impl CxxString { /// internal null bytes. As such, the returned pointer only makes sense as a /// string in combination with the length returned by [`len()`][len]. /// + /// Modifying the string data through this pointer has undefined behavior. + /// /// [data]: https://en.cppreference.com/w/cpp/string/basic_string/data /// [len]: #method.len pub fn as_ptr(&self) -> *const u8 { unsafe { string_data(self) } } + /// Produces a nul-terminated string view of this string's contents. + /// + /// Matches the behavior of C++ [std::string::c_str][c_str]. + /// + /// If this string contains no internal '\0' bytes, then + /// `self.as_c_str().count_bytes() == self.len()`. But if it does, the CStr + /// only refers to the part of the string up to the first nul byte. + /// + /// [c_str]: https://en.cppreference.com/w/cpp/string/basic_string/c_str + pub fn as_c_str(&self) -> &CStr { + // Since C++11, string[string.size()] is guaranteed to be \0. + unsafe { CStr::from_ptr(self.as_ptr().cast::()) } + } + /// Validates that the C++ string contains UTF-8 data and produces a view of /// it as a Rust &str, otherwise an error. pub fn to_str(&self) -> Result<&str, Utf8Error> { @@ -146,9 +170,9 @@ impl CxxString { /// sequences with the U+FFFD [replacement character] and returns a /// Cow::Owned String. /// - /// [replacement character]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html + /// [replacement character]: char::REPLACEMENT_CHARACTER #[cfg(feature = "alloc")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] pub fn to_string_lossy(&self) -> Cow { String::from_utf8_lossy(self.as_bytes()) } @@ -171,8 +195,8 @@ impl CxxString { /// Ensures that this string's capacity is at least `additional` bytes /// larger than its length. /// - /// The capacity may be increased by more than `additional` bytes if it - /// chooses, to amortize the cost of frequent reallocations. + /// The capacity may be increased by more than `additional` bytes if the + /// implementation chooses, to amortize the cost of frequent reallocations. /// /// **The meaning of the argument is not the same as /// [std::string::reserve][reserve] in C++.** The C++ standard library and @@ -241,7 +265,7 @@ impl Eq for CxxString {} impl PartialOrd for CxxString { fn partial_cmp(&self, other: &Self) -> Option { - self.as_bytes().partial_cmp(other.as_bytes()) + Some(self.cmp(other)) } } @@ -257,37 +281,128 @@ impl Hash for CxxString { } } +impl fmt::Write for Pin<&mut CxxString> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.as_mut().push_str(s); + Ok(()) + } +} + +#[cfg(feature = "std")] +impl std::io::Write for Pin<&mut CxxString> { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.as_mut().push_bytes(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + #[doc(hidden)] #[repr(C)] pub struct StackString { // Static assertions in cxx.cc validate that this is large enough and // aligned enough. - space: MaybeUninit<[usize; 8]>, + space: UnsafeCell>, } -#[allow(missing_docs)] +unsafe impl Sync for StackString {} +impl RefUnwindSafe for StackString {} + impl StackString { pub fn new() -> Self { StackString { - space: MaybeUninit::uninit(), + space: UnsafeCell::new(MaybeUninit::uninit()), } } - pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> { + #[allow(clippy::mut_from_ref)] + pub unsafe fn init(&self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> { let value = value.as_ref(); unsafe { - let this = &mut *self.space.as_mut_ptr().cast::>(); + let this = &mut *self.space.get().cast::>(); string_init(this, value.as_ptr(), value.len()); Pin::new_unchecked(&mut *this.as_mut_ptr()) } } + + pub unsafe fn drop_guard(&self) -> impl Drop + '_ { + struct StackStringDropGuard<'a>(&'a StackString); + + impl<'a> Drop for StackStringDropGuard<'a> { + fn drop(&mut self) { + unsafe { + let this = &mut *self.0.space.get().cast::>(); + string_destroy(this); + } + } + } + + StackStringDropGuard(self) + } } -impl Drop for StackString { - fn drop(&mut self) { +#[cfg(all(miri, feature = "alloc"))] +mod miri { + use super::CxxString; + use alloc::vec::Vec; + use core::mem; + use core::mem::MaybeUninit; + use core::pin::Pin; + use core::ptr; + use core::slice; + + pub(super) type CxxStringRepr = [MaybeUninit; mem::size_of::>()]; + + #[unsafe(export_name = "cxxbridge1$cxx_string$init")] + unsafe extern "C" fn string_init( + this: &mut MaybeUninit, + ptr: *const u8, + len: usize, + ) { unsafe { - let this = &mut *self.space.as_mut_ptr().cast::>(); - string_destroy(this); + this.as_mut_ptr() + .cast::>() + .write(slice::from_raw_parts(ptr, len).to_vec()); } } + + #[unsafe(export_name = "cxxbridge1$cxx_string$destroy")] + unsafe extern "C" fn string_destroy(this: &mut MaybeUninit) { + unsafe { + ptr::drop_in_place(this.as_mut_ptr().cast::>()); + } + } + + #[unsafe(export_name = "cxxbridge1$cxx_string$data")] + unsafe extern "C" fn string_data(this: &CxxString) -> *const u8 { + let vec = unsafe { &*ptr::from_ref(this).cast::>() }; + vec.as_ptr() + } + + #[unsafe(export_name = "cxxbridge1$cxx_string$length")] + unsafe extern "C" fn string_length(this: &CxxString) -> usize { + let vec = unsafe { &*ptr::from_ref(this).cast::>() }; + vec.len() + } + + #[unsafe(export_name = "cxxbridge1$cxx_string$clear")] + unsafe extern "C" fn string_clear(this: Pin<&mut CxxString>) { + let vec = unsafe { &mut *ptr::from_mut(this.get_unchecked_mut()).cast::>() }; + vec.clear(); + } + + #[unsafe(export_name = "cxxbridge1$cxx_string$reserve_total")] + unsafe extern "C" fn string_reserve_total(this: Pin<&mut CxxString>, new_cap: usize) { + let vec = unsafe { &mut *ptr::from_mut(this.get_unchecked_mut()).cast::>() }; + vec.reserve(new_cap.saturating_sub(vec.len())); + } + + #[unsafe(export_name = "cxxbridge1$cxx_string$push")] + unsafe extern "C" fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize) { + let vec = unsafe { &mut *ptr::from_mut(this.get_unchecked_mut()).cast::>() }; + vec.extend_from_slice(unsafe { slice::from_raw_parts(ptr, len) }); + } } diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs index abf9297a8..f7247c5d1 100644 --- a/src/cxx_vector.rs +++ b/src/cxx_vector.rs @@ -4,12 +4,14 @@ use crate::extern_type::ExternType; use crate::kind::Trivial; use crate::string::CxxString; +use crate::unique_ptr::UniquePtr; use core::ffi::c_void; use core::fmt::{self, Debug}; use core::iter::FusedIterator; use core::marker::{PhantomData, PhantomPinned}; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::pin::Pin; +use core::ptr; use core::slice; /// Binding to C++ `std::vector>`. @@ -36,6 +38,13 @@ impl CxxVector where T: VectorElement, { + /// Constructs a new heap allocated vector, wrapped by UniquePtr. + /// + /// The C++ vector is default constructed. + pub fn new() -> UniquePtr { + unsafe { UniquePtr::from_raw(T::__vector_new()) } + } + /// Returns the number of elements in the vector. /// /// Matches the behavior of C++ [std::vector\::size][size]. @@ -45,6 +54,15 @@ where T::__vector_size(self) } + /// Returns the capacity of the vector. + /// + /// Matches the behavior of C++ [std::vector\::capacity][capacity]. + /// + /// [capacity]: https://en.cppreference.com/w/cpp/container/vector/capacity + pub fn capacity(&self) -> usize { + T::__vector_capacity(self) + } + /// Returns true if the vector contains no elements. /// /// Matches the behavior of C++ [std::vector\::empty][empty]. @@ -66,6 +84,10 @@ where /// Returns a pinned mutable reference to an element at the given position, /// or `None` if out of bounds. + /// + /// This method cannot be named "get\_mut" due to a conflict with + /// `Pin::get_mut`. + #[doc(alias = "get_mut")] pub fn index_mut(self: Pin<&mut Self>, pos: usize) -> Option> { if pos < self.len() { Some(unsafe { self.index_unchecked_mut(pos) }) @@ -85,9 +107,9 @@ where /// /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at pub unsafe fn get_unchecked(&self, pos: usize) -> &T { - let this = self as *const CxxVector as *mut CxxVector; + let this = ptr::from_ref::>(self).cast_mut(); unsafe { - let ptr = T::__get_unchecked(this, pos) as *const T; + let ptr = T::__get_unchecked(this, pos).cast_const(); &*ptr } } @@ -103,6 +125,10 @@ where /// [std::vector\::operator\[\]][operator_at]. /// /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at + /// + /// This method cannot be named "get\_unchecked\_mut" due to a conflict with + /// `Pin::get_unchecked_mut`. + #[doc(alias = "get_unchecked_mut")] pub unsafe fn index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> { unsafe { let ptr = T::__get_unchecked(self.get_unchecked_mut(), pos); @@ -125,7 +151,7 @@ where // which upholds the invariants. &[] } else { - let this = self as *const CxxVector as *mut CxxVector; + let this = ptr::from_ref::>(self).cast_mut(); let ptr = unsafe { T::__get_unchecked(this, 0) }; unsafe { slice::from_raw_parts(ptr, len) } } @@ -188,6 +214,51 @@ where }) } } + + /// Ensures that this vector's capacity is at least `additional` elements + /// larger than its length. + /// + /// The capacity may be increased by more than `additional` elements if the + /// implementation chooses, to amortize the cost of frequent reallocations. + /// + /// **The meaning of the argument is not the same as + /// [std::vector\::reserve][reserve] in C++.** The C++ standard library + /// and Rust standard library both have a `reserve` method on vectors, but + /// in C++ code the argument always refers to total capacity, whereas in + /// Rust code it always refers to additional capacity. This API on + /// `CxxVector` follows the Rust convention, the same way that for the + /// length accessor we use the Rust conventional `len()` naming and not C++ + /// `size()`. + /// + /// # Panics + /// + /// Panics if the new capacity overflows usize, or if `T` is not + /// move-constructible in C++. + /// + /// [reserve]: https://en.cppreference.com/w/cpp/container/vector/reserve.html + pub fn reserve(self: Pin<&mut Self>, additional: usize) { + let new_cap = self + .len() + .checked_add(additional) + .expect("CxxVector capacity overflow"); + unsafe { T::__reserve(self, new_cap) } + } +} + +impl Extend for Pin<&mut CxxVector> +where + T: ExternType + VectorElement, +{ + fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + let iter = iter.into_iter(); + self.as_mut().reserve(iter.size_hint().0); + for element in iter { + self.as_mut().push(element); + } + } } /// Iterator over elements of a `CxxVector` by shared reference. @@ -271,7 +342,7 @@ where // Extend lifetime to allow simultaneous holding of nonoverlapping // elements, analogous to slice::split_first_mut. unsafe { - let ptr = Pin::into_inner_unchecked(next) as *mut T; + let ptr = ptr::from_mut::(Pin::into_inner_unchecked(next)); Some(Pin::new_unchecked(&mut *ptr)) } } @@ -306,7 +377,9 @@ where /// `CxxVector` in generic code. /// /// This trait has no publicly callable or implementable methods. Implementing -/// it outside of the CXX codebase is not supported. +/// it outside of the CXX codebase requires using [explicit shim trait impls], +/// adding the line `impl CxxVector {}` in the same `cxx::bridge` that +/// defines `MyType`. /// /// # Example /// @@ -330,14 +403,22 @@ where /// /// Writing the same generic function without a `VectorElement` trait bound /// would not compile. +/// +/// [explicit shim trait impls]: https://cxx.rs/extern-c++.html#explicit-shim-trait-impls pub unsafe trait VectorElement: Sized { #[doc(hidden)] fn __typename(f: &mut fmt::Formatter) -> fmt::Result; #[doc(hidden)] + fn __vector_new() -> *mut CxxVector; + #[doc(hidden)] fn __vector_size(v: &CxxVector) -> usize; #[doc(hidden)] + fn __vector_capacity(v: &CxxVector) -> usize; + #[doc(hidden)] unsafe fn __get_unchecked(v: *mut CxxVector, pos: usize) -> *mut Self; #[doc(hidden)] + unsafe fn __reserve(v: Pin<&mut CxxVector>, new_cap: usize); + #[doc(hidden)] unsafe fn __push_back(v: Pin<&mut CxxVector>, value: &mut ManuallyDrop) { // Opaque C type vector elements do not get this method because they can // never exist by value on the Rust side of the bridge. @@ -369,20 +450,16 @@ macro_rules! vector_element_by_value_methods { (opaque, $segment:expr, $ty:ty) => {}; (trivial, $segment:expr, $ty:ty) => { unsafe fn __push_back(v: Pin<&mut CxxVector<$ty>>, value: &mut ManuallyDrop<$ty>) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$push_back")] - fn __push_back(_: Pin<&mut CxxVector<$ty>>, _: &mut ManuallyDrop<$ty>); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$push_back")] + fn __push_back(_: Pin<&mut CxxVector<$ty>>, _: &mut ManuallyDrop<$ty>); } unsafe { __push_back(v, value) } } unsafe fn __pop_back(v: Pin<&mut CxxVector<$ty>>, out: &mut MaybeUninit<$ty>) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$pop_back")] - fn __pop_back(_: Pin<&mut CxxVector<$ty>>, _: &mut MaybeUninit<$ty>); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$pop_back")] + fn __pop_back(_: Pin<&mut CxxVector<$ty>>, _: &mut MaybeUninit<$ty>); } unsafe { __pop_back(v, out) } } @@ -398,71 +475,78 @@ macro_rules! impl_vector_element { fn __typename(f: &mut fmt::Formatter) -> fmt::Result { f.write_str($name) } + fn __vector_new() -> *mut CxxVector { + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$new")] + fn __vector_new() -> *mut CxxVector<$ty>; + } + unsafe { __vector_new() } + } fn __vector_size(v: &CxxVector<$ty>) -> usize { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")] - fn __vector_size(_: &CxxVector<$ty>) -> usize; - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")] + fn __vector_size(_: &CxxVector<$ty>) -> usize; } unsafe { __vector_size(v) } } + fn __vector_capacity(v: &CxxVector<$ty>) -> usize { + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$capacity")] + fn __vector_capacity(_: &CxxVector<$ty>) -> usize; + } + unsafe { __vector_capacity(v) } + } unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")] - fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty; - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")] + fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty; } unsafe { __get_unchecked(v, pos) } } + unsafe fn __reserve(v: Pin<&mut CxxVector<$ty>>, new_cap: usize) { + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$reserve")] + fn __reserve(_: Pin<&mut CxxVector<$ty>>, _: usize); + } + unsafe { __reserve(v, new_cap) } + } vector_element_by_value_methods!($kind, $segment, $ty); fn __unique_ptr_null() -> MaybeUninit<*mut c_void> { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")] - fn __unique_ptr_null(this: *mut MaybeUninit<*mut c_void>); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")] + fn __unique_ptr_null(this: *mut MaybeUninit<*mut c_void>); } let mut repr = MaybeUninit::uninit(); unsafe { __unique_ptr_null(&mut repr) } repr } unsafe fn __unique_ptr_raw(raw: *mut CxxVector) -> MaybeUninit<*mut c_void> { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")] - fn __unique_ptr_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxVector<$ty>); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")] + fn __unique_ptr_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxVector<$ty>); } let mut repr = MaybeUninit::uninit(); unsafe { __unique_ptr_raw(&mut repr, raw) } repr } unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")] - fn __unique_ptr_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxVector<$ty>; - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")] + fn __unique_ptr_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxVector<$ty>; } unsafe { __unique_ptr_get(&repr) } } unsafe fn __unique_ptr_release(mut repr: MaybeUninit<*mut c_void>) -> *mut CxxVector { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")] - fn __unique_ptr_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxVector<$ty>; - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")] + fn __unique_ptr_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxVector<$ty>; } unsafe { __unique_ptr_release(&mut repr) } } unsafe fn __unique_ptr_drop(mut repr: MaybeUninit<*mut c_void>) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")] - fn __unique_ptr_drop(this: *mut MaybeUninit<*mut c_void>); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")] + fn __unique_ptr_drop(this: *mut MaybeUninit<*mut c_void>); } unsafe { __unique_ptr_drop(&mut repr) } } diff --git a/src/exception.rs b/src/exception.rs index 259b27d4d..52b3b2065 100644 --- a/src/exception.rs +++ b/src/exception.rs @@ -3,8 +3,10 @@ use alloc::boxed::Box; use core::fmt::{self, Display}; +use core::error::Error as StdError; + /// Exception thrown from an `extern "C++"` function. -#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] #[derive(Debug)] pub struct Exception { pub(crate) what: Box, @@ -16,9 +18,7 @@ impl Display for Exception { } } -#[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] -impl std::error::Error for Exception {} +impl StdError for Exception {} impl Exception { #[allow(missing_docs)] diff --git a/src/extern_type.rs b/src/extern_type.rs index d131ae127..e6688d633 100644 --- a/src/extern_type.rs +++ b/src/extern_type.rs @@ -1,5 +1,5 @@ use self::kind::{Kind, Opaque, Trivial}; -use crate::CxxString; +use crate::string::CxxString; #[cfg(feature = "alloc")] use alloc::string::String; @@ -191,7 +191,6 @@ macro_rules! impl_extern_type { $($( $(#[$($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; @@ -217,7 +216,7 @@ impl_extern_type! { f64 = "double" #[cfg(feature = "alloc")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] String = "rust::String" [Opaque] diff --git a/src/hash.rs b/src/hash.rs index 4c92173f7..ee349b405 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,12 +1,6 @@ -use core::hash::{Hash, Hasher}; +use core::hash::{BuildHasher as _, Hash}; #[doc(hidden)] pub fn 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 + foldhash::quality::FixedState::default().hash_one(value) as usize } diff --git a/src/lib.rs b/src/lib.rs index 77ec7cff0..050ffe0ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ //! //!
    //! -//! *Compiler support: requires rustc 1.60+ and c++11 or newer*
    +//! *Compiler support: requires rustc 1.88+ and c++11 or newer*
    //! *[Release notes](https://github.com/dtolnay/cxx/releases)* //! //!
    @@ -140,7 +140,7 @@ //! $ cargo expand --manifest-path demo/Cargo.toml //! //! # run C++ code generator and print to stdout -//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs +//! $ cargo run --manifest-path bridge/cmd/Cargo.toml -- demo/src/main.rs //! ``` //! //!
    @@ -251,10 +251,9 @@ //! fn main() { //! cxx_build::bridge("src/main.rs") // returns a cc::Build //! .file("src/demo.cc") -//! .flag_if_supported("-std=c++11") +//! .std("c++11") //! .compile("cxxbridge-demo"); //! -//! println!("cargo:rerun-if-changed=src/main.rs"); //! println!("cargo:rerun-if-changed=src/demo.cc"); //! println!("cargo:rerun-if-changed=include/demo.h"); //! } @@ -267,7 +266,7 @@ //! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate //! way of invoking the C++ code generator as a standalone command line tool. //! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be -//! built from the *gen/cmd* directory of . +//! built from the *bridge/cmd* directory of . //! //! ```bash //! $ cargo install cxxbridge-cmd @@ -364,39 +363,32 @@ //! #![no_std] -#![doc(html_root_url = "https://docs.rs/cxx/1.0.91")] +#![doc(html_root_url = "https://docs.rs/cxx/1.0.199")] +#![cfg_attr(docsrs, feature(doc_cfg))] #![deny( improper_ctypes, improper_ctypes_definitions, missing_docs, unsafe_op_in_unsafe_fn )] -#![cfg_attr(doc_cfg, feature(doc_cfg))] -#![allow(non_camel_case_types)] +#![warn(clippy::alloc_instead_of_core, clippy::std_instead_of_alloc)] +#![expect(non_camel_case_types)] #![allow( - clippy::cognitive_complexity, - clippy::declare_interior_mutable_const, + clippy::cast_possible_truncation, clippy::doc_markdown, - clippy::empty_enum, - clippy::extra_unused_type_parameters, - clippy::inherent_to_string, + clippy::elidable_lifetime_names, clippy::items_after_statements, - clippy::large_enum_variant, clippy::len_without_is_empty, clippy::missing_errors_doc, clippy::missing_safety_doc, - clippy::module_inception, - clippy::module_name_repetitions, clippy::must_use_candidate, clippy::needless_doctest_main, + clippy::needless_lifetimes, + clippy::needless_pass_by_value, clippy::new_without_default, - 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 + clippy::uninlined_format_args )] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] #[cfg(built_with_cargo)] extern crate link_cplusplus; @@ -440,7 +432,6 @@ compile_error! { #[macro_use] mod macros; -mod c_char; mod cxx_vector; mod exception; mod extern_type; @@ -457,7 +448,6 @@ mod rust_string; mod rust_type; mod rust_vec; mod shared_ptr; -mod sip; #[path = "cxx_string.rs"] mod string; mod symbols; @@ -469,8 +459,9 @@ mod weak_ptr; pub use crate::cxx_vector::CxxVector; #[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] pub use crate::exception::Exception; -pub use crate::extern_type::{kind, ExternType}; +pub use crate::extern_type::{ExternType, kind}; pub use crate::shared_ptr::SharedPtr; pub use crate::string::CxxString; pub use crate::unique_ptr::UniquePtr; @@ -494,27 +485,23 @@ pub type Vector = CxxVector; // 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::result::{Result, r#try}; 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}; + pub use crate::rust_type::{ + ImplBox, ImplVec, RustType, Without, require_box, require_unpin, require_vec, with, + }; #[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::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 index 8ccf0f93b..0140392a6 100644 --- a/src/lossy.rs +++ b/src/lossy.rs @@ -2,7 +2,7 @@ use core::char; use core::fmt::{self, Write as _}; use core::str; -pub fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { +pub(crate) fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { loop { match str::from_utf8(bytes) { Ok(valid) => return f.write_str(valid), @@ -21,7 +21,7 @@ pub fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { } } -pub fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { +pub(crate) fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { f.write_char('"')?; while !bytes.is_empty() { diff --git a/src/macros/concat.rs b/src/macros/concat.rs deleted file mode 100644 index 5ee77c527..000000000 --- a/src/macros/concat.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[macro_export] -#[doc(hidden)] -macro_rules! attr { - (#[$name:ident = $value:expr] $($rest:tt)*) => { - #[$name = $value] - $($rest)* - }; -} diff --git a/src/macros/mod.rs b/src/macros/mod.rs index d12d96bd4..b070c0577 100644 --- a/src/macros/mod.rs +++ b/src/macros/mod.rs @@ -1,4 +1,2 @@ #[macro_use] mod assert; -#[macro_use] -mod concat; diff --git a/src/opaque.rs b/src/opaque.rs index e0f8ce2c2..11c011cc5 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -1,8 +1,10 @@ #![allow(missing_docs)] use crate::void; +use core::cell::UnsafeCell; use core::marker::{PhantomData, PhantomPinned}; use core::mem; +use core::panic::RefUnwindSafe; // . size = 0 // . align = 1 @@ -10,11 +12,22 @@ use core::mem; // . !Send // . !Sync // . !Unpin +// . not readonly +// . unwind-safe #[repr(C, packed)] pub struct Opaque { _private: [*const void; 0], _pinned: PhantomData, + _mutable: SyncUnsafeCell>, } +impl RefUnwindSafe for Opaque {} + +// TODO: https://github.com/rust-lang/rust/issues/95439 +#[repr(transparent)] +struct SyncUnsafeCell(UnsafeCell); + +unsafe impl Sync for SyncUnsafeCell {} + const_assert_eq!(0, mem::size_of::()); const_assert_eq!(1, mem::align_of::()); diff --git a/src/result.rs b/src/result.rs index ba77858e3..f2d287bd2 100644 --- a/src/result.rs +++ b/src/result.rs @@ -12,7 +12,7 @@ use core::str; #[repr(C)] #[derive(Copy, Clone)] -pub struct PtrLen { +pub(crate) struct PtrLen { pub ptr: NonNull, pub len: usize, } @@ -37,12 +37,10 @@ where } unsafe fn to_c_error(msg: String) -> Result { - let mut msg = msg; - unsafe { msg.as_mut_vec() }.push(b'\0'); let ptr = msg.as_ptr(); let len = msg.len(); - extern "C" { + unsafe extern "C" { #[link_name = "cxxbridge1$error"] fn error(ptr: *const u8, len: usize) -> NonNull; } diff --git a/src/rust_string.rs b/src/rust_string.rs index 0e0c5a836..b431c81c9 100644 --- a/src/rust_string.rs +++ b/src/rust_string.rs @@ -17,11 +17,11 @@ impl RustString { } pub fn from_ref(s: &String) -> &Self { - unsafe { &*(s as *const String as *const RustString) } + unsafe { &*(ptr::from_ref::(s).cast::()) } } pub fn from_mut(s: &mut String) -> &mut Self { - unsafe { &mut *(s as *mut String as *mut RustString) } + unsafe { &mut *(ptr::from_mut::(s).cast::()) } } pub fn into_string(self) -> String { @@ -29,11 +29,11 @@ impl RustString { } pub fn as_string(&self) -> &String { - unsafe { &*(self as *const RustString as *const String) } + unsafe { &*(ptr::from_ref::(self).cast::()) } } pub fn as_mut_string(&mut self) -> &mut String { - unsafe { &mut *(self as *mut RustString as *mut String) } + unsafe { &mut *(ptr::from_mut::(self).cast::()) } } } diff --git a/src/rust_type.rs b/src/rust_type.rs index eacb5309f..a489b03f1 100644 --- a/src/rust_type.rs +++ b/src/rust_type.rs @@ -1,5 +1,50 @@ #![allow(missing_docs)] +use crate::extern_type::ExternType; +use crate::kind::Trivial; +use core::marker::{PhantomData, Unpin}; +use core::ops::Deref; + pub unsafe trait RustType {} pub unsafe trait ImplBox {} pub unsafe trait ImplVec {} + +// Opaque Rust types are required to be Unpin. +pub fn require_unpin() {} + +pub fn require_box() {} +pub fn require_vec() {} + +pub struct With(PhantomData); +pub struct Without; + +pub const fn with() -> With { + With(PhantomData) +} + +impl With { + #[allow(clippy::unused_self)] + pub const fn check_slice(&self) {} +} + +impl Deref for With { + type Target = Without; + fn deref(&self) -> &Self::Target { + &Without + } +} + +pub trait SliceOfExternType { + type Kind; +} +impl SliceOfExternType for &[T] { + type Kind = T::Kind; +} +impl SliceOfExternType for &mut [T] { + type Kind = T::Kind; +} + +impl Without { + #[allow(clippy::unused_self)] + pub const fn check_slice>(&self) {} +} diff --git a/src/rust_vec.rs b/src/rust_vec.rs index acb7e8902..cc5fc80de 100644 --- a/src/rust_vec.rs +++ b/src/rust_vec.rs @@ -1,12 +1,10 @@ #![cfg(feature = "alloc")] #![allow(missing_docs)] -use crate::rust_string::RustString; -use alloc::string::String; use alloc::vec::Vec; use core::ffi::c_void; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::mem::{self, MaybeUninit}; use core::ptr; // ABI compatible with C++ rust::Vec (not necessarily alloc::vec::Vec). @@ -26,11 +24,11 @@ impl RustVec { } pub fn from_ref(v: &Vec) -> &Self { - unsafe { &*(v as *const Vec as *const RustVec) } + unsafe { &*(ptr::from_ref::>(v).cast::>()) } } pub fn from_mut(v: &mut Vec) -> &mut Self { - unsafe { &mut *(v as *mut Vec as *mut RustVec) } + unsafe { &mut *(ptr::from_mut::>(v).cast::>()) } } pub fn into_vec(self) -> Vec { @@ -38,11 +36,11 @@ impl RustVec { } pub fn as_vec(&self) -> &Vec { - unsafe { &*(self as *const RustVec as *const Vec) } + unsafe { &*(ptr::from_ref::>(self).cast::>()) } } pub fn as_mut_vec(&mut self) -> &mut Vec { - unsafe { &mut *(self as *mut RustVec as *mut Vec) } + unsafe { &mut *(ptr::from_mut::>(self).cast::>()) } } pub fn len(&self) -> usize { @@ -74,40 +72,6 @@ impl RustVec { } } -impl RustVec { - pub fn from_vec_string(v: Vec) -> Self { - let mut v = ManuallyDrop::new(v); - let ptr = v.as_mut_ptr().cast::(); - let len = v.len(); - let cap = v.capacity(); - Self::from(unsafe { Vec::from_raw_parts(ptr, len, cap) }) - } - - pub fn from_ref_vec_string(v: &Vec) -> &Self { - Self::from_ref(unsafe { &*(v as *const Vec as *const Vec) }) - } - - pub fn from_mut_vec_string(v: &mut Vec) -> &mut Self { - Self::from_mut(unsafe { &mut *(v as *mut Vec as *mut Vec) }) - } - - pub fn into_vec_string(self) -> Vec { - let mut v = ManuallyDrop::new(self.into_vec()); - let ptr = v.as_mut_ptr().cast::(); - let len = v.len(); - let cap = v.capacity(); - unsafe { Vec::from_raw_parts(ptr, len, cap) } - } - - pub fn as_vec_string(&self) -> &Vec { - unsafe { &*(self as *const RustVec as *const Vec) } - } - - pub fn as_mut_vec_string(&mut self) -> &mut Vec { - unsafe { &mut *(self as *mut RustVec as *mut Vec) } - } -} - impl Drop for RustVec { fn drop(&mut self) { unsafe { ptr::drop_in_place(self.as_mut_vec()) } diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs index 64c866196..76af8ffa5 100644 --- a/src/shared_ptr.rs +++ b/src/shared_ptr.rs @@ -1,15 +1,47 @@ +use crate::extern_type::ExternType; use crate::fmt::display; use crate::kind::Trivial; use crate::string::CxxString; +use crate::unique_ptr::{UniquePtr, UniquePtrTarget}; use crate::weak_ptr::{WeakPtr, WeakPtrTarget}; -use crate::ExternType; +use core::cmp::Ordering; use core::ffi::c_void; use core::fmt::{self, Debug, Display}; +use core::hash::{Hash, Hasher}; use core::marker::PhantomData; use core::mem::MaybeUninit; use core::ops::Deref; +use core::pin::Pin; +use core::ptr; /// Binding to C++ `std::shared_ptr`. +/// +///
    +/// +/// **WARNING:** Unlike Rust's `Arc`, a C++ shared pointer manipulates +/// pointers to 2 separate objects in general. +/// +/// 1. One is the **managed** pointer, and its identity is associated with +/// shared ownership of a strong and weak count shared by other SharedPtr and +/// WeakPtr instances having the same managed pointer. +/// +/// 2. The other is the **stored** pointer, which is commonly either the same as +/// the managed pointer, or is a pointer into some member of the managed +/// object, but can be any unrelated pointer in general. +/// +/// The managed pointer is the one passed to a deleter upon the strong count +/// reaching zero, but the stored pointer is the one accessed by deref +/// operations and methods such as `is_null`. +/// +/// A shared pointer is considered **empty** if the strong count is zero, +/// meaning the managed pointer has been deleted or is about to be deleted. A +/// shared pointer is considered **null** if the stored pointer is the null +/// pointer. All combinations are possible. To be explicit, a shared pointer can +/// be nonempty and nonnull, or nonempty and null, or empty and nonnull, or +/// empty and null. In general all of these cases need to be considered when +/// handling a SharedPtr. +/// +///
    #[repr(C)] pub struct SharedPtr where @@ -23,7 +55,7 @@ impl SharedPtr where T: SharedPtrTarget, { - /// Makes a new SharedPtr wrapping a null pointer. + /// Makes a new SharedPtr that is both **empty** and **null**. /// /// Matches the behavior of default-constructing a std::shared\_ptr. pub fn null() -> Self { @@ -36,6 +68,8 @@ where } /// Allocates memory on the heap and makes a SharedPtr owner for it. + /// + /// The shared pointer will be **nonempty** and **nonnull**. pub fn new(value: T) -> Self where T: ExternType, @@ -48,20 +82,128 @@ where } } - /// Checks whether the SharedPtr does not own an object. + /// Creates a shared pointer from a C++ heap-allocated pointer. + /// + /// Matches the behavior of std::shared\_ptr's constructor `explicit shared_ptr(T*)`. + /// + /// The SharedPtr gains ownership of the pointer and will call + /// `std::default_delete` on it when the refcount goes to zero. + /// + /// The object pointed to by the input pointer is not relocated by this + /// operation, so any pointers into this data structure elsewhere in the + /// program continue to be valid. + /// + /// The resulting shared pointer is **nonempty** regardless of whether the + /// input pointer is null, but may be either **null** or **nonnull**. + /// + /// # Panics + /// + /// Panics if `T` is an incomplete type (including `void`) or is not + /// destructible. + /// + /// # Safety + /// + /// Pointer must either be null or point to a valid instance of T + /// heap-allocated in C++ by `new`. + #[track_caller] + pub unsafe fn from_raw(raw: *mut T) -> Self { + let mut shared_ptr = MaybeUninit::>::uninit(); + let new = shared_ptr.as_mut_ptr().cast(); + unsafe { + T::__raw(new, raw); + shared_ptr.assume_init() + } + } + + /// Checks whether the SharedPtr holds a null stored pointer. /// /// This is the opposite of [std::shared_ptr\::operator bool](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool). + /// + ///
    + /// + /// This method is unrelated to the state of the reference count. It is + /// possible to have a SharedPtr that is nonnull but empty (has a refcount + /// of 0), typically from having been constructed using the alias + /// constructors in C++. Inversely, it is also possible to be null and + /// nonempty. + /// + ///
    pub fn is_null(&self) -> bool { - let this = self as *const Self as *const c_void; + let this = ptr::from_ref::(self).cast::(); let ptr = unsafe { T::__get(this) }; ptr.is_null() } - /// Returns a reference to the object owned by this SharedPtr if any, - /// otherwise None. + /// Returns a reference to the object pointed to by the stored pointer if + /// nonnull, otherwise None. + /// + ///
    + /// + /// The shared pointer's managed object may or may not already have been + /// destroyed. + /// + ///
    pub fn as_ref(&self) -> Option<&T> { - let this = self as *const Self as *const c_void; - unsafe { T::__get(this).as_ref() } + let ptr = self.as_ptr(); + unsafe { ptr.as_ref() } + } + + /// Returns a mutable pinned reference to the object pointed to by the + /// stored pointer. + /// + ///
    + /// + /// The shared pointer's managed object may or may not already have been + /// destroyed. + /// + ///
    + /// + /// # Panics + /// + /// Panics if the SharedPtr holds a null stored pointer. + /// + /// # Safety + /// + /// This method makes no attempt to ascertain the state of the reference + /// count. In particular, unlike `Arc::get_mut`, we do not enforce absence + /// of other SharedPtr and WeakPtr referring to the same data as this one. + /// As always, it is Undefined Behavior to have simultaneous references to + /// the same value while a Rust exclusive reference to it exists anywhere in + /// the program. + /// + /// For the special case of CXX [opaque C++ types], this method can be used + /// to safely call thread-safe non-const member functions on a C++ object + /// without regard for whether the reference is exclusive. This capability + /// applies only to opaque types `extern "C++" { type T; }`. It does not + /// apply to extern types defined with a non-opaque Rust representation + /// `extern "C++" { type T = ...; }`. + /// + /// [opaque C++ types]: https://cxx.rs/extern-c++.html#opaque-c-types + pub unsafe fn pin_mut_unchecked(&mut self) -> Pin<&mut T> { + let ptr = self.as_mut_ptr(); + match unsafe { ptr.as_mut() } { + Some(target) => unsafe { Pin::new_unchecked(target) }, + None => panic!( + "called pin_mut_unchecked on a null SharedPtr<{}>", + display(T::__typename), + ), + } + } + + /// Returns the SharedPtr's stored pointer as a raw const pointer. + pub fn as_ptr(&self) -> *const T { + let this = ptr::from_ref::(self).cast::(); + unsafe { T::__get(this) } + } + + /// Returns the SharedPtr's stored pointer as a raw mutable pointer. + /// + /// As with [std::shared_ptr\::get](https://en.cppreference.com/w/cpp/memory/shared_ptr/get), + /// this doesn't require that you hold an exclusive reference to the + /// SharedPtr. This differs from Rust norms, so extra care should be taken + /// in the way the pointer is used. + pub fn as_mut_ptr(&self) -> *mut T { + self.as_ptr().cast_mut() } /// Constructs new WeakPtr as a non-owning reference to the object managed @@ -69,11 +211,11 @@ where /// too. /// /// Matches the behavior of [std::weak_ptr\::weak_ptr(const std::shared_ptr\ \&)](https://en.cppreference.com/w/cpp/memory/weak_ptr/weak_ptr). - pub fn downgrade(self: &SharedPtr) -> WeakPtr + pub fn downgrade(&self) -> WeakPtr where T: WeakPtrTarget, { - let this = self as *const Self as *const c_void; + let this = ptr::from_ref::(self).cast::(); let mut weak_ptr = MaybeUninit::>::uninit(); let new = weak_ptr.as_mut_ptr().cast(); unsafe { @@ -93,7 +235,7 @@ where fn clone(&self) -> Self { let mut shared_ptr = MaybeUninit::>::uninit(); let new = shared_ptr.as_mut_ptr().cast(); - let this = self as *const Self as *mut c_void; + let this = ptr::from_ref::(self).cast::(); unsafe { T::__clone(this, new); shared_ptr.assume_init() @@ -110,7 +252,7 @@ where T: SharedPtrTarget, { fn drop(&mut self) { - let this = self as *mut Self as *mut c_void; + let this = ptr::from_mut::(self).cast::(); unsafe { T::__drop(this) } } } @@ -156,6 +298,56 @@ where } } +impl PartialEq for SharedPtr +where + T: PartialEq + SharedPtrTarget, +{ + fn eq(&self, other: &Self) -> bool { + self.as_ref() == other.as_ref() + } +} + +impl Eq for SharedPtr where T: Eq + SharedPtrTarget {} + +impl PartialOrd for SharedPtr +where + T: PartialOrd + SharedPtrTarget, +{ + fn partial_cmp(&self, other: &Self) -> Option { + PartialOrd::partial_cmp(&self.as_ref(), &other.as_ref()) + } +} + +impl Ord for SharedPtr +where + T: Ord + SharedPtrTarget, +{ + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&self.as_ref(), &other.as_ref()) + } +} + +impl Hash for SharedPtr +where + T: Hash + SharedPtrTarget, +{ + fn hash(&self, hasher: &mut H) + where + H: Hasher, + { + self.as_ref().hash(hasher); + } +} + +impl From> for SharedPtr +where + T: UniquePtrTarget + SharedPtrTarget, +{ + fn from(unique: UniquePtr) -> Self { + unsafe { SharedPtr::from_raw(UniquePtr::into_raw(unique)) } + } +} + /// Trait bound for types which may be used as the `T` inside of a /// `SharedPtr` in generic code. /// @@ -191,13 +383,15 @@ pub unsafe trait SharedPtrTarget { where Self: Sized, { - // Opoaque C types do not get this method because they can never exist - // by value on the Rust side of the bridge. + // Opaque C types do not get this method because they can never exist by + // value on the Rust side of the bridge. let _ = value; let _ = new; unreachable!() } #[doc(hidden)] + unsafe fn __raw(new: *mut c_void, raw: *mut Self); + #[doc(hidden)] unsafe fn __clone(this: *const c_void, new: *mut c_void); #[doc(hidden)] unsafe fn __get(this: *const c_void) -> *const Self; @@ -212,47 +406,44 @@ macro_rules! impl_shared_ptr_target { f.write_str($name) } unsafe fn __null(new: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$null")] - fn __null(new: *mut c_void); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$null")] + fn __null(new: *mut c_void); } unsafe { __null(new) } } unsafe fn __new(value: Self, new: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$uninit")] - fn __uninit(new: *mut c_void) -> *mut c_void; - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$uninit")] + fn __uninit(new: *mut c_void) -> *mut c_void; } unsafe { __uninit(new).cast::<$ty>().write(value) } } + unsafe fn __raw(new: *mut c_void, raw: *mut Self) { + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$raw")] + fn __raw(new: *mut c_void, raw: *mut c_void); + } + unsafe { __raw(new, raw.cast::()) } + } unsafe fn __clone(this: *const c_void, new: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$clone")] - fn __clone(this: *const c_void, new: *mut c_void); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$clone")] + fn __clone(this: *const c_void, new: *mut c_void); } unsafe { __clone(this, new) } } unsafe fn __get(this: *const c_void) -> *const Self { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$get")] - fn __get(this: *const c_void) -> *const c_void; - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$get")] + fn __get(this: *const c_void) -> *const c_void; } unsafe { __get(this) }.cast() } unsafe fn __drop(this: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$drop")] - fn __drop(this: *mut c_void); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$drop")] + fn __drop(this: *mut c_void); } unsafe { __drop(this) } } diff --git a/src/sip.rs b/src/sip.rs deleted file mode 100644 index 9e1d050a5..000000000 --- a/src/sip.rs +++ /dev/null @@ -1,228 +0,0 @@ -// 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: -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 b8fe1b5da..32394c667 100644 --- a/src/symbols/exception.rs +++ b/src/symbols/exception.rs @@ -6,7 +6,7 @@ use alloc::string::String; use core::ptr::NonNull; use core::slice; -#[export_name = "cxxbridge1$exception"] +#[unsafe(export_name = "cxxbridge1$exception")] unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> PtrLen { let slice = unsafe { slice::from_raw_parts(ptr, len) }; let string = String::from_utf8_lossy(slice); diff --git a/src/symbols/rust_slice.rs b/src/symbols/rust_slice.rs index df215acf5..6f7fc5787 100644 --- a/src/symbols/rust_slice.rs +++ b/src/symbols/rust_slice.rs @@ -2,19 +2,19 @@ use crate::rust_slice::RustSlice; use core::mem::MaybeUninit; use core::ptr::{self, NonNull}; -#[export_name = "cxxbridge1$slice$new"] +#[unsafe(export_name = "cxxbridge1$slice$new")] unsafe extern "C" fn slice_new(this: &mut MaybeUninit, ptr: NonNull<()>, len: usize) { let this = this.as_mut_ptr(); let rust_slice = RustSlice::from_raw_parts(ptr, len); unsafe { ptr::write(this, rust_slice) } } -#[export_name = "cxxbridge1$slice$ptr"] +#[unsafe(export_name = "cxxbridge1$slice$ptr")] unsafe extern "C" fn slice_ptr(this: &RustSlice) -> NonNull<()> { this.as_non_null_ptr() } -#[export_name = "cxxbridge1$slice$len"] +#[unsafe(export_name = "cxxbridge1$slice$len")] unsafe extern "C" fn slice_len(this: &RustSlice) -> usize { this.len() } diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs index 3b33bc4a5..161a211cd 100644 --- a/src/symbols/rust_str.rs +++ b/src/symbols/rust_str.rs @@ -5,21 +5,21 @@ use core::ptr; use core::slice; use core::str; -#[export_name = "cxxbridge1$str$new"] +#[unsafe(export_name = "cxxbridge1$str$new")] unsafe extern "C" fn str_new(this: &mut MaybeUninit<&str>) { let this = this.as_mut_ptr(); unsafe { ptr::write(this, "") } } #[cfg(feature = "alloc")] -#[export_name = "cxxbridge1$str$ref"] +#[unsafe(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(); let s = string.as_str(); unsafe { ptr::write(this, s) } } -#[export_name = "cxxbridge1$str$from"] +#[unsafe(export_name = "cxxbridge1$str$from")] unsafe extern "C" fn str_from(this: &mut MaybeUninit<&str>, ptr: *const u8, len: usize) -> bool { let slice = unsafe { slice::from_raw_parts(ptr, len) }; match str::from_utf8(slice) { @@ -32,12 +32,12 @@ unsafe extern "C" fn str_from(this: &mut MaybeUninit<&str>, ptr: *const u8, len: } } -#[export_name = "cxxbridge1$str$ptr"] +#[unsafe(export_name = "cxxbridge1$str$ptr")] unsafe extern "C" fn str_ptr(this: &&str) -> *const u8 { this.as_ptr() } -#[export_name = "cxxbridge1$str$len"] +#[unsafe(export_name = "cxxbridge1$str$len")] unsafe extern "C" fn str_len(this: &&str) -> usize { this.len() } diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs index 8b7c8c481..0d5bfed52 100644 --- a/src/symbols/rust_string.rs +++ b/src/symbols/rust_string.rs @@ -7,21 +7,21 @@ use core::ptr; use core::slice; use core::str; -#[export_name = "cxxbridge1$string$new"] +#[unsafe(export_name = "cxxbridge1$string$new")] unsafe extern "C" fn string_new(this: &mut MaybeUninit) { let this = this.as_mut_ptr(); let new = String::new(); unsafe { ptr::write(this, new) } } -#[export_name = "cxxbridge1$string$clone"] +#[unsafe(export_name = "cxxbridge1$string$clone")] unsafe extern "C" fn string_clone(this: &mut MaybeUninit, other: &String) { let this = this.as_mut_ptr(); let clone = other.clone(); unsafe { ptr::write(this, clone) } } -#[export_name = "cxxbridge1$string$from_utf8"] +#[unsafe(export_name = "cxxbridge1$string$from_utf8")] unsafe extern "C" fn string_from_utf8( this: &mut MaybeUninit, ptr: *const u8, @@ -39,7 +39,7 @@ unsafe extern "C" fn string_from_utf8( } } -#[export_name = "cxxbridge1$string$from_utf8_lossy"] +#[unsafe(export_name = "cxxbridge1$string$from_utf8_lossy")] unsafe extern "C" fn string_from_utf8_lossy( this: &mut MaybeUninit, ptr: *const u8, @@ -51,7 +51,7 @@ unsafe extern "C" fn string_from_utf8_lossy( unsafe { ptr::write(this, owned) } } -#[export_name = "cxxbridge1$string$from_utf16"] +#[unsafe(export_name = "cxxbridge1$string$from_utf16")] unsafe extern "C" fn string_from_utf16( this: &mut MaybeUninit, ptr: *const u16, @@ -68,7 +68,7 @@ unsafe extern "C" fn string_from_utf16( } } -#[export_name = "cxxbridge1$string$from_utf16_lossy"] +#[unsafe(export_name = "cxxbridge1$string$from_utf16_lossy")] unsafe extern "C" fn string_from_utf16_lossy( this: &mut MaybeUninit, ptr: *const u16, @@ -80,32 +80,32 @@ unsafe extern "C" fn string_from_utf16_lossy( unsafe { ptr::write(this, owned) } } -#[export_name = "cxxbridge1$string$drop"] +#[unsafe(export_name = "cxxbridge1$string$drop")] unsafe extern "C" fn string_drop(this: &mut ManuallyDrop) { unsafe { ManuallyDrop::drop(this) } } -#[export_name = "cxxbridge1$string$ptr"] +#[unsafe(export_name = "cxxbridge1$string$ptr")] unsafe extern "C" fn string_ptr(this: &String) -> *const u8 { this.as_ptr() } -#[export_name = "cxxbridge1$string$len"] +#[unsafe(export_name = "cxxbridge1$string$len")] unsafe extern "C" fn string_len(this: &String) -> usize { this.len() } -#[export_name = "cxxbridge1$string$capacity"] +#[unsafe(export_name = "cxxbridge1$string$capacity")] unsafe extern "C" fn string_capacity(this: &String) -> usize { this.capacity() } -#[export_name = "cxxbridge1$string$reserve_additional"] +#[unsafe(export_name = "cxxbridge1$string$reserve_additional")] unsafe extern "C" fn string_reserve_additional(this: &mut String, additional: usize) { this.reserve(additional); } -#[export_name = "cxxbridge1$string$reserve_total"] +#[unsafe(export_name = "cxxbridge1$string$reserve_total")] unsafe extern "C" fn string_reserve_total(this: &mut String, new_cap: usize) { if new_cap > this.capacity() { let additional = new_cap - this.len(); diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs index 89c7da44e..0c29a4b19 100644 --- a/src/symbols/rust_vec.rs +++ b/src/symbols/rust_vec.rs @@ -1,9 +1,9 @@ #![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::ffi::c_char; use core::mem; use core::ptr; @@ -14,53 +14,37 @@ macro_rules! rust_vec_shims { const_assert_eq!(mem::align_of::>(), mem::align_of::>()); const _: () = { - attr! { - #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$new")] - unsafe extern "C" fn __new(this: *mut RustVec<$ty>) { - unsafe { ptr::write(this, RustVec::new()) } - } + #[unsafe(export_name = concat!("cxxbridge1$rust_vec$", $segment, "$new"))] + unsafe extern "C" fn __new(this: *mut RustVec<$ty>) { + unsafe { ptr::write(this, RustVec::new()) } } - attr! { - #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$drop")] - unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) { - unsafe { ptr::drop_in_place(this) } - } + #[unsafe(export_name = concat!("cxxbridge1$rust_vec$", $segment, "$drop"))] + unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) { + unsafe { ptr::drop_in_place(this) } } - attr! { - #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$len")] - unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize { - unsafe { &*this }.len() - } + #[unsafe(export_name = concat!("cxxbridge1$rust_vec$", $segment, "$len"))] + unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize { + unsafe { &*this }.len() } - attr! { - #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$capacity")] - unsafe extern "C" fn __capacity(this: *const RustVec<$ty>) -> usize { - unsafe { &*this }.capacity() - } + #[unsafe(export_name = concat!("cxxbridge1$rust_vec$", $segment, "$capacity"))] + unsafe extern "C" fn __capacity(this: *const RustVec<$ty>) -> usize { + unsafe { &*this }.capacity() } - attr! { - #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$data")] - unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty { - unsafe { &*this }.as_ptr() - } + #[unsafe(export_name = concat!("cxxbridge1$rust_vec$", $segment, "$data"))] + unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty { + unsafe { &*this }.as_ptr() } - attr! { - #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$reserve_total")] - unsafe extern "C" fn __reserve_total(this: *mut RustVec<$ty>, new_cap: usize) { - unsafe { &mut *this }.reserve_total(new_cap); - } + #[unsafe(export_name = concat!("cxxbridge1$rust_vec$", $segment, "$reserve_total"))] + unsafe extern "C" fn __reserve_total(this: *mut RustVec<$ty>, new_cap: usize) { + unsafe { &mut *this }.reserve_total(new_cap); } - attr! { - #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$set_len")] - unsafe extern "C" fn __set_len(this: *mut RustVec<$ty>, len: usize) { - unsafe { (*this).set_len(len) } - } + #[unsafe(export_name = concat!("cxxbridge1$rust_vec$", $segment, "$set_len"))] + unsafe extern "C" fn __set_len(this: *mut RustVec<$ty>, len: usize) { + 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) } - } + #[unsafe(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/type_id.rs b/src/type_id.rs index bd2b4ea61..c10c112e6 100644 --- a/src/type_id.rs +++ b/src/type_id.rs @@ -1,6 +1,6 @@ /// For use in impls of the `ExternType` trait. See [`ExternType`]. /// -/// [`ExternType`]: trait.ExternType.html +/// [`ExternType`]: crate::ExternType #[macro_export] macro_rules! type_id { ($($path:tt)*) => { diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs index 33992059e..16742a832 100644 --- a/src/unique_ptr.rs +++ b/src/unique_ptr.rs @@ -1,14 +1,22 @@ use crate::cxx_vector::{CxxVector, VectorElement}; +use crate::extern_type::ExternType; use crate::fmt::display; use crate::kind::Trivial; use crate::string::CxxString; -use crate::ExternType; +#[cfg(feature = "std")] +use alloc::string::String; +#[cfg(feature = "std")] +use alloc::vec::Vec; +use core::cmp::Ordering; use core::ffi::c_void; use core::fmt::{self, Debug, Display}; +use core::hash::{Hash, Hasher}; use core::marker::PhantomData; use core::mem::{self, MaybeUninit}; use core::ops::{Deref, DerefMut}; use core::pin::Pin; +#[cfg(feature = "std")] +use std::io::{self, IoSlice, Read, Seek, SeekFrom, Write}; /// Binding to C++ `std::unique_ptr>`. #[repr(C)] @@ -49,21 +57,22 @@ where /// /// This is the opposite of [std::unique_ptr\::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool). pub fn is_null(&self) -> bool { - let ptr = unsafe { T::__get(self.repr) }; - ptr.is_null() + self.as_ptr().is_null() } /// Returns a reference to the object owned by this UniquePtr if any, /// otherwise None. pub fn as_ref(&self) -> Option<&T> { - unsafe { T::__get(self.repr).as_ref() } + let ptr = self.as_ptr(); + unsafe { ptr.as_ref() } } /// Returns a mutable pinned reference to the object owned by this UniquePtr /// if any, otherwise None. pub fn as_mut(&mut self) -> Option> { + let ptr = self.as_mut_ptr(); unsafe { - let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?; + let mut_reference = ptr.as_mut()?; Some(Pin::new_unchecked(mut_reference)) } } @@ -84,6 +93,23 @@ where } } + /// Returns a raw const pointer to the object owned by this UniquePtr if + /// any, otherwise the null pointer. + pub fn as_ptr(&self) -> *const T { + unsafe { T::__get(self.repr) } + } + + /// Returns a raw mutable pointer to the object owned by this UniquePtr if + /// any, otherwise the null pointer. + /// + /// As with [std::unique_ptr\::get](https://en.cppreference.com/w/cpp/memory/unique_ptr/get), + /// this doesn't require that you hold an exclusive reference to the + /// UniquePtr. This differs from Rust norms, so extra care should be taken + /// in the way the pointer is used. + pub fn as_mut_ptr(&self) -> *mut T { + self.as_ptr().cast_mut() + } + /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T. /// /// Matches the behavior of [std::unique_ptr\::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release). @@ -181,6 +207,151 @@ where } } +impl PartialEq for UniquePtr +where + T: PartialEq + UniquePtrTarget, +{ + fn eq(&self, other: &Self) -> bool { + self.as_ref() == other.as_ref() + } +} + +impl Eq for UniquePtr where T: Eq + UniquePtrTarget {} + +impl PartialOrd for UniquePtr +where + T: PartialOrd + UniquePtrTarget, +{ + fn partial_cmp(&self, other: &Self) -> Option { + PartialOrd::partial_cmp(&self.as_ref(), &other.as_ref()) + } +} + +impl Ord for UniquePtr +where + T: Ord + UniquePtrTarget, +{ + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&self.as_ref(), &other.as_ref()) + } +} + +impl Hash for UniquePtr +where + T: Hash + UniquePtrTarget, +{ + fn hash(&self, hasher: &mut H) + where + H: Hasher, + { + self.as_ref().hash(hasher); + } +} + +/// Forwarding `Read` trait implementation in a manner similar to `Box`. +/// +/// Note that the implementation will panic for null `UniquePtr`. +#[cfg(feature = "std")] +impl Read for UniquePtr +where + for<'a> Pin<&'a mut T>: Read, + T: UniquePtrTarget, +{ + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.pin_mut().read(buf) + } + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.pin_mut().read_to_end(buf) + } + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + self.pin_mut().read_to_string(buf) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + self.pin_mut().read_exact(buf) + } + + // TODO: Foward other `Read` trait methods when they get stabilized (e.g. + // `read_buf` and/or `is_read_vectored`). +} + +/// Forwarding `Seek` trait implementation in a manner similar to `Box`. +/// +/// Note that the implementation will panic for null `UniquePtr`. +#[cfg(feature = "std")] +impl Seek for UniquePtr +where + for<'a> Pin<&'a mut T>: Seek, + T: UniquePtrTarget, +{ + #[inline] + fn seek(&mut self, pos: SeekFrom) -> io::Result { + self.pin_mut().seek(pos) + } + + #[inline] + fn rewind(&mut self) -> io::Result<()> { + self.pin_mut().rewind() + } + + #[inline] + fn stream_position(&mut self) -> io::Result { + self.pin_mut().stream_position() + } + + #[inline] + fn seek_relative(&mut self, offset: i64) -> io::Result<()> { + self.pin_mut().seek_relative(offset) + } + + // TODO: Foward other `Seek` trait methods if/when possible: + // * `stream_len`: If/when stabilized +} + +/// Forwarding `Write` trait implementation in a manner similar to `Box`. +/// +/// Note that the implementation will panic for null `UniquePtr`. +#[cfg(feature = "std")] +impl Write for UniquePtr +where + for<'a> Pin<&'a mut T>: Write, + T: UniquePtrTarget, +{ + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.pin_mut().write(buf) + } + + #[inline] + fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { + self.pin_mut().write_vectored(bufs) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + self.pin_mut().flush() + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.pin_mut().write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + self.pin_mut().write_fmt(fmt) + } + + // TODO: Foward other `Write` trait methods when they get stabilized (e.g. + // `write_all_vectored` and/or `is_write_vectored`). +} + /// Trait bound for types which may be used as the `T` inside of a /// `UniquePtr` in generic code. /// @@ -231,7 +402,7 @@ pub unsafe trait UniquePtrTarget { unsafe fn __drop(repr: MaybeUninit<*mut c_void>); } -extern "C" { +unsafe extern "C" { #[link_name = "cxxbridge1$unique_ptr$std$string$null"] fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>); #[link_name = "cxxbridge1$unique_ptr$std$string$raw"] @@ -251,23 +422,23 @@ unsafe impl UniquePtrTarget for CxxString { fn __null() -> MaybeUninit<*mut c_void> { let mut repr = MaybeUninit::uninit(); unsafe { - unique_ptr_std_string_null(&mut repr); + unique_ptr_std_string_null(&raw mut repr); } repr } unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { let mut repr = MaybeUninit::uninit(); - unsafe { unique_ptr_std_string_raw(&mut repr, raw) } + unsafe { unique_ptr_std_string_raw(&raw mut repr, raw) } repr } unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self { - unsafe { unique_ptr_std_string_get(&repr) } + unsafe { unique_ptr_std_string_get(&raw const repr) } } unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self { - unsafe { unique_ptr_std_string_release(&mut repr) } + unsafe { unique_ptr_std_string_release(&raw mut repr) } } unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) { - unsafe { unique_ptr_std_string_drop(&mut repr) } + unsafe { unique_ptr_std_string_drop(&raw mut repr) } } } diff --git a/src/vector.rs b/src/vector.rs index 4afd4879a..9ee2ddcc3 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -2,8 +2,8 @@ //! //! `CxxVector` itself is exposed at the crate root. -pub use crate::cxx_vector::{Iter, IterMut, VectorElement}; #[doc(inline)] pub use crate::Vector; +pub use crate::cxx_vector::{Iter, IterMut, VectorElement}; #[doc(no_inline)] pub use cxx::CxxVector; diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs index e9320f374..9bb34eb83 100644 --- a/src/weak_ptr.rs +++ b/src/weak_ptr.rs @@ -4,6 +4,7 @@ use core::ffi::c_void; use core::fmt::{self, Debug}; use core::marker::PhantomData; use core::mem::MaybeUninit; +use core::ptr; /// Binding to C++ `std::weak_ptr`. /// @@ -44,7 +45,7 @@ where where T: SharedPtrTarget, { - let this = self as *const Self as *const c_void; + let this = ptr::from_ref::(self).cast::(); let mut shared_ptr = MaybeUninit::>::uninit(); let new = shared_ptr.as_mut_ptr().cast(); unsafe { @@ -64,7 +65,7 @@ where fn clone(&self) -> Self { let mut weak_ptr = MaybeUninit::>::uninit(); let new = weak_ptr.as_mut_ptr().cast(); - let this = self as *const Self as *mut c_void; + let this = ptr::from_ref::(self).cast::(); unsafe { T::__clone(this, new); weak_ptr.assume_init() @@ -77,7 +78,7 @@ where T: WeakPtrTarget, { fn drop(&mut self) { - let this = self as *mut Self as *mut c_void; + let this = ptr::from_mut::(self).cast::(); unsafe { T::__drop(this) } } } @@ -118,47 +119,37 @@ macro_rules! impl_weak_ptr_target { f.write_str($name) } unsafe fn __null(new: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")] - fn __null(new: *mut c_void); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")] + fn __null(new: *mut c_void); } unsafe { __null(new) } } unsafe fn __clone(this: *const c_void, new: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")] - fn __clone(this: *const c_void, new: *mut c_void); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")] + fn __clone(this: *const c_void, new: *mut c_void); } unsafe { __clone(this, new) } } unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")] - fn __downgrade(shared: *const c_void, weak: *mut c_void); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")] + fn __downgrade(shared: *const c_void, weak: *mut c_void); } unsafe { __downgrade(shared, weak) } } unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")] - fn __upgrade(weak: *const c_void, shared: *mut c_void); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")] + fn __upgrade(weak: *const c_void, shared: *mut c_void); } unsafe { __upgrade(weak, shared) } } unsafe fn __drop(this: *mut c_void) { - extern "C" { - attr! { - #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")] - fn __drop(this: *mut c_void); - } + unsafe extern "C" { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")] + fn __drop(this: *mut c_void); } unsafe { __drop(this) } } diff --git a/syntax/atom.rs b/syntax/atom.rs index d4ad78f17..08e04a30a 100644 --- a/syntax/atom.rs +++ b/syntax/atom.rs @@ -3,7 +3,7 @@ use proc_macro2::Ident; use std::fmt::{self, Display}; #[derive(Copy, Clone, PartialEq)] -pub enum Atom { +pub(crate) enum Atom { Bool, Char, // C char, not Rust char U8, @@ -23,11 +23,11 @@ pub enum Atom { } impl Atom { - pub fn from(ident: &Ident) -> Option { + pub(crate) fn from(ident: &Ident) -> Option { Self::from_str(ident.to_string().as_str()) } - pub fn from_str(s: &str) -> Option { + pub(crate) fn from_str(s: &str) -> Option { use self::Atom::*; match s { "bool" => Some(Bool), diff --git a/syntax/attrs.rs b/syntax/attrs.rs index 46d010e0a..8b66ae98e 100644 --- a/syntax/attrs.rs +++ b/syntax/attrs.rs @@ -1,12 +1,11 @@ use crate::syntax::cfg::CfgExpr; use crate::syntax::namespace::Namespace; use crate::syntax::report::Errors; -use crate::syntax::Atom::{self, *}; -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::{parenthesized, token, Attribute, Error, LitStr, Path, Result, Token}; +use crate::syntax::repr::Repr; +use crate::syntax::{Derive, Doc, ForeignName, cfg}; +use proc_macro2::Ident; +use syn::parse::ParseStream; +use syn::{Attribute, Error, Expr, Lit, LitStr, Meta, Path, Result, Token}; // Intended usage: // @@ -27,15 +26,16 @@ use syn::{parenthesized, token, Attribute, Error, LitStr, Path, Result, Token}; // ); // #[derive(Default)] -pub struct Parser<'a> { +pub(crate) struct Parser<'a> { pub cfg: Option<&'a mut CfgExpr>, pub doc: Option<&'a mut Doc>, pub derives: Option<&'a mut Vec>, - pub repr: Option<&'a mut Option>, + pub repr: Option<&'a mut Option>, + pub default: Option<&'a mut bool>, pub namespace: Option<&'a mut Namespace>, pub cxx_name: Option<&'a mut Option>, pub rust_name: Option<&'a mut Option>, - pub variants_from_header: Option<&'a mut Option>, + pub self_type: Option<&'a mut Option>, pub ignore_unrecognized: bool, // Suppress clippy needless_update lint ("struct update has no effect, all @@ -44,11 +44,13 @@ pub struct Parser<'a> { pub(crate) _more: (), } -pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> OtherAttrs { - let mut passthrough_attrs = Vec::new(); +#[must_use] +pub(crate) fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> OtherAttrs { + let mut other_attrs = OtherAttrs::new(); for attr in attrs { - if attr.path.is_ident("doc") { - match parse_doc_attribute.parse2(attr.tokens.clone()) { + let attr_path = attr.path(); + if attr_path.is_ident("doc") { + match parse_doc_attribute(&attr.meta) { Ok(attr) => { if let Some(doc) = &mut parser.doc { match attr { @@ -63,7 +65,7 @@ pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> Othe break; } } - } else if attr.path.is_ident("derive") { + } else if attr_path.is_ident("derive") { match attr.parse_args_with(|attr: ParseStream| parse_derive_attribute(cx, attr)) { Ok(attr) => { if let Some(derives) = &mut parser.derives { @@ -76,8 +78,8 @@ pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> Othe break; } } - } else if attr.path.is_ident("repr") { - match attr.parse_args_with(parse_repr_attribute) { + } else if attr_path.is_ident("repr") { + match attr.parse_args::() { Ok(attr) => { if let Some(repr) = &mut parser.repr { **repr = Some(attr); @@ -89,8 +91,21 @@ pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> Othe break; } } - } else if attr.path.is_ident("namespace") { - match parse_namespace_attribute.parse2(attr.tokens.clone()) { + } else if attr_path.is_ident("default") { + match parse_default_attribute(&attr.meta) { + Ok(()) => { + if let Some(default) = &mut parser.default { + **default = true; + continue; + } + } + Err(err) => { + cx.push(err); + break; + } + } + } else if attr_path.is_ident("namespace") { + match Namespace::parse_meta(&attr.meta) { Ok(attr) => { if let Some(namespace) = &mut parser.namespace { **namespace = attr; @@ -102,8 +117,8 @@ pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> Othe break; } } - } else if attr.path.is_ident("cxx_name") { - match parse_cxx_name_attribute.parse2(attr.tokens.clone()) { + } else if attr_path.is_ident("cxx_name") { + match parse_cxx_name_attribute(&attr.meta) { Ok(attr) => { if let Some(cxx_name) = &mut parser.cxx_name { **cxx_name = Some(attr); @@ -115,8 +130,8 @@ pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> Othe break; } } - } else if attr.path.is_ident("rust_name") { - match parse_rust_name_attribute.parse2(attr.tokens.clone()) { + } else if attr_path.is_ident("rust_name") { + match parse_rust_ident_attribute(&attr.meta) { Ok(attr) => { if let Some(rust_name) = &mut parser.rust_name { **rust_name = Some(attr); @@ -128,12 +143,25 @@ pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> Othe break; } } - } else if attr.path.is_ident("cfg") { - match cfg::parse_attribute.parse2(attr.tokens.clone()) { + } else if attr_path.is_ident("Self") { + match parse_rust_ident_attribute(&attr.meta) { + Ok(attr) => { + if let Some(self_type) = &mut parser.self_type { + **self_type = Some(attr); + continue; + } + } + Err(err) => { + cx.push(err); + break; + } + } + } else if attr_path.is_ident("cfg") { + match cfg::parse_attribute(&attr) { Ok(cfg_expr) => { if let Some(cfg) = &mut parser.cfg { - cfg.merge(cfg_expr); - passthrough_attrs.push(attr); + cfg.merge_and(cfg_expr); + other_attrs.cfg.push(attr); continue; } } @@ -142,36 +170,26 @@ pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> Othe 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); - } - if let Some(variants_from_header) = &mut parser.variants_from_header { - **variants_from_header = Some(attr); - continue; - } - } else if attr.path.is_ident("allow") - || attr.path.is_ident("warn") - || attr.path.is_ident("deny") - || attr.path.is_ident("forbid") - || attr.path.is_ident("deprecated") - || attr.path.is_ident("must_use") + } else if attr_path.is_ident("allow") + || attr_path.is_ident("warn") + || attr_path.is_ident("deny") + || attr_path.is_ident("forbid") { - // https://doc.rust-lang.org/reference/attributes/diagnostics.html - passthrough_attrs.push(attr); + other_attrs.lint.push(attr); continue; - } else if attr.path.is_ident("serde") { - passthrough_attrs.push(attr); + } else if attr_path.is_ident("deprecated") + || attr_path.is_ident("must_use") + || attr_path.is_ident("serde") + { + other_attrs.passthrough.push(attr); continue; - } else if attr.path.segments.len() > 1 { - let tool = &attr.path.segments.first().unwrap().ident; + } else if attr_path.segments.len() > 1 { + let tool = &attr_path.segments.first().unwrap().ident; if tool == "rustfmt" { // Skip, rustfmt only needs to find it in the pre-expansion source file. continue; } else if tool == "clippy" { - passthrough_attrs.push(attr); + other_attrs.lint.push(attr); continue; } } @@ -180,7 +198,7 @@ pub fn parse(cx: &mut Errors, attrs: Vec, mut parser: Parser) -> Othe break; } } - OtherAttrs(passthrough_attrs) + other_attrs } enum DocAttribute { @@ -192,111 +210,115 @@ mod kw { syn::custom_keyword!(hidden); } -fn parse_doc_attribute(input: ParseStream) -> Result { - let lookahead = input.lookahead1(); - if lookahead.peek(Token![=]) { - input.parse::()?; - let lit: LitStr = input.parse()?; - Ok(DocAttribute::Doc(lit)) - } else if lookahead.peek(token::Paren) { - let content; - parenthesized!(content in input); - content.parse::()?; - Ok(DocAttribute::Hidden) - } else { - Err(lookahead.error()) +fn parse_doc_attribute(meta: &Meta) -> Result { + match meta { + Meta::NameValue(meta) => { + if let Expr::Lit(expr) = &meta.value + && let Lit::Str(lit) = &expr.lit + { + return Ok(DocAttribute::Doc(lit.clone())); + } + } + Meta::List(meta) => { + meta.parse_args::()?; + return Ok(DocAttribute::Hidden); + } + Meta::Path(_) => {} } + Err(Error::new_spanned(meta, "unsupported doc attribute")) } fn parse_derive_attribute(cx: &mut Errors, input: ParseStream) -> Result> { - let paths = input.parse_terminated::(Path::parse_mod_style)?; + let paths = input.parse_terminated(Path::parse_mod_style, Token![,])?; let mut derives = Vec::new(); for path in paths { - if let Some(ident) = path.get_ident() { - if let Some(derive) = Derive::from(ident) { - derives.push(derive); - continue; - } + if let Some(ident) = path.get_ident() + && let Some(derive) = Derive::from(ident) + { + derives.push(derive); + continue; } cx.error(path, "unsupported derive"); } Ok(derives) } -fn parse_repr_attribute(input: ParseStream) -> Result { - let begin = input.cursor(); - let ident: Ident = input.parse()?; - if let Some(atom) = Atom::from(&ident) { - match atom { - U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize if input.is_empty() => { - return Ok(atom); - } - _ => {} - } - } - Err(Error::new_spanned( - begin.token_stream(), - "unrecognized repr", +fn parse_default_attribute(meta: &Meta) -> Result<()> { + let error_span = match meta { + Meta::Path(_) => return Ok(()), + Meta::List(meta) => meta.delimiter.span().open(), + Meta::NameValue(meta) => meta.eq_token.span, + }; + Err(Error::new( + error_span, + "#[default] attribute does not accept an argument", )) } -fn parse_namespace_attribute(input: ParseStream) -> Result { - input.parse::()?; - let namespace = input.parse::()?; - Ok(namespace) -} - -fn parse_cxx_name_attribute(input: ParseStream) -> Result { - input.parse::()?; - if input.peek(LitStr) { - let lit: LitStr = input.parse()?; - ForeignName::parse(&lit.value(), lit.span()) - } else { - let ident: Ident = input.parse()?; - ForeignName::parse(&ident.to_string(), ident.span()) +fn parse_cxx_name_attribute(meta: &Meta) -> Result { + if let Meta::NameValue(meta) = meta { + match &meta.value { + Expr::Lit(expr) => { + if let Lit::Str(lit) = &expr.lit { + return ForeignName::parse(&lit.value(), lit.span()); + } + } + Expr::Path(expr) => { + if let Some(ident) = expr.path.get_ident() { + return ForeignName::parse(&ident.to_string(), ident.span()); + } + } + _ => {} + } } + Err(Error::new_spanned(meta, "unsupported cxx_name attribute")) } -fn parse_rust_name_attribute(input: ParseStream) -> Result { - input.parse::()?; - if input.peek(LitStr) { - let lit: LitStr = input.parse()?; - lit.parse() - } else { - input.parse() +fn parse_rust_ident_attribute(meta: &Meta) -> Result { + if let Meta::NameValue(meta) = meta { + match &meta.value { + Expr::Lit(expr) => { + if let Lit::Str(lit) = &expr.lit { + return lit.parse(); + } + } + Expr::Path(expr) => { + if let Some(ident) = expr.path.get_ident() { + return Ok(ident.clone()); + } + } + _ => {} + } } + Err(Error::new_spanned( + meta, + format!( + "unsupported `{}` attribute", + meta.path().get_ident().unwrap(), + ), + )) } #[derive(Clone)] -pub struct OtherAttrs(Vec); +pub(crate) struct OtherAttrs { + pub cfg: Vec, + pub lint: Vec, + pub passthrough: Vec, +} impl OtherAttrs { - pub fn none() -> Self { - OtherAttrs(Vec::new()) - } - - pub fn extend(&mut self, other: Self) { - self.0.extend(other.0); + pub(crate) fn new() -> Self { + OtherAttrs { + cfg: Vec::new(), + lint: Vec::new(), + passthrough: Vec::new(), + } } -} -impl ToTokens for OtherAttrs { - fn to_tokens(&self, tokens: &mut TokenStream) { - for attr in &self.0 { - let Attribute { - pound_token, - style, - bracket_token, - path, - tokens: attr_tokens, - } = attr; - pound_token.to_tokens(tokens); - let _ = style; // ignore; render outer and inner attrs both as outer - bracket_token.surround(tokens, |tokens| { - path.to_tokens(tokens); - attr_tokens.to_tokens(tokens); - }); - } + pub(crate) fn extend(&mut self, other: Self) { + self.cfg.extend(other.cfg); + self.lint.extend(other.lint); + self.passthrough.extend(other.passthrough); } } diff --git a/syntax/cfg.rs b/syntax/cfg.rs index d486b9958..b28c7ea82 100644 --- a/syntax/cfg.rs +++ b/syntax/cfg.rs @@ -1,10 +1,13 @@ +use indexmap::{IndexSet as Set, indexset as set}; use proc_macro2::Ident; +use std::hash::{Hash, Hasher}; +use std::iter; use std::mem; use syn::parse::{Error, ParseStream, Result}; -use syn::{parenthesized, token, LitStr, Token}; +use syn::{Attribute, LitStr, Token, parenthesized, token}; #[derive(Clone)] -pub enum CfgExpr { +pub(crate) enum CfgExpr { Unconditional, Eq(Ident, Option), All(Vec), @@ -12,10 +15,19 @@ pub enum CfgExpr { Not(Box), } +#[derive(Clone)] +pub(crate) enum ComputedCfg<'a> { + Leaf(&'a CfgExpr), + All(Set<&'a CfgExpr>), + Any(Set>), +} + impl CfgExpr { - pub fn merge(&mut self, expr: CfgExpr) { + pub(crate) fn merge_and(&mut self, expr: CfgExpr) { if let CfgExpr::Unconditional = self { *self = expr; + } else if let CfgExpr::Unconditional = expr { + // drop } else if let CfgExpr::All(list) = self { list.push(expr); } else { @@ -25,12 +37,122 @@ impl CfgExpr { } } -pub fn parse_attribute(input: ParseStream) -> Result { - let content; - parenthesized!(content in input); - let cfg_expr = content.call(parse_single)?; - content.parse::>()?; - Ok(cfg_expr) +impl<'a> ComputedCfg<'a> { + pub(crate) fn all(one: &'a CfgExpr, two: &'a CfgExpr) -> Self { + if let (cfg, CfgExpr::Unconditional) | (CfgExpr::Unconditional, cfg) = (one, two) { + ComputedCfg::Leaf(cfg) + } else if one == two { + ComputedCfg::Leaf(one) + } else { + ComputedCfg::All(set![one, two]) + } + } + + pub(crate) fn merge_or(&mut self, other: impl Into>) { + let other = other.into(); + if let ComputedCfg::Leaf(CfgExpr::Unconditional) = self { + // drop + } else if let ComputedCfg::Leaf(CfgExpr::Unconditional) = other { + *self = other; + } else if *self == other { + // drop + } else if let ComputedCfg::Any(list) = self { + list.insert(other); + } else { + let prev = mem::replace(self, ComputedCfg::Any(Set::new())); + let ComputedCfg::Any(list) = self else { + unreachable!(); + }; + list.extend([prev, other]); + } + } +} + +impl<'a> From<&'a CfgExpr> for ComputedCfg<'a> { + fn from(cfg: &'a CfgExpr) -> Self { + ComputedCfg::Leaf(cfg) + } +} + +impl Eq for CfgExpr {} + +impl PartialEq for CfgExpr { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (CfgExpr::Unconditional, CfgExpr::Unconditional) => true, + (CfgExpr::Eq(this_ident, None), CfgExpr::Eq(other_ident, None)) => { + this_ident == other_ident + } + ( + CfgExpr::Eq(this_ident, Some(this_value)), + CfgExpr::Eq(other_ident, Some(other_value)), + ) => { + this_ident == other_ident + && this_value.token().to_string() == other_value.token().to_string() + } + (CfgExpr::All(this), CfgExpr::All(other)) + | (CfgExpr::Any(this), CfgExpr::Any(other)) => this == other, + (CfgExpr::Not(this), CfgExpr::Not(other)) => this == other, + (_, _) => false, + } + } +} + +impl Hash for CfgExpr { + fn hash(&self, hasher: &mut H) { + mem::discriminant(self).hash(hasher); + match self { + CfgExpr::Unconditional => {} + CfgExpr::Eq(ident, value) => { + ident.hash(hasher); + // syn::LitStr does not have its own Hash impl + value.as_ref().map(LitStr::value).hash(hasher); + } + CfgExpr::All(inner) | CfgExpr::Any(inner) => inner.hash(hasher), + CfgExpr::Not(inner) => inner.hash(hasher), + } + } +} + +impl<'a> Eq for ComputedCfg<'a> {} + +impl<'a> PartialEq for ComputedCfg<'a> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (ComputedCfg::Leaf(this), ComputedCfg::Leaf(other)) => this == other, + // For the purpose of deduplicating the contents of an `all` or + // `any`, we only consider sets equal if they contain the same cfgs + // in the same order. + (ComputedCfg::All(this), ComputedCfg::All(other)) => { + this.len() == other.len() + && iter::zip(this, other).all(|(this, other)| this == other) + } + (ComputedCfg::Any(this), ComputedCfg::Any(other)) => { + this.len() == other.len() + && iter::zip(this, other).all(|(this, other)| this == other) + } + (_, _) => false, + } + } +} + +impl<'a> Hash for ComputedCfg<'a> { + fn hash(&self, hasher: &mut H) { + mem::discriminant(self).hash(hasher); + match self { + ComputedCfg::Leaf(cfg) => cfg.hash(hasher), + ComputedCfg::All(inner) => inner.iter().for_each(|cfg| cfg.hash(hasher)), + ComputedCfg::Any(inner) => inner.iter().for_each(|cfg| cfg.hash(hasher)), + } + } +} + +pub(crate) fn parse_attribute(attr: &Attribute) -> Result { + attr.parse_args_with(|input: ParseStream| { + let cfg_expr = input.call(parse_single)?; + input.parse::>()?; + Ok(cfg_expr) + }) } fn parse_single(input: ParseStream) -> Result { diff --git a/syntax/check.rs b/syntax/check.rs index 66883be03..486fae38e 100644 --- a/syntax/check.rs +++ b/syntax/check.rs @@ -1,12 +1,14 @@ use crate::syntax::atom::Atom::{self, *}; +use crate::syntax::message::Message; use crate::syntax::report::Errors; use crate::syntax::visit::{self, Visit}; use crate::syntax::{ - error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Lifetimes, - NamedType, Ptr, Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types, + Api, Array, Enum, ExternFn, ExternType, FnKind, Impl, Lang, Lifetimes, NamedType, Ptr, + Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types, error, ident, + trivial, }; use proc_macro2::{Delimiter, Group, Ident, TokenStream}; -use quote::{quote, ToTokens}; +use quote::{ToTokens, quote}; use std::fmt::Display; use syn::{GenericParam, Generics, Lifetime}; @@ -19,14 +21,14 @@ pub(crate) struct Check<'a> { pub(crate) enum Generator { // cxx-build crate, cxxbridge cli, cxx-gen. - #[allow(dead_code)] + #[cfg_attr(proc_macro, expect(dead_code))] Build, // cxxbridge-macro. This is relevant in that the macro output is going to // get fed straight to rustc, so for errors that rustc already contains // logic to catch (probably with a better diagnostic than what the proc // macro API is able to produce), we avoid duplicating them in our own // diagnostics. - #[allow(dead_code)] + #[cfg_attr(not(proc_macro), expect(dead_code))] Macro, } @@ -123,13 +125,19 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) { } match Atom::from(&ident.rust) { - 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, + None + | Some( + Bool | Char | U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize | F32 + | F64 | RustString, + ) => return, Some(CxxString) => {} } } Type::Str(_) => return, + Type::RustBox(ty1) => { + check_type_box(cx, ty1); + return; + } _ => {} } @@ -162,10 +170,12 @@ fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) { } match Atom::from(&ident.rust) { - None | Some(Bool) | 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(CxxString) => return, - Some(Char) | Some(RustString) => {} + None + | Some( + Bool | U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize | F32 | F64 + | CxxString, + ) => return, + Some(Char | RustString) => {} } } else if let Type::CxxVector(_) = &ptr.inner { cx.error(ptr, "std::shared_ptr is not supported yet"); @@ -183,10 +193,12 @@ fn check_type_weak_ptr(cx: &mut Check, ptr: &Ty1) { } match Atom::from(&ident.rust) { - None | Some(Bool) | 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(CxxString) => return, - Some(Char) | Some(RustString) => {} + None + | Some( + Bool | U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize | F32 | F64 + | CxxString, + ) => return, + Some(Char | RustString) => {} } } else if let Type::CxxVector(_) = &ptr.inner { cx.error(ptr, "std::weak_ptr is not supported yet"); @@ -207,11 +219,12 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) { } match Atom::from(&ident.rust) { - None | 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(CxxString) => return, + None + | Some( + U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize | F32 | F64 | CxxString, + ) => return, Some(Char) => { /* todo */ } - Some(Bool) | Some(RustString) => {} + Some(Bool | RustString) => {} } } @@ -219,22 +232,29 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) { } fn check_type_ref(cx: &mut Check, ty: &Ref) { - if ty.mutable && !ty.pinned { - if let Some(requires_pin) = match &ty.inner { - Type::Ident(ident) if ident.rust == CxxString || is_opaque_cxx(cx, &ident.rust) => { + if ty.mutable + && !ty.pinned + && let Some(requires_pin) = match &ty.inner { + Type::Ident(ident) + if ident.rust == CxxString + || (cx.types.cxx.contains(&ident.rust) + && !cx.types.structs.contains_key(&ident.rust) + && !cx.types.enums.contains_key(&ident.rust) + && !cx.types.aliases.contains_key(&ident.rust)) => + { Some(ident.rust.to_string()) } Type::CxxVector(_) => Some("CxxVector<...>".to_owned()), _ => None, - } { - cx.error( - ty, - format!( - "mutable reference to C++ type requires a pin -- use Pin<&mut {}>", - requires_pin, - ), - ); } + { + cx.error( + ty, + format!( + "mutable reference to C++ type requires a pin -- use Pin<&mut {}>", + requires_pin, + ), + ); } match ty.inner { @@ -263,7 +283,7 @@ fn check_type_ptr(cx: &mut Check, ty: &Ptr) { } fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) { - let supported = !is_unsized(cx, &ty.inner) + let supported = !is_unsized(cx.types, &ty.inner) || match &ty.inner { Type::Ident(ident) => { cx.types.rust.contains(&ident.rust) || cx.types.aliases.contains_key(&ident.rust) @@ -274,17 +294,19 @@ fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) { if !supported { let mutable = if ty.mutable { "mut " } else { "" }; let mut msg = format!("unsupported &{}[T] element type", mutable); - if let Type::Ident(ident) = &ty.inner { - if is_opaque_cxx(cx, &ident.rust) { - msg += ": opaque C++ type is not supported yet"; - } + if let Type::Ident(ident) = &ty.inner + && cx.types.cxx.contains(&ident.rust) + && !cx.types.structs.contains_key(&ident.rust) + && !cx.types.enums.contains_key(&ident.rust) + { + msg += ": opaque C++ type is not supported yet"; } cx.error(ty, msg); } } fn check_type_array(cx: &mut Check, ty: &Array) { - let supported = !is_unsized(cx, &ty.inner); + let supported = !is_unsized(cx.types, &ty.inner); if !supported { cx.error(ty, "unsupported array element type"); @@ -297,13 +319,13 @@ fn check_type_fn(cx: &mut Check, ty: &Signature) { } for arg in &ty.args { - if let Type::Ptr(_) = arg.ty { - if ty.unsafety.is_none() { - cx.error( - arg, - "pointer argument requires that the function pointer be marked unsafe", - ); - } + if let Type::Ptr(_) = arg.ty + && ty.unsafety.is_none() + { + cx.error( + arg, + "pointer argument requires that the function pointer be marked unsafe", + ); } } } @@ -318,17 +340,37 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) { cx.error(span, "structs without any fields are not supported"); } - if cx.types.cxx.contains(&name.rust) { - if let Some(ety) = cx.types.untrusted.get(&name.rust) { - let msg = "extern shared struct must be declared in an `unsafe extern` block"; - cx.error(ety, msg); - } + if cx.types.cxx.contains(&name.rust) + && let Some(ety) = cx.types.untrusted.get(&name.rust) + { + let msg = "extern shared struct must be declared in an `unsafe extern` block"; + cx.error(ety, msg); } for derive in &strct.derives { - if derive.what == Trait::ExternType { - let msg = format!("derive({}) on shared struct is not supported", derive); - cx.error(derive, msg); + match derive.what { + Trait::Clone + | Trait::Copy + | Trait::Debug + | Trait::Default + | Trait::Eq + | Trait::Hash + | Trait::Ord + | Trait::PartialEq + | Trait::PartialOrd + | Trait::Serialize + | Trait::Deserialize => {} + Trait::BitAnd | Trait::BitOr | Trait::BitXor => { + let msg = format!( + "derive({}) is currently only supported on enums, not structs", + derive, + ); + cx.error(derive, msg); + } + Trait::ExternType => { + let msg = format!("derive({}) on shared struct is not supported", derive); + cx.error(derive, msg); + } } } @@ -338,8 +380,8 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) { field, "function pointers in a struct field are not implemented yet", ); - } else if is_unsized(cx, &field.ty) { - let desc = describe(cx, &field.ty); + } else if is_unsized(cx.types, &field.ty) { + let desc = describe(cx.types, &field.ty); let msg = format!("using {} by value is not supported", desc); cx.error(field, msg); } @@ -350,7 +392,7 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) { check_reserved_name(cx, &enm.name.rust); check_lifetimes(cx, &enm.generics); - if enm.variants.is_empty() && !enm.explicit_repr && !enm.variants_from_header { + if enm.variants.is_empty() && !enm.explicit_repr { let span = span_for_enum_error(enm); cx.error( span, @@ -359,9 +401,38 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) { } for derive in &enm.derives { - if derive.what == Trait::Default || derive.what == Trait::ExternType { - let msg = format!("derive({}) on shared enum is not supported", derive); - cx.error(derive, msg); + match derive.what { + Trait::BitAnd + | Trait::BitOr + | Trait::BitXor + | Trait::Clone + | Trait::Copy + | Trait::Debug + | Trait::Eq + | Trait::Hash + | Trait::Ord + | Trait::PartialEq + | Trait::PartialOrd + | Trait::Serialize + | Trait::Deserialize => {} + Trait::Default => { + let default_variants = enm.variants.iter().filter(|v| v.default).count(); + if default_variants != 1 { + let mut msg = Message::new(); + write!( + msg, + "derive(Default) on enum requires exactly one variant to be marked with #[default]" + ); + if default_variants > 0 { + write!(msg, " (found {})", default_variants); + } + cx.error(derive, msg); + } + } + Trait::ExternType => { + let msg = "derive(ExternType) on shared enum is not supported"; + cx.error(derive, msg); + } } } } @@ -376,7 +447,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) { } let lang = match ety.lang { Lang::Rust => "Rust", - Lang::Cxx => "C++", + Lang::Cxx | Lang::CxxUnwind => "C++", }; let msg = format!( "derive({}) on opaque {} type is not supported yet", @@ -402,7 +473,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) { fn check_api_fn(cx: &mut Check, efn: &ExternFn) { match efn.lang { - Lang::Cxx => { + Lang::Cxx | Lang::CxxUnwind => { if !efn.generics.params.is_empty() && !efn.trusted { let ref span = span_for_generics_error(efn); cx.error(span, "extern C++ function with lifetimes must be declared in `unsafe extern \"C++\"` block"); @@ -420,40 +491,61 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) { } } - check_generics(cx, &efn.sig.generics); + check_generics(cx, &efn.generics); - if let Some(receiver) = &efn.receiver { - let ref span = span_for_receiver_error(receiver); + match &efn.kind { + FnKind::Method(receiver) => { + let ref span = span_for_receiver_error(receiver); - if receiver.ty.rust == "Self" { - let mutability = match receiver.mutable { - true => "mut ", - false => "", - }; - let msg = format!( - "unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &{mutability}TheType`", - mutability = mutability, - ); - cx.error(span, msg); - } else if cx.types.enums.contains_key(&receiver.ty.rust) { - cx.error( - span, - "unsupported receiver type; C++ does not allow member functions on enums", - ); - } else if !cx.types.structs.contains_key(&receiver.ty.rust) - && !cx.types.cxx.contains(&receiver.ty.rust) - && !cx.types.rust.contains(&receiver.ty.rust) - { - cx.error(span, "unrecognized receiver type"); - } else if receiver.mutable && !receiver.pinned && is_opaque_cxx(cx, &receiver.ty.rust) { - cx.error( - span, - format!( - "mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut {}>`", - receiver.ty.rust, - ), - ); + if receiver.ty.rust == "Self" { + let mutability = match receiver.mutable { + true => "mut ", + false => "", + }; + let msg = format!( + "unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &{mutability}TheType`", + mutability = mutability, + ); + cx.error(span, msg); + } else if cx.types.enums.contains_key(&receiver.ty.rust) { + cx.error( + span, + "unsupported receiver type; C++ does not allow member functions on enums", + ); + } else if !cx.types.structs.contains_key(&receiver.ty.rust) + && !cx.types.cxx.contains(&receiver.ty.rust) + && !cx.types.rust.contains(&receiver.ty.rust) + { + cx.error(span, "unrecognized receiver type"); + } else if receiver.mutable + && !receiver.pinned + && cx.types.cxx.contains(&receiver.ty.rust) + && !cx.types.structs.contains_key(&receiver.ty.rust) + && !cx.types.aliases.contains_key(&receiver.ty.rust) + { + cx.error( + span, + format!( + "mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut {}>`", + receiver.ty.rust, + ), + ); + } + } + FnKind::Assoc(self_type) => { + if cx.types.enums.contains_key(self_type) { + cx.error( + self_type, + "unsupported self type; C++ does not allow member functions on enums", + ); + } else if !cx.types.structs.contains_key(self_type) + && !cx.types.cxx.contains(self_type) + && !cx.types.rust.contains(self_type) + { + cx.error(self_type, "unrecognized self type"); + } } + FnKind::Free => {} } for arg in &efn.args { @@ -465,14 +557,14 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) { ); } } else if let Type::Ptr(_) = arg.ty { - if efn.sig.unsafety.is_none() { + if efn.unsafety.is_none() { cx.error( arg, "pointer argument requires that the function be marked unsafe", ); } - } else if is_unsized(cx, &arg.ty) { - let desc = describe(cx, &arg.ty); + } else if is_unsized(cx.types, &arg.ty) { + let desc = describe(cx.types, &arg.ty); let msg = format!("passing {} by value is not supported", desc); cx.error(arg, msg); } @@ -481,8 +573,8 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) { if let Some(ty) = &efn.ret { if let Type::Fn(_) = ty { cx.error(ty, "returning a function pointer is not implemented yet"); - } else if is_unsized(cx, ty) { - let desc = describe(cx, ty); + } else if is_unsized(cx.types, ty) { + let desc = describe(cx.types, ty); let msg = format!("returning {} by value is not supported", desc); cx.error(ty, msg); } @@ -521,19 +613,19 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) { | Type::WeakPtr(ty) | Type::CxxVector(ty) => { if let Type::Ident(inner) = &ty.inner { - if Atom::from(&inner.rust).is_none() { - return; + // Reject `impl Vec` and other built-in impls. + if Atom::from(&inner.rust).is_some() { + cx.error(imp, "unsupported Self type of explicit impl"); } } } - _ => {} + // Reject `impl fn() -> &S {}`, `impl [S]`, etc. + _ => cx.error(imp, "unsupported Self type of explicit impl"), } - - cx.error(imp, "unsupported Self type of explicit impl"); } fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) { - if efn.sig.unsafety.is_some() { + if efn.unsafety.is_some() { // Unrestricted as long as the function is made unsafe-to-call. return; } @@ -544,13 +636,12 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) { _ => return, } - if let Some(receiver) = &efn.receiver { + if let Some(receiver) = efn.receiver() { if receiver.mutable { return; } - let resolve = match cx.types.try_resolve(&receiver.ty) { - Some(resolve) => resolve, - None => return, + let Some(resolve) = cx.types.try_resolve(&receiver.ty) else { + return; }; if !resolve.generics.lifetimes.is_empty() { return; @@ -634,13 +725,19 @@ fn check_generics(cx: &mut Check, generics: &Generics) { } } -fn is_unsized(cx: &mut Check, ty: &Type) -> bool { +fn is_unsized(types: &Types, ty: &Type) -> bool { match ty { Type::Ident(ident) => { let ident = &ident.rust; - ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident) - } - Type::Array(array) => is_unsized(cx, &array.inner), + ident == CxxString + || (types.cxx.contains(ident) + && !types.structs.contains_key(ident) + && !types.enums.contains_key(ident) + && !(types.aliases.contains_key(ident) + && types.required_trivial.contains_key(ident))) + || types.rust.contains(ident) + } + Type::Array(array) => is_unsized(types, &array.inner), Type::CxxVector(_) | Type::Fn(_) | Type::Void(_) => true, Type::RustBox(_) | Type::RustVec(_) @@ -654,24 +751,17 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool { } } -fn is_opaque_cxx(cx: &mut Check, ty: &Ident) -> bool { - cx.types.cxx.contains(ty) - && !cx.types.structs.contains_key(ty) - && !cx.types.enums.contains_key(ty) - && !(cx.types.aliases.contains_key(ty) && cx.types.required_trivial.contains_key(ty)) -} - fn span_for_struct_error(strct: &Struct) -> TokenStream { let struct_token = strct.struct_token; let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new()); - brace_token.set_span(strct.brace_token.span); + brace_token.set_span(strct.brace_token.span.join()); quote!(#struct_token #brace_token) } fn span_for_enum_error(enm: &Enum) -> TokenStream { let enum_token = enm.enum_token; let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new()); - brace_token.set_span(enm.brace_token.span); + brace_token.set_span(enm.brace_token.span.join()); quote!(#enum_token #brace_token) } @@ -695,18 +785,18 @@ fn span_for_generics_error(efn: &ExternFn) -> TokenStream { quote!(#unsafety #fn_token #generics) } -fn describe(cx: &mut Check, ty: &Type) -> String { +fn describe(types: &Types, ty: &Type) -> String { match ty { Type::Ident(ident) => { - if cx.types.structs.contains_key(&ident.rust) { + if types.structs.contains_key(&ident.rust) { "struct".to_owned() - } else if cx.types.enums.contains_key(&ident.rust) { + } else if types.enums.contains_key(&ident.rust) { "enum".to_owned() - } else if cx.types.aliases.contains_key(&ident.rust) { + } else if types.aliases.contains_key(&ident.rust) { "C++ type".to_owned() - } else if cx.types.cxx.contains(&ident.rust) { + } else if types.cxx.contains(&ident.rust) { "opaque C++ type".to_owned() - } else if cx.types.rust.contains(&ident.rust) { + } else if types.rust.contains(&ident.rust) { "opaque Rust type".to_owned() } else if Atom::from(&ident.rust) == Some(CxxString) { "C++ string".to_owned() diff --git a/syntax/derive.rs b/syntax/derive.rs index 7727fbc94..641263020 100644 --- a/syntax/derive.rs +++ b/syntax/derive.rs @@ -2,13 +2,16 @@ use proc_macro2::{Ident, Span}; use std::fmt::{self, Display}; #[derive(Copy, Clone)] -pub struct Derive { +pub(crate) struct Derive { pub what: Trait, pub span: Span, } #[derive(Copy, Clone, PartialEq)] -pub enum Trait { +pub(crate) enum Trait { + BitAnd, + BitOr, + BitXor, Clone, Copy, Debug, @@ -24,8 +27,11 @@ pub enum Trait { } impl Derive { - pub fn from(ident: &Ident) -> Option { + pub(crate) fn from(ident: &Ident) -> Option { let what = match ident.to_string().as_str() { + "BitAnd" => Trait::BitAnd, + "BitOr" => Trait::BitOr, + "BitXor" => Trait::BitXor, "Clone" => Trait::Clone, "Copy" => Trait::Copy, "Debug" => Trait::Debug, @@ -54,6 +60,9 @@ impl PartialEq for Derive { impl AsRef for Trait { fn as_ref(&self) -> &str { match self { + Trait::BitAnd => "BitAnd", + Trait::BitOr => "BitOr", + Trait::BitXor => "BitXor", Trait::Clone => "Clone", Trait::Copy => "Copy", Trait::Debug => "Debug", @@ -76,6 +85,6 @@ impl Display for Derive { } } -pub fn contains(derives: &[Derive], query: Trait) -> bool { +pub(crate) fn contains(derives: &[Derive], query: Trait) -> bool { derives.iter().any(|derive| derive.what == query) } diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs index 21a6d00a3..2dbc2d03c 100644 --- a/syntax/discriminant.rs +++ b/syntax/discriminant.rs @@ -5,17 +5,16 @@ use std::cmp::Ordering; use std::collections::BTreeSet; use std::fmt::{self, Display}; use std::str::FromStr; -use std::u64; use syn::{Error, Expr, Lit, Result, Token, UnOp}; -pub struct DiscriminantSet { +pub(crate) struct DiscriminantSet { repr: Option, values: BTreeSet, previous: Option, } #[derive(Copy, Clone, Eq, PartialEq)] -pub struct Discriminant { +pub(crate) struct Discriminant { sign: Sign, magnitude: u64, } @@ -27,7 +26,7 @@ enum Sign { } impl DiscriminantSet { - pub fn new(repr: Option) -> Self { + pub(crate) fn new(repr: Option) -> Self { DiscriminantSet { repr, values: BTreeSet::new(), @@ -35,7 +34,7 @@ impl DiscriminantSet { } } - pub fn insert(&mut self, expr: &Expr) -> Result { + pub(crate) fn insert(&mut self, expr: &Expr) -> Result { let (discriminant, repr) = expr_to_discriminant(expr)?; match (self.repr, repr) { (None, Some(new_repr)) => { @@ -62,7 +61,7 @@ impl DiscriminantSet { insert(self, discriminant) } - pub fn insert_next(&mut self) -> Result { + pub(crate) fn insert_next(&mut self) -> Result { let discriminant = match self.previous { None => Discriminant::zero(), Some(mut discriminant) => match discriminant.sign { @@ -86,7 +85,7 @@ impl DiscriminantSet { insert(self, discriminant) } - pub fn inferred_repr(&self) -> Result { + pub(crate) fn inferred_repr(&self) -> Result { if let Some(repr) = self.repr { return Ok(repr); } @@ -133,16 +132,15 @@ fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option)> { } fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result { - if let Some(expected_repr) = set.repr { - if let Some(limits) = Limits::of(expected_repr) { - if discriminant < limits.min || limits.max < discriminant { - let msg = format!( - "discriminant value `{}` is outside the limits of {}", - discriminant, expected_repr, - ); - return Err(Error::new(Span::call_site(), msg)); - } - } + if let Some(expected_repr) = set.repr + && let Some(limits) = Limits::of(expected_repr) + && (discriminant < limits.min || limits.max < discriminant) + { + let msg = format!( + "discriminant value `{}` is outside the limits of {}", + discriminant, expected_repr, + ); + return Err(Error::new(Span::call_site(), msg)); } set.values.insert(discriminant); set.previous = Some(discriminant); @@ -150,7 +148,7 @@ fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result Self { + pub(crate) const fn zero() -> Self { Discriminant { sign: Sign::Positive, magnitude: 0, @@ -179,29 +177,6 @@ impl Discriminant { magnitude: i.wrapping_abs() as u64, } } - - #[cfg(feature = "experimental-enum-variants-from-header")] - pub const fn checked_succ(self) -> Option { - match self.sign { - Sign::Negative => { - if self.magnitude == 1 { - Some(Discriminant::zero()) - } else { - Some(Discriminant { - sign: Sign::Negative, - magnitude: self.magnitude - 1, - }) - } - } - Sign::Positive => match self.magnitude.checked_add(1) { - Some(magnitude) => Some(Discriminant { - sign: Sign::Positive, - magnitude, - }), - None => None, - }, - } - } } impl Display for Discriminant { @@ -275,14 +250,14 @@ fn parse_int_suffix(suffix: &str) -> Result> { } #[derive(Copy, Clone)] -struct Limits { - repr: Atom, - min: Discriminant, - max: Discriminant, +pub(crate) struct Limits { + pub repr: Atom, + pub min: Discriminant, + pub max: Discriminant, } impl Limits { - fn of(repr: Atom) -> Option { + pub(crate) fn of(repr: Atom) -> Option { for limits in &LIMITS { if limits.repr == repr { return Some(*limits); @@ -296,41 +271,41 @@ const LIMITS: [Limits; 8] = [ Limits { repr: U8, min: Discriminant::zero(), - max: Discriminant::pos(std::u8::MAX as u64), + max: Discriminant::pos(u8::MAX as u64), }, Limits { repr: I8, - min: Discriminant::neg(std::i8::MIN as i64), - max: Discriminant::pos(std::i8::MAX as u64), + min: Discriminant::neg(i8::MIN as i64), + max: Discriminant::pos(i8::MAX as u64), }, Limits { repr: U16, min: Discriminant::zero(), - max: Discriminant::pos(std::u16::MAX as u64), + max: Discriminant::pos(u16::MAX as u64), }, Limits { repr: I16, - min: Discriminant::neg(std::i16::MIN as i64), - max: Discriminant::pos(std::i16::MAX as u64), + min: Discriminant::neg(i16::MIN as i64), + max: Discriminant::pos(i16::MAX as u64), }, Limits { repr: U32, min: Discriminant::zero(), - max: Discriminant::pos(std::u32::MAX as u64), + max: Discriminant::pos(u32::MAX as u64), }, Limits { repr: I32, - min: Discriminant::neg(std::i32::MIN as i64), - max: Discriminant::pos(std::i32::MAX as u64), + min: Discriminant::neg(i32::MIN as i64), + max: Discriminant::pos(i32::MAX as u64), }, Limits { repr: U64, min: Discriminant::zero(), - max: Discriminant::pos(std::u64::MAX), + max: Discriminant::pos(u64::MAX), }, Limits { repr: I64, - min: Discriminant::neg(std::i64::MIN), - max: Discriminant::pos(std::i64::MAX as u64), + min: Discriminant::neg(i64::MIN), + max: Discriminant::pos(i64::MAX as u64), }, ]; diff --git a/syntax/doc.rs b/syntax/doc.rs index 5de824f3a..096b63f9e 100644 --- a/syntax/doc.rs +++ b/syntax/doc.rs @@ -1,31 +1,31 @@ use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; +use quote::{ToTokens, quote}; use syn::LitStr; -pub struct Doc { - pub(crate) hidden: bool, +pub(crate) struct Doc { + pub hidden: bool, fragments: Vec, } impl Doc { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Doc { hidden: false, fragments: Vec::new(), } } - pub fn push(&mut self, lit: LitStr) { + pub(crate) fn push(&mut self, lit: LitStr) { self.fragments.push(lit); } - #[allow(dead_code)] // only used by cxx-build, not cxxbridge-macro - pub fn is_empty(&self) -> bool { + #[cfg_attr(proc_macro, expect(dead_code))] + pub(crate) 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 { + #[cfg_attr(proc_macro, expect(dead_code))] + pub(crate) fn to_string(&self) -> String { let mut doc = String::new(); for lit in &self.fragments { doc += &lit.value(); diff --git a/syntax/error.rs b/syntax/error.rs index f40c4a8e9..0dc9b08a3 100644 --- a/syntax/error.rs +++ b/syntax/error.rs @@ -1,9 +1,11 @@ use std::fmt::{self, Display}; #[derive(Copy, Clone)] -pub struct Error { +pub(crate) struct Error { pub msg: &'static str, + #[cfg_attr(proc_macro, expect(dead_code))] pub label: Option<&'static str>, + #[cfg_attr(proc_macro, expect(dead_code))] pub note: Option<&'static str>, } @@ -13,7 +15,7 @@ impl Display for Error { } } -pub static ERRORS: &[Error] = &[ +pub(crate) static ERRORS: &[Error] = &[ BOX_CXX_TYPE, CXXBRIDGE_RESERVED, CXX_STRING_BY_VALUE, @@ -27,67 +29,67 @@ pub static ERRORS: &[Error] = &[ USE_NOT_ALLOWED, ]; -pub static BOX_CXX_TYPE: Error = Error { +pub(crate) static BOX_CXX_TYPE: Error = Error { msg: "Box of a C++ type is not supported yet", label: None, note: Some("hint: use UniquePtr<> or SharedPtr<>"), }; -pub static CXXBRIDGE_RESERVED: Error = Error { +pub(crate) static CXXBRIDGE_RESERVED: Error = Error { msg: "identifiers starting with cxxbridge are reserved", label: Some("reserved identifier"), note: Some("identifiers starting with cxxbridge are reserved"), }; -pub static CXX_STRING_BY_VALUE: Error = Error { +pub(crate) static CXX_STRING_BY_VALUE: Error = Error { msg: "C++ string by value is not supported", label: None, note: Some("hint: wrap it in a UniquePtr<>"), }; -pub static CXX_TYPE_BY_VALUE: Error = Error { +pub(crate) static CXX_TYPE_BY_VALUE: Error = Error { msg: "C++ type by value is not supported", label: None, note: Some("hint: wrap it in a UniquePtr<> or SharedPtr<>"), }; -pub static DISCRIMINANT_OVERFLOW: Error = Error { +pub(crate) static DISCRIMINANT_OVERFLOW: Error = Error { msg: "discriminant overflow on value after ", label: Some("discriminant overflow"), note: Some("note: explicitly set `= 0` if that is desired outcome"), }; -pub static DOT_INCLUDE: Error = Error { +pub(crate) static DOT_INCLUDE: Error = Error { msg: "#include relative to `.` or `..` is not supported in Cargo builds", label: Some("#include relative to `.` or `..` is not supported in Cargo builds"), note: Some("note: use a path starting with the crate name"), }; -pub static DOUBLE_UNDERSCORE: Error = Error { +pub(crate) static DOUBLE_UNDERSCORE: Error = Error { msg: "identifiers containing double underscore are reserved in C++", label: Some("reserved identifier"), note: Some("identifiers containing double underscore are reserved in C++"), }; -pub static RESERVED_LIFETIME: Error = Error { +pub(crate) static RESERVED_LIFETIME: Error = Error { msg: "invalid lifetime parameter name: `'static`", label: Some("'static is a reserved lifetime name"), note: None, }; -pub static RUST_TYPE_BY_VALUE: Error = Error { +pub(crate) static RUST_TYPE_BY_VALUE: Error = Error { msg: "opaque Rust type by value is not supported", label: None, note: Some("hint: wrap it in a Box<>"), }; -pub static UNSUPPORTED_TYPE: Error = Error { +pub(crate) static UNSUPPORTED_TYPE: Error = Error { msg: "unsupported type: ", label: Some("unsupported type"), note: None, }; -pub static USE_NOT_ALLOWED: Error = Error { +pub(crate) static USE_NOT_ALLOWED: Error = Error { msg: "`use` items are not allowed within cxx bridge", label: Some("not allowed"), note: Some( diff --git a/syntax/file.rs b/syntax/file.rs index 71f11eec8..77f0ce8a5 100644 --- a/syntax/file.rs +++ b/syntax/file.rs @@ -3,23 +3,28 @@ use crate::syntax::namespace::Namespace; use quote::quote; use syn::parse::{Error, Parse, ParseStream, Result}; use syn::{ - braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl, - ItemStruct, ItemUse, LitStr, Token, Visibility, + Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl, ItemStruct, ItemUse, + LitStr, Token, Visibility, braced, token, }; -pub struct Module { +pub(crate) struct Module { + #[expect(dead_code)] pub cfg: CfgExpr, pub namespace: Namespace, pub attrs: Vec, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub vis: Visibility, pub unsafety: Option, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub mod_token: Token![mod], + #[cfg_attr(not(proc_macro), expect(dead_code))] pub ident: Ident, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub brace_token: token::Brace, pub content: Vec, } -pub enum Item { +pub(crate) enum Item { Struct(ItemStruct), Enum(ItemEnum), ForeignMod(ItemForeignMod), @@ -28,10 +33,11 @@ pub enum Item { Other(RustItem), } -pub struct ItemForeignMod { +pub(crate) struct ItemForeignMod { pub attrs: Vec, pub unsafety: Option, pub abi: Abi, + #[expect(dead_code)] pub brace_token: token::Brace, pub items: Vec, } diff --git a/syntax/ident.rs b/syntax/ident.rs index bb2281e72..0751b8584 100644 --- a/syntax/ident.rs +++ b/syntax/ident.rs @@ -1,5 +1,5 @@ use crate::syntax::check::Check; -use crate::syntax::{error, Api, Pair}; +use crate::syntax::{Api, Pair, error}; fn check(cx: &mut Check, name: &Pair) { for segment in &name.namespace { diff --git a/syntax/impls.rs b/syntax/impls.rs index 36e1f322a..7ea233f6e 100644 --- a/syntax/impls.rs +++ b/syntax/impls.rs @@ -201,14 +201,12 @@ impl PartialEq for Ptr { mutable, inner, mutability: _, - constness: _, } = self; let Ptr { star: _, mutable: mutable2, inner: inner2, mutability: _, - constness: _, } = other; mutable == mutable2 && inner == inner2 } @@ -221,7 +219,6 @@ impl Hash for Ptr { mutable, inner, mutability: _, - constness: _, } = self; mutable.hash(state); inner.hash(state); @@ -313,7 +310,7 @@ impl PartialEq for Signature { unsafety, fn_token: _, generics: _, - receiver, + kind, args, ret, throws, @@ -325,7 +322,7 @@ impl PartialEq for Signature { unsafety: unsafety2, fn_token: _, generics: _, - receiver: receiver2, + kind: kind2, args: args2, ret: ret2, throws: throws2, @@ -334,7 +331,7 @@ impl PartialEq for Signature { } = other; asyncness.is_some() == asyncness2.is_some() && unsafety.is_some() == unsafety2.is_some() - && receiver == receiver2 + && kind == kind2 && ret == ret2 && throws == throws2 && args.len() == args2.len() @@ -369,7 +366,7 @@ impl Hash for Signature { unsafety, fn_token: _, generics: _, - receiver, + kind, args, ret, throws, @@ -378,7 +375,7 @@ impl Hash for Signature { } = self; asyncness.is_some().hash(state); unsafety.is_some().hash(state); - receiver.hash(state); + kind.hash(state); for arg in args { let Var { cfg: _, diff --git a/syntax/improper.rs b/syntax/improper.rs index f19eb86a7..2f2f0b42e 100644 --- a/syntax/improper.rs +++ b/syntax/improper.rs @@ -1,18 +1,22 @@ use self::ImproperCtype::*; +use crate::syntax::Types; use crate::syntax::atom::Atom::{self, *}; -use crate::syntax::{Type, Types}; +use crate::syntax::query::TypeQuery; use proc_macro2::Ident; -pub enum ImproperCtype<'a> { +pub(crate) enum ImproperCtype<'a> { Definite(bool), Depends(&'a Ident), } impl<'a> Types<'a> { // yes, no, maybe - pub fn determine_improper_ctype(&self, ty: &Type) -> ImproperCtype<'a> { - match ty { - Type::Ident(ident) => { + pub(crate) fn determine_improper_ctype( + &self, + ty: impl Into>, + ) -> ImproperCtype<'a> { + match ty.into() { + TypeQuery::Ident(ident) => { let ident = &ident.rust; if let Some(atom) = Atom::from(ident) { Definite(atom == RustString) @@ -22,18 +26,19 @@ impl<'a> Types<'a> { Definite(self.rust.contains(ident) || self.aliases.contains_key(ident)) } } - Type::RustBox(_) - | Type::RustVec(_) - | Type::Str(_) - | Type::Fn(_) - | Type::Void(_) - | Type::SliceRef(_) => Definite(true), - Type::UniquePtr(_) | Type::SharedPtr(_) | Type::WeakPtr(_) | Type::CxxVector(_) => { - Definite(false) - } - Type::Ref(ty) => self.determine_improper_ctype(&ty.inner), - Type::Ptr(ty) => self.determine_improper_ctype(&ty.inner), - Type::Array(ty) => self.determine_improper_ctype(&ty.inner), + TypeQuery::RustBox + | TypeQuery::RustVec + | TypeQuery::Str + | TypeQuery::Fn + | TypeQuery::Void + | TypeQuery::SliceRef => Definite(true), + TypeQuery::UniquePtr + | TypeQuery::SharedPtr + | TypeQuery::WeakPtr + | TypeQuery::CxxVector => Definite(false), + TypeQuery::Ref(ty) => self.determine_improper_ctype(&ty.inner), + TypeQuery::Ptr(ty) => self.determine_improper_ctype(&ty.inner), + TypeQuery::Array(ty) => self.determine_improper_ctype(&ty.inner), } } } diff --git a/syntax/instantiate.rs b/syntax/instantiate.rs index b6cbf24b5..401c58ce1 100644 --- a/syntax/instantiate.rs +++ b/syntax/instantiate.rs @@ -1,10 +1,12 @@ -use crate::syntax::{NamedType, Ty1, Type}; +use crate::syntax::map::UnorderedMap; +use crate::syntax::resolve::Resolution; +use crate::syntax::types::Types; +use crate::syntax::{Symbol, Ty1, Type, mangle}; use proc_macro2::{Ident, Span}; use std::hash::{Hash, Hasher}; -use syn::Token; -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub enum ImplKey<'a> { +#[derive(PartialEq, Eq, Hash)] +pub(crate) enum ImplKey<'a> { RustBox(NamedImplKey<'a>), RustVec(NamedImplKey<'a>), UniquePtr(NamedImplKey<'a>), @@ -13,49 +15,68 @@ pub enum ImplKey<'a> { CxxVector(NamedImplKey<'a>), } -#[derive(Copy, Clone)] -pub struct NamedImplKey<'a> { +impl<'a> ImplKey<'a> { + /// Whether to produce FFI symbols instantiating the given generic type even + /// when an explicit `impl Foo {}` is not present in the current bridge. + /// + /// The main consideration is that the same instantiation must not be + /// present in two places, which is accomplished using trait impls and the + /// orphan rule. Every instantiation of a C++ template like `CxxVector` + /// and Rust generic type like `Vec` requires the implementation of + /// traits defined by the `cxx` crate for some local type or for a + /// fundamental type like `Box`. + pub(crate) fn is_implicit_impl_ok(&self, types: &Types) -> bool { + // TODO: relax this for Rust generics to allow Vec> etc. + types.is_local(self.inner()) + } + + /// Returns the type argument in the generic instantiation described by + /// `self`. For example, if `self` represents `UniquePtr` then this + /// will return `u32`. + fn inner(&self) -> &'a Type { + let named_impl_key = match self { + ImplKey::RustBox(key) + | ImplKey::RustVec(key) + | ImplKey::UniquePtr(key) + | ImplKey::SharedPtr(key) + | ImplKey::WeakPtr(key) + | ImplKey::CxxVector(key) => key, + }; + named_impl_key.inner + } +} + +pub(crate) struct NamedImplKey<'a> { + #[cfg_attr(not(proc_macro), expect(dead_code))] pub begin_span: Span, - pub rust: &'a Ident, - pub lt_token: Option, - pub gt_token: Option]>, + /// Mangled form of the `inner` type. + pub symbol: Symbol, + /// Generic type - e.g. `UniquePtr`. + #[cfg_attr(proc_macro, expect(dead_code))] + pub outer: &'a Type, + /// Generic type argument - e.g. `u8` from `UniquePtr`. + pub inner: &'a Type, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub end_span: Span, } impl Type { - pub(crate) fn impl_key(&self) -> Option { - if let Type::RustBox(ty) = self { - if let Type::Ident(ident) = &ty.inner { - return Some(ImplKey::RustBox(NamedImplKey::new(ty, ident))); - } - } else if let Type::RustVec(ty) = self { - if let Type::Ident(ident) = &ty.inner { - return Some(ImplKey::RustVec(NamedImplKey::new(ty, ident))); - } - } else if let Type::UniquePtr(ty) = self { - if let Type::Ident(ident) = &ty.inner { - return Some(ImplKey::UniquePtr(NamedImplKey::new(ty, ident))); - } - } else if let Type::SharedPtr(ty) = self { - if let Type::Ident(ident) = &ty.inner { - return Some(ImplKey::SharedPtr(NamedImplKey::new(ty, ident))); - } - } else if let Type::WeakPtr(ty) = self { - if let Type::Ident(ident) = &ty.inner { - return Some(ImplKey::WeakPtr(NamedImplKey::new(ty, ident))); - } - } else if let Type::CxxVector(ty) = self { - if let Type::Ident(ident) = &ty.inner { - return Some(ImplKey::CxxVector(NamedImplKey::new(ty, ident))); - } + pub(crate) fn impl_key(&self, res: &UnorderedMap<&Ident, Resolution>) -> Option { + match self { + Type::RustBox(ty) => Some(ImplKey::RustBox(NamedImplKey::new(self, ty, res)?)), + Type::RustVec(ty) => Some(ImplKey::RustVec(NamedImplKey::new(self, ty, res)?)), + Type::UniquePtr(ty) => Some(ImplKey::UniquePtr(NamedImplKey::new(self, ty, res)?)), + Type::SharedPtr(ty) => Some(ImplKey::SharedPtr(NamedImplKey::new(self, ty, res)?)), + Type::WeakPtr(ty) => Some(ImplKey::WeakPtr(NamedImplKey::new(self, ty, res)?)), + Type::CxxVector(ty) => Some(ImplKey::CxxVector(NamedImplKey::new(self, ty, res)?)), + _ => None, } - None } } impl<'a> PartialEq for NamedImplKey<'a> { fn eq(&self, other: &Self) -> bool { - PartialEq::eq(self.rust, other.rust) + PartialEq::eq(&self.symbol, &other.symbol) } } @@ -63,18 +84,19 @@ impl<'a> Eq for NamedImplKey<'a> {} impl<'a> Hash for NamedImplKey<'a> { fn hash(&self, hasher: &mut H) { - self.rust.hash(hasher); + self.symbol.hash(hasher); } } impl<'a> NamedImplKey<'a> { - fn new(outer: &Ty1, inner: &'a NamedType) -> Self { - NamedImplKey { - begin_span: outer.name.span(), - rust: &inner.rust, - lt_token: inner.generics.lt_token, - gt_token: inner.generics.gt_token, - end_span: outer.rangle.span, - } + fn new(outer: &'a Type, ty1: &'a Ty1, res: &UnorderedMap<&Ident, Resolution>) -> Option { + let inner = &ty1.inner; + Some(NamedImplKey { + symbol: mangle::typename(inner, res)?, + begin_span: ty1.name.span(), + outer, + inner, + end_span: ty1.rangle.span, + }) } } diff --git a/syntax/mangle.rs b/syntax/mangle.rs index 287b44341..1e482ea36 100644 --- a/syntax/mangle.rs +++ b/syntax/mangle.rs @@ -5,16 +5,14 @@ // examples: // - cxxbridge1$exception // defining characteristics: -// - 2 segments -// - starts with cxxbridge +// - 2 segments, none an integer // // (b) Behavior on a builtin binding without generic parameter. // pattern: {CXXBRIDGE} $ {TYPE} $ {NAME} // examples: // - cxxbridge1$string$len // defining characteristics: -// - 3 segments -// - starts with cxxbridge +// - 3 segments, none an integer // // (c) Behavior on a builtin binding with generic parameter. // pattern: {CXXBRIDGE} $ {TYPE} $ {PARAM...} $ {NAME} @@ -22,35 +20,32 @@ // - cxxbridge1$box$org$rust$Struct$alloc // - cxxbridge1$unique_ptr$std$vector$u8$drop // defining characteristics: -// - 4+ segments -// - starts with cxxbridge +// - 4+ segments, none an integer // // (d) User-defined extern function. -// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {NAME} +// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {CXXVERSION} $ {NAME} // examples: -// - cxxbridge1$new_client -// - org$rust$cxxbridge1$new_client +// - cxxbridge1$189$new_client +// - org$rust$cxxbridge1$189$new_client // defining characteristics: -// - cxxbridge is second from end -// FIXME: conflict with (a) if they collide with one of our one-off symbol names in the global namespace +// - second segment from end is an integer // // (e) User-defined extern member function. -// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ {NAME} +// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {CXXVERSION} $ {TYPE} $ {NAME} // examples: -// - org$cxxbridge1$Struct$get +// - org$cxxbridge1$189$Struct$get // defining characteristics: -// - cxxbridge is third from end -// FIXME: conflict with (b) if e.g. user binds a type in global namespace that collides with our builtin type names +// - third segment from end is an integer // // (f) Operator overload. -// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ operator $ {NAME} +// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {CXXVERSION} $ {TYPE} $ operator $ {NAME} // examples: -// - org$rust$cxxbridge1$Struct$operator$eq +// - org$rust$cxxbridge1$189$Struct$operator$eq // defining characteristics: // - second segment from end is `operator` (not possible in type or namespace names) // // (g) Closure trampoline. -// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE?} $ {NAME} $ {ARGUMENT} $ {DIRECTION} +// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {CXXVERSION} $ {TYPE?} $ {NAME} $ {ARGUMENT} $ {DIRECTION} // examples: // - org$rust$cxxbridge1$Struct$invoke$f$0 // defining characteristics: @@ -73,10 +68,14 @@ // - CXXBRIDGE1_STRUCT_org$rust$Struct // - CXXBRIDGE1_ENUM_Enabled +use crate::syntax::map::UnorderedMap; +use crate::syntax::resolve::Resolution; use crate::syntax::symbol::{self, Symbol}; -use crate::syntax::{ExternFn, Pair, Types}; +use crate::syntax::{ExternFn, Pair, Type, Types}; +use proc_macro2::Ident; const CXXBRIDGE: &str = "cxxbridge1"; +const CXXVERSION: &str = env!("CARGO_PKG_VERSION_PATCH"); macro_rules! join { ($($segment:expr),+ $(,)?) => { @@ -84,25 +83,27 @@ macro_rules! join { }; } -pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol { - match &efn.receiver { - Some(receiver) => { - let receiver_ident = types.resolve(&receiver.ty); +pub(crate) fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol { + match efn.self_type() { + Some(self_type) => { + let self_type_ident = types.resolve(self_type); join!( efn.name.namespace, CXXBRIDGE, - receiver_ident.name.cxx, + CXXVERSION, + self_type_ident.name.cxx, efn.name.rust, ) } - None => join!(efn.name.namespace, CXXBRIDGE, efn.name.rust), + None => join!(efn.name.namespace, CXXBRIDGE, CXXVERSION, efn.name.rust), } } -pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol { +pub(crate) fn operator(receiver: &Pair, operator: &'static str) -> Symbol { join!( receiver.namespace, CXXBRIDGE, + CXXVERSION, receiver.cxx, "operator", operator, @@ -110,11 +111,30 @@ pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol { } // The C half of a function pointer trampoline. -pub fn c_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol { +pub(crate) fn c_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol { join!(extern_fn(efn, types), var.rust, 0) } // The Rust half of a function pointer trampoline. -pub fn r_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol { +pub(crate) fn r_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol { join!(extern_fn(efn, types), var.rust, 1) } + +/// Mangles the given type (e.g. `Box`) into a symbol +/// fragment (`box$org$rust$Struct`) to be used in the name of generic +/// instantiations (`cxxbridge1$box$org$rust$Struct$alloc`) pertaining to that +/// type. +/// +/// Generic instantiation is not supported for all types in full generality. +/// This function must handle unsupported types gracefully by returning `None` +/// because it is used early during construction of the data structures that are +/// the input to 'syntax/check.rs', and unsupported generic instantiations are +/// only reported as an error later. +pub(crate) fn typename(t: &Type, res: &UnorderedMap<&Ident, Resolution>) -> Option { + match t { + Type::Ident(named_type) => res.get(&named_type.rust).map(|res| res.name.to_symbol()), + Type::CxxVector(ty1) => typename(&ty1.inner, res).map(|s| join!("std", "vector", s)), + Type::RustBox(ty1) => typename(&ty1.inner, res).map(|s| join!("box", s)), + _ => None, + } +} diff --git a/syntax/map.rs b/syntax/map.rs index 526b793bd..5db99d3d9 100644 --- a/syntax/map.rs +++ b/syntax/map.rs @@ -1,81 +1,52 @@ use std::borrow::Borrow; use std::hash::Hash; use std::ops::Index; -use std::slice; -pub use self::ordered::OrderedMap; -pub use self::unordered::UnorderedMap; -pub use std::collections::hash_map::Entry; +pub(crate) use self::ordered::OrderedMap; +pub(crate) use self::unordered::UnorderedMap; +pub(crate) use std::collections::hash_map::Entry; mod ordered { - use super::{Entry, Iter, UnorderedMap}; - use std::borrow::Borrow; + use indexmap::Equivalent; use std::hash::Hash; - use std::mem; - pub struct OrderedMap { - map: UnorderedMap, - vec: Vec<(K, V)>, - } + pub(crate) struct OrderedMap(indexmap::IndexMap); impl OrderedMap { - pub fn new() -> Self { - OrderedMap { - map: UnorderedMap::new(), - vec: Vec::new(), - } + pub(crate) fn new() -> Self { + OrderedMap(indexmap::IndexMap::new()) } - pub fn iter(&self) -> Iter { - Iter(self.vec.iter()) + pub(crate) fn keys(&self) -> indexmap::map::Keys { + self.0.keys() } - pub fn keys(&self) -> impl Iterator { - self.vec.iter().map(|(k, _v)| k) + pub(crate) fn contains_key(&self, key: &Q) -> bool + where + Q: ?Sized + Hash + Equivalent, + { + self.0.contains_key(key) } } impl OrderedMap where - K: Copy + Hash + Eq, + K: Hash + Eq, { - pub fn insert(&mut self, key: K, value: V) -> Option { - match self.map.entry(key) { - Entry::Occupied(entry) => { - let i = &mut self.vec[*entry.get()]; - Some(mem::replace(&mut i.1, value)) - } - Entry::Vacant(entry) => { - entry.insert(self.vec.len()); - self.vec.push((key, value)); - None - } - } - } - - pub fn contains_key(&self, key: &Q) -> bool - where - K: Borrow, - Q: ?Sized + Hash + Eq, - { - self.map.contains_key(key) + pub(crate) fn insert(&mut self, key: K, value: V) -> Option { + self.0.insert(key, value) } - pub fn get(&self, key: &Q) -> Option<&V> - where - K: Borrow, - Q: ?Sized + Hash + Eq, - { - let i = *self.map.get(key)?; - Some(&self.vec[i].1) + pub(crate) fn entry(&mut self, key: K) -> indexmap::map::Entry { + self.0.entry(key) } } impl<'a, K, V> IntoIterator for &'a OrderedMap { type Item = (&'a K, &'a V); - type IntoIter = Iter<'a, K, V>; + type IntoIter = indexmap::map::Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { - self.iter() + self.0.iter() } } } @@ -88,10 +59,10 @@ mod unordered { // Wrapper prohibits accidentally introducing iteration over the map, which // could lead to nondeterministic generated code. - pub struct UnorderedMap(HashMap); + pub(crate) struct UnorderedMap(HashMap); impl UnorderedMap { - pub fn new() -> Self { + pub(crate) fn new() -> Self { UnorderedMap(HashMap::new()) } } @@ -100,11 +71,11 @@ mod unordered { where K: Hash + Eq, { - pub fn insert(&mut self, key: K, value: V) -> Option { + pub(crate) fn insert(&mut self, key: K, value: V) -> Option { self.0.insert(key, value) } - pub fn contains_key(&self, key: &Q) -> bool + pub(crate) fn contains_key(&self, key: &Q) -> bool where K: Borrow, Q: ?Sized + Hash + Eq, @@ -112,7 +83,7 @@ mod unordered { self.0.contains_key(key) } - pub fn get(&self, key: &Q) -> Option<&V> + pub(crate) fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: ?Sized + Hash + Eq, @@ -120,12 +91,12 @@ mod unordered { self.0.get(key) } - pub fn entry(&mut self, key: K) -> Entry { + pub(crate) fn entry(&mut self, key: K) -> Entry { self.0.entry(key) } #[allow(dead_code)] // only used by cxx-build, not cxxbridge-macro - pub fn remove(&mut self, key: &Q) -> Option + pub(crate) fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: ?Sized + Hash + Eq, @@ -133,7 +104,7 @@ mod unordered { self.0.remove(key) } - pub fn keys(&self) -> UnorderedSet + pub(crate) fn keys(&self) -> UnorderedSet where K: Copy, { @@ -146,21 +117,6 @@ mod unordered { } } -pub struct Iter<'a, K, V>(slice::Iter<'a, (K, V)>); - -impl<'a, K, V> Iterator for Iter<'a, K, V> { - type Item = (&'a K, &'a V); - - fn next(&mut self) -> Option { - let (k, v) = self.0.next()?; - Some((k, v)) - } - - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } -} - impl Default for UnorderedMap { fn default() -> Self { UnorderedMap::new() diff --git a/syntax/message.rs b/syntax/message.rs new file mode 100644 index 000000000..244ee3bd9 --- /dev/null +++ b/syntax/message.rs @@ -0,0 +1,27 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use std::fmt::{self, Display}; + +pub(crate) struct Message(String); + +impl Message { + pub fn new() -> Self { + Message(String::new()) + } + + pub fn write_fmt(&mut self, args: fmt::Arguments) { + fmt::Write::write_fmt(&mut self.0, args).unwrap(); + } +} + +impl Display for Message { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(formatter) + } +} + +impl ToTokens for Message { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.0.to_tokens(tokens); + } +} diff --git a/syntax/mod.rs b/syntax/mod.rs index 4f19d9641..988a74c95 100644 --- a/syntax/mod.rs +++ b/syntax/mod.rs @@ -1,33 +1,39 @@ // Functionality that is shared between the cxxbridge macro and the cmd. -pub mod atom; -pub mod attrs; -pub mod cfg; -pub mod check; -pub mod derive; -mod discriminant; +pub(crate) mod atom; +pub(crate) mod attrs; +pub(crate) mod cfg; +pub(crate) mod check; +pub(crate) mod derive; +pub(crate) mod discriminant; mod doc; -pub mod error; -pub mod file; -pub mod ident; +pub(crate) mod error; +pub(crate) mod file; +pub(crate) mod ident; mod impls; mod improper; -pub mod instantiate; -pub mod mangle; -pub mod map; +pub(crate) mod instantiate; +pub(crate) mod mangle; +pub(crate) mod map; +pub(crate) mod message; mod names; -pub mod namespace; +pub(crate) mod namespace; mod parse; mod pod; -pub mod qualified; -pub mod report; -pub mod resolve; -pub mod set; -pub mod symbol; +pub(crate) mod primitive; +pub(crate) mod qualified; +pub(crate) mod query; +pub(crate) mod report; +pub(crate) mod repr; +pub(crate) mod resolve; +pub(crate) mod set; +mod signature; +pub(crate) mod symbol; mod tokens; mod toposort; -pub mod trivial; -pub mod types; +pub(crate) mod trivial; +pub(crate) mod types; +pub(crate) mod unpin; mod visit; use self::attrs::OtherAttrs; @@ -38,17 +44,18 @@ 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, Token, Type as RustType}; +use syn::{Expr, Generics, Lifetime, LitInt, PointerMutability, Token, Type as RustType}; -pub use self::atom::Atom; -pub use self::derive::{Derive, Trait}; -pub use self::discriminant::Discriminant; -pub use self::doc::Doc; -pub use self::names::ForeignName; -pub use self::parse::parse_items; -pub use self::types::Types; +pub(crate) use self::atom::Atom; +pub(crate) use self::derive::{Derive, Trait}; +pub(crate) use self::discriminant::Discriminant; +pub(crate) use self::doc::Doc; +pub(crate) use self::names::ForeignName; +pub(crate) use self::parse::parse_items; +pub(crate) use self::types::Types; -pub enum Api { +pub(crate) enum Api { + #[cfg_attr(proc_macro, expect(dead_code))] Include(Include), Struct(Struct), Enum(Enum), @@ -60,11 +67,13 @@ pub enum Api { Impl(Impl), } -pub struct Include { +pub(crate) struct Include { pub cfg: CfgExpr, pub path: String, pub kind: IncludeKind, + #[cfg_attr(proc_macro, expect(dead_code))] pub begin_span: Span, + #[cfg_attr(proc_macro, expect(dead_code))] pub end_span: Span, } @@ -77,27 +86,33 @@ pub enum IncludeKind { Bracketed, } -pub struct ExternType { +pub(crate) struct ExternType { + #[cfg_attr(proc_macro, expect(dead_code))] pub cfg: CfgExpr, pub lang: Lang, pub doc: Doc, pub derives: Vec, pub attrs: OtherAttrs, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub visibility: Token![pub], pub type_token: Token![type], pub name: Pair, pub generics: Lifetimes, + #[expect(dead_code)] pub colon_token: Option, pub bounds: Vec, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub semi_token: Token![;], pub trusted: bool, } -pub struct Struct { +pub(crate) struct Struct { pub cfg: CfgExpr, pub doc: Doc, pub derives: Vec, + pub align: Option, pub attrs: OtherAttrs, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub visibility: Token![pub], pub struct_token: Token![struct], pub name: Pair, @@ -106,39 +121,34 @@ pub struct Struct { pub fields: Vec, } -pub struct Enum { +pub(crate) struct Enum { pub cfg: CfgExpr, pub doc: Doc, pub derives: Vec, pub attrs: OtherAttrs, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub visibility: Token![pub], pub enum_token: Token![enum], pub name: Pair, pub generics: Lifetimes, pub brace_token: Brace, pub variants: Vec, - pub variants_from_header: bool, - pub variants_from_header_attr: Option, pub repr: EnumRepr, pub explicit_repr: bool, } -pub enum EnumRepr { - Native { - atom: Atom, - repr_type: Type, - }, - #[cfg(feature = "experimental-enum-variants-from-header")] - Foreign { - rust_type: syn::Path, - }, +pub(crate) struct EnumRepr { + pub atom: Atom, + pub repr_type: Type, } -pub struct ExternFn { +pub(crate) struct ExternFn { pub cfg: CfgExpr, pub lang: Lang, pub doc: Doc, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub attrs: OtherAttrs, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub visibility: Token![pub], pub name: Pair, pub sig: Signature, @@ -146,44 +156,52 @@ pub struct ExternFn { pub trusted: bool, } -pub struct TypeAlias { +pub(crate) struct TypeAlias { + #[cfg_attr(proc_macro, expect(dead_code))] pub cfg: CfgExpr, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub doc: Doc, pub derives: Vec, pub attrs: OtherAttrs, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub visibility: Token![pub], pub type_token: Token![type], pub name: Pair, pub generics: Lifetimes, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub eq_token: Token![=], + #[cfg_attr(not(proc_macro), expect(dead_code))] pub ty: RustType, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub semi_token: Token![;], } -pub struct Impl { +pub(crate) struct Impl { pub cfg: CfgExpr, + #[expect(dead_code)] + pub attrs: OtherAttrs, pub impl_token: Token![impl], pub impl_generics: Lifetimes, + #[expect(dead_code)] pub negative: bool, pub ty: Type, - pub ty_generics: Lifetimes, pub brace_token: Brace, pub negative_token: Option, } #[derive(Clone, Default)] -pub struct Lifetimes { +pub(crate) struct Lifetimes { pub lt_token: Option, pub lifetimes: Punctuated, pub gt_token: Option]>, } -pub struct Signature { +pub(crate) struct Signature { pub asyncness: Option, pub unsafety: Option, pub fn_token: Token![fn], pub generics: Generics, - pub receiver: Option, + pub kind: FnKind, pub args: Punctuated, pub ret: Option, pub throws: bool, @@ -191,39 +209,58 @@ pub struct Signature { pub throws_tokens: Option<(kw::Result, Token![<], Token![>])>, } -pub struct Var { +#[derive(PartialEq, Hash)] +pub(crate) enum FnKind { + /// Rust method or C++ non-static member function. + Method(Receiver), + /// Rust associated function or C++ static member function. + Assoc(Ident), + /// Non-member function. + Free, +} + +pub(crate) struct Var { pub cfg: CfgExpr, pub doc: Doc, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub attrs: OtherAttrs, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub visibility: Token![pub], pub name: Pair, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub colon_token: Token![:], pub ty: Type, } -pub struct Receiver { +pub(crate) struct Receiver { pub pinned: bool, pub ampersand: Token![&], pub lifetime: Option, pub mutable: bool, pub var: Token![self], pub ty: NamedType, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub colon_token: Token![:], pub shorthand: bool, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>, pub mutability: Option, } -pub struct Variant { +pub(crate) struct Variant { + #[cfg_attr(proc_macro, expect(dead_code))] pub cfg: CfgExpr, pub doc: Doc, + pub default: bool, + #[cfg_attr(not(proc_macro), expect(dead_code))] pub attrs: OtherAttrs, pub name: Pair, pub discriminant: Discriminant, + #[expect(dead_code)] pub expr: Option, } -pub enum Type { +pub(crate) enum Type { Ident(NamedType), RustBox(Box), RustVec(Box), @@ -240,14 +277,14 @@ pub enum Type { Array(Box), } -pub struct Ty1 { +pub(crate) struct Ty1 { pub name: Ident, pub langle: Token![<], pub inner: Type, pub rangle: Token![>], } -pub struct Ref { +pub(crate) struct Ref { pub pinned: bool, pub ampersand: Token![&], pub lifetime: Option, @@ -257,15 +294,14 @@ pub struct Ref { pub mutability: Option, } -pub struct Ptr { +pub(crate) struct Ptr { pub star: Token![*], pub mutable: bool, pub inner: Type, - pub mutability: Option, - pub constness: Option, + pub mutability: PointerMutability, } -pub struct SliceRef { +pub(crate) struct SliceRef { pub ampersand: Token![&], pub lifetime: Option, pub mutable: bool, @@ -274,7 +310,7 @@ pub struct SliceRef { pub mutability: Option, } -pub struct Array { +pub(crate) struct Array { pub bracket: Bracket, pub inner: Type, pub semi_token: Token![;], @@ -283,15 +319,16 @@ pub struct Array { } #[derive(Copy, Clone, PartialEq)] -pub enum Lang { +pub(crate) enum Lang { Cxx, + CxxUnwind, Rust, } // An association of a defined Rust name with a fully resolved, namespace // qualified C++ name. #[derive(Clone)] -pub struct Pair { +pub(crate) struct Pair { pub namespace: Namespace, pub cxx: ForeignName, pub rust: Ident, @@ -300,7 +337,7 @@ pub struct Pair { // Wrapper for a type which needs to be resolved before it can be printed in // C++. #[derive(PartialEq, Eq, Hash)] -pub struct NamedType { +pub(crate) struct NamedType { pub rust: Ident, pub generics: Lifetimes, } diff --git a/syntax/names.rs b/syntax/names.rs index 329a10221..7afa5a9e3 100644 --- a/syntax/names.rs +++ b/syntax/names.rs @@ -8,12 +8,12 @@ use syn::parse::{Error, Parser, Result}; use syn::punctuated::Punctuated; #[derive(Clone)] -pub struct ForeignName { +pub(crate) struct ForeignName { text: String, } impl Pair { - pub fn to_symbol(&self) -> Symbol { + pub(crate) fn to_symbol(&self) -> Symbol { let segments = self .namespace .iter() @@ -24,7 +24,7 @@ impl Pair { } impl NamedType { - pub fn new(rust: Ident) -> Self { + pub(crate) fn new(rust: Ident) -> Self { let generics = Lifetimes { lt_token: None, lifetimes: Punctuated::new(), @@ -32,14 +32,10 @@ impl NamedType { }; NamedType { rust, generics } } - - pub fn span(&self) -> Span { - self.rust.span() - } } impl ForeignName { - pub fn parse(text: &str, span: Span) -> Result { + pub(crate) fn parse(text: &str, span: Span) -> Result { // TODO: support C++ names containing whitespace (`unsigned int`) or // non-alphanumeric characters (`operator++`). match Ident::parse_any.parse_str(text) { diff --git a/syntax/namespace.rs b/syntax/namespace.rs index 07185e187..cebc147e6 100644 --- a/syntax/namespace.rs +++ b/syntax/namespace.rs @@ -1,30 +1,27 @@ use crate::syntax::qualified::QualifiedName; -use quote::IdentFragment; -use std::fmt::{self, Display}; -use std::iter::FromIterator; use std::slice::Iter; -use syn::parse::{Parse, ParseStream, Result}; -use syn::{Ident, Token}; +use syn::parse::{Error, Parse, ParseStream, Result}; +use syn::{Expr, Ident, Lit, Meta, Token}; mod kw { syn::custom_keyword!(namespace); } -#[derive(Clone, Default)] -pub struct Namespace { +#[derive(Clone, Default, PartialEq)] +pub(crate) struct Namespace { segments: Vec, } impl Namespace { - pub const ROOT: Self = Namespace { + pub(crate) const ROOT: Self = Namespace { segments: Vec::new(), }; - pub fn iter(&self) -> Iter { + pub(crate) fn iter(&self) -> Iter { self.segments.iter() } - pub fn parse_bridge_attr_namespace(input: ParseStream) -> Result { + pub(crate) fn parse_bridge_attr_namespace(input: ParseStream) -> Result { if input.is_empty() { return Ok(Namespace::ROOT); } @@ -35,6 +32,37 @@ impl Namespace { input.parse::>()?; Ok(namespace) } + + pub(crate) fn parse_meta(meta: &Meta) -> Result { + if let Meta::NameValue(meta) = meta { + match &meta.value { + Expr::Lit(expr) => { + if let Lit::Str(lit) = &expr.lit { + let segments = QualifiedName::parse_quoted(lit)?.segments; + return Ok(Namespace { segments }); + } + } + Expr::Path(expr) + if expr.qself.is_none() + && expr + .path + .segments + .iter() + .all(|segment| segment.arguments.is_none()) => + { + let segments = expr + .path + .segments + .iter() + .map(|segment| segment.ident.clone()) + .collect(); + return Ok(Namespace { segments }); + } + _ => {} + } + } + Err(Error::new_spanned(meta, "unsupported namespace attribute")) + } } impl Default for &Namespace { @@ -51,21 +79,6 @@ impl Parse for Namespace { } } -impl Display for Namespace { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for segment in self { - write!(f, "{}$", segment)?; - } - Ok(()) - } -} - -impl IdentFragment for Namespace { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(self, f) - } -} - impl<'a> IntoIterator for &'a Namespace { type Item = &'a Ident; type IntoIter = Iter<'a, Ident>; diff --git a/syntax/parse.rs b/syntax/parse.rs index 1754c6006..20d888996 100644 --- a/syntax/parse.rs +++ b/syntax/parse.rs @@ -1,13 +1,14 @@ +use crate::syntax::Atom::*; 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; -use crate::syntax::Atom::*; +use crate::syntax::repr::Repr; use crate::syntax::{ - attrs, error, Api, Array, Derive, Doc, Enum, EnumRepr, ExternFn, ExternType, ForeignName, Impl, + Api, Array, Derive, Doc, Enum, EnumRepr, ExternFn, ExternType, FnKind, ForeignName, Impl, Include, IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref, - Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant, + Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant, attrs, error, }; use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree}; use quote::{format_ident, quote, quote_spanned}; @@ -17,17 +18,17 @@ use syn::punctuated::Punctuated; use syn::{ Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr, - Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound, - TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypePtr, - TypeReference, Variant as RustVariant, Visibility, + Pat, PathArguments, PointerMutability, ReceiverKind, Result, ReturnType, Safety, + Signature as RustSignature, Token, TraitBound, Type as RustType, TypeArray, TypeFnPtr, + TypeParamBound, TypePath, TypePtr, TypeReference, Variant as RustVariant, Visibility, }; -pub mod kw { +pub(crate) mod kw { syn::custom_keyword!(Pin); syn::custom_keyword!(Result); } -pub fn parse_items( +pub(crate) fn parse_items( cx: &mut Errors, items: Vec, trusted: bool, @@ -42,7 +43,7 @@ pub fn parse_items( }, Item::Enum(item) => apis.push(parse_enum(cx, item, namespace)), Item::ForeignMod(foreign_mod) => { - parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace) + parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace); } Item::Impl(item) => match parse_impl(cx, item) { Ok(imp) => apis.push(imp), @@ -59,6 +60,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> let mut cfg = CfgExpr::Unconditional; let mut doc = Doc::new(); let mut derives = Vec::new(); + let mut repr = None; let mut namespace = namespace.clone(); let mut cxx_name = None; let mut rust_name = None; @@ -69,6 +71,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> cfg: Some(&mut cfg), doc: Some(&mut doc), derives: Some(&mut derives), + repr: Some(&mut repr), namespace: Some(&mut namespace), cxx_name: Some(&mut cxx_name), rust_name: Some(&mut rust_name), @@ -76,6 +79,15 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> }, ); + let align = match repr { + Some(Repr::Align(align)) => Some(align), + Some(Repr::Atom(_atom, span)) => { + cx.push(Error::new(span, "unsupported alignment on a struct")); + None + } + None => None, + }; + let named_fields = match item.fields { Fields::Named(fields) => fields, Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")), @@ -177,6 +189,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> cfg, doc, derives, + align, attrs, visibility, struct_token, @@ -195,7 +208,6 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { let mut namespace = namespace.clone(); let mut cxx_name = None; let mut rust_name = None; - let mut variants_from_header = None; let attrs = attrs::parse( cx, item.attrs, @@ -207,7 +219,6 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { namespace: Some(&mut namespace), cxx_name: Some(&mut cxx_name), rust_name: Some(&mut rust_name), - variants_from_header: Some(&mut variants_from_header), ..Default::default() }, ); @@ -223,6 +234,15 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { cx.error(where_clause, "enum with where-clause is not supported"); } + let repr = match repr { + Some(Repr::Atom(atom, _span)) => Some(atom), + Some(Repr::Align(align)) => { + cx.error(align, "C++ does not support custom alignment on an enum"); + None + } + None => None, + }; + let mut variants = Vec::new(); let mut discriminants = DiscriminantSet::new(repr); for variant in item.variants { @@ -250,7 +270,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { let name = pair(namespace, &item.ident, cxx_name, rust_name); let repr_ident = Ident::new(repr.as_ref(), Span::call_site()); let repr_type = Type::Ident(NamedType::new(repr_ident)); - let repr = EnumRepr::Native { + let repr = EnumRepr { atom: repr, repr_type, }; @@ -259,8 +279,6 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { lifetimes: Punctuated::new(), gt_token: None, }; - let variants_from_header_attr = variants_from_header; - let variants_from_header = variants_from_header_attr.is_some(); Api::Enum(Enum { cfg, @@ -273,8 +291,6 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { generics, brace_token, variants, - variants_from_header, - variants_from_header_attr, repr, explicit_repr, }) @@ -287,6 +303,7 @@ fn parse_variant( ) -> Result { let mut cfg = CfgExpr::Unconditional; let mut doc = Doc::new(); + let mut default = false; let mut cxx_name = None; let mut rust_name = None; let attrs = attrs::parse( @@ -295,6 +312,7 @@ fn parse_variant( attrs::Parser { cfg: Some(&mut cfg), doc: Some(&mut doc), + default: Some(&mut default), cxx_name: Some(&mut cxx_name), rust_name: Some(&mut rust_name), ..Default::default() @@ -325,6 +343,7 @@ fn parse_variant( Ok(Variant { cfg, doc, + default, attrs, name, discriminant, @@ -353,7 +372,7 @@ fn parse_foreign_mod( cx.error(span, "extern \"Rust\" block does not need to be unsafe"); } } - Lang::Cxx => {} + Lang::Cxx | Lang::CxxUnwind => {} } let trusted = trusted || foreign_mod.unsafety.is_some(); @@ -422,12 +441,11 @@ fn parse_foreign_mod( if let (Some(single_type), None) = (types.next(), types.next()) { let single_type = single_type.clone(); for item in &mut items { - if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item { - if let Some(receiver) = &mut efn.receiver { - if receiver.ty.rust == "Self" { - receiver.ty.rust = single_type.rust.clone(); - } - } + if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item + && let Some(receiver) = efn.sig.receiver_mut() + && receiver.ty.rust == "Self" + { + receiver.ty.rust = single_type.rust.clone(); } } } @@ -436,18 +454,16 @@ fn parse_foreign_mod( } fn parse_lang(abi: &Abi) -> Result { - let name = match &abi.name { - Some(name) => name, - None => { - return Err(Error::new_spanned( - abi, - "ABI name is required, extern \"C++\" or extern \"Rust\"", - )); - } + let Some(name) = &abi.name else { + return Err(Error::new_spanned( + abi, + "ABI name is required, extern \"C++\" or extern \"Rust\"", + )); }; match name.value().as_str() { "C++" => Ok(Lang::Cxx), + "C++-unwind" => Ok(Lang::CxxUnwind), "Rust" => Ok(Lang::Rust), _ => Err(Error::new_spanned( abi, @@ -489,17 +505,13 @@ fn parse_extern_type( let type_token = foreign_type.type_token; let visibility = visibility_pub(&foreign_type.vis, type_token.span); let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name); - let generics = Lifetimes { - lt_token: None, - lifetimes: Punctuated::new(), - gt_token: None, - }; + let generics = extern_type_lifetimes(cx, foreign_type.generics); let colon_token = None; let bounds = Vec::new(); let semi_token = foreign_type.semi_token; (match lang { - Lang::Cxx => Api::CxxType, + Lang::Cxx | Lang::CxxUnwind => Api::CxxType, Lang::Rust => Api::RustType, })(ExternType { cfg, @@ -532,6 +544,7 @@ fn parse_extern_fn( let mut namespace = namespace.clone(); let mut cxx_name = None; let mut rust_name = None; + let mut self_type = None; let mut attrs = attrs.clone(); attrs.extend(attrs::parse( cx, @@ -542,6 +555,7 @@ fn parse_extern_fn( namespace: Some(&mut namespace), cxx_name: Some(&mut cxx_name), rust_name: Some(&mut rust_name), + self_type: Some(&mut self_type), ..Default::default() }, )); @@ -566,7 +580,7 @@ fn parse_extern_fn( )); } - if foreign_fn.sig.asyncness.is_some() && !cfg!(feature = "experimental-async-fn") { + if foreign_fn.sig.asyncness.is_some() { return Err(Error::new_spanned( foreign_fn, "async function is not directly supported yet, but see https://cxx.rs/async.html \ @@ -596,22 +610,46 @@ fn parse_extern_fn( let (arg, comma) = arg.into_tuple(); match arg { FnArg::Receiver(arg) => { - if let Some((ampersand, lifetime)) = &arg.reference { - receiver = Some(Receiver { - pinned: false, - ampersand: *ampersand, - lifetime: lifetime.clone(), - mutable: arg.mutability.is_some(), - var: arg.self_token, - colon_token: Token![:](arg.self_token.span), - ty: NamedType::new(Ident::new("Self", arg.self_token.span)), - shorthand: true, - pin_tokens: None, - mutability: arg.mutability, - }); - continue; + match &arg.kind { + ReceiverKind::Value => {} + ReceiverKind::Reference(ampersand, lifetime, mutability) => { + receiver = Some(Receiver { + pinned: false, + ampersand: *ampersand, + lifetime: lifetime.clone(), + mutable: mutability.is_some(), + var: arg.self_token, + colon_token: Token![:](arg.self_token.span), + ty: NamedType::new(Ident::new("Self", arg.self_token.span)), + shorthand: true, + pin_tokens: None, + mutability: *mutability, + }); + continue; + } + ReceiverKind::Typed(colon_token, ty) => { + let ty = parse_type(ty)?; + if let Type::Ref(reference) = ty + && let Type::Ident(ident) = reference.inner + { + receiver = Some(Receiver { + pinned: reference.pinned, + ampersand: reference.ampersand, + lifetime: reference.lifetime, + mutable: reference.mutable, + var: Token![self](ident.rust.span()), + colon_token: *colon_token, + ty: ident, + shorthand: false, + pin_tokens: reference.pin_tokens, + mutability: reference.mutability, + }); + continue; + } + } + _ => {} } - return Err(Error::new_spanned(arg, "unsupported signature")); + return Err(Error::new_spanned(arg, "unsupported method receiver")); } FnArg::Typed(arg) => { let ident = match arg.pat.as_ref() { @@ -622,54 +660,47 @@ fn parse_extern_fn( _ => return Err(Error::new_spanned(arg, "unsupported signature")), }; 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, - name, - colon_token, - ty, - }); - if let Some(comma) = comma { - args.push_punct(*comma); - } - continue; - } - if let Type::Ref(reference) = ty { - if let Type::Ident(ident) = reference.inner { - receiver = Some(Receiver { - pinned: reference.pinned, - ampersand: reference.ampersand, - lifetime: reference.lifetime, - mutable: reference.mutable, - var: Token![self](ident.rust.span()), - colon_token: arg.colon_token, - ty: ident, - shorthand: false, - pin_tokens: reference.pin_tokens, - mutability: reference.mutability, - }); - continue; - } + let cfg = CfgExpr::Unconditional; + let doc = Doc::new(); + let attrs = OtherAttrs::new(); + 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, + name, + colon_token, + ty, + }); + if let Some(comma) = comma { + args.push_punct(*comma); } - return Err(Error::new_spanned(arg, "unsupported method receiver")); } } } + let kind = match (self_type, receiver) { + (None, None) => FnKind::Free, + (Some(self_type), None) => FnKind::Assoc(self_type), + (None, Some(receiver)) => FnKind::Method(receiver), + (Some(self_type), Some(receiver)) => { + let msg = "function with Self type must not have a `self` argument"; + cx.error(self_type, msg); + FnKind::Method(receiver) + } + }; + 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 unsafety = match foreign_fn.sig.safety { + Safety::Safe(_) | Safety::Default => None, + Safety::Unsafe(unsafety) => Some(unsafety), + }; let fn_token = foreign_fn.sig.fn_token; let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span); let visibility = visibility_pub(&foreign_fn.vis, inherited_span); @@ -679,7 +710,7 @@ fn parse_extern_fn( let semi_token = foreign_fn.semi_token; Ok(match lang { - Lang::Cxx => Api::CxxFunction, + Lang::Cxx | Lang::CxxUnwind => Api::CxxFunction, Lang::Rust => Api::RustFunction, }(ExternFn { cfg, @@ -693,7 +724,7 @@ fn parse_extern_fn( unsafety, fn_token, generics, - receiver, + kind, args, ret, throws, @@ -756,6 +787,45 @@ fn parse_extern_verbatim_type( let type_token: Token![type] = input.parse()?; let ident: Ident = input.parse()?; let generics: Generics = input.parse()?; + let lifetimes = extern_type_lifetimes(cx, generics); + let lookahead = input.lookahead1(); + if lookahead.peek(Token![=]) { + // type Alias = crate::path::to::Type; + parse_type_alias( + cx, + unparsed_attrs, + visibility, + type_token, + ident, + lifetimes, + input, + lang, + extern_block_cfg, + namespace, + attrs, + ) + } else if lookahead.peek(Token![:]) { + // type Opaque: Bound2 + Bound2; + parse_extern_type_bounded( + cx, + unparsed_attrs, + visibility, + type_token, + ident, + lifetimes, + input, + lang, + trusted, + extern_block_cfg, + namespace, + attrs, + ) + } else { + Err(lookahead.error()) + } +} + +fn extern_type_lifetimes(cx: &mut Errors, generics: Generics) -> Lifetimes { let mut lifetimes = Punctuated::new(); let mut has_unsupported_generic_param = false; for pair in generics.params.into_pairs() { @@ -788,45 +858,10 @@ fn parse_extern_verbatim_type( } } } - let lifetimes = Lifetimes { + Lifetimes { lt_token: generics.lt_token, lifetimes, gt_token: generics.gt_token, - }; - let lookahead = input.lookahead1(); - if lookahead.peek(Token![=]) { - // type Alias = crate::path::to::Type; - parse_type_alias( - 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, - unparsed_attrs, - visibility, - type_token, - ident, - lifetimes, - input, - lang, - trusted, - extern_block_cfg, - namespace, - attrs, - ) - } else { - Err(lookahead.error()) } } @@ -919,18 +954,22 @@ fn parse_extern_type_bounded( match input.parse()? { TypeParamBound::Trait(TraitBound { paren_token: None, - modifier: TraitBoundModifier::None, lifetimes: None, + modifiers, + maybe: None, path, }) if if let Some(derive) = path.get_ident().and_then(Derive::from) { bounds.push(derive); true } else { false - } => {} - bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => { - cx.error(bound, "unsupported trait"); + } => + { + if let Err(unsupported) = modifiers.require_empty() { + cx.push(unsupported); + } } + bound => cx.error(bound, "unsupported trait"), } let lookahead = input.lookahead1(); @@ -970,7 +1009,7 @@ fn parse_extern_type_bounded( let name = pair(namespace, &ident, cxx_name, rust_name); Ok(match lang { - Lang::Cxx => Api::CxxType, + Lang::Cxx | Lang::CxxUnwind => Api::CxxType, Lang::Rust => Api::RustType, }(ExternType { cfg, @@ -993,7 +1032,7 @@ fn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result { let impl_token = imp.impl_token; let mut cfg = CfgExpr::Unconditional; - attrs::parse( + let attrs = attrs::parse( cx, imp.attrs, attrs::Parser { @@ -1004,19 +1043,25 @@ fn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result { if !imp.items.is_empty() { let mut span = Group::new(Delimiter::Brace, TokenStream::new()); - span.set_span(imp.brace_token.span); + span.set_span(imp.brace_token.span.join()); return Err(Error::new_spanned(span, "expected an empty impl block")); } - if let Some((bang, path, for_token)) = &imp.trait_ { + if let Some((path, for_token)) = &imp.trait_ { let self_ty = &imp.self_ty; - let span = quote!(#bang #path #for_token #self_ty); + let span = quote!(#path #for_token #self_ty); return Err(Error::new_spanned( span, "unexpected impl, expected something like `impl UniquePtr {}`", )); } + if let Some(bang) = &imp.modifiers.polarity { + return Err(Error::new_spanned(bang, "unexpected impl polarity")); + } + + imp.modifiers.require_empty()?; + if let Some(where_clause) = imp.generics.where_clause { return Err(Error::new_spanned( where_clause, @@ -1051,48 +1096,29 @@ fn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result { let mut self_ty = *imp.self_ty; if let RustType::Verbatim(ty) = &self_ty { let mut iter = ty.clone().into_iter(); - if let Some(TokenTree::Punct(punct)) = iter.next() { - if punct.as_char() == '!' { - let ty = iter.collect::(); - if !ty.is_empty() { - negative_token = Some(Token![!](punct.span())); - self_ty = syn::parse2(ty)?; - } + if let Some(TokenTree::Punct(punct)) = iter.next() + && punct.as_char() == '!' + { + let ty = iter.collect::(); + if !ty.is_empty() { + negative_token = Some(Token![!](punct.span())); + self_ty = syn::parse2(ty)?; } } } let ty = parse_type(&self_ty)?; - let ty_generics = match &ty { - Type::RustBox(ty) - | Type::RustVec(ty) - | Type::UniquePtr(ty) - | Type::SharedPtr(ty) - | Type::WeakPtr(ty) - | Type::CxxVector(ty) => match &ty.inner { - Type::Ident(ident) => ident.generics.clone(), - _ => Lifetimes::default(), - }, - Type::Ident(_) - | Type::Ref(_) - | Type::Ptr(_) - | Type::Str(_) - | Type::Fn(_) - | Type::Void(_) - | Type::SliceRef(_) - | Type::Array(_) => Lifetimes::default(), - }; let negative = negative_token.is_some(); let brace_token = imp.brace_token; Ok(Api::Impl(Impl { cfg, + attrs, impl_token, impl_generics, negative, ty, - ty_generics, brace_token, negative_token, })) @@ -1150,8 +1176,8 @@ fn parse_type(ty: &RustType) -> Result { RustType::Ptr(ty) => parse_type_ptr(ty), RustType::Path(ty) => parse_type_path(ty), RustType::Array(ty) => parse_type_array(ty), - RustType::BareFn(ty) => parse_type_fn(ty), - RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)), + RustType::FnPtr(ty) => parse_type_fn(ty), + RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span.join())), _ => Err(Error::new_spanned(ty, "unsupported type")), } } @@ -1201,9 +1227,11 @@ fn parse_type_reference(ty: &TypeReference) -> Result { fn parse_type_ptr(ty: &TypePtr) -> Result { let star = ty.star_token; - let mutable = ty.mutability.is_some(); - let constness = ty.const_token; - let mutability = ty.mutability; + let mutability = ty.mutability.clone(); + let mutable = match &mutability { + PointerMutability::Const(_) => false, + PointerMutability::Mut(_) => true, + }; let inner = parse_type(&ty.elem)?; @@ -1212,7 +1240,6 @@ fn parse_type_ptr(ty: &TypePtr) -> Result { mutable, inner, mutability, - constness, }))) } @@ -1326,22 +1353,25 @@ fn parse_type_path(ty: &TypePath) -> Result { } } + if ty.qself.is_none() && path.segments.len() == 2 && path.segments[0].ident == "cxx" { + return Err(Error::new_spanned( + ty, + "unexpected `cxx::` qualifier found in a `#[cxx::bridge]`", + )); + } + Err(Error::new_spanned(ty, "unsupported type")) } fn parse_type_array(ty: &TypeArray) -> Result { let inner = parse_type(&ty.elem)?; - let len_expr = if let Expr::Lit(lit) = &ty.len { - lit - } else { + let Expr::Lit(len_expr) = &ty.len else { let msg = "unsupported expression, array length must be an integer literal"; return Err(Error::new_spanned(&ty.len, msg)); }; - let len_token = if let Lit::Int(int) = &len_expr.lit { - int.clone() - } else { + let Lit::Int(len_token) = &len_expr.lit else { let msg = "array length must be an integer literal"; return Err(Error::new_spanned(len_expr, msg)); }; @@ -1360,11 +1390,11 @@ fn parse_type_array(ty: &TypeArray) -> Result { inner, semi_token, len, - len_token, + len_token: len_token.clone(), }))) } -fn parse_type_fn(ty: &TypeBareFn) -> Result { +fn parse_type_fn(ty: &TypeFnPtr) -> Result { if ty.lifetimes.is_some() { return Err(Error::new_spanned( ty, @@ -1387,7 +1417,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result { let (ident, colon_token) = match &arg.name { Some((ident, colon_token)) => (ident.clone(), *colon_token), None => { - let fn_span = ty.paren_token.span; + let fn_span = ty.paren_token.span.join(); let ident = format_ident!("arg{}", i, span = fn_span); let colon_token = Token![:](fn_span); (ident, colon_token) @@ -1396,7 +1426,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result { let ty = parse_type(&arg.ty)?; let cfg = CfgExpr::Unconditional; let doc = Doc::new(); - let attrs = OtherAttrs::none(); + let attrs = OtherAttrs::new(); let visibility = Token![pub](ident.span()); let name = pair(Namespace::default(), &ident, None, None); Ok(Var { @@ -1419,7 +1449,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result { let unsafety = ty.unsafety; let fn_token = ty.fn_token; let generics = Generics::default(); - let receiver = None; + let kind = FnKind::Free; let paren_token = ty.paren_token; Ok(Type::Fn(Box::new(Signature { @@ -1427,7 +1457,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result { unsafety, fn_token, generics, - receiver, + kind, args, ret, throws, @@ -1450,14 +1480,14 @@ fn parse_return_type( if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 { let segment = &path.segments[0]; let ident = segment.ident.clone(); - if let PathArguments::AngleBracketed(generic) = &segment.arguments { - if ident == "Result" && generic.args.len() == 1 { - if let GenericArgument::Type(arg) = &generic.args[0] { - ret = arg; - *throws_tokens = - Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token)); - } - } + if let PathArguments::AngleBracketed(generic) = &segment.arguments + && ident == "Result" + && generic.args.len() == 1 + && let GenericArgument::Type(arg) = &generic.args[0] + { + ret = arg; + *throws_tokens = + Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token)); } } } @@ -1470,8 +1500,7 @@ fn parse_return_type( fn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] { Token![pub](match vis { - Visibility::Public(vis) => vis.pub_token.span, - Visibility::Crate(vis) => vis.crate_token.span, + Visibility::Public(vis) => vis.span, Visibility::Restricted(vis) => vis.pub_token.span, Visibility::Inherited => inherited, }) diff --git a/syntax/pod.rs b/syntax/pod.rs index 0bf152eea..f2b155530 100644 --- a/syntax/pod.rs +++ b/syntax/pod.rs @@ -1,10 +1,11 @@ use crate::syntax::atom::Atom::{self, *}; -use crate::syntax::{derive, Trait, Type, Types}; +use crate::syntax::query::TypeQuery; +use crate::syntax::{Types, primitive}; impl<'a> Types<'a> { - pub fn is_guaranteed_pod(&self, ty: &Type) -> bool { - match ty { - Type::Ident(ident) => { + pub(crate) fn is_guaranteed_pod(&self, ty: impl Into>) -> bool { + match ty.into() { + TypeQuery::Ident(ident) => { let ident = &ident.rust; if let Some(atom) = Atom::from(ident) { match atom { @@ -13,24 +14,26 @@ impl<'a> Types<'a> { CxxString | RustString => false, } } else if let Some(strct) = self.structs.get(ident) { - derive::contains(&strct.derives, Trait::Copy) - || strct - .fields - .iter() - .all(|field| self.is_guaranteed_pod(&field.ty)) + strct.fields.iter().all(|field| { + primitive::kind(&field.ty).is_none() && self.is_guaranteed_pod(&field.ty) + }) } else { self.enums.contains_key(ident) } } - Type::RustBox(_) - | Type::RustVec(_) - | Type::UniquePtr(_) - | Type::SharedPtr(_) - | Type::WeakPtr(_) - | Type::CxxVector(_) - | Type::Void(_) => false, - Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) | Type::Ptr(_) => true, - Type::Array(array) => self.is_guaranteed_pod(&array.inner), + TypeQuery::RustBox + | TypeQuery::RustVec + | TypeQuery::UniquePtr + | TypeQuery::SharedPtr + | TypeQuery::WeakPtr + | TypeQuery::CxxVector + | TypeQuery::Void => false, + TypeQuery::Ref(_) + | TypeQuery::Str + | TypeQuery::Fn + | TypeQuery::SliceRef + | TypeQuery::Ptr(_) => true, + TypeQuery::Array(array) => self.is_guaranteed_pod(&array.inner), } } } diff --git a/syntax/primitive.rs b/syntax/primitive.rs new file mode 100644 index 000000000..d2869ac22 --- /dev/null +++ b/syntax/primitive.rs @@ -0,0 +1,22 @@ +use crate::syntax::Type; +use crate::syntax::atom::Atom::{self, *}; + +pub(crate) enum PrimitiveKind { + Boolean, + Number, + Pointer, +} + +pub(crate) fn kind(ty: &Type) -> Option { + match ty { + Type::Ident(ident) => Atom::from(&ident.rust).and_then(|atom| match atom { + Bool => Some(PrimitiveKind::Boolean), + Char | U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize | F32 | F64 => { + Some(PrimitiveKind::Number) + } + CxxString | RustString => None, + }), + Type::Ptr(_) => Some(PrimitiveKind::Pointer), + _ => None, + } +} diff --git a/syntax/qualified.rs b/syntax/qualified.rs index 5f182fa9b..07c9908c6 100644 --- a/syntax/qualified.rs +++ b/syntax/qualified.rs @@ -2,28 +2,32 @@ use syn::ext::IdentExt; use syn::parse::{Error, ParseStream, Result}; use syn::{Ident, LitStr, Token}; -pub struct QualifiedName { +pub(crate) struct QualifiedName { pub segments: Vec, } impl QualifiedName { - pub fn parse_unquoted(input: ParseStream) -> Result { + pub(crate) fn parse_quoted(lit: &LitStr) -> Result { + if lit.value().is_empty() { + let segments = Vec::new(); + Ok(QualifiedName { segments }) + } else { + lit.parse_with(|input: ParseStream| { + let allow_raw = false; + parse_unquoted(input, allow_raw) + }) + } + } + + pub(crate) fn parse_unquoted(input: ParseStream) -> Result { let allow_raw = true; parse_unquoted(input, allow_raw) } - pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result { + pub(crate) fn parse_quoted_or_unquoted(input: ParseStream) -> Result { if input.peek(LitStr) { let lit: LitStr = input.parse()?; - if lit.value().is_empty() { - let segments = Vec::new(); - Ok(QualifiedName { segments }) - } else { - lit.parse_with(|input: ParseStream| { - let allow_raw = false; - parse_unquoted(input, allow_raw) - }) - } + Self::parse_quoted(&lit) } else { Self::parse_unquoted(input) } diff --git a/syntax/query.rs b/syntax/query.rs new file mode 100644 index 000000000..a3b9f280a --- /dev/null +++ b/syntax/query.rs @@ -0,0 +1,46 @@ +use crate::syntax::{Array, NamedType, Ptr, Ref, Type}; + +#[derive(Copy, Clone)] +pub(crate) enum TypeQuery<'a> { + Ident(&'a NamedType), + RustBox, + RustVec, + UniquePtr, + SharedPtr, + WeakPtr, + Ref(&'a Ref), + Ptr(&'a Ptr), + Str, + CxxVector, + Fn, + Void, + SliceRef, + Array(&'a Array), +} + +impl<'a> From<&'a NamedType> for TypeQuery<'a> { + fn from(query: &'a NamedType) -> Self { + TypeQuery::Ident(query) + } +} + +impl<'a> From<&'a Type> for TypeQuery<'a> { + fn from(query: &'a Type) -> Self { + match query { + Type::Ident(query) => TypeQuery::Ident(query), + Type::RustBox(_) => TypeQuery::RustBox, + Type::RustVec(_) => TypeQuery::RustVec, + Type::UniquePtr(_) => TypeQuery::UniquePtr, + Type::SharedPtr(_) => TypeQuery::SharedPtr, + Type::WeakPtr(_) => TypeQuery::WeakPtr, + Type::Ref(query) => TypeQuery::Ref(query), + Type::Ptr(query) => TypeQuery::Ptr(query), + Type::Str(_) => TypeQuery::Str, + Type::CxxVector(_) => TypeQuery::CxxVector, + Type::Fn(_) => TypeQuery::Fn, + Type::Void(_) => TypeQuery::Void, + Type::SliceRef(_) => TypeQuery::SliceRef, + Type::Array(query) => TypeQuery::Array(query), + } + } +} diff --git a/syntax/report.rs b/syntax/report.rs index d1d8bc9ba..4cdedd00e 100644 --- a/syntax/report.rs +++ b/syntax/report.rs @@ -2,28 +2,27 @@ use quote::ToTokens; use std::fmt::Display; use syn::{Error, Result}; -pub struct Errors { +pub(crate) struct Errors { errors: Vec, } impl Errors { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Errors { errors: Vec::new() } } - pub fn error(&mut self, sp: impl ToTokens, msg: impl Display) { + pub(crate) fn error(&mut self, sp: impl ToTokens, msg: impl Display) { self.errors.push(Error::new_spanned(sp, msg)); } - pub fn push(&mut self, error: Error) { + pub(crate) fn push(&mut self, error: Error) { self.errors.push(error); } - pub fn propagate(&mut self) -> Result<()> { + pub(crate) fn propagate(&mut self) -> Result<()> { let mut iter = self.errors.drain(..); - let mut all_errors = match iter.next() { - Some(err) => err, - None => return Ok(()), + let Some(mut all_errors) = iter.next() else { + return Ok(()); }; for err in iter { all_errors.combine(err); diff --git a/syntax/repr.rs b/syntax/repr.rs new file mode 100644 index 000000000..d034c03dc --- /dev/null +++ b/syntax/repr.rs @@ -0,0 +1,53 @@ +use crate::syntax::Atom::{self, *}; +use proc_macro2::{Ident, Span}; +use syn::parse::{Error, Parse, ParseStream, Result}; +use syn::{Expr, LitInt, parenthesized}; + +pub(crate) enum Repr { + Align(LitInt), + Atom(Atom, Span), +} + +impl Parse for Repr { + fn parse(input: ParseStream) -> Result { + let begin = input.cursor(); + let ident: Ident = input.parse()?; + if let Some(atom) = Atom::from(&ident) { + match atom { + U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize if input.is_empty() => { + return Ok(Repr::Atom(atom, ident.span())); + } + _ => {} + } + } else if ident == "align" { + let content; + parenthesized!(content in input); + let align_expr: Expr = content.fork().parse()?; + if !matches!(align_expr, Expr::Lit(_)) { + return Err(Error::new_spanned( + align_expr, + "invalid repr(align) attribute: an arithmetic expression is not supported", + )); + } + let align_lit: LitInt = content.parse()?; + let align: u32 = align_lit.base10_parse()?; + if !align.is_power_of_two() { + return Err(Error::new_spanned( + align_lit, + "invalid repr(align) attribute: not a power of two", + )); + } + if align > 2u32.pow(13) { + return Err(Error::new_spanned( + align_lit, + "invalid repr(align) attribute: larger than 2^13", + )); + } + return Ok(Repr::Align(align_lit)); + } + Err(Error::new_spanned( + begin.token_stream(), + "unrecognized repr", + )) + } +} diff --git a/syntax/resolve.rs b/syntax/resolve.rs index 3a2635bd3..cc89d142a 100644 --- a/syntax/resolve.rs +++ b/syntax/resolve.rs @@ -1,15 +1,17 @@ -use crate::syntax::instantiate::NamedImplKey; +use crate::syntax::attrs::OtherAttrs; use crate::syntax::{Lifetimes, NamedType, Pair, Types}; use proc_macro2::Ident; #[derive(Copy, Clone)] -pub struct Resolution<'a> { +pub(crate) struct Resolution<'a> { pub name: &'a Pair, + #[cfg_attr(not(proc_macro), expect(dead_code))] + pub attrs: &'a OtherAttrs, pub generics: &'a Lifetimes, } impl<'a> Types<'a> { - pub fn resolve(&self, ident: &impl UnresolvedName) -> Resolution<'a> { + pub(crate) fn resolve(&self, ident: &impl UnresolvedName) -> Resolution<'a> { let ident = ident.ident(); match self.try_resolve(ident) { Some(resolution) => resolution, @@ -17,13 +19,13 @@ impl<'a> Types<'a> { } } - pub fn try_resolve(&self, ident: &impl UnresolvedName) -> Option> { + pub(crate) fn try_resolve(&self, ident: &impl UnresolvedName) -> Option> { let ident = ident.ident(); self.resolutions.get(ident).copied() } } -pub trait UnresolvedName { +pub(crate) trait UnresolvedName { fn ident(&self) -> &Ident; } @@ -38,9 +40,3 @@ impl UnresolvedName for NamedType { &self.rust } } - -impl<'a> UnresolvedName for NamedImplKey<'a> { - fn ident(&self) -> &Ident { - self.rust - } -} diff --git a/syntax/set.rs b/syntax/set.rs index ca0c43e0a..451e23c28 100644 --- a/syntax/set.rs +++ b/syntax/set.rs @@ -1,15 +1,14 @@ use std::fmt::{self, Debug}; use std::slice; -pub use self::ordered::OrderedSet; -pub use self::unordered::UnorderedSet; +pub(crate) use self::ordered::OrderedSet; +pub(crate) use self::unordered::UnorderedSet; mod ordered { use super::{Iter, UnorderedSet}; - use std::borrow::Borrow; use std::hash::Hash; - pub struct OrderedSet { + pub(crate) struct OrderedSet { set: UnorderedSet, vec: Vec, } @@ -18,44 +17,28 @@ mod ordered { where T: Hash + Eq, { - pub fn new() -> Self { + pub(crate) fn new() -> Self { OrderedSet { set: UnorderedSet::new(), vec: Vec::new(), } } - pub fn insert(&mut self, value: &'a T) -> bool { + pub(crate) fn insert(&mut self, value: &'a T) -> bool { let new = self.set.insert(value); if new { self.vec.push(value); } new } - - pub fn contains(&self, value: &Q) -> bool - where - &'a T: Borrow, - Q: ?Sized + Hash + Eq, - { - self.set.contains(value) - } - - pub fn get(&self, value: &Q) -> Option<&'a T> - where - &'a T: Borrow, - Q: ?Sized + Hash + Eq, - { - self.set.get(value).copied() - } } impl<'a, T> OrderedSet<&'a T> { - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.vec.is_empty() } - pub fn iter(&self) -> Iter<'_, 'a, T> { + pub(crate) fn iter(&self) -> Iter<'_, 'a, T> { Iter(self.vec.iter()) } } @@ -67,6 +50,14 @@ mod ordered { self.iter() } } + + impl<'a, T> IntoIterator for OrderedSet<&'a T> { + type Item = &'a T; + type IntoIter = as IntoIterator>::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.vec.into_iter() + } + } } mod unordered { @@ -76,21 +67,21 @@ mod unordered { // Wrapper prohibits accidentally introducing iteration over the set, which // could lead to nondeterministic generated code. - pub struct UnorderedSet(HashSet); + pub(crate) struct UnorderedSet(HashSet); impl UnorderedSet where T: Hash + Eq, { - pub fn new() -> Self { + pub(crate) fn new() -> Self { UnorderedSet(HashSet::new()) } - pub fn insert(&mut self, value: T) -> bool { + pub(crate) fn insert(&mut self, value: T) -> bool { self.0.insert(value) } - pub fn contains(&self, value: &Q) -> bool + pub(crate) fn contains(&self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Hash + Eq, @@ -98,7 +89,8 @@ mod unordered { self.0.contains(value) } - pub fn get(&self, value: &Q) -> Option<&T> + #[allow(dead_code)] // only used by cxx-build, not cxxbridge-cmd + pub(crate) fn get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: ?Sized + Hash + Eq, @@ -106,13 +98,20 @@ mod unordered { self.0.get(value) } - pub fn retain(&mut self, f: impl FnMut(&T) -> bool) { + pub(crate) fn retain(&mut self, f: impl FnMut(&T) -> bool) { self.0.retain(f); } + + #[cfg_attr(not(proc_macro), expect(dead_code))] + pub(crate) fn extend(&mut self, iter: impl IntoIterator) { + for value in iter { + self.insert(value); + } + } } } -pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>); +pub(crate) struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>); impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> { type Item = &'a T; @@ -126,7 +125,7 @@ impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> { } } -impl<'a, T> Debug for OrderedSet<&'a T> +impl Debug for OrderedSet<&T> where T: Debug, { diff --git a/syntax/signature.rs b/syntax/signature.rs new file mode 100644 index 000000000..5fbb77157 --- /dev/null +++ b/syntax/signature.rs @@ -0,0 +1,109 @@ +use crate::syntax::set::{OrderedSet, UnorderedSet}; +use crate::syntax::{FnKind, Receiver, Signature, Type}; +use proc_macro2::Ident; +use syn::Lifetime; + +impl Signature { + pub fn receiver(&self) -> Option<&Receiver> { + match &self.kind { + FnKind::Method(receiver) => Some(receiver), + FnKind::Assoc(_) | FnKind::Free => None, + } + } + + pub fn receiver_mut(&mut self) -> Option<&mut Receiver> { + match &mut self.kind { + FnKind::Method(receiver) => Some(receiver), + FnKind::Assoc(_) | FnKind::Free => None, + } + } + + pub fn self_type(&self) -> Option<&Ident> { + match &self.kind { + FnKind::Method(receiver) => Some(&receiver.ty.rust), + FnKind::Assoc(self_type) => Some(self_type), + FnKind::Free => None, + } + } + + #[cfg_attr(not(proc_macro), allow(dead_code))] + pub fn undeclared_lifetimes<'a>(&'a self) -> OrderedSet<&'a Lifetime> { + let mut declared_lifetimes = UnorderedSet::new(); + for param in self.generics.lifetimes() { + declared_lifetimes.insert(¶m.lifetime); + } + + let mut undeclared_lifetimes = OrderedSet::new(); + let mut collect_lifetime = |lifetime: &'a Lifetime| { + if lifetime.ident != "_" + && lifetime.ident != "static" + && !declared_lifetimes.contains(lifetime) + { + undeclared_lifetimes.insert(lifetime); + } + }; + + match &self.kind { + FnKind::Method(receiver) => { + if let Some(lifetime) = &receiver.lifetime { + collect_lifetime(lifetime); + } + for lifetime in &receiver.ty.generics.lifetimes { + collect_lifetime(lifetime); + } + } + FnKind::Assoc(self_type) => { + // If support is added for explicit lifetimes in the Self type + // of static member functions, that needs to be handled here. + let _: &Ident = self_type; + } + FnKind::Free => {} + } + + fn collect_type<'a>(collect_lifetime: &mut impl FnMut(&'a Lifetime), ty: &'a Type) { + match ty { + Type::Ident(named_type) => { + for lifetime in &named_type.generics.lifetimes { + collect_lifetime(lifetime); + } + } + Type::RustBox(ty1) + | Type::RustVec(ty1) + | Type::UniquePtr(ty1) + | Type::SharedPtr(ty1) + | Type::WeakPtr(ty1) + | Type::CxxVector(ty1) => collect_type(collect_lifetime, &ty1.inner), + Type::Ref(ty) | Type::Str(ty) => { + if let Some(lifetime) = &ty.lifetime { + collect_lifetime(lifetime); + } + collect_type(collect_lifetime, &ty.inner); + } + Type::Ptr(ty) => collect_type(collect_lifetime, &ty.inner), + Type::Fn(signature) => { + for lifetime in signature.undeclared_lifetimes() { + collect_lifetime(lifetime); + } + } + Type::Void(_) => {} + Type::SliceRef(ty) => { + if let Some(lifetime) = &ty.lifetime { + collect_lifetime(lifetime); + } + collect_type(collect_lifetime, &ty.inner); + } + Type::Array(ty) => collect_type(collect_lifetime, &ty.inner), + } + } + + for arg in &self.args { + collect_type(&mut collect_lifetime, &arg.ty); + } + + if let Some(ret) = &self.ret { + collect_type(&mut collect_lifetime, ret); + } + + undeclared_lifetimes + } +} diff --git a/syntax/symbol.rs b/syntax/symbol.rs index 4c1607e32..24f87506d 100644 --- a/syntax/symbol.rs +++ b/syntax/symbol.rs @@ -5,8 +5,9 @@ use quote::ToTokens; use std::fmt::{self, Display, Write}; // A mangled symbol consisting of segments separated by '$'. -// For example: cxxbridge1$string$new -pub struct Symbol(String); +// Example: cxxbridge1$string$new +#[derive(Eq, Hash, PartialEq)] +pub(crate) struct Symbol(String); impl Display for Symbol { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -30,7 +31,7 @@ impl Symbol { assert!(self.0.len() > len_before); } - pub fn from_idents<'a>(it: impl Iterator) -> Self { + pub(crate) fn from_idents<'a>(it: impl Iterator) -> Self { let mut symbol = Symbol(String::new()); for segment in it { segment.write(&mut symbol); @@ -38,9 +39,14 @@ impl Symbol { assert!(!symbol.0.is_empty()); symbol } + + #[cfg_attr(proc_macro, expect(dead_code))] + pub(crate) fn contains(&self, ch: char) -> bool { + self.0.contains(ch) + } } -pub trait Segment { +pub(crate) trait Segment { fn write(&self, symbol: &mut Symbol); } @@ -100,7 +106,7 @@ where } } -pub fn join(segments: &[&dyn Segment]) -> Symbol { +pub(crate) fn join(segments: &[&dyn Segment]) -> Symbol { let mut symbol = Symbol(String::new()); for segment in segments { segment.write(&mut symbol); diff --git a/syntax/tokens.rs b/syntax/tokens.rs index a9f42bd43..3b1c4e23f 100644 --- a/syntax/tokens.rs +++ b/syntax/tokens.rs @@ -4,8 +4,8 @@ use crate::syntax::{ Ref, Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, }; use proc_macro2::{Ident, Span, TokenStream}; -use quote::{quote_spanned, ToTokens}; -use syn::{token, Token}; +use quote::{ToTokens, quote_spanned}; +use syn::{Token, token}; impl ToTokens for Type { fn to_tokens(&self, tokens: &mut TokenStream) { @@ -13,7 +13,7 @@ impl ToTokens for Type { Type::Ident(ident) => { if ident.rust == Char { let span = ident.rust.span(); - tokens.extend(quote_spanned!(span=> ::cxx::private::)); + tokens.extend(quote_spanned!(span=> ::cxx::core::ffi::)); } else if ident.rust == CxxString { let span = ident.rust.span(); tokens.extend(quote_spanned!(span=> ::cxx::)); @@ -116,11 +116,9 @@ impl ToTokens for Ptr { mutable: _, inner, mutability, - constness, } = self; star.to_tokens(tokens); mutability.to_tokens(tokens); - constness.to_tokens(tokens); inner.to_tokens(tokens); } } @@ -213,7 +211,7 @@ impl ToTokens for ExternFn { fn to_tokens(&self, tokens: &mut TokenStream) { // Notional token range for error reporting purposes. self.unsafety.to_tokens(tokens); - self.sig.fn_token.to_tokens(tokens); + self.fn_token.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } @@ -222,11 +220,11 @@ impl ToTokens for Impl { fn to_tokens(&self, tokens: &mut TokenStream) { let Impl { cfg: _, + attrs: _, impl_token, impl_generics, negative: _, ty, - ty_generics: _, brace_token, negative_token, } = self; @@ -258,7 +256,7 @@ impl ToTokens for Signature { unsafety: _, fn_token, generics: _, - receiver: _, + kind: _, args, ret, throws: _, @@ -270,7 +268,7 @@ impl ToTokens for Signature { args.to_tokens(tokens); }); if let Some(ret) = ret { - Token![->](paren_token.span).to_tokens(tokens); + Token![->](paren_token.span.join()).to_tokens(tokens); if let Some((result, langle, rangle)) = throws_tokens { result.to_tokens(tokens); langle.to_tokens(tokens); @@ -280,7 +278,7 @@ impl ToTokens for Signature { ret.to_tokens(tokens); } } else if let Some((result, langle, rangle)) = throws_tokens { - Token![->](paren_token.span).to_tokens(tokens); + Token![->](paren_token.span.join()).to_tokens(tokens); result.to_tokens(tokens); langle.to_tokens(tokens); token::Paren(langle.span).surround(tokens, |_| ()); @@ -291,11 +289,8 @@ impl ToTokens for Signature { 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), - } + let EnumRepr { atom, repr_type: _ } = self; + atom.to_tokens(tokens); } } diff --git a/syntax/toposort.rs b/syntax/toposort.rs index 8fe55b8b1..4125af043 100644 --- a/syntax/toposort.rs +++ b/syntax/toposort.rs @@ -7,7 +7,7 @@ enum Mark { Visited, } -pub fn sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> { +pub(crate) fn sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> { let mut sorted = Vec::new(); let ref mut marks = Map::new(); for api in apis { @@ -36,13 +36,12 @@ fn visit<'a>( } let mut result = Ok(()); for field in &strct.fields { - if let Type::Ident(ident) = &field.ty { - if let Some(inner) = types.structs.get(&ident.rust) { - if visit(cx, inner, sorted, marks, types).is_err() { - cx.error(field, "unsupported cyclic data structure"); - result = Err(()); - } - } + if let Type::Ident(ident) = &field.ty + && let Some(inner) = types.structs.get(&ident.rust) + && visit(cx, inner, sorted, marks, types).is_err() + { + cx.error(field, "unsupported cyclic data structure"); + result = Err(()); } } marks.insert(strct, Mark::Visited); diff --git a/syntax/trivial.rs b/syntax/trivial.rs index 067e2d755..9761ccb58 100644 --- a/syntax/trivial.rs +++ b/syntax/trivial.rs @@ -1,26 +1,41 @@ -use crate::syntax::map::UnorderedMap; +use crate::syntax::cfg::ComputedCfg; +use crate::syntax::instantiate::ImplKey; +use crate::syntax::map::{OrderedMap, UnorderedMap}; +use crate::syntax::resolve::Resolution; use crate::syntax::set::{OrderedSet as Set, UnorderedSet}; -use crate::syntax::{Api, Enum, ExternFn, NamedType, Pair, Struct, Type}; +use crate::syntax::types::ConditionalImpl; +use crate::syntax::{Api, Enum, ExternFn, NamedType, Pair, SliceRef, Struct, Type, TypeAlias}; use proc_macro2::Ident; use std::fmt::{self, Display}; #[derive(Copy, Clone)] -pub enum TrivialReason<'a> { +pub(crate) enum TrivialReason<'a> { StructField(&'a Struct), FunctionArgument(&'a ExternFn), FunctionReturn(&'a ExternFn), - BoxTarget, - VecElement, - SliceElement { mutable: bool }, - UnpinnedMut(&'a ExternFn), + BoxTarget { + // Whether the extern functions used by rust::Box are being produced + // within this cxx::bridge expansion, as opposed to the boxed type being + // a type alias from a different module. + #[cfg_attr(not(proc_macro), expect(dead_code))] + local: bool, + }, + VecElement { + #[cfg_attr(not(proc_macro), expect(dead_code))] + local: bool, + }, + SliceElement(&'a SliceRef), } -pub fn required_trivial_reasons<'a>( +pub(crate) fn required_trivial_reasons<'a>( apis: &'a [Api], - all: &Set<&'a Type>, + all: &OrderedMap<&'a Type, ComputedCfg>, structs: &UnorderedMap<&'a Ident, &'a Struct>, enums: &UnorderedMap<&'a Ident, &'a Enum>, cxx: &UnorderedSet<&'a Ident>, + aliases: &UnorderedMap<&'a Ident, &'a TypeAlias>, + impls: &OrderedMap, ConditionalImpl<'a>>, + resolutions: &UnorderedMap<&Ident, Resolution>, ) -> UnorderedMap<&'a Ident, Vec>> { let mut required_trivial = UnorderedMap::new(); @@ -47,70 +62,45 @@ pub fn required_trivial_reasons<'a>( } } Api::CxxFunction(efn) | Api::RustFunction(efn) => { - if let Some(receiver) = &efn.receiver { - if receiver.mutable && !receiver.pinned { - let reason = TrivialReason::UnpinnedMut(efn); - insist_extern_types_are_trivial(&receiver.ty, reason); - } - } for arg in &efn.args { - match &arg.ty { - Type::Ident(ident) => { - let reason = TrivialReason::FunctionArgument(efn); - insist_extern_types_are_trivial(ident, reason); - } - Type::Ref(ty) => { - if ty.mutable && !ty.pinned { - if let Type::Ident(ident) = &ty.inner { - let reason = TrivialReason::UnpinnedMut(efn); - insist_extern_types_are_trivial(ident, reason); - } - } - } - _ => {} + if let Type::Ident(ident) = &arg.ty { + let reason = TrivialReason::FunctionArgument(efn); + insist_extern_types_are_trivial(ident, reason); } } - if let Some(ret) = &efn.ret { - match ret { - Type::Ident(ident) => { - let reason = TrivialReason::FunctionReturn(efn); - insist_extern_types_are_trivial(ident, reason); - } - Type::Ref(ty) => { - if ty.mutable && !ty.pinned { - if let Type::Ident(ident) = &ty.inner { - let reason = TrivialReason::UnpinnedMut(efn); - insist_extern_types_are_trivial(ident, reason); - } - } - } - _ => {} - } + if let Some(Type::Ident(ident)) = &efn.ret { + let reason = TrivialReason::FunctionReturn(efn); + insist_extern_types_are_trivial(ident, reason); } } _ => {} } } - for ty in all { + for (ty, _cfg) in all { + // Ignore cfg. For now if any use of an extern type requires it to be + // trivial, we enforce that it is trivial in all configurations. This + // can potentially be relaxed if there is a motivating use case. match ty { - Type::RustBox(ty) => { - if let Type::Ident(ident) = &ty.inner { - let reason = TrivialReason::BoxTarget; + Type::RustBox(ty1) => { + if let Type::Ident(ident) = &ty1.inner { + let local = !aliases.contains_key(&ident.rust) + || impls.contains_key(&ty.impl_key(resolutions).unwrap()); + let reason = TrivialReason::BoxTarget { local }; insist_extern_types_are_trivial(ident, reason); } } - Type::RustVec(ty) => { - if let Type::Ident(ident) = &ty.inner { - let reason = TrivialReason::VecElement; + Type::RustVec(ty1) => { + if let Type::Ident(ident) = &ty1.inner { + let local = !aliases.contains_key(&ident.rust) + || impls.contains_key(&ty.impl_key(resolutions).unwrap()); + let reason = TrivialReason::VecElement { local }; insist_extern_types_are_trivial(ident, reason); } } Type::SliceRef(ty) => { if let Type::Ident(ident) = &ty.inner { - let reason = TrivialReason::SliceElement { - mutable: ty.mutable, - }; + let reason = TrivialReason::SliceElement(ty); insist_extern_types_are_trivial(ident, reason); } } @@ -124,7 +114,7 @@ pub fn required_trivial_reasons<'a>( // Context: // "type {type} should be trivially move constructible and trivially destructible in C++ to be used as {what} in Rust" // "needs a cxx::ExternType impl in order to be used as {what}" -pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display + 'a { +pub(crate) fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display + 'a { struct Description<'a> { name: &'a Pair, reasons: &'a [TrivialReason<'a>], @@ -139,7 +129,6 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display let mut vec_element = false; let mut slice_shared_element = false; let mut slice_mut_element = false; - let mut unpinned_mut = Set::new(); for reason in self.reasons { match reason { @@ -152,18 +141,15 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display TrivialReason::FunctionReturn(efn) => { return_of.insert(&efn.name.rust); } - TrivialReason::BoxTarget => box_target = true, - TrivialReason::VecElement => vec_element = true, - TrivialReason::SliceElement { mutable } => { - if *mutable { + TrivialReason::BoxTarget { .. } => box_target = true, + TrivialReason::VecElement { .. } => vec_element = true, + TrivialReason::SliceElement(slice) => { + if slice.mutable { slice_mut_element = true; } else { slice_shared_element = true; } } - TrivialReason::UnpinnedMut(efn) => { - unpinned_mut.insert(&efn.name.rust); - } } } @@ -212,13 +198,6 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display param: self.name, }); } - if !unpinned_mut.is_empty() { - clauses.push(Clause::Set { - article: "a", - desc: "non-pinned mutable reference in signature of", - set: &unpinned_mut, - }); - } for (i, clause) in clauses.iter().enumerate() { if i == 0 { diff --git a/syntax/types.rs b/syntax/types.rs index 82b453008..ae6cba5ab 100644 --- a/syntax/types.rs +++ b/syntax/types.rs @@ -1,19 +1,24 @@ +use crate::syntax::attrs::OtherAttrs; +use crate::syntax::cfg::ComputedCfg; use crate::syntax::improper::ImproperCtype; use crate::syntax::instantiate::ImplKey; use crate::syntax::map::{OrderedMap, UnorderedMap}; +use crate::syntax::query::TypeQuery; use crate::syntax::report::Errors; use crate::syntax::resolve::Resolution; -use crate::syntax::set::{OrderedSet, UnorderedSet}; +use crate::syntax::set::UnorderedSet; use crate::syntax::trivial::{self, TrivialReason}; +use crate::syntax::unpin::{self, UnpinReason}; use crate::syntax::visit::{self, Visit}; use crate::syntax::{ - toposort, Api, Atom, Enum, EnumRepr, ExternType, Impl, Lifetimes, Pair, Struct, Type, TypeAlias, + Api, Atom, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Struct, Type, TypeAlias, toposort, }; +use indexmap::map::Entry; use proc_macro2::Ident; use quote::ToTokens; -pub struct Types<'a> { - pub all: OrderedSet<&'a Type>, +pub(crate) struct Types<'a> { + pub all: OrderedMap<&'a Type, ComputedCfg<'a>>, pub structs: UnorderedMap<&'a Ident, &'a Struct>, pub enums: UnorderedMap<&'a Ident, &'a Enum>, pub cxx: UnorderedSet<&'a Ident>, @@ -21,15 +26,27 @@ pub struct Types<'a> { pub aliases: UnorderedMap<&'a Ident, &'a TypeAlias>, pub untrusted: UnorderedMap<&'a Ident, &'a ExternType>, pub required_trivial: UnorderedMap<&'a Ident, Vec>>, - pub impls: OrderedMap, Option<&'a Impl>>, + #[cfg_attr(not(proc_macro), expect(dead_code))] + pub required_unpin: UnorderedMap<&'a Ident, UnpinReason<'a>>, + pub impls: OrderedMap, ConditionalImpl<'a>>, pub resolutions: UnorderedMap<&'a Ident, Resolution<'a>>, + #[cfg_attr(not(proc_macro), expect(dead_code))] + pub associated_fn: UnorderedMap<&'a Ident, Vec<&'a ExternFn>>, pub struct_improper_ctypes: UnorderedSet<&'a Ident>, pub toposorted_structs: Vec<&'a Struct>, } +pub(crate) struct ConditionalImpl<'a> { + pub cfg: ComputedCfg<'a>, + // None for implicit impls, which arise from using a generic type + // instantiation in a struct field or function signature. + #[cfg_attr(not(proc_macro), expect(dead_code))] + pub explicit_impl: Option<&'a Impl>, +} + impl<'a> Types<'a> { - pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self { - let mut all = OrderedSet::new(); + pub(crate) fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self { + let mut all = OrderedMap::new(); let mut structs = UnorderedMap::new(); let mut enums = UnorderedMap::new(); let mut cxx = UnorderedSet::new(); @@ -38,25 +55,50 @@ impl<'a> Types<'a> { let mut untrusted = UnorderedMap::new(); let mut impls = OrderedMap::new(); let mut resolutions = UnorderedMap::new(); + let mut associated_fn = UnorderedMap::new(); let struct_improper_ctypes = UnorderedSet::new(); let toposorted_structs = Vec::new(); - fn visit<'a>(all: &mut OrderedSet<&'a Type>, ty: &'a Type) { - struct CollectTypes<'s, 'a>(&'s mut OrderedSet<&'a Type>); + fn visit<'a>( + all: &mut OrderedMap<&'a Type, ComputedCfg<'a>>, + ty: &'a Type, + cfg: impl Into>, + ) { + struct CollectTypes<'s, 'a> { + all: &'s mut OrderedMap<&'a Type, ComputedCfg<'a>>, + cfg: ComputedCfg<'a>, + } impl<'s, 'a> Visit<'a> for CollectTypes<'s, 'a> { fn visit_type(&mut self, ty: &'a Type) { - self.0.insert(ty); + match self.all.entry(ty) { + Entry::Vacant(entry) => { + entry.insert(self.cfg.clone()); + } + Entry::Occupied(mut entry) => entry.get_mut().merge_or(self.cfg.clone()), + } visit::visit_type(self, ty); } } - CollectTypes(all).visit_type(ty); + let mut visitor = CollectTypes { + all, + cfg: cfg.into(), + }; + visitor.visit_type(ty); } - let mut add_resolution = |name: &'a Pair, generics: &'a Lifetimes| { - resolutions.insert(&name.rust, Resolution { name, generics }); - }; + let mut add_resolution = + |name: &'a Pair, attrs: &'a OtherAttrs, generics: &'a Lifetimes| { + resolutions.insert( + &name.rust, + Resolution { + name, + attrs, + generics, + }, + ); + }; let mut type_names = UnorderedSet::new(); let mut function_names = UnorderedSet::new(); @@ -79,21 +121,21 @@ impl<'a> Types<'a> { // If already declared as a struct or enum, or if // colliding with something other than an extern C++ // type, then error. - duplicate_name(cx, strct, ident); + duplicate_name(cx, strct, ItemName::Type(ident)); } structs.insert(&strct.name.rust, strct); for field in &strct.fields { - visit(&mut all, &field.ty); + let cfg = ComputedCfg::all(&strct.cfg, &field.cfg); + visit(&mut all, &field.ty, cfg); } - add_resolution(&strct.name, &strct.generics); + add_resolution(&strct.name, &strct.attrs, &strct.generics); } Api::Enum(enm) => { - match &enm.repr { - EnumRepr::Native { atom: _, repr_type } => { - all.insert(repr_type); + match all.entry(&enm.repr.repr_type) { + Entry::Vacant(entry) => { + entry.insert(ComputedCfg::Leaf(&enm.cfg)); } - #[cfg(feature = "experimental-enum-variants-from-header")] - EnumRepr::Foreign { rust_type: _ } => {} + Entry::Occupied(mut entry) => entry.get_mut().merge_or(&enm.cfg), } let ident = &enm.name.rust; if !type_names.insert(ident) @@ -104,15 +146,10 @@ impl<'a> Types<'a> { // If already declared as a struct or enum, or if // colliding with something other than an extern C++ // type, then error. - duplicate_name(cx, enm, ident); + duplicate_name(cx, enm, ItemName::Type(ident)); } enums.insert(ident, enm); - if enm.variants_from_header { - // #![variants_from_header] enums are implicitly extern - // C++ type. - cxx.insert(&enm.name.rust); - } - add_resolution(&enm.name, &enm.generics); + add_resolution(&enm.name, &enm.attrs, &enm.generics); } Api::CxxType(ety) => { let ident = &ety.name.rust; @@ -123,70 +160,64 @@ impl<'a> Types<'a> { // If already declared as an extern C++ type, or if // colliding with something which is neither struct nor // enum, then error. - duplicate_name(cx, ety, ident); + duplicate_name(cx, ety, ItemName::Type(ident)); } cxx.insert(ident); if !ety.trusted { untrusted.insert(ident, ety); } - add_resolution(&ety.name, &ety.generics); + add_resolution(&ety.name, &ety.attrs, &ety.generics); } Api::RustType(ety) => { let ident = &ety.name.rust; if !type_names.insert(ident) { - duplicate_name(cx, ety, ident); + duplicate_name(cx, ety, ItemName::Type(ident)); } rust.insert(ident); - add_resolution(&ety.name, &ety.generics); + add_resolution(&ety.name, &ety.attrs, &ety.generics); } Api::CxxFunction(efn) | Api::RustFunction(efn) => { // Note: duplication of the C++ name is fine because C++ has // function overloading. - if !function_names.insert((&efn.receiver, &efn.name.rust)) { - duplicate_name(cx, efn, &efn.name.rust); + let self_type = efn.self_type(); + if let Some(self_type) = self_type { + associated_fn + .entry(self_type) + .or_insert_with(Vec::new) + .push(efn); + } + if !self_type.is_some_and(|self_type| self_type == "Self") + && !function_names.insert((self_type, &efn.name.rust)) + { + duplicate_name(cx, efn, ItemName::Function(self_type, &efn.name.rust)); } for arg in &efn.args { - visit(&mut all, &arg.ty); + visit(&mut all, &arg.ty, &efn.cfg); } if let Some(ret) = &efn.ret { - visit(&mut all, ret); + visit(&mut all, ret, &efn.cfg); } } Api::TypeAlias(alias) => { let ident = &alias.name.rust; if !type_names.insert(ident) { - duplicate_name(cx, alias, ident); + duplicate_name(cx, alias, ItemName::Type(ident)); } cxx.insert(ident); aliases.insert(ident, alias); - add_resolution(&alias.name, &alias.generics); + add_resolution(&alias.name, &alias.attrs, &alias.generics); } Api::Impl(imp) => { - visit(&mut all, &imp.ty); - if let Some(key) = imp.ty.impl_key() { - impls.insert(key, Some(imp)); - } + visit(&mut all, &imp.ty, &imp.cfg); } } } - for ty in &all { - let impl_key = match ty.impl_key() { - Some(impl_key) => impl_key, - None => continue, - }; - let implicit_impl = match impl_key { - ImplKey::RustBox(ident) - | ImplKey::RustVec(ident) - | ImplKey::UniquePtr(ident) - | ImplKey::SharedPtr(ident) - | ImplKey::WeakPtr(ident) - | ImplKey::CxxVector(ident) => { - Atom::from(ident.rust).is_none() && !aliases.contains_key(ident.rust) - } - }; - if implicit_impl && !impls.contains_key(&impl_key) { - impls.insert(impl_key, None); + for api in apis { + if let Api::Impl(imp) = api + && let Some(key) = imp.ty.impl_key(&resolutions) + { + impls.insert(key, ConditionalImpl::from(imp)); } } @@ -194,8 +225,19 @@ impl<'a> Types<'a> { // we check that this is permissible. We do this _after_ scanning all // the APIs above, in case some function or struct references a type // which is declared subsequently. - let required_trivial = - trivial::required_trivial_reasons(apis, &all, &structs, &enums, &cxx); + let required_trivial = trivial::required_trivial_reasons( + apis, + &all, + &structs, + &enums, + &cxx, + &aliases, + &impls, + &resolutions, + ); + + let required_unpin = + unpin::required_unpin_reasons(apis, &all, &structs, &enums, &cxx, &aliases); let mut types = Types { all, @@ -206,14 +248,30 @@ impl<'a> Types<'a> { aliases, untrusted, required_trivial, + required_unpin, impls, resolutions, + associated_fn, struct_improper_ctypes, toposorted_structs, }; types.toposorted_structs = toposort::sort(cx, apis, &types); + for (ty, cfg) in &types.all { + let Some(impl_key) = ty.impl_key(&types.resolutions) else { + continue; + }; + if impl_key.is_implicit_impl_ok(&types) { + match types.impls.entry(impl_key) { + Entry::Vacant(entry) => { + entry.insert(ConditionalImpl::from(cfg.clone())); + } + Entry::Occupied(mut entry) => entry.get_mut().cfg.merge_or(cfg.clone()), + } + } + } + let mut unresolved_structs = types.structs.keys(); let mut new_information = true; while new_information { @@ -241,11 +299,18 @@ impl<'a> Types<'a> { types } - pub fn needs_indirect_abi(&self, ty: &Type) -> bool { + pub(crate) fn needs_indirect_abi(&self, ty: impl Into>) -> bool { + let ty = ty.into(); match ty { - Type::RustBox(_) | Type::UniquePtr(_) => false, - Type::Array(_) => true, - _ => !self.is_guaranteed_pod(ty), + TypeQuery::RustBox + | TypeQuery::UniquePtr + | TypeQuery::Ref(_) + | TypeQuery::Ptr(_) + | TypeQuery::Str + | TypeQuery::Fn + | TypeQuery::SliceRef => false, + TypeQuery::Array(_) => true, + _ => !self.is_guaranteed_pod(ty) || self.is_considered_improper_ctype(ty), } } @@ -255,7 +320,7 @@ impl<'a> Types<'a> { // refuses to believe that C could know how to supply us with a pointer to a // Rust String, even though C could easily have obtained that pointer // legitimately from a Rust call. - pub fn is_considered_improper_ctype(&self, ty: &Type) -> bool { + pub(crate) fn is_considered_improper_ctype(&self, ty: impl Into>) -> bool { match self.determine_improper_ctype(ty) { ImproperCtype::Definite(improper) => improper, ImproperCtype::Depends(ident) => self.struct_improper_ctypes.contains(ident), @@ -264,22 +329,111 @@ impl<'a> Types<'a> { // Types which we need to assume could possibly exist by value on the Rust // side. - pub fn is_maybe_trivial(&self, ty: &Ident) -> bool { - self.structs.contains_key(ty) - || self.enums.contains_key(ty) - || self.aliases.contains_key(ty) + pub(crate) fn is_maybe_trivial(&self, ty: &Type) -> bool { + match ty { + Type::Ident(named_type) => { + let ident = &named_type.rust; + self.structs.contains_key(ident) + || self.enums.contains_key(ident) + || self.aliases.contains_key(ident) + } + Type::CxxVector(_) => false, + // No other type can appear as the inner type of CxxVector, + // UniquePtr, or SharedPtr. + _ => unreachable!("syntax/check.rs should reject other types"), + } + } + + pub(crate) fn contains_elided_lifetime(&self, ty: &Type) -> bool { + match ty { + Type::Ident(ty) => { + Atom::from(&ty.rust).is_none() + && ty.generics.lifetimes.len() + != self.resolve(&ty.rust).generics.lifetimes.len() + } + Type::RustBox(ty) + | Type::RustVec(ty) + | Type::UniquePtr(ty) + | Type::SharedPtr(ty) + | Type::WeakPtr(ty) + | Type::CxxVector(ty) => self.contains_elided_lifetime(&ty.inner), + Type::Ref(ty) => ty.lifetime.is_none() || self.contains_elided_lifetime(&ty.inner), + Type::Ptr(ty) => self.contains_elided_lifetime(&ty.inner), + Type::Str(ty) => ty.lifetime.is_none(), + Type::SliceRef(ty) => ty.lifetime.is_none() || self.contains_elided_lifetime(&ty.inner), + Type::Array(ty) => self.contains_elided_lifetime(&ty.inner), + Type::Fn(_) | Type::Void(_) => false, + } + } + + /// Whether the current module is responsible for generic type + /// instantiations pertaining to the given type. + pub(crate) fn is_local(&self, ty: &Type) -> bool { + match ty { + Type::Ident(ident) => { + Atom::from(&ident.rust).is_none() && !self.aliases.contains_key(&ident.rust) + } + Type::RustBox(ty1) => { + // https://doc.rust-lang.org/reference/glossary.html#fundamental-type-constructors + // "Any time a type T is considered local [...] Box [... is] + // also considered local." + self.is_local(&ty1.inner) + } + Type::Array(_) + | Type::CxxVector(_) + | Type::Fn(_) + | Type::Void(_) + | Type::RustVec(_) + | Type::UniquePtr(_) + | Type::SharedPtr(_) + | Type::WeakPtr(_) + | Type::Ref(_) + | Type::Ptr(_) + | Type::Str(_) + | Type::SliceRef(_) => false, + } } } impl<'t, 'a> IntoIterator for &'t Types<'a> { type Item = &'a Type; - type IntoIter = crate::syntax::set::Iter<'t, 'a, Type>; + type IntoIter = std::iter::Copied>>; fn into_iter(self) -> Self::IntoIter { - self.all.into_iter() + self.all.keys().copied() + } +} + +impl<'a> From> for ConditionalImpl<'a> { + fn from(cfg: ComputedCfg<'a>) -> Self { + ConditionalImpl { + cfg, + explicit_impl: None, + } + } +} + +impl<'a> From<&'a Impl> for ConditionalImpl<'a> { + fn from(imp: &'a Impl) -> Self { + ConditionalImpl { + cfg: ComputedCfg::Leaf(&imp.cfg), + explicit_impl: Some(imp), + } } } -fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) { - let msg = format!("the name `{}` is defined multiple times", ident); +enum ItemName<'a> { + Type(&'a Ident), + Function(Option<&'a Ident>, &'a Ident), +} + +fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, name: ItemName) { + let description = match name { + ItemName::Type(name) => format!("type `{}`", name), + ItemName::Function(Some(self_type), name) => { + format!("associated function `{}::{}`", self_type, name) + } + ItemName::Function(None, name) => format!("function `{}`", name), + }; + let msg = format!("the {} is defined multiple times", description); cx.error(sp, msg); } diff --git a/syntax/unpin.rs b/syntax/unpin.rs new file mode 100644 index 000000000..b3a442254 --- /dev/null +++ b/syntax/unpin.rs @@ -0,0 +1,64 @@ +use crate::syntax::cfg::ComputedCfg; +use crate::syntax::map::{OrderedMap, UnorderedMap}; +use crate::syntax::set::UnorderedSet; +use crate::syntax::{Api, Enum, NamedType, Receiver, Ref, SliceRef, Struct, Type, TypeAlias}; +use proc_macro2::Ident; + +#[cfg_attr(not(proc_macro), expect(dead_code))] +pub(crate) enum UnpinReason<'a> { + Receiver(&'a Receiver), + Ref(&'a Ref), + Slice(&'a SliceRef), +} + +pub(crate) fn required_unpin_reasons<'a>( + apis: &'a [Api], + all: &OrderedMap<&'a Type, ComputedCfg>, + structs: &UnorderedMap<&'a Ident, &'a Struct>, + enums: &UnorderedMap<&'a Ident, &'a Enum>, + cxx: &UnorderedSet<&'a Ident>, + aliases: &UnorderedMap<&'a Ident, &'a TypeAlias>, +) -> UnorderedMap<&'a Ident, UnpinReason<'a>> { + let mut reasons = UnorderedMap::new(); + + let is_extern_type_alias = |ty: &NamedType| -> bool { + cxx.contains(&ty.rust) + && !structs.contains_key(&ty.rust) + && !enums.contains_key(&ty.rust) + && aliases.contains_key(&ty.rust) + }; + + for (ty, _cfgs) in all { + if let Type::SliceRef(slice) = ty + && let Type::Ident(inner) = &slice.inner + && slice.mutable + && is_extern_type_alias(inner) + { + reasons.insert(&inner.rust, UnpinReason::Slice(slice)); + } + } + + for api in apis { + if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api + && let Some(receiver) = efn.receiver() + && receiver.mutable + && !receiver.pinned + && is_extern_type_alias(&receiver.ty) + { + reasons.insert(&receiver.ty.rust, UnpinReason::Receiver(receiver)); + } + } + + for (ty, _cfg) in all { + if let Type::Ref(ty) = ty + && let Type::Ident(inner) = &ty.inner + && ty.mutable + && !ty.pinned + && is_extern_type_alias(inner) + { + reasons.insert(&inner.rust, UnpinReason::Ref(ty)); + } + } + + reasons +} diff --git a/syntax/visit.rs b/syntax/visit.rs index 2f31378f2..e31b8c41b 100644 --- a/syntax/visit.rs +++ b/syntax/visit.rs @@ -1,12 +1,12 @@ use crate::syntax::Type; -pub trait Visit<'a> { +pub(crate) trait Visit<'a> { fn visit_type(&mut self, ty: &'a Type) { visit_type(self, ty); } } -pub fn visit_type<'a, V>(visitor: &mut V, ty: &'a Type) +pub(crate) fn visit_type<'a, V>(visitor: &mut V, ty: &'a Type) where V: Visit<'a> + ?Sized, { diff --git a/tests/BUCK b/tests/BUCK index 865eebc93..21f44ff62 100644 --- a/tests/BUCK +++ b/tests/BUCK @@ -3,7 +3,7 @@ load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_test( name = "test", srcs = ["test.rs"], - edition = "2018", + edition = "2024", deps = [ ":ffi", "//:cxx", @@ -18,10 +18,11 @@ rust_library( "ffi/module.rs", ], crate = "cxx_test_suite", - edition = "2018", + edition = "2024", deps = [ ":impl", "//:cxx", + "//third-party:serde", ], ) @@ -33,11 +34,12 @@ cxx_library( ":module/source", ], exported_deps = ["//:core"], - exported_headers = { - "ffi/lib.rs.h": ":bridge/header", - "ffi/module.rs.h": ":module/header", - "ffi/tests.h": "ffi/tests.h", - }, + exported_headers = [ + ":bridge/header", + ":module/header", + "ffi/tests.h", + ], + preferred_linkage = "static", ) rust_cxx_bridge( diff --git a/tests/BUILD b/tests/BUILD.bazel similarity index 81% rename from tests/BUILD rename to tests/BUILD.bazel index 3c25d9633..a3c62b21f 100644 --- a/tests/BUILD +++ b/tests/BUILD.bazel @@ -6,7 +6,7 @@ rust_test( name = "test", size = "small", srcs = ["test.rs"], - edition = "2018", + edition = "2024", deps = [ ":cxx_test_suite", "//:cxx", @@ -15,26 +15,32 @@ rust_test( rust_library( name = "cxx_test_suite", + testonly = True, srcs = [ "ffi/cast.rs", "ffi/lib.rs", "ffi/module.rs", ], - edition = "2018", - deps = [ + edition = "2024", + link_deps = [ ":impl", + ], + deps = [ "//:cxx", + "@crates.io//:serde", ], ) cc_library( name = "impl", + testonly = True, srcs = [ "ffi/tests.cc", ":bridge/source", ":module/source", ], hdrs = ["ffi/tests.h"], + linkstatic = True, deps = [ ":bridge/include", ":module/include", @@ -44,12 +50,14 @@ cc_library( rust_cxx_bridge( name = "bridge", + testonly = True, src = "ffi/lib.rs", deps = [":impl"], ) rust_cxx_bridge( name = "module", + testonly = True, src = "ffi/module.rs", deps = [":impl"], ) diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 000000000..c55ab9115 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,41 @@ +# Testing + +This document provides an outline of different kinds of tests used by the `cxx` +project. + +## Errors from proc macro + +We want to verify that the `#[cxx::bridge]` macro reports expected error +messages when invoked by `rustc` on certain inputs. + +Such verification is handled by test cases underneath **tests/ui** directory and +driven by **tests/compiletest.rs**. The test cases consist of a pair of files: + +* **foo.rs** is the input +* **foo.stderr** is the expected Rust compiler diagnostic + +## Errors from C++ compiler + +We want to verify that cxx's generated C++ code triggers expected C++ compiler +diagnostics on certain inputs. + +Such verification is covered by **tests/cpp_ui_tests.rs**. + +## End-to-end functionality + +End-to-end functional tests are structured as follows: + +* The code under test is contained underneath **tests/ffi** directory which + contains: + - Rust code under test &emdash; the `cxx-test-suite` crate (**lib.rs** and + **module.rs**) with: + - A few `#[cxx::bridge]` invocations + - Rust types (e.g. `struct R`) + - Rust functions and methods (e.g. `fn r_return_primitive`) + - C/C++ code under test (**tests.h** and **tests.cc**) + - C++ types (e.g. `class C`) + - C++ functions and methods (e.g. `c_return_primitive`) +* The testcases can be found in: + - Rust calling into C++: **tests/test.rs**. + - C++ calling into Rust: **tests/ffi/test.cc**. These tests are manually + dispatched from the `cxx_run_test` function in **tests/ffi/test.cc**. diff --git a/tests/compiletest.rs b/tests/compiletest.rs index cd58514f1..97ab136dc 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -1,7 +1,7 @@ #[allow(unused_attributes)] -#[rustversion::attr(not(nightly), ignore)] -#[cfg_attr(skip_ui_tests, ignore)] -#[cfg_attr(miri, ignore)] +#[rustversion::attr(not(nightly), ignore = "requires nightly")] +#[cfg_attr(skip_ui_tests, ignore = "disabled by `--cfg=skip_ui_tests`")] +#[cfg_attr(miri, ignore = "incompatible with miri")] #[test] fn ui() { let t = trybuild::TestCases::new(); diff --git a/tests/cpp_compile/mod.rs b/tests/cpp_compile/mod.rs new file mode 100644 index 000000000..d60c7edbe --- /dev/null +++ b/tests/cpp_compile/mod.rs @@ -0,0 +1,194 @@ +//! This test harness is for verifying that the C++ code from cxx's C++ code +//! generator (via `cxx_gen`) triggers the intended C++ compiler diagnostics. + +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] + +use proc_macro2::TokenStream; +use std::borrow::Cow; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::{self, Stdio}; +use tempfile::TempDir; + +mod smoke_test; + +/// 1. Takes a `#[cxx::bridge]` and generates `.cc` and `.h` files, +/// 2. Places additional source files (typically handwritten header files), +/// 3. Compiles the generated `.cc` file. +pub struct Test { + temp_dir: TempDir, + + /// Path to the `.cc` file (in `temp_dir`) that is generated by the + /// `cxx_gen` crate out of the `cxx_bridge` argument passed to `Test::new`. + generated_cc: PathBuf, +} + +impl Test { + /// Creates a new test for the given `cxx_bridge`. + /// + /// Example: + /// + /// ``` + /// let test = Test::new(quote!{ + /// #[cxx::bridge] + /// mod ffi { + /// unsafe extern "C++" { + /// include!("include.h"); + /// pub fn do_cpp_thing(); + /// } + /// } + /// }); + /// ``` + /// + /// # Panics + /// + /// Panics if there is a failure when generating `.cc` and `.h` files from + /// the `cxx_bridge`. + #[must_use] + pub fn new(cxx_bridge: TokenStream) -> Self { + let prefix = concat!(env!("CARGO_CRATE_NAME"), "-"); + let scratch = scratch::path("cxx-test-suite"); + let temp_dir = TempDir::with_prefix_in(prefix, scratch).unwrap(); + let generated_h = temp_dir.path().join("cxx_bridge.generated.h"); + let generated_cc = temp_dir.path().join("cxx_bridge.generated.cc"); + + let opt = cxx_gen::Opt::default(); + let generated = cxx_gen::generate_header_and_cc(cxx_bridge, &opt).unwrap(); + fs::write(&generated_h, &generated.header).unwrap(); + fs::write(&generated_cc, &generated.implementation).unwrap(); + + Self { + temp_dir, + generated_cc, + } + } + + /// Writes a file to the temporary test directory. + /// + /// The new file will be present in the `-I` include path passed to the C++ + /// compiler. + /// + /// # Panics + /// + /// Panics if there is an error when writing the file. + pub fn write_file(&self, filename: impl AsRef, contents: &str) { + fs::write(self.temp_dir.path().join(filename), contents).unwrap(); + } + + /// Compiles the `.cc` file generated in `Self::new`. + /// + /// # Panics + /// + /// Panics if there is a problem with spawning the C++ compiler. + /// (Compilation errors will *not* result in a panic.) + #[must_use] + pub fn compile(&self) -> CompilationResult { + let mut build = cc::Build::new(); + build + .include(self.temp_dir.path()) + .out_dir(self.temp_dir.path()) + .cpp(true); + + // Arbitrarily using C++20 for now. If some test cases require a + // specific C++ standard, we can make this configurable. + build.std("c++20"); + + // Set info required by the `cc` crate. + // + // The correct host triple during execution of this test is the target + // triple from the Rust compilation of this test -- not the Rust host + // triple. + build + .opt_level(3) + .host(target_triple::TARGET) + .target(target_triple::TARGET); + + // The `cc` crate does not currently expose the `Command` for building a + // single C++ source file. Work around that by passing `-c `. + let mut command = build.get_compiler().to_command(); + command + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .current_dir(self.temp_dir.path()) + .arg("-c") + .arg(&self.generated_cc); + let output = command.spawn().unwrap().wait_with_output().unwrap(); + CompilationResult(output) + } +} + +/// Wrapper around the output from a C++ compiler. +pub struct CompilationResult(process::Output); + +impl CompilationResult { + fn stdout(&self) -> Cow { + String::from_utf8_lossy(&self.0.stdout) + } + + fn stderr(&self) -> Cow { + String::from_utf8_lossy(&self.0.stderr) + } + + fn dump_output_and_panic(&self, msg: &str) -> ! { + eprintln!("{}", self.stdout()); + eprintln!("{}", self.stderr()); + panic!("{msg}"); + } + + fn error_lines(&self) -> Vec { + assert!(!self.0.status.success()); + + // MSVC reports errors to stdout rather than stderr, so consider both. + let stdout = self.stdout(); + let stderr = self.stderr(); + let all_lines = stdout.lines().chain(stderr.lines()); + + all_lines + .filter(|line| { + // This should match MSVC error output + // (e.g. `file.cc(): error C2338: static_assert failed: ...`) + // as well as Clang or GCC error output + // (e.g. `file.cc::: error: static assertion failed: ...` + line.contains(": error") + }) + .map(str::to_owned) + .collect() + } + + /// Asserts that the C++ compilation succeeded. + /// + /// # Panics + /// + /// Panics if the C++ compiler reported an error. + pub fn assert_success(&self) { + if !self.0.status.success() { + self.dump_output_and_panic("Compiler reported an error"); + } + } + + /// Verifies that the compilation failed with a single error, and return the + /// stderr line describing this error. + /// + /// Note that different compilers may return slightly different error + /// messages, so tests should be careful to only verify presence of some + /// substrings. + /// + /// # Panics + /// + /// Panics if there was no error, or if there was more than a single error. + #[must_use] + pub fn expect_single_error(&self) -> String { + let error_lines = self.error_lines(); + if error_lines.is_empty() { + self.dump_output_and_panic("No error lines found, despite non-zero exit code?"); + } + if error_lines.len() > 1 { + self.dump_output_and_panic("Unexpectedly more than 1 error line was present"); + } + + // `eprintln` to help with debugging test failues that may happen later. + let single_error_line = error_lines.into_iter().next().unwrap(); + eprintln!("Got single error as expected: {single_error_line}"); + single_error_line + } +} diff --git a/tests/cpp_compile/smoke_test.rs b/tests/cpp_compile/smoke_test.rs new file mode 100644 index 000000000..7f54478a7 --- /dev/null +++ b/tests/cpp_compile/smoke_test.rs @@ -0,0 +1,66 @@ +use crate::cpp_compile; +use indoc::indoc; +use quote::quote; + +#[test] +fn test_success() { + let test = cpp_compile::Test::new(quote! { + #[cxx::bridge] + mod ffi { + unsafe extern "C++" { + include!("include.h"); + pub fn do_cpp_thing(); + } + } + }); + test.write_file( + "include.h", + indoc! {" + void do_cpp_thing(); + "}, + ); + test.compile().assert_success(); +} + +#[test] +fn test_failure() { + let test = cpp_compile::Test::new(quote! { + #[cxx::bridge] + mod ffi { + unsafe extern "C++" { + include!("include.h"); + } + } + }); + test.write_file( + "include.h", + indoc! {r#" + static_assert(false, "This is a failure smoke test"); + "#}, + ); + let err_msg = test.compile().expect_single_error(); + assert!(err_msg.contains("This is a failure smoke test")); +} + +#[test] +#[should_panic = "Unexpectedly more than 1 error line was present"] +fn test_unexpected_extra_error() { + let test = cpp_compile::Test::new(quote! { + #[cxx::bridge] + mod ffi { + unsafe extern "C++" { + include!("include.h"); + } + } + }); + test.write_file( + "include.h", + indoc! {r#" + static_assert(false, "First error line"); + static_assert(false, "Second error line"); + "#}, + ); + + // We `should_panic` inside `expect_single_error` below: + let _ = test.compile().expect_single_error(); +} diff --git a/tests/cpp_ui_tests.rs b/tests/cpp_ui_tests.rs new file mode 100644 index 000000000..06a8efd99 --- /dev/null +++ b/tests/cpp_ui_tests.rs @@ -0,0 +1,28 @@ +mod cpp_compile; + +use indoc::indoc; +use quote::quote; + +/// This is a regression test for `static_assert(::rust::is_complete...)` +/// which we started to emit in +#[test] +fn test_unique_ptr_of_incomplete_foward_declared_pointee() { + let test = cpp_compile::Test::new(quote! { + #[cxx::bridge] + mod ffi { + unsafe extern "C++" { + include!("include.h"); + type ForwardDeclaredType; + } + impl UniquePtr {} + } + }); + test.write_file( + "include.h", + indoc! {" + class ForwardDeclaredType; + "}, + ); + let err_msg = test.compile().expect_single_error(); + assert!(err_msg.contains("definition of `::ForwardDeclaredType` is required")); +} diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs index e91675d9d..f9f2347a2 100644 --- a/tests/cxx_gen.rs +++ b/tests/cxx_gen.rs @@ -1,8 +1,8 @@ -#![allow(clippy::field_reassign_with_default)] - -use cxx_gen::{generate_header_and_cc, Opt}; +use cxx_gen::{Opt, generate_header_and_cc}; use std::str; +const CXXPREFIX: &str = concat!("cxxbridge1$", env!("CARGO_PKG_VERSION_PATCH")); + const BRIDGE0: &str = r#" #[cxx::bridge] mod ffi { @@ -20,7 +20,7 @@ fn test_extern_c_function() { let output = str::from_utf8(&generated.implementation).unwrap(); // To avoid continual breakage we won't test every byte. // Let's look for the major features. - assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::Str foo)")); + assert!(output.contains(&format!("void {CXXPREFIX}$do_cpp_thing(::rust::Str foo)"))); } #[test] @@ -30,5 +30,53 @@ fn test_impl_annotation() { let source = BRIDGE0.parse().unwrap(); let generated = generate_header_and_cc(source, &opt).unwrap(); let output = str::from_utf8(&generated.implementation).unwrap(); - assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::Str foo)")); + assert!(output.contains(&format!( + "ANNOTATION void {CXXPREFIX}$do_cpp_thing(::rust::Str foo)", + ))); +} + +const BRIDGE1: &str = r#" + #[cxx::bridge] + mod ffi { + extern "C++" { + type CppType; + } + + extern "Rust" { + fn rust_method_cpp_receiver(self: Pin<&mut CppType>); + } + } +"#; + +// Ensure that implementing a Rust method on an opaque C++ type only causes +// generation of the member function definition, not a member function +// declaration in a class definition. +// +// The member function declaration will come from whichever header provides the +// C++ class definition. +// +// This allows for developers and crates that are producing both C++ and Rust +// code to have a C++ method implemented in Rust without having to use a free +// function and passing through the C++ "this" as an argument. +#[test] +fn test_extern_rust_method_on_c_type() { + let opt = Opt::default(); + let source = BRIDGE1.parse().unwrap(); + let generated = generate_header_and_cc(source, &opt).unwrap(); + let header = str::from_utf8(&generated.header).unwrap(); + let implementation = str::from_utf8(&generated.implementation).unwrap(); + + // Check that the header doesn't have the Rust method. + assert!(!header.contains("rust_method_cpp_receiver")); + + // Check that there is a generated C signature bridging to the Rust method. + assert!(implementation.contains(&format!( + "void {CXXPREFIX}$CppType$rust_method_cpp_receiver(::CppType &self) noexcept;", + ))); + + // Check that there is an implementation on the C++ class calling the Rust method. + assert!(implementation.contains("void CppType::rust_method_cpp_receiver() noexcept {")); + assert!(implementation.contains(&format!( + "{CXXPREFIX}$CppType$rust_method_cpp_receiver(*this);", + ))); } diff --git a/tests/cxx_string.rs b/tests/cxx_string.rs index 67444fa56..4b9c72aa4 100644 --- a/tests/cxx_string.rs +++ b/tests/cxx_string.rs @@ -1,4 +1,13 @@ -use cxx::{let_cxx_string, CxxString}; +#![allow( + clippy::items_after_statements, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap, + clippy::unused_async +)] + +use cxx::{CxxString, let_cxx_string}; +use std::fmt::Write as _; +use std::panic::{self, RefUnwindSafe}; #[test] fn test_async_cxx_string() { @@ -12,11 +21,50 @@ fn test_async_cxx_string() { // https://github.com/dtolnay/cxx/issues/693 fn assert_send(_: impl Send) {} assert_send(f()); + + fn assert_sync(_: impl Sync) {} + assert_sync(f()); + + fn assert_ref_unwind_safe(_: impl RefUnwindSafe) {} + assert_ref_unwind_safe(f()); +} + +#[test] +fn test_display() { + let_cxx_string!(s = b"w\"x\'y\xF1\x80\xF1\x80z"); + + assert_eq!(format!("{}", s), "w\"x'y\u{fffd}\u{fffd}z"); } #[test] fn test_debug() { - let_cxx_string!(s = "x\"y\'z"); + let_cxx_string!(s = b"w\"x\'y\xF1\x80z"); + + assert_eq!(format!("{:?}", s), r#""w\"x'y\xf1\x80z""#); +} - assert_eq!(format!("{:?}", s), r#""x\"y'z""#); +#[test] +fn test_fmt_write() { + let_cxx_string!(s = ""); + + let name = "world"; + write!(s, "Hello, {name}!").unwrap(); + assert_eq!(s.to_str(), Ok("Hello, world!")); +} + +#[test] +fn test_io_write() { + let_cxx_string!(s = ""); + let mut reader: &[u8] = b"Hello, world!"; + + std::io::copy(&mut reader, &mut s).unwrap(); + assert_eq!(s.to_str(), Ok("Hello, world!")); +} + +#[test] +#[allow(unused_variables)] +fn test_panic() { + let _ = panic::catch_unwind(|| { + let_cxx_string!(s = None::<&[u8]>.unwrap()); + }); } diff --git a/tests/cxx_vector.rs b/tests/cxx_vector.rs new file mode 100644 index 000000000..de9e8efef --- /dev/null +++ b/tests/cxx_vector.rs @@ -0,0 +1,7 @@ +use cxx::CxxVector; + +#[test] +fn test_cxx_vector_new() { + let vector = CxxVector::::new(); + assert!(vector.is_empty()); +} diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml index ef91f4f6d..d0971abb4 100644 --- a/tests/ffi/Cargo.toml +++ b/tests/ffi/Cargo.toml @@ -2,7 +2,7 @@ name = "cxx-test-suite" version = "0.0.0" authors = ["David Tolnay "] -edition = "2018" +edition = "2024" publish = false [lib] @@ -10,7 +10,8 @@ path = "lib.rs" [dependencies] cxx = { path = "../..", default-features = false } +serde = { version = "1", features = ["derive"] } [build-dependencies] -cxx-build = { path = "../../gen/build" } +cxx-build = { path = "../../bridge/build" } cxxbridge-flags = { path = "../../flags" } diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs index 86f8cd3a5..98f9af52c 100644 --- a/tests/ffi/build.rs +++ b/tests/ffi/build.rs @@ -1,3 +1,6 @@ +#![allow(unknown_lints)] +#![allow(unexpected_cfgs)] + use cxx_build::CFG; fn main() { @@ -9,10 +12,13 @@ fn main() { let sources = vec!["lib.rs", "module.rs"]; let mut build = cxx_build::bridges(sources); build.file("tests.cc"); - build.flag_if_supported(cxxbridge_flags::STD); + build.std(cxxbridge_flags::STD); build.warnings_into_errors(cfg!(deny_warnings)); if cfg!(not(target_env = "msvc")) { build.define("CXX_TEST_INSTANTIATIONS", None); } build.compile("cxx-test-suite"); + + println!("cargo:rerun-if-changed=tests.cc"); + println!("cargo:rerun-if-changed=tests.h"); } diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs index d6a5f0286..9a8ad7add 100644 --- a/tests/ffi/lib.rs +++ b/tests/ffi/lib.rs @@ -1,29 +1,44 @@ #![allow( + clippy::assert_is_empty, clippy::boxed_local, - clippy::derive_partial_eq_without_eq, - clippy::just_underscores_and_digits, + clippy::elidable_lifetime_names, + clippy::missing_errors_doc, clippy::missing_safety_doc, clippy::must_use_candidate, clippy::needless_lifetimes, clippy::needless_pass_by_value, - clippy::ptr_arg, - clippy::trivially_copy_pass_by_ref, + clippy::unnecessary_literal_bound, clippy::unnecessary_wraps, clippy::unused_self )] +#![allow(unknown_lints)] +#![warn(rust_2024_compatibility)] +#![forbid(unsafe_op_in_unsafe_fn)] +#![deny(warnings)] // Check that expansion of `cxx::bridge` doesn't trigger warnings. pub mod cast; pub mod module; -use cxx::{type_id, CxxString, CxxVector, ExternType, SharedPtr, UniquePtr}; +use cxx::{CxxString, CxxVector, ExternType, SharedPtr, UniquePtr, type_id}; use std::fmt::{self, Display}; use std::mem::MaybeUninit; use std::os::raw::c_char; #[cxx::bridge(namespace = "tests")] pub mod ffi { - #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] + extern "C++" { + include!("tests/ffi/tests.h"); + + type Undefined; + type Private; + type Unmovable; + type Array; + } + + #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] + #[serde(deny_unknown_fields)] struct Shared { + #[serde(default)] z: usize, } @@ -32,9 +47,10 @@ pub mod ffi { msg: String, } - #[derive(Debug, Hash, PartialOrd, Ord)] + #[derive(Debug, Hash, PartialOrd, Ord, Default, BitAnd, BitOr, BitXor)] enum Enum { AVal, + #[default] BVal = 2020, #[cxx_name = "CVal"] LastVal, @@ -58,7 +74,7 @@ pub mod ffi { enum ABEnum { ABAVal, ABBVal = 2020, - ABCVal, + ABCVal = -2147483648i32, } #[namespace = "A::B"] @@ -79,19 +95,22 @@ pub mod ffi { e: COwnedEnum, } - pub struct Array { + pub struct WithArray { a: [i32; 4], b: Buffer, } + #[repr(align(4))] + pub struct OveralignedStruct { + b: [u8; 4], + } + #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct StructWithLifetime<'a> { s: &'a str, } unsafe extern "C++" { - include!("tests/ffi/tests.h"); - type C; fn c_return_primitive() -> usize; @@ -201,7 +220,9 @@ pub mod ffi { fn c_method_on_shared(self: &Shared) -> usize; fn c_method_ref_on_shared(self: &Shared) -> &usize; fn c_method_mut_on_shared(self: &mut Shared) -> &mut usize; - fn c_set_array(self: &mut Array, value: i32); + #[Self = "Shared"] + fn c_static_method_on_shared() -> usize; + fn c_set_array(self: &mut WithArray, value: i32); fn c_get_use_count(weak: &WeakPtr) -> usize; @@ -216,6 +237,16 @@ pub mod ffi { #[namespace = "other"] fn ns_c_take_ns_shared(shared: AShared); + + #[Self = "C"] + fn c_static_method() -> usize; + } + + struct ContainsOpaqueRust<'a> { + boxed: Box, + vecked: Vec, + referenced: &'a mut OpaqueRust, + sliced: &'a mut [OpaqueRust], } extern "C++" { @@ -223,6 +254,7 @@ pub mod ffi { type COwnedEnum; type Job = crate::module::ffi::Job; + type OpaqueRust = crate::module::OpaqueRust; } extern "Rust" { @@ -236,6 +268,7 @@ pub mod ffi { fn c_return_borrow<'a>(s: &'a CxxString) -> UniquePtr>; #[rust_name = "c_return_borrow_elided"] + #[allow(unknown_lints, mismatched_lifetime_syntaxes)] fn c_return_borrow(s: &CxxString) -> UniquePtr; fn const_member(self: &Borrow); @@ -266,6 +299,7 @@ pub mod ffi { fn r_return_ref(shared: &Shared) -> &usize; fn r_return_mut(shared: &mut Shared) -> &mut usize; fn r_return_str(shared: &Shared) -> &str; + unsafe fn r_return_str_via_out_param<'a>(shared: &'a Shared, out_param: &mut &'a str); fn r_return_sliceu8(shared: &Shared) -> &[u8]; fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8]; fn r_return_rust_string() -> String; @@ -273,6 +307,10 @@ pub mod ffi { fn r_return_rust_vec() -> Vec; fn r_return_rust_vec_string() -> Vec; fn r_return_rust_vec_extern_struct() -> Vec; + #[allow(clippy::vec_box)] + fn r_return_rust_vec_box() -> Vec>; + #[allow(clippy::vec_box)] + fn r_return_rust_vec_box_other_module_type() -> Vec>; fn r_return_ref_rust_vec(shared: &Shared) -> &Vec; fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec; fn r_return_identity(_: usize) -> usize; @@ -308,10 +346,22 @@ pub mod ffi { fn get(self: &R) -> usize; fn set(self: &mut R, n: usize) -> usize; fn r_method_on_shared(self: &Shared) -> String; - fn r_get_array_sum(self: &Array) -> i32; + fn r_get_array_sum(self: &WithArray) -> i32; + // Ensure that a Rust method can be implemented on an opaque C++ type. + fn r_method_on_c_get_mut(self: Pin<&mut C>) -> &mut usize; #[cxx_name = "rAliasedFunction"] fn r_aliased_function(x: i32) -> String; + + #[Self = "Shared"] + fn r_static_method_on_shared() -> usize; + + #[Self = "R"] + fn r_static_method() -> usize; + } + + unsafe extern "C++" { + fn c_member_function_on_rust_type(self: &R); } struct Dag0 { @@ -337,11 +387,28 @@ pub mod ffi { impl Box {} impl CxxVector {} + impl SharedPtr {} + impl SharedPtr {} + impl CxxVector {} + impl UniquePtr {} +} + +#[rustfmt::skip] +#[cxx::bridge(namespace = "tests")] +pub mod ffi_no_rustfmt { + // Rustfmt would replace `StructWithLifetime2<>` by `StructWithLifetime2`, + // but the test is meant to cover specifically the former spelling. + pub struct StructWithLifetime2<'a> { + s: &'a str, + } + extern "Rust" { + fn r_take_unique_ptr_of_struct_with_lifetime2(_: UniquePtr>); + } } mod other { use cxx::kind::{Opaque, Trivial}; - use cxx::{type_id, CxxString, ExternType}; + use cxx::{CxxString, ExternType, type_id}; #[repr(C)] pub struct D { @@ -356,7 +423,7 @@ mod other { pub mod f { use cxx::kind::Opaque; - use cxx::{type_id, CxxString, ExternType}; + use cxx::{CxxString, ExternType, type_id}; #[repr(C)] pub struct F { @@ -403,22 +470,37 @@ impl R { self.0 = n; n } + + fn r_static_method() -> usize { + 2024 + } } -pub struct Reference<'a>(&'a String); +pub struct Reference<'a>(pub &'a String); impl ffi::Shared { fn r_method_on_shared(&self) -> String { "2020".to_owned() } + + fn r_static_method_on_shared() -> usize { + 2023 + } } -impl ffi::Array { +impl ffi::WithArray { pub fn r_get_array_sum(&self) -> i32 { self.a.iter().sum() } } +// A Rust method implemented on an opaque C++ type. +impl ffi::C { + pub fn r_method_on_c_get_mut(self: core::pin::Pin<&mut Self>) -> &mut usize { + self.getMut() + } +} + #[derive(Default)] #[repr(C)] pub struct Buffer([c_char; 12]); @@ -452,14 +534,16 @@ fn r_return_box() -> Box { } fn r_return_unique_ptr() -> UniquePtr { - extern "C" { + #[allow(missing_unsafe_on_extern)] + unsafe extern "C" { fn cxx_test_suite_get_unique_ptr() -> *mut ffi::C; } unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr()) } } fn r_return_shared_ptr() -> SharedPtr { - extern "C" { + #[allow(missing_unsafe_on_extern)] + unsafe extern "C" { fn cxx_test_suite_get_shared_ptr(repr: *mut SharedPtr); } let mut shared_ptr = MaybeUninit::>::uninit(); @@ -483,6 +567,11 @@ fn r_return_str(shared: &ffi::Shared) -> &str { "2020" } +fn r_return_str_via_out_param<'a>(shared: &'a ffi::Shared, out_param: &mut &'a str) { + let _ = shared; + *out_param = "2020"; +} + fn r_return_sliceu8(shared: &ffi::Shared) -> &[u8] { let _ = shared; b"2020" @@ -497,7 +586,8 @@ fn r_return_rust_string() -> String { } fn r_return_unique_ptr_string() -> UniquePtr { - extern "C" { + #[allow(missing_unsafe_on_extern)] + unsafe extern "C" { fn cxx_test_suite_get_unique_ptr_string() -> *mut CxxString; } unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr_string()) } @@ -515,6 +605,16 @@ fn r_return_rust_vec_extern_struct() -> Vec { Vec::new() } +#[allow(clippy::vec_box)] +fn r_return_rust_vec_box() -> Vec> { + vec![Box::new(R(2020))] +} + +#[allow(clippy::vec_box)] +fn r_return_rust_vec_box_other_module_type() -> Vec> { + vec![Box::new(module::OpaqueRust(2025))] +} + fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec { let _ = shared; unimplemented!() @@ -619,6 +719,11 @@ fn r_take_enum(e: ffi::Enum) { let _ = e; } +fn r_take_unique_ptr_of_struct_with_lifetime2( + _: cxx::UniquePtr, +) { +} + fn r_try_return_void() -> Result<(), Error> { Ok(()) } diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs index 21a86206d..faa2ec7ca 100644 --- a/tests/ffi/module.rs +++ b/tests/ffi/module.rs @@ -1,3 +1,7 @@ +#![deny(warnings)] // Check that expansion of `cxx::bridge` doesn't trigger warnings. + +pub struct OpaqueRust(pub i32); + #[cxx::bridge(namespace = "tests")] pub mod ffi { struct Job { @@ -10,9 +14,19 @@ pub mod ffi { type C = crate::ffi::C; fn c_take_unique_ptr(c: UniquePtr); + fn c_lifetime_elision_member_fn(self: &C) -> &CxxVector; + fn c_lifetime_elision_fn(c: &C) -> &CxxVector; + } + + extern "Rust" { + #[derive(ExternType)] + type OpaqueRust; } impl Vec {} + impl Box {} + impl Vec {} + impl Vec> {} } #[cxx::bridge(namespace = "tests")] diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index 8cf74bebb..22d67b340 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -1,20 +1,30 @@ #include "tests/ffi/tests.h" #include "tests/ffi/lib.rs.h" +#include #include #include #include #include #include +#ifdef __cpp_lib_span +#include +#endif // __cpp_lib_span #include #include #include +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wshadow" +#endif + extern "C" void cxx_test_suite_set_correct() noexcept; extern "C" tests::R *cxx_test_suite_get_box() noexcept; extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept; namespace tests { +static_assert(4 == alignof(OveralignedStruct), "expected 4 byte alignment"); + static constexpr char SLICE_DATA[] = "2020"; C::C(size_t n) : n(n) {} @@ -44,7 +54,9 @@ const size_t &Shared::c_method_ref_on_shared() const noexcept { size_t &Shared::c_method_mut_on_shared() noexcept { return this->z; } -void Array::c_set_array(int32_t val) noexcept { +size_t Shared::c_static_method_on_shared() noexcept { return 2025; } + +void WithArray::c_set_array(int32_t val) noexcept { this->a = {val, val, val, val}; } @@ -611,6 +623,14 @@ extern "C" std::string *cxx_test_suite_get_unique_ptr_string() noexcept { return std::unique_ptr(new std::string("2020")).release(); } +const std::vector &C::c_lifetime_elision_member_fn() const { + return this->get_v(); +} + +const std::vector &c_lifetime_elision_fn(const C &c) { + return c.get_v(); +} + rust::String C::cOverloadedMethod(int32_t x) const { return rust::String(std::to_string(x)); } @@ -627,6 +647,8 @@ rust::String cOverloadedFunction(rust::Str x) { return rust::String(std::string(x)); } +size_t C::c_static_method() { return 2026; } + void c_take_trivial_ptr(std::unique_ptr d) { if (d->d == 30) { cxx_test_suite_set_correct(); @@ -757,6 +779,8 @@ std::unique_ptr<::F::F> c_return_ns_opaque_ptr() { return f; } +void R::c_member_function_on_rust_type() const noexcept {} + extern "C" const char *cxx_run_test() noexcept { #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -786,6 +810,10 @@ extern "C" const char *cxx_run_test() noexcept { ASSERT(r_return_enum(0) == Enum::AVal); ASSERT(r_return_enum(1) == Enum::BVal); ASSERT(r_return_enum(2021) == Enum::CVal); + ASSERT(Shared::r_static_method_on_shared() == 2023); + ASSERT(R::r_static_method() == 2024); + ASSERT(r_return_rust_vec_box()[0]->get() == 2020); + ASSERT(r_return_rust_vec_box_other_module_type().size() == 1); r_take_primitive(2020); r_take_shared(Shared{2020}); @@ -866,13 +894,25 @@ extern "C" const char *cxx_run_test() noexcept { cstring.reserve(5); ASSERT(cstring.capacity() >= 5); + { + rust::Str out_param; + r_return_str_via_out_param(Shared{2020}, out_param); + ASSERT(out_param == "2020"); + +#if __cplusplus >= 201703L + std::string_view out_param_as_string_view{out_param}; + ASSERT(out_param_as_string_view == "2020"); +#endif + } + rust::Str cstr = "test"; rust::Str other_cstr = "foo"; swap(cstr, other_cstr); ASSERT(cstr == "foo"); ASSERT(other_cstr == "test"); - const char *utf8_literal = u8"Test string"; + // Auto because u8"..." is `const char*` before C++20, and `const char8_t*` since. + const auto *utf8_literal = u8"Test string"; const char16_t *utf16_literal = u"Test string"; rust::String utf8_rstring = utf8_literal; rust::String utf16_rstring = utf16_literal; @@ -884,6 +924,72 @@ extern "C" const char *cxx_run_test() noexcept { rust::String bad_utf16_rstring = rust::String::lossy(bad_utf16_literal); ASSERT(bad_utf8_rstring == bad_utf16_rstring); + // Test Slice explicit constructor from container + { + std::vector cpp_vec{1, 2, 3}; + rust::Slice slice_of_cpp_vec(cpp_vec); + ASSERT(slice_of_cpp_vec.data() == cpp_vec.data()); + ASSERT(slice_of_cpp_vec.size() == cpp_vec.size()); + ASSERT(slice_of_cpp_vec[0] == 1); + } + + // Test Slice template deduction guides +#ifdef __cpp_deduction_guides + { + // std::array -> Slice + std::array cpp_array{1, 2, 3}; + auto auto_slice_of_cpp_array = rust::Slice(cpp_array); + static_assert( + std::is_same_v>); + } + { + // const std::array -> Slice + const std::array cpp_array{1, 2, 3}; + auto auto_slice_of_cpp_array = rust::Slice(cpp_array); + static_assert(std::is_same_v>); + } + { + // std::array -> Slice + std::array cpp_array{1, 2, 3}; + auto auto_slice_of_cpp_array = rust::Slice(cpp_array); + static_assert(std::is_same_v>); + } + { + // std::vector -> Slice + std::vector cpp_vec{1, 2, 3}; + auto auto_slice_of_cpp_vec = rust::Slice(cpp_vec); + static_assert( + std::is_same_v>); + } + { + // const std::vector -> Slice + const std::vector cpp_vec{1, 2, 3}; + auto auto_slice_of_cpp_vec = rust::Slice(cpp_vec); + static_assert(std::is_same_v>); + } +#ifdef __cpp_lib_span + { + // std::span -> Slice + std::array cpp_array{1, 2, 3}; + std::span cpp_span(cpp_array); + auto auto_slice_of_cpp_span = rust::Slice(cpp_span); + static_assert( + std::is_same_v>); + } + { + // std::span -> Slice + const std::array cpp_array{1, 2, 3}; + std::span cpp_span(cpp_array); + auto auto_slice_of_cpp_span = rust::Slice(cpp_span); + static_assert(std::is_same_v>); + } +#endif // __cpp_lib_span +#endif // __cpp_deduction_guides + rust::Vec vec1{1, 2}; rust::Vec vec2{3, 4}; swap(vec1, vec2); diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h index dc02e4ff8..ab6a868bd 100644 --- a/tests/ffi/tests.h +++ b/tests/ffi/tests.h @@ -8,7 +8,7 @@ struct AShared; enum class AEnum : uint16_t; namespace B { struct ABShared; -enum class ABEnum : uint16_t; +enum class ABEnum : int32_t; } // namespace B } // namespace A @@ -34,6 +34,19 @@ class H { namespace tests { +class Undefined; + +class Private { +private: + ~Private(); +}; + +struct Unmovable { + Unmovable(Unmovable &&) = delete; +}; + +using Array = int[]; + struct R; struct Shared; struct SharedString; @@ -51,8 +64,14 @@ class C { size_t get_fail(); const std::vector &get_v() const; std::vector &get_v(); + const std::vector &c_lifetime_elision_member_fn() const; rust::String cOverloadedMethod(int32_t x) const; rust::String cOverloadedMethod(rust::Str x) const; + static size_t c_static_method(); + // Unlike the other contents of this class, the C++ definition of this member + // function is generated by CXX and forwards to a Rust method implementation + // in an `impl ffi::C` block. + size_t &r_method_on_c_get_mut() noexcept; private: size_t n; @@ -212,6 +231,7 @@ std::unique_ptr c_return_opaque_ptr(); E &c_return_opaque_mut_pin(E &e); std::unique_ptr<::F::F> c_return_ns_opaque_ptr(); +const std::vector &c_lifetime_elision_fn(const C &c); rust::String cOverloadedFunction(int32_t x); rust::String cOverloadedFunction(rust::Str x); diff --git a/tests/test.rs b/tests/test.rs index bcf0a2cd1..aa2346538 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,25 +1,25 @@ #![allow( clippy::assertions_on_constants, - clippy::assertions_on_result_states, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::float_cmp, clippy::needless_pass_by_value, - clippy::unit_cmp, - clippy::unseparated_literal_suffix + clippy::unit_cmp )] -use cxx::SharedPtr; +use cxx::{CxxVector, SharedPtr, UniquePtr}; use cxx_test_suite::module::ffi2; -use cxx_test_suite::{cast, ffi, R}; +use cxx_test_suite::{R, cast, ffi}; use std::cell::Cell; use std::ffi::CStr; +use std::panic::{self, RefUnwindSafe, UnwindSafe}; +use std::ptr; thread_local! { - static CORRECT: Cell = Cell::new(false); + static CORRECT: Cell = const { Cell::new(false) }; } -#[no_mangle] +#[unsafe(no_mangle)] extern "C" fn cxx_test_suite_set_correct() { CORRECT.with(|correct| correct.set(true)); } @@ -54,7 +54,9 @@ fn test_c_return() { 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!(c"2020", ffi::c_return_unique_ptr_string().as_c_str()); assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len()); + assert!(4 <= ffi::c_return_unique_ptr_vector_u8().capacity()); assert_eq!( 200_u8, ffi::c_return_unique_ptr_vector_u8().into_iter().sum(), @@ -64,6 +66,7 @@ fn test_c_return() { ffi::c_return_unique_ptr_vector_f64().into_iter().sum(), ); assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().len()); + assert!(2 <= ffi::c_return_unique_ptr_vector_shared().capacity()); assert_eq!( 2021_usize, ffi::c_return_unique_ptr_vector_shared() @@ -91,8 +94,8 @@ fn test_c_return() { enm @ ffi::AEnum::AAVal => assert_eq!(0, enm.repr), _ => assert!(false), } - match ffi::c_return_nested_ns_enum(0) { - enm @ ffi::ABEnum::ABAVal => assert_eq!(0, enm.repr), + match ffi::c_return_nested_ns_enum(2021) { + enm @ ffi::ABEnum::ABCVal => assert_eq!(i32::MIN, enm.repr), _ => assert!(false), } } @@ -158,7 +161,10 @@ fn test_c_take() { assert_eq!(vector.pin_mut().pop(), Some(9)); check!(ffi::c_take_unique_ptr_vector_u8(vector)); let mut vector = ffi::c_return_unique_ptr_vector_f64(); - vector.pin_mut().push(9.0); + vector.pin_mut().extend(Some(9.0)); + assert!(vector.pin_mut().capacity() >= 1); + vector.pin_mut().reserve(100); + assert!(vector.pin_mut().capacity() >= 101); check!(ffi::c_take_unique_ptr_vector_f64(vector)); let mut vector = ffi::c_return_unique_ptr_vector_shared(); vector.pin_mut().push(ffi::Shared { z: 9 }); @@ -234,12 +240,12 @@ fn test_c_callback() { #[test] fn test_c_call_r() { fn cxx_run_test() { - extern "C" { + unsafe extern "C" { fn cxx_run_test() -> *const i8; } let failure = unsafe { cxx_run_test() }; if !failure.is_null() { - let msg = unsafe { CStr::from_ptr(failure as *mut std::os::raw::c_char) }; + let msg = unsafe { CStr::from_ptr(failure.cast::().cast_mut()) }; eprintln!("{}", msg.to_string_lossy()); } } @@ -256,20 +262,26 @@ fn test_c_method_calls() { assert_eq!(2021, unique_ptr.get()); assert_eq!(2021, unique_ptr.get2()); assert_eq!(2021, *unique_ptr.getRef()); + assert_eq!(2021, unsafe { &mut *unique_ptr.as_mut_ptr() }.get()); + assert_eq!(2021, unsafe { &*unique_ptr.as_ptr() }.get()); assert_eq!(2021, *unique_ptr.pin_mut().getMut()); assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap()); assert!(unique_ptr.pin_mut().get_fail().is_err()); assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared()); assert_eq!(2022, *ffi::Shared { z: 2022 }.c_method_ref_on_shared()); assert_eq!(2023, *ffi::Shared { z: 2023 }.c_method_mut_on_shared()); + assert_eq!(2025, ffi::Shared::c_static_method_on_shared()); + assert_eq!(2026, ffi::C::c_static_method()); let val = 42; - let mut array = ffi::Array { + let mut array = ffi::WithArray { 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()); + + R(2020).c_member_function_on_rust_type(); } #[test] @@ -286,6 +298,56 @@ fn test_shared_ptr_weak_ptr() { assert!(weak_ptr.upgrade().is_null()); } +#[test] +fn test_unique_to_shared_ptr_string() { + let unique = ffi::c_return_unique_ptr_string(); + let ptr = ptr::addr_of!(*unique); + let shared = SharedPtr::from(unique); + assert_eq!(ptr::addr_of!(*shared), ptr); + assert_eq!(*shared, *"2020"); +} + +#[test] +fn test_unique_to_shared_ptr_cpp_type() { + let unique = ffi::c_return_unique_ptr(); + let ptr = ptr::addr_of!(*unique); + let shared = SharedPtr::from(unique); + assert_eq!(ptr::addr_of!(*shared), ptr); +} + +#[test] +fn test_unique_to_shared_ptr_null() { + let unique = UniquePtr::::null(); + assert!(unique.is_null()); + let shared = SharedPtr::from(unique); + assert!(shared.is_null()); +} + +#[test] +fn test_shared_ptr_from_raw() { + let shared = unsafe { SharedPtr::::from_raw(ptr::null_mut()) }; + assert!(shared.is_null()); +} + +#[test] +#[should_panic = "tests::Undefined is not destructible"] +fn test_shared_ptr_from_raw_undefined() { + unsafe { SharedPtr::::from_raw(ptr::null_mut()) }; +} + +#[test] +#[should_panic = "tests::Private is not destructible"] +fn test_shared_ptr_from_raw_private() { + unsafe { SharedPtr::::from_raw(ptr::null_mut()) }; +} + +#[test] +#[should_panic = "tests::Unmovable is not move constructible"] +fn test_vector_reserve_unmovable() { + let mut vector = CxxVector::::new(); + vector.pin_mut().reserve(10); +} + #[test] fn test_c_ns_method_calls() { let unique_ptr = ffi2::ns_c_return_unique_ptr_ns(); @@ -301,6 +363,16 @@ fn test_enum_representations() { assert_eq!(2021, ffi::Enum::LastVal.repr); } +#[test] +fn test_enum_default() { + assert_eq!(ffi::Enum::BVal, ffi::Enum::default()); +} + +#[test] +fn test_struct_repr_align() { + assert_eq!(4, std::mem::align_of::()); +} + #[test] fn test_debug() { assert_eq!("Shared { z: 1 }", format!("{:?}", ffi::Shared { z: 1 })); @@ -308,14 +380,14 @@ fn test_debug() { assert_eq!("Enum(9)", format!("{:?}", ffi::Enum { repr: 9 })); } -#[no_mangle] +#[unsafe(no_mangle)] extern "C" fn cxx_test_suite_get_box() -> *mut R { Box::into_raw(Box::new(R(2020usize))) } -#[no_mangle] +#[unsafe(no_mangle)] unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const R) -> bool { - (*r).0 == 2020 + unsafe { (*r).0 == 2020 } } #[test] @@ -376,5 +448,19 @@ fn test_raw_ptr() { let c3 = ffi::c_return_const_ptr(2025); assert_eq!(2025, unsafe { ffi::c_take_const_ptr(c3) }); - assert_eq!(2025, unsafe { ffi::c_take_mut_ptr(c3 as *mut ffi::C) }); // deletes c3 + assert_eq!(2025, unsafe { ffi::c_take_mut_ptr(c3.cast_mut()) }); // deletes c3 +} + +#[test] +#[allow(clippy::items_after_statements, clippy::no_effect_underscore_binding)] +fn test_unwind_safe() { + fn inspect(_c: &ffi::C) {} + let _unwind_safe = |c: UniquePtr| panic::catch_unwind(|| drop(c)); + let _ref_unwind_safe = |c: &ffi::C| panic::catch_unwind(|| inspect(c)); + + fn require_unwind_safe() {} + require_unwind_safe::(); + + fn require_ref_unwind_safe() {} + require_ref_unwind_safe::(); } diff --git a/tests/ui/array_len_suffix.stderr b/tests/ui/array_len_suffix.stderr index 1dde790e8..b15b03e9f 100644 --- a/tests/ui/array_len_suffix.stderr +++ b/tests/ui/array_len_suffix.stderr @@ -4,7 +4,9 @@ error[E0308]: mismatched types 4 | fn array() -> [String; 12u16]; | ^^^^^ expected `usize`, found `u16` | + = note: array length can only be `usize` help: change the type of the numeric literal from `u16` to `usize` | -4 | fn array() -> [String; 12usize]; - | ~~~~~ +4 - fn array() -> [String; 12u16]; +4 + fn array() -> [String; 12usize]; + | diff --git a/tests/ui/cxx_crate_name_qualified_cxx_string.rs b/tests/ui/cxx_crate_name_qualified_cxx_string.rs new file mode 100644 index 000000000..14bac1477 --- /dev/null +++ b/tests/ui/cxx_crate_name_qualified_cxx_string.rs @@ -0,0 +1,17 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn foo(x: CxxString); + fn bar(x: &cxx::CxxString); + } +} + +fn foo(_: &cxx::CxxString) { + todo!() +} + +fn bar(_: &cxx::CxxString) { + todo!() +} + +fn main() {} diff --git a/tests/ui/cxx_crate_name_qualified_cxx_string.stderr b/tests/ui/cxx_crate_name_qualified_cxx_string.stderr new file mode 100644 index 000000000..7859cef64 --- /dev/null +++ b/tests/ui/cxx_crate_name_qualified_cxx_string.stderr @@ -0,0 +1,5 @@ +error: unexpected `cxx::` qualifier found in a `#[cxx::bridge]` + --> tests/ui/cxx_crate_name_qualified_cxx_string.rs:5:20 + | +5 | fn bar(x: &cxx::CxxString); + | ^^^^^^^^^^^^^^ diff --git a/tests/ui/deny_elided_lifetimes.rs b/tests/ui/deny_elided_lifetimes.rs index 0ab3f750a..da77eede5 100644 --- a/tests/ui/deny_elided_lifetimes.rs +++ b/tests/ui/deny_elided_lifetimes.rs @@ -1,4 +1,18 @@ -#![deny(elided_lifetimes_in_paths)] +#![deny(elided_lifetimes_in_paths, mismatched_lifetime_syntaxes)] + +use cxx::ExternType; +use std::marker::PhantomData; + +#[repr(C)] +struct Alias<'a> { + ptr: *const std::ffi::c_void, + lifetime: PhantomData<&'a str>, +} + +unsafe impl<'a> ExternType for Alias<'a> { + type Id = cxx::type_id!("Alias"); + type Kind = cxx::kind::Trivial; +} #[cxx::bridge] mod ffi { @@ -13,6 +27,7 @@ mod ffi { unsafe extern "C++" { type Cpp<'a>; + type Alias<'a> = crate::Alias<'a>; fn lifetime_named<'a>(s: &'a i32) -> UniquePtr>; diff --git a/tests/ui/deny_elided_lifetimes.stderr b/tests/ui/deny_elided_lifetimes.stderr index 857bb5b7f..136afb33a 100644 --- a/tests/ui/deny_elided_lifetimes.stderr +++ b/tests/ui/deny_elided_lifetimes.stderr @@ -1,15 +1,34 @@ error: hidden lifetime parameters in types are deprecated - --> tests/ui/deny_elided_lifetimes.rs:21:50 + --> tests/ui/deny_elided_lifetimes.rs:36:50 | -21 | fn lifetime_elided(s: &i32) -> UniquePtr; +36 | fn lifetime_elided(s: &i32) -> UniquePtr; | ^^^ expected lifetime parameter | note: the lint level is defined here --> tests/ui/deny_elided_lifetimes.rs:1:9 | -1 | #![deny(elided_lifetimes_in_paths)] + 1 | #![deny(elided_lifetimes_in_paths, mismatched_lifetime_syntaxes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime | -21 | fn lifetime_elided(s: &i32) -> UniquePtr>; +36 | fn lifetime_elided(s: &i32) -> UniquePtr>; + | ++++ + +error: hiding a lifetime that's elided elsewhere is confusing + --> tests/ui/deny_elided_lifetimes.rs:36:31 + | +36 | fn lifetime_elided(s: &i32) -> UniquePtr; + | ^^^^ ^^^ the same lifetime is hidden here + | | + | the lifetime is elided here + | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +note: the lint level is defined here + --> tests/ui/deny_elided_lifetimes.rs:1:36 + | + 1 | #![deny(elided_lifetimes_in_paths, mismatched_lifetime_syntaxes)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `'_` for type paths + | +36 | fn lifetime_elided(s: &i32) -> UniquePtr>; | ++++ diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr index 54ab987b4..64e1099ef 100644 --- a/tests/ui/deny_missing_docs.stderr +++ b/tests/ui/deny_missing_docs.stderr @@ -7,7 +7,7 @@ error: missing documentation for a struct note: the lint level is defined here --> tests/ui/deny_missing_docs.rs:6:9 | -6 | #![deny(missing_docs)] + 6 | #![deny(missing_docs)] | ^^^^^^^^^^^^ error: missing documentation for a struct field diff --git a/tests/ui/derive_bit_struct.rs b/tests/ui/derive_bit_struct.rs new file mode 100644 index 000000000..85a758523 --- /dev/null +++ b/tests/ui/derive_bit_struct.rs @@ -0,0 +1,9 @@ +#[cxx::bridge] +mod ffi { + #[derive(BitAnd, BitOr, BitXor)] + struct Struct { + x: i32, + } +} + +fn main() {} diff --git a/tests/ui/derive_bit_struct.stderr b/tests/ui/derive_bit_struct.stderr new file mode 100644 index 000000000..4365cf31a --- /dev/null +++ b/tests/ui/derive_bit_struct.stderr @@ -0,0 +1,17 @@ +error: derive(BitAnd) is currently only supported on enums, not structs + --> tests/ui/derive_bit_struct.rs:3:14 + | +3 | #[derive(BitAnd, BitOr, BitXor)] + | ^^^^^^ + +error: derive(BitOr) is currently only supported on enums, not structs + --> tests/ui/derive_bit_struct.rs:3:22 + | +3 | #[derive(BitAnd, BitOr, BitXor)] + | ^^^^^ + +error: derive(BitXor) is currently only supported on enums, not structs + --> tests/ui/derive_bit_struct.rs:3:29 + | +3 | #[derive(BitAnd, BitOr, BitXor)] + | ^^^^^^ diff --git a/tests/ui/derive_default.rs b/tests/ui/derive_default.rs new file mode 100644 index 000000000..3f601b6bf --- /dev/null +++ b/tests/ui/derive_default.rs @@ -0,0 +1,33 @@ +#[cxx::bridge] +mod ffi { + #[derive(Default)] + enum NoDefault { + Two, + Three, + Five, + Seven, + } + + #[derive(Default)] + enum MultipleDefault { + #[default] + Two, + Three, + Five, + #[default] + Seven, + } +} + +#[cxx::bridge] +mod ffi2 { + #[derive(Default)] + enum BadDefault { + #[default(repr)] + Two, + #[default = 3] + Three, + } +} + +fn main() {} diff --git a/tests/ui/derive_default.stderr b/tests/ui/derive_default.stderr new file mode 100644 index 000000000..e7a526c80 --- /dev/null +++ b/tests/ui/derive_default.stderr @@ -0,0 +1,23 @@ +error: derive(Default) on enum requires exactly one variant to be marked with #[default] + --> tests/ui/derive_default.rs:3:14 + | +3 | #[derive(Default)] + | ^^^^^^^ + +error: derive(Default) on enum requires exactly one variant to be marked with #[default] (found 2) + --> tests/ui/derive_default.rs:11:14 + | +11 | #[derive(Default)] + | ^^^^^^^ + +error: #[default] attribute does not accept an argument + --> tests/ui/derive_default.rs:26:18 + | +26 | #[default(repr)] + | ^ + +error: #[default] attribute does not accept an argument + --> tests/ui/derive_default.rs:28:19 + | +28 | #[default = 3] + | ^ diff --git a/tests/ui/derive_duplicate.stderr b/tests/ui/derive_duplicate.stderr index 759208629..f40d5a6df 100644 --- a/tests/ui/derive_duplicate.stderr +++ b/tests/ui/derive_duplicate.stderr @@ -1,7 +1,7 @@ -error[E0119]: conflicting implementations of trait `Clone` for type `Struct` +error[E0119]: conflicting implementations of trait `Clone` for type `ffi::Struct` --> tests/ui/derive_duplicate.rs:3:21 | 3 | #[derive(Clone, Clone)] - | ----- ^^^^^ conflicting implementation for `Struct` + | ----- ^^^^^ conflicting implementation for `ffi::Struct` | | | first implementation here diff --git a/tests/ui/derive_noncopy.stderr b/tests/ui/derive_noncopy.stderr index 419b0f22d..b4f35d3e4 100644 --- a/tests/ui/derive_noncopy.stderr +++ b/tests/ui/derive_noncopy.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> tests/ui/derive_noncopy.rs:4:12 | 4 | struct TryCopy { diff --git a/tests/ui/duplicate_method.rs b/tests/ui/duplicate_method.rs new file mode 100644 index 000000000..1118e8fd1 --- /dev/null +++ b/tests/ui/duplicate_method.rs @@ -0,0 +1,19 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + type T; + fn t_method(&self); + fn t_method(&self); + } +} + +#[cxx::bridge] +mod ffi { + extern "Rust" { + type U; + fn u_method(&self); + fn u_method(&mut self); + } +} + +fn main() {} diff --git a/tests/ui/duplicate_method.stderr b/tests/ui/duplicate_method.stderr new file mode 100644 index 000000000..37e35c2e1 --- /dev/null +++ b/tests/ui/duplicate_method.stderr @@ -0,0 +1,11 @@ +error: the associated function `T::t_method` is defined multiple times + --> tests/ui/duplicate_method.rs:6:9 + | +6 | fn t_method(&self); + | ^^^^^^^^^^^^^^^^^^^ + +error: the associated function `U::u_method` is defined multiple times + --> tests/ui/duplicate_method.rs:15:9 + | +15 | fn u_method(&mut self); + | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/empty_struct.rs b/tests/ui/empty_struct.rs index 060cfe0fa..3f7f06ed1 100644 --- a/tests/ui/empty_struct.rs +++ b/tests/ui/empty_struct.rs @@ -1,6 +1,18 @@ +#![allow(unexpected_cfgs)] + #[cxx::bridge] mod ffi { struct Empty {} } +#[cxx::bridge] +mod ffi2 { + struct ConditionallyEmpty { + #[cfg(target_os = "nonexistent")] + never: u8, + #[cfg(target_os = "another")] + another: u8, + } +} + fn main() {} diff --git a/tests/ui/empty_struct.stderr b/tests/ui/empty_struct.stderr index f6fbfc117..2feed5893 100644 --- a/tests/ui/empty_struct.stderr +++ b/tests/ui/empty_struct.stderr @@ -1,5 +1,11 @@ error: structs without any fields are not supported - --> tests/ui/empty_struct.rs:3:5 + --> tests/ui/empty_struct.rs:5:5 | -3 | struct Empty {} +5 | struct Empty {} | ^^^^^^^^^^^^^^^ + +error: structs without any fields are not supported + --> tests/ui/empty_struct.rs:10:5 + | +10 | struct ConditionallyEmpty { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/enum_assoc.rs b/tests/ui/enum_assoc.rs new file mode 100644 index 000000000..15a1f4819 --- /dev/null +++ b/tests/ui/enum_assoc.rs @@ -0,0 +1,16 @@ +#[cxx::bridge] +mod ffi { + enum Enum { + Variant, + } + extern "Rust" { + #[Self = "Enum"] + fn f(); + } +} + +impl ffi::Enum { + fn f() {} +} + +fn main() {} diff --git a/tests/ui/enum_assoc.stderr b/tests/ui/enum_assoc.stderr new file mode 100644 index 000000000..f7340192d --- /dev/null +++ b/tests/ui/enum_assoc.stderr @@ -0,0 +1,5 @@ +error: unsupported self type; C++ does not allow member functions on enums + --> tests/ui/enum_assoc.rs:7:18 + | +7 | #[Self = "Enum"] + | ^^^^^^ diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr index 5808d6f8f..4c2591b92 100644 --- a/tests/ui/enum_match_without_wildcard.stderr +++ b/tests/ui/enum_match_without_wildcard.stderr @@ -1,17 +1,17 @@ -error[E0004]: non-exhaustive patterns: `ffi::A { repr: 2_u8..=u8::MAX }` not covered +error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered --> tests/ui/enum_match_without_wildcard.rs:12:11 | 12 | match a { - | ^ pattern `ffi::A { repr: 2_u8..=u8::MAX }` not covered + | ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered | -note: `ffi::A` defined here +note: `A` defined here --> tests/ui/enum_match_without_wildcard.rs:3:10 | -3 | enum A { + 3 | enum A { | ^ - = note: the matched value is of type `ffi::A` + = note: the matched value is of type `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!(), +15 ~ A { repr: 2_u8..=u8::MAX } => todo!(), | diff --git a/tests/ui/expected_named.stderr b/tests/ui/expected_named.stderr index 0068bdf36..c0fa04de7 100644 --- a/tests/ui/expected_named.stderr +++ b/tests/ui/expected_named.stderr @@ -5,7 +5,7 @@ error[E0106]: missing lifetime specifier | ^^^^^^^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | 5 | fn borrowed() -> UniquePtr>; | +++++++++ diff --git a/tests/ui/explicit_impl_of_bad_unique_ptr.rs b/tests/ui/explicit_impl_of_bad_unique_ptr.rs new file mode 100644 index 000000000..284b4213a --- /dev/null +++ b/tests/ui/explicit_impl_of_bad_unique_ptr.rs @@ -0,0 +1,6 @@ +#[cxx::bridge] +mod ffi { + impl UniquePtr> {} +} + +fn main() {} diff --git a/tests/ui/explicit_impl_of_bad_unique_ptr.stderr b/tests/ui/explicit_impl_of_bad_unique_ptr.stderr new file mode 100644 index 000000000..ea28d3991 --- /dev/null +++ b/tests/ui/explicit_impl_of_bad_unique_ptr.stderr @@ -0,0 +1,5 @@ +error: unsupported unique_ptr target type + --> tests/ui/explicit_impl_of_bad_unique_ptr.rs:3:10 + | +3 | impl UniquePtr> {} + | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/extern_shared_struct.rs b/tests/ui/extern_shared_struct.rs new file mode 100644 index 000000000..6f0af8d67 --- /dev/null +++ b/tests/ui/extern_shared_struct.rs @@ -0,0 +1,15 @@ +#![deny(deprecated)] + +#[cxx::bridge] +pub mod ffi { + struct StructX { + a: u64, + } + + #[namespace = "mine"] + unsafe extern "C++" { + type StructX; + } +} + +fn main() {} diff --git a/tests/ui/extern_shared_struct.stderr b/tests/ui/extern_shared_struct.stderr new file mode 100644 index 000000000..a2d1ff75b --- /dev/null +++ b/tests/ui/extern_shared_struct.stderr @@ -0,0 +1,34 @@ +error: use of deprecated struct `ffi::_::StructX`: + Shared struct redeclared as an unsafe extern C++ type is deprecated. + If this is intended to be a shared struct, remove this `type StructX`. + If this is intended to be an extern type, change it to: + + use cxx::ExternType; + + #[repr(C)] + pub struct StructX { + ... + } + + unsafe impl ExternType for StructX { + type Id = cxx::type_id!("mine::StructX"); + type Kind = cxx::kind::Trivial; + } + + pub mod ffi { + #[namespace = "mine"] + extern "C++" { + type StructX = crate::StructX; + } + ... + } + --> tests/ui/extern_shared_struct.rs:11:14 + | +11 | type StructX; + | ^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/extern_shared_struct.rs:1:9 + | + 1 | #![deny(deprecated)] + | ^^^^^^^^^^ diff --git a/tests/ui/include.stderr b/tests/ui/include.stderr index 45cc55911..b801530e1 100644 --- a/tests/ui/include.stderr +++ b/tests/ui/include.stderr @@ -11,10 +11,10 @@ error: unexpected token | ^^^^ error: expected `>` - --> tests/ui/include.rs:6:17 + --> tests/ui/include.rs:6:26 | 6 | include!( tests/ui/include.rs:7:23 diff --git a/tests/ui/missing_unsafe.stderr b/tests/ui/missing_unsafe.stderr index e7dcba749..981b34af3 100644 --- a/tests/ui/missing_unsafe.stderr +++ b/tests/ui/missing_unsafe.stderr @@ -1,4 +1,4 @@ -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block +error[E0133]: call to unsafe function `f` is unsafe and requires unsafe block --> tests/ui/missing_unsafe.rs:4:12 | 4 | fn f(x: i32); diff --git a/tests/ui/nonlocal_rust_type.stderr b/tests/ui/nonlocal_rust_type.stderr index f6cb06cb6..1df7a2c09 100644 --- a/tests/ui/nonlocal_rust_type.stderr +++ b/tests/ui/nonlocal_rust_type.stderr @@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | 10 | type OptBuilder<'a>; | ^^^^^-------------- - | | | - | | `Option` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | | + | `Option` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate @@ -14,8 +15,9 @@ error[E0117]: only traits defined in the current crate can be implemented for ty | 14 | rs: Box>, | ^^^^-------------- - | | | - | | `Option` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | | + | `Option` is not defined in the current crate | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules = note: define and implement a trait or new type instead diff --git a/tests/ui/opaque_autotraits.stderr b/tests/ui/opaque_autotraits.stderr index c6447c558..dacde1356 100644 --- a/tests/ui/opaque_autotraits.stderr +++ b/tests/ui/opaque_autotraits.stderr @@ -5,17 +5,21 @@ error[E0277]: `*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 void; 0]` - = note: required because it appears within the type `Opaque` -note: required because it appears within the type `Opaque` + = note: required because it appears within the type `[*const cxx::void; 0]` +note: required because it appears within the type `cxx::private::Opaque` + --> src/opaque.rs + | + | pub struct Opaque { + | ^^^^^^ +note: required because it appears within the type `ffi::Opaque` --> tests/ui/opaque_autotraits.rs:4:14 | -4 | type Opaque; + 4 | type Opaque; | ^^^^^^ note: required by a bound in `assert_send` --> tests/ui/opaque_autotraits.rs:8:19 | -8 | fn assert_send() {} + 8 | fn assert_send() {} | ^^^^ required by this bound in `assert_send` error[E0277]: `*const cxx::void` cannot be shared between threads safely @@ -25,17 +29,21 @@ error[E0277]: `*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 void; 0]` - = note: required because it appears within the type `Opaque` -note: required because it appears within the type `Opaque` + = note: required because it appears within the type `[*const cxx::void; 0]` +note: required because it appears within the type `cxx::private::Opaque` + --> src/opaque.rs + | + | pub struct Opaque { + | ^^^^^^ +note: required because it appears within the type `ffi::Opaque` --> tests/ui/opaque_autotraits.rs:4:14 | -4 | type Opaque; + 4 | type Opaque; | ^^^^^^ note: required by a bound in `assert_sync` --> tests/ui/opaque_autotraits.rs:9:19 | -9 | fn assert_sync() {} + 9 | fn assert_sync() {} | ^^^^ required by this bound in `assert_sync` error[E0277]: `PhantomPinned` cannot be unpinned @@ -44,13 +52,22 @@ error[E0277]: `PhantomPinned` cannot be unpinned 15 | assert_unpin::(); | ^^^^^^^^^^^ 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` - = note: required because it appears within the type `Opaque` -note: required because it appears within the type `Opaque` + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope +note: required because it appears within the type `PhantomData` + --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ +note: required because it appears within the type `cxx::private::Opaque` + --> src/opaque.rs + | + | pub struct Opaque { + | ^^^^^^ +note: required because it appears within the type `ffi::Opaque` --> tests/ui/opaque_autotraits.rs:4:14 | -4 | type Opaque; + 4 | type Opaque; | ^^^^^^ note: required by a bound in `assert_unpin` --> tests/ui/opaque_autotraits.rs:10:20 diff --git a/tests/ui/pin_mut_alias.rs b/tests/ui/pin_mut_alias.rs new file mode 100644 index 000000000..f88e4f327 --- /dev/null +++ b/tests/ui/pin_mut_alias.rs @@ -0,0 +1,106 @@ +mod arg { + use cxx::ExternType; + use std::marker::{PhantomData, PhantomPinned}; + + struct Arg(PhantomPinned); + + unsafe impl ExternType for Arg { + type Id = cxx::type_id!("Arg"); + type Kind = cxx::kind::Opaque; + } + + struct ArgLife<'a>(PhantomPinned, PhantomData<&'a ()>); + + unsafe impl<'a> ExternType for ArgLife<'a> { + type Id = cxx::type_id!("ArgLife"); + type Kind = cxx::kind::Opaque; + } + + #[cxx::bridge] + mod ffi { + unsafe extern "C++" { + type Arg = crate::arg::Arg; + fn f(arg: &mut Arg); + } + } + + #[cxx::bridge] + mod ffi_life { + unsafe extern "C++" { + type ArgLife<'a> = crate::arg::ArgLife<'a>; + fn fl<'b, 'c>(arg: &'b mut ArgLife<'c>); + } + } +} + +mod receiver { + use cxx::ExternType; + use std::marker::{PhantomData, PhantomPinned}; + + struct Receiver(PhantomPinned); + + unsafe impl ExternType for Receiver { + type Id = cxx::type_id!("Receiver"); + type Kind = cxx::kind::Opaque; + } + + struct ReceiverLife<'a>(PhantomPinned, PhantomData<&'a ()>); + + unsafe impl<'a> ExternType for ReceiverLife<'a> { + type Id = cxx::type_id!("ReceiverLife"); + type Kind = cxx::kind::Opaque; + } + + #[cxx::bridge] + mod ffi { + unsafe extern "C++" { + type Receiver = crate::receiver::Receiver; + fn g(&mut self); + } + } + + #[cxx::bridge] + mod ffi_life { + unsafe extern "C++" { + type ReceiverLife<'a> = crate::receiver::ReceiverLife<'a>; + fn g<'b>(&'b mut self); + } + } +} + +mod receiver2 { + use cxx::ExternType; + use std::marker::{PhantomData, PhantomPinned}; + + struct Receiver2(PhantomPinned); + + unsafe impl ExternType for Receiver2 { + type Id = cxx::type_id!("Receiver2"); + type Kind = cxx::kind::Opaque; + } + + struct ReveiverLife2<'a>(PhantomPinned, PhantomData<&'a ()>); + + unsafe impl<'a> ExternType for ReveiverLife2<'a> { + type Id = cxx::type_id!("ReveiverLife2"); + type Kind = cxx::kind::Opaque; + } + + #[cxx::bridge] + mod ffi { + unsafe extern "C++" { + type Receiver2 = crate::receiver2::Receiver2; + fn h(self: &mut Receiver2); + } + } + + #[cxx::bridge] + mod ffi_life { + unsafe extern "C++" { + type ReveiverLife2<'a> = crate::receiver2::ReveiverLife2<'a>; + fn h<'b, 'c>(self: &'b mut ReveiverLife2<'c>); + } + } +} + +fn main() {} diff --git a/tests/ui/pin_mut_alias.stderr b/tests/ui/pin_mut_alias.stderr new file mode 100644 index 000000000..f16986825 --- /dev/null +++ b/tests/ui/pin_mut_alias.stderr @@ -0,0 +1,47 @@ +error[E0277]: mutable reference to C++ type requires a pin -- use Pin<&mut Arg> + --> tests/ui/pin_mut_alias.rs:23:23 + | +23 | fn f(arg: &mut Arg); + | ^^^^^^^^ use `Pin<&mut Arg>` + | + = help: the trait `ReferenceToUnpin_Arg` is not implemented for `&mut arg::Arg` + +error[E0277]: mutable reference to C++ type requires a pin -- use Pin<&mut ArgLife> + --> tests/ui/pin_mut_alias.rs:31:32 + | +31 | fn fl<'b, 'c>(arg: &'b mut ArgLife<'c>); + | ^^^^^^^^^^^^^^^^^^^ use `Pin<&'b mut ArgLife<'c>>` + | + = help: the trait `ReferenceToUnpin_ArgLife` is not implemented for `&mut arg::ArgLife<'_>` + +error[E0277]: mutable reference to C++ type requires a pin -- use Pin<&mut Receiver> + --> tests/ui/pin_mut_alias.rs:58:18 + | +58 | fn g(&mut self); + | ^^^^^^^^^ use `self: Pin<&mut Receiver>` + | + = help: the trait `ReferenceToUnpin_Receiver` is not implemented for `&mut receiver::Receiver` + +error[E0277]: mutable reference to C++ type requires a pin -- use Pin<&mut ReceiverLife> + --> tests/ui/pin_mut_alias.rs:66:22 + | +66 | fn g<'b>(&'b mut self); + | ^^^^^^^^^^^^ use `self: Pin<&'b mut ReceiverLife<'_>>` + | + = help: the trait `ReferenceToUnpin_ReceiverLife` is not implemented for `&mut receiver::ReceiverLife<'_>` + +error[E0277]: mutable reference to C++ type requires a pin -- use Pin<&mut Receiver2> + --> tests/ui/pin_mut_alias.rs:93:24 + | +93 | fn h(self: &mut Receiver2); + | ^^^^^^^^^^^^^^ use `Pin<&mut Receiver2>` + | + = help: the trait `ReferenceToUnpin_Receiver2` is not implemented for `&mut receiver2::Receiver2` + +error[E0277]: mutable reference to C++ type requires a pin -- use Pin<&mut ReveiverLife2> + --> tests/ui/pin_mut_alias.rs:101:32 + | +101 | fn h<'b, 'c>(self: &'b mut ReveiverLife2<'c>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ use `Pin<&'b mut ReveiverLife2<'c>>` + | + = help: the trait `ReferenceToUnpin_ReveiverLife2` is not implemented for `&mut receiver2::ReveiverLife2<'_>` diff --git a/tests/ui/pin_mut_opaque.rs b/tests/ui/pin_mut_opaque.rs index ac1ca43af..1fc62c43e 100644 --- a/tests/ui/pin_mut_opaque.rs +++ b/tests/ui/pin_mut_opaque.rs @@ -8,7 +8,6 @@ mod ffi { fn s(s: &mut CxxString); fn v(v: &mut CxxVector); } - } fn main() {} diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr index 8a5e019b3..0c9598b57 100644 --- a/tests/ui/pin_mut_opaque.stderr +++ b/tests/ui/pin_mut_opaque.stderr @@ -16,12 +16,6 @@ error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<.. 9 | fn v(v: &mut CxxVector); | ^^^^^^^^^^^^^^^^^^ -error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference in signature of `f`, `g`, `h` - --> 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>` --> tests/ui/pin_mut_opaque.rs:6:14 | diff --git a/tests/ui/ptr_no_const_mut.stderr b/tests/ui/ptr_no_const_mut.stderr index 4b1bf06fd..a6d447864 100644 --- a/tests/ui/ptr_no_const_mut.stderr +++ b/tests/ui/ptr_no_const_mut.stderr @@ -6,10 +6,10 @@ error: expected `mut` or `const` keyword in raw pointer type | help: add `mut` or `const` here | -6 | fn get_neither_const_nor_mut() -> *const C; - | +++++ 6 | fn get_neither_const_nor_mut() -> *mut C; | +++ +6 | fn get_neither_const_nor_mut() -> *const C; + | +++++ error: expected `const` or `mut` --> tests/ui/ptr_no_const_mut.rs:6:44 diff --git a/tests/ui/repr_align_suffixed.rs b/tests/ui/repr_align_suffixed.rs new file mode 100644 index 000000000..790885fe4 --- /dev/null +++ b/tests/ui/repr_align_suffixed.rs @@ -0,0 +1,9 @@ +#[cxx::bridge] +mod ffi { + #[repr(align(2int))] + struct StructSuffix { + i: i32, + } +} + +fn main() {} diff --git a/tests/ui/repr_align_suffixed.stderr b/tests/ui/repr_align_suffixed.stderr new file mode 100644 index 000000000..c45617334 --- /dev/null +++ b/tests/ui/repr_align_suffixed.stderr @@ -0,0 +1,7 @@ +error: invalid suffix `int` for number literal + --> tests/ui/repr_align_suffixed.rs:3:18 + | +3 | #[repr(align(2int))] + | ^^^^ invalid suffix `int` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) diff --git a/tests/ui/repr_unsupported.rs b/tests/ui/repr_unsupported.rs new file mode 100644 index 000000000..386bde695 --- /dev/null +++ b/tests/ui/repr_unsupported.rs @@ -0,0 +1,19 @@ +#[cxx::bridge] +mod ffi { + #[repr(align(2))] + enum EnumAlign { + A, + } + + #[repr(i64)] + struct StructInt { + i: i32, + } + + #[repr(align(1 << 10))] + struct StructExpr { + i: i32, + } +} + +fn main() {} diff --git a/tests/ui/repr_unsupported.stderr b/tests/ui/repr_unsupported.stderr new file mode 100644 index 000000000..e80f59c47 --- /dev/null +++ b/tests/ui/repr_unsupported.stderr @@ -0,0 +1,17 @@ +error: C++ does not support custom alignment on an enum + --> tests/ui/repr_unsupported.rs:3:18 + | +3 | #[repr(align(2))] + | ^ + +error: unsupported alignment on a struct + --> tests/ui/repr_unsupported.rs:8:12 + | +8 | #[repr(i64)] + | ^^^ + +error: invalid repr(align) attribute: an arithmetic expression is not supported + --> tests/ui/repr_unsupported.rs:13:18 + | +13 | #[repr(align(1 << 10))] + | ^^^^^^^ diff --git a/tests/ui/result_no_display.stderr b/tests/ui/result_no_display.stderr index 44d4b31da..7efb8a9e5 100644 --- a/tests/ui/result_no_display.stderr +++ b/tests/ui/result_no_display.stderr @@ -2,7 +2,10 @@ error[E0277]: `NonError` doesn't implement `std::fmt::Display` --> tests/ui/result_no_display.rs:4:19 | 4 | fn f() -> Result<()>; - | ^^^^^^^^^^ `NonError` cannot be formatted with the default formatter + | ^^^^^^^^^^ unsatisfied trait bound | - = help: the trait `std::fmt::Display` is not implemented for `NonError` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: the trait `std::fmt::Display` is not implemented for `NonError` + --> tests/ui/result_no_display.rs:8:1 + | +8 | pub struct NonError; + | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust_pinned.stderr b/tests/ui/rust_pinned.stderr index a0fc03382..03d5e1493 100644 --- a/tests/ui/rust_pinned.stderr +++ b/tests/ui/rust_pinned.stderr @@ -1,17 +1,18 @@ error[E0277]: `PhantomPinned` cannot be unpinned --> tests/ui/rust_pinned.rs:6:14 | -6 | type Pinned; + 6 | type Pinned; | ^^^^^^ within `Pinned`, the trait `Unpin` is not implemented for `PhantomPinned` | - = note: consider using `Box::pin` + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required because it appears within the type `Pinned` --> tests/ui/rust_pinned.rs:10:12 | 10 | pub struct Pinned { | ^^^^^^ -note: required by a bound in `__AssertUnpin` - --> tests/ui/rust_pinned.rs:6:9 +note: required by a bound in `cxx::private::require_unpin` + --> src/rust_type.rs | -6 | type Pinned; - | ^^^^^^^^^^^^ required by this bound in `__AssertUnpin` + | pub fn require_unpin() {} + | ^^^^^ required by this bound in `require_unpin` diff --git a/tests/ui/self_lifetimes.rs b/tests/ui/self_lifetimes.rs new file mode 100644 index 000000000..3014abd42 --- /dev/null +++ b/tests/ui/self_lifetimes.rs @@ -0,0 +1,12 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type Thing<'a, 'b>; + + fn zero(self: &Thing<>); + fn one<'a>(self: &Thing<'a>); + fn three<'a, 'b, 'c>(self: &Thing<'a, 'b, 'c>); + } +} + +fn main() {} diff --git a/tests/ui/self_lifetimes.stderr b/tests/ui/self_lifetimes.stderr new file mode 100644 index 000000000..8b70362a4 --- /dev/null +++ b/tests/ui/self_lifetimes.stderr @@ -0,0 +1,42 @@ +error[E0726]: implicit elided lifetime not allowed here + --> tests/ui/self_lifetimes.rs:6:24 + | +6 | fn zero(self: &Thing<>); + | ^^^^^^^ expected lifetime parameters + | +help: indicate the anonymous lifetimes + | +6 | fn zero(self: &Thing<'_, '_, >); + | +++++++ + +error[E0107]: struct takes 2 lifetime arguments but 1 lifetime argument was supplied + --> tests/ui/self_lifetimes.rs:7:27 + | +7 | fn one<'a>(self: &Thing<'a>); + | ^^^^^ -- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: struct defined here, with 2 lifetime parameters: `'a`, `'b` + --> tests/ui/self_lifetimes.rs:4:14 + | +4 | type Thing<'a, 'b>; + | ^^^^^ -- -- +help: add missing lifetime argument + | +7 | fn one<'a>(self: &Thing<'a, 'a>); + | ++++ + +error[E0107]: struct takes 2 lifetime arguments but 3 lifetime arguments were supplied + --> tests/ui/self_lifetimes.rs:8:37 + | +8 | fn three<'a, 'b, 'c>(self: &Thing<'a, 'b, 'c>); + | ^^^^^ ---- help: remove the lifetime argument + | | + | expected 2 lifetime arguments + | +note: struct defined here, with 2 lifetime parameters: `'a`, `'b` + --> tests/ui/self_lifetimes.rs:4:14 + | +4 | type Thing<'a, 'b>; + | ^^^^^ -- -- diff --git a/tests/ui/self_type_and_receiver.rs b/tests/ui/self_type_and_receiver.rs new file mode 100644 index 000000000..fed3dd324 --- /dev/null +++ b/tests/ui/self_type_and_receiver.rs @@ -0,0 +1,11 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type T; + + #[Self = "T"] + fn method(self: &T); + } +} + +fn main() {} diff --git a/tests/ui/self_type_and_receiver.stderr b/tests/ui/self_type_and_receiver.stderr new file mode 100644 index 000000000..8e4a2292a --- /dev/null +++ b/tests/ui/self_type_and_receiver.stderr @@ -0,0 +1,5 @@ +error: function with Self type must not have a `self` argument + --> tests/ui/self_type_and_receiver.rs:6:18 + | +6 | #[Self = "T"] + | ^^^ diff --git a/tests/ui/slice_of_pinned.rs b/tests/ui/slice_of_pinned.rs new file mode 100644 index 000000000..77582a5dd --- /dev/null +++ b/tests/ui/slice_of_pinned.rs @@ -0,0 +1,20 @@ +use cxx::{type_id, ExternType}; +use std::marker::PhantomPinned; + +#[repr(C)] +struct Pinned(usize, PhantomPinned); + +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type Pinned = crate::Pinned; + fn f(_: &[Pinned], _: &mut [Pinned]); + } +} + +unsafe impl ExternType for Pinned { + type Id = type_id!("Pinned"); + type Kind = cxx::kind::Trivial; +} + +fn main() {} diff --git a/tests/ui/slice_of_pinned.stderr b/tests/ui/slice_of_pinned.stderr new file mode 100644 index 000000000..2e8d83a12 --- /dev/null +++ b/tests/ui/slice_of_pinned.stderr @@ -0,0 +1,7 @@ +error[E0277]: mutable slice of pinned type is not supported + --> tests/ui/slice_of_pinned.rs:11:31 + | +11 | fn f(_: &[Pinned], _: &mut [Pinned]); + | ^^^^^^^^^^^^^ requires `Pinned: Unpin` + | + = help: the trait `SliceOfUnpin_Pinned` is not implemented for `&mut [Pinned]` diff --git a/tests/ui/slice_of_type_alias.stderr b/tests/ui/slice_of_type_alias.stderr index 9339da37a..85ca589c7 100644 --- a/tests/ui/slice_of_type_alias.stderr +++ b/tests/ui/slice_of_type_alias.stderr @@ -1,16 +1,11 @@ -error[E0271]: type mismatch resolving `::Kind == Trivial` - --> tests/ui/slice_of_type_alias.rs:13:14 +error[E0271]: type mismatch resolving `<&[ElementOpaque] as SliceOfExternType>::Kind == Trivial` + --> tests/ui/slice_of_type_alias.rs:16:21 | -13 | type ElementOpaque = crate::ElementOpaque; - | ^^^^^^^^^^^^^ type mismatch resolving `::Kind == Trivial` +16 | fn g(slice: &[ElementOpaque]); + | ^^^^^^^^^^^^^^^^ expected `Trivial`, found `Opaque` | -note: expected this to be `Trivial` - --> tests/ui/slice_of_type_alias.rs:27:17 +note: required by a bound in `cxx::private::Without::check_slice` + --> src/rust_type.rs | -27 | type Kind = cxx::kind::Opaque; - | ^^^^^^^^^^^^^^^^^ -note: required by a bound in `verify_extern_kind` - --> src/extern_type.rs - | - | pub fn verify_extern_kind, Kind: self::Kind>() {} - | ^^^^^^^^^^^ required by this bound in `verify_extern_kind` + | pub const fn check_slice>(&self) {} + | ^^^^^^^^^^^^^^ required by this bound in `Without::check_slice` diff --git a/tests/ui/struct_align.rs b/tests/ui/struct_align.rs new file mode 100644 index 000000000..e12052f7a --- /dev/null +++ b/tests/ui/struct_align.rs @@ -0,0 +1,20 @@ +#[cxx::bridge] +mod ffi { + #[repr(align(3))] + struct SharedA { + b: [u8; 4], + } + + // 1073741824 = 2^30 + #[repr(align(1073741824))] + struct SharedB { + b: [u8; 4], + } + + #[repr(align(-2))] + struct SharedC { + b: [u8; 4], + } +} + +fn main() {} diff --git a/tests/ui/struct_align.stderr b/tests/ui/struct_align.stderr new file mode 100644 index 000000000..6e039051e --- /dev/null +++ b/tests/ui/struct_align.stderr @@ -0,0 +1,17 @@ +error: invalid repr(align) attribute: not a power of two + --> tests/ui/struct_align.rs:3:18 + | +3 | #[repr(align(3))] + | ^ + +error: invalid repr(align) attribute: larger than 2^13 + --> tests/ui/struct_align.rs:9:18 + | +9 | #[repr(align(1073741824))] + | ^^^^^^^^^^ + +error: invalid repr(align) attribute: an arithmetic expression is not supported + --> tests/ui/struct_align.rs:14:18 + | +14 | #[repr(align(-2))] + | ^^ diff --git a/tests/ui/undeclared_lifetime.rs b/tests/ui/undeclared_lifetime.rs new file mode 100644 index 000000000..da96fba62 --- /dev/null +++ b/tests/ui/undeclared_lifetime.rs @@ -0,0 +1,17 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + fn f0(_: &'a CxxString); + fn g0<'a>(_: &'b CxxString); + + type This<'a>; + fn f1(self: &This, _: &'a CxxString); + fn g1<'a>(self: &This, _: &'b CxxString); + fn f2(self: &'a This); + fn g2<'a>(self: &'b This); + fn f3(self: &This<'a>); + fn g3<'a>(self: &This<'b>); + } +} + +fn main() {} diff --git a/tests/ui/undeclared_lifetime.stderr b/tests/ui/undeclared_lifetime.stderr new file mode 100644 index 000000000..9f17385b1 --- /dev/null +++ b/tests/ui/undeclared_lifetime.stderr @@ -0,0 +1,103 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> tests/ui/undeclared_lifetime.rs:4:19 + | +4 | fn f0(_: &'a CxxString); + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +4 | fn f0<'a>(_: &'a CxxString); + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> tests/ui/undeclared_lifetime.rs:5:23 + | +5 | fn g0<'a>(_: &'b CxxString); + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +5 | fn g0<'b, 'a>(_: &'b CxxString); + | +++ + +error[E0261]: use of undeclared lifetime name `'a` + --> tests/ui/undeclared_lifetime.rs:8:32 + | +8 | fn f1(self: &This, _: &'a CxxString); + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +8 | fn f1<'a>(self: &This, _: &'a CxxString); + | ++++ +help: consider introducing lifetime `'a` here + | +8 | fn f1<'a>(self: &This, _: &'a CxxString); + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> tests/ui/undeclared_lifetime.rs:9:36 + | +9 | fn g1<'a>(self: &This, _: &'b CxxString); + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +9 | fn g1<'b, 'a>(self: &This, _: &'b CxxString); + | +++ +help: consider introducing lifetime `'b` here + | +9 | fn g1<'b, 'a>(self: &This, _: &'b CxxString); + | +++ + +error[E0261]: use of undeclared lifetime name `'a` + --> tests/ui/undeclared_lifetime.rs:10:22 + | +10 | fn f2(self: &'a This); + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +10 | fn f2<'a>(self: &'a This); + | ++++ +help: consider introducing lifetime `'a` here + | +10 | fn f2<'a>(self: &'a This); + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> tests/ui/undeclared_lifetime.rs:11:26 + | +11 | fn g2<'a>(self: &'b This); + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +11 | fn g2<'b, 'a>(self: &'b This); + | +++ +help: consider introducing lifetime `'b` here + | +11 | fn g2<'b, 'a>(self: &'b This); + | +++ + +error[E0261]: use of undeclared lifetime name `'a` + --> tests/ui/undeclared_lifetime.rs:12:27 + | +12 | fn f3(self: &This<'a>); + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +12 | fn f3<'a>(self: &This<'a>); + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> tests/ui/undeclared_lifetime.rs:13:31 + | +13 | fn g3<'a>(self: &This<'b>); + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +13 | fn g3<'b, 'a>(self: &This<'b>); + | +++ diff --git a/tests/ui/unique_ptr_to_opaque.stderr b/tests/ui/unique_ptr_to_opaque.stderr index 3c121e54c..79edff725 100644 --- a/tests/ui/unique_ptr_to_opaque.stderr +++ b/tests/ui/unique_ptr_to_opaque.stderr @@ -9,10 +9,13 @@ error[E0271]: type mismatch resolving `::Kind == Trivial` note: expected this to be `Trivial` --> tests/ui/unique_ptr_to_opaque.rs:8:21 | -8 | type Kind = cxx::kind::Opaque; + 8 | type Kind = cxx::kind::Opaque; | ^^^^^^^^^^^^^^^^^ note: required by a bound in `UniquePtr::::new` --> src/unique_ptr.rs | + | pub fn new(value: T) -> Self + | --- required by a bound in this associated function + | where | T: ExternType, | ^^^^^^^^^^^^^^ required by this bound in `UniquePtr::::new` diff --git a/tests/ui/unique_ptr_twice.stderr b/tests/ui/unique_ptr_twice.stderr index b21791fbe..b3ca2bc68 100644 --- a/tests/ui/unique_ptr_twice.stderr +++ b/tests/ui/unique_ptr_twice.stderr @@ -1,7 +1,7 @@ error[E0119]: conflicting implementations of trait `UniquePtrTarget` for type `here::C` --> tests/ui/unique_ptr_twice.rs:16:5 | -7 | impl UniquePtr {} + 7 | impl UniquePtr {} | ---------------- first implementation here ... 16 | impl UniquePtr {} diff --git a/tests/ui/unpin_impl.stderr b/tests/ui/unpin_impl.stderr index afe5a8066..888d64fbc 100644 --- a/tests/ui/unpin_impl.stderr +++ b/tests/ui/unpin_impl.stderr @@ -1,14 +1,8 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> tests/ui/unpin_impl.rs:4:14 | 4 | type Opaque; | ^^^^^^ cannot infer type - -error[E0283]: type annotations needed - --> tests/ui/unpin_impl.rs:1:1 - | -1 | #[cxx::bridge] - | ^^^^^^^^^^^^^^ cannot infer type | note: multiple `impl`s satisfying `ffi::Opaque: __AmbiguousIfImpl<_>` found --> tests/ui/unpin_impl.rs:1:1 diff --git a/tests/ui/vec_opaque.stderr b/tests/ui/vec_opaque.stderr index ae01adfc3..649b987eb 100644 --- a/tests/ui/vec_opaque.stderr +++ b/tests/ui/vec_opaque.stderr @@ -10,14 +10,19 @@ error: needs a cxx::ExternType impl in order to be used as a vector element in V 11 | type Job; | ^^^^^^^^ -error[E0271]: type mismatch resolving `::Kind == Trivial` +error[E0277]: the trait bound `handle::Job: cxx::private::ImplVec` is not satisfied --> tests/ui/vec_opaque.rs:22:14 | 22 | type Job = crate::handle::Job; - | ^^^ expected `Trivial`, found `Opaque` + | ^^^ unsatisfied trait bound | -note: required by a bound in `verify_extern_kind` - --> src/extern_type.rs +help: the trait `cxx::private::ImplVec` is not implemented for `handle::Job` + --> tests/ui/vec_opaque.rs:4:9 | - | pub fn verify_extern_kind, Kind: self::Kind>() {} - | ^^^^^^^^^^^ required by this bound in `verify_extern_kind` + 4 | type Job; + | ^^^^^^^^ +note: required by a bound in `cxx::private::require_vec` + --> src/rust_type.rs + | + | pub fn require_vec() {} + | ^^^^^^^ required by this bound in `require_vec` diff --git a/tests/ui/vector_autotraits.stderr b/tests/ui/vector_autotraits.stderr index 8851cedc1..6bd6bb7c6 100644 --- a/tests/ui/vector_autotraits.stderr +++ b/tests/ui/vector_autotraits.stderr @@ -5,16 +5,28 @@ error[E0277]: `*const cxx::void` cannot be sent between threads safely | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const cxx::void` cannot be sent between threads safely | = help: within `CxxVector`, the trait `Send` is not implemented for `*const cxx::void` - = note: required because it appears within the type `[*const void; 0]` - = note: required because it appears within the type `Opaque` + = note: required because it appears within the type `[*const cxx::void; 0]` +note: required because it appears within the type `cxx::private::Opaque` + --> src/opaque.rs + | + | pub struct Opaque { + | ^^^^^^ note: required because it appears within the type `NotThreadSafe` --> tests/ui/vector_autotraits.rs:7:14 | -7 | type NotThreadSafe; + 7 | type NotThreadSafe; | ^^^^^^^^^^^^^ = 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` +note: required because it appears within the type `PhantomData<[NotThreadSafe]>` + --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ +note: required because it appears within the type `CxxVector` + --> src/cxx_vector.rs + | + | pub struct CxxVector { + | ^^^^^^^^^ note: required by a bound in `assert_send` --> tests/ui/vector_autotraits.rs:16:19 | diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr index d3ed3a0c1..9ae3c6fd1 100644 --- a/tests/ui/wrong_type_id.stderr +++ b/tests/ui/wrong_type_id.stderr @@ -1,13 +1,19 @@ -error[E0271]: type mismatch resolving `::Id == (f, o, l, l, y, (), B, y, t, e, ..., ..., ..., ..., ...)` +error[E0271]: type mismatch resolving `::Id == (f, o, l, l, y, (), B, y, t, e, R, a, n, g, 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 + | ^^^^^^^^^ type mismatch resolving `::Id == (f, o, l, l, y, (), B, y, t, e, R, a, n, g, e)` | - = 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` +note: expected this to be `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)` + --> tests/ui/wrong_type_id.rs:1:1 + | + 1 | #[cxx::bridge(namespace = "folly")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)` + found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)` +note: required by a bound in `cxx::private::verify_extern_type` --> src/extern_type.rs | | pub fn verify_extern_type, Id>() {} | ^^^^^^^ required by this bound in `verify_extern_type` + = note: this error originates in the attribute macro `cxx::bridge` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/third-party/.cargo/.gitignore b/third-party/.cargo/.gitignore new file mode 100644 index 000000000..2011220cb --- /dev/null +++ b/third-party/.cargo/.gitignore @@ -0,0 +1,5 @@ +/.global-cache +/.package-cache +/.package-cache-mutate +/config.toml +/registry/ diff --git a/third-party/.gitignore b/third-party/.gitignore index b05094889..2332034f1 100644 --- a/third-party/.gitignore +++ b/third-party/.gitignore @@ -1,2 +1,2 @@ -/.cargo -/vendor +/target/ +/vendor/ diff --git a/third-party/BUCK b/third-party/BUCK index dddbab6b8..8141d3505 100644 --- a/third-party/BUCK +++ b/third-party/BUCK @@ -1,490 +1,669 @@ # @generated by `reindeer buckify` -load("//tools/buck:buildscript.bzl", "buildscript_args") +load("@prelude//rust:cargo_buildscript.bzl", "buildscript_run") +load("@prelude//rust:cargo_package.bzl", "cargo") -rust_library( - name = "bitflags-1.3.2", - srcs = [ - "vendor/bitflags-1.3.2/src/example_generated.rs", - "vendor/bitflags-1.3.2/src/lib.rs", +http_archive( + name = "anstyle-1.0.14.crate", + sha256 = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000", + strip_prefix = "anstyle-1.0.14", + urls = ["https://static.crates.io/crates/anstyle/1.0.14/download"], + visibility = [], +) + +cargo.rust_library( + name = "anstyle-1", + srcs = [":anstyle-1.0.14.crate"], + crate = "anstyle", + crate_root = "anstyle-1.0.14.crate/src/lib.rs", + edition = "2021", + features = [ + "default", + "std", ], - crate = "bitflags", - crate_root = "vendor/bitflags-1.3.2/src/lib.rs", - edition = "2018", - features = ["default"], - rustc_flags = ["--cap-lints=allow"], visibility = [], ) alias( name = "cc", - actual = ":cc-1.0.79", + actual = ":cc-1", visibility = ["PUBLIC"], ) -rust_library( - name = "cc-1.0.79", - srcs = [ - "vendor/cc-1.0.79/src/com.rs", - "vendor/cc-1.0.79/src/lib.rs", - "vendor/cc-1.0.79/src/registry.rs", - "vendor/cc-1.0.79/src/setup_config.rs", - "vendor/cc-1.0.79/src/vs_instances.rs", - "vendor/cc-1.0.79/src/winapi.rs", - "vendor/cc-1.0.79/src/windows_registry.rs", - ], +http_archive( + name = "cc-1.4.2.crate", + sha256 = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e", + strip_prefix = "cc-1.4.2", + urls = ["https://static.crates.io/crates/cc/1.4.2/download"], + visibility = [], +) + +cargo.rust_library( + name = "cc-1", + srcs = [":cc-1.4.2.crate"], crate = "cc", - crate_root = "vendor/cc-1.0.79/src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], + crate_root = "cc-1.4.2.crate/src/lib.rs", + edition = "2021", visibility = [], + deps = [ + ":find-msvc-tools-0.1", + ":shlex-2", + ], ) alias( name = "clap", - actual = ":clap-4.1.4", + actual = ":clap-4", visibility = ["PUBLIC"], ) -rust_library( - name = "clap-4.1.4", - srcs = [ - "vendor/clap-4.1.4/examples/demo.md", - "vendor/clap-4.1.4/examples/demo.rs", - "vendor/clap-4.1.4/src/_cookbook/cargo_example.rs", - "vendor/clap-4.1.4/src/_cookbook/cargo_example_derive.rs", - "vendor/clap-4.1.4/src/_cookbook/escaped_positional.rs", - "vendor/clap-4.1.4/src/_cookbook/escaped_positional_derive.rs", - "vendor/clap-4.1.4/src/_cookbook/find.rs", - "vendor/clap-4.1.4/src/_cookbook/git.rs", - "vendor/clap-4.1.4/src/_cookbook/git_derive.rs", - "vendor/clap-4.1.4/src/_cookbook/mod.rs", - "vendor/clap-4.1.4/src/_cookbook/multicall_busybox.rs", - "vendor/clap-4.1.4/src/_cookbook/multicall_hostname.rs", - "vendor/clap-4.1.4/src/_cookbook/pacman.rs", - "vendor/clap-4.1.4/src/_cookbook/repl.rs", - "vendor/clap-4.1.4/src/_cookbook/typed_derive.rs", - "vendor/clap-4.1.4/src/_derive/_tutorial.rs", - "vendor/clap-4.1.4/src/_derive/mod.rs", - "vendor/clap-4.1.4/src/_faq.rs", - "vendor/clap-4.1.4/src/_features.rs", - "vendor/clap-4.1.4/src/_tutorial.rs", - "vendor/clap-4.1.4/src/builder/action.rs", - "vendor/clap-4.1.4/src/builder/app_settings.rs", - "vendor/clap-4.1.4/src/builder/arg.rs", - "vendor/clap-4.1.4/src/builder/arg_group.rs", - "vendor/clap-4.1.4/src/builder/arg_predicate.rs", - "vendor/clap-4.1.4/src/builder/arg_settings.rs", - "vendor/clap-4.1.4/src/builder/command.rs", - "vendor/clap-4.1.4/src/builder/debug_asserts.rs", - "vendor/clap-4.1.4/src/builder/mod.rs", - "vendor/clap-4.1.4/src/builder/os_str.rs", - "vendor/clap-4.1.4/src/builder/possible_value.rs", - "vendor/clap-4.1.4/src/builder/range.rs", - "vendor/clap-4.1.4/src/builder/resettable.rs", - "vendor/clap-4.1.4/src/builder/str.rs", - "vendor/clap-4.1.4/src/builder/styled_str.rs", - "vendor/clap-4.1.4/src/builder/tests.rs", - "vendor/clap-4.1.4/src/builder/value_hint.rs", - "vendor/clap-4.1.4/src/builder/value_parser.rs", - "vendor/clap-4.1.4/src/derive.rs", - "vendor/clap-4.1.4/src/error/context.rs", - "vendor/clap-4.1.4/src/error/format.rs", - "vendor/clap-4.1.4/src/error/kind.rs", - "vendor/clap-4.1.4/src/error/mod.rs", - "vendor/clap-4.1.4/src/lib.rs", - "vendor/clap-4.1.4/src/macros.rs", - "vendor/clap-4.1.4/src/mkeymap.rs", - "vendor/clap-4.1.4/src/output/fmt.rs", - "vendor/clap-4.1.4/src/output/help.rs", - "vendor/clap-4.1.4/src/output/help_template.rs", - "vendor/clap-4.1.4/src/output/mod.rs", - "vendor/clap-4.1.4/src/output/textwrap/core.rs", - "vendor/clap-4.1.4/src/output/textwrap/mod.rs", - "vendor/clap-4.1.4/src/output/textwrap/word_separators.rs", - "vendor/clap-4.1.4/src/output/textwrap/wrap_algorithms.rs", - "vendor/clap-4.1.4/src/output/usage.rs", - "vendor/clap-4.1.4/src/parser/arg_matcher.rs", - "vendor/clap-4.1.4/src/parser/error.rs", - "vendor/clap-4.1.4/src/parser/features/mod.rs", - "vendor/clap-4.1.4/src/parser/features/suggestions.rs", - "vendor/clap-4.1.4/src/parser/matches/any_value.rs", - "vendor/clap-4.1.4/src/parser/matches/arg_matches.rs", - "vendor/clap-4.1.4/src/parser/matches/matched_arg.rs", - "vendor/clap-4.1.4/src/parser/matches/mod.rs", - "vendor/clap-4.1.4/src/parser/matches/value_source.rs", - "vendor/clap-4.1.4/src/parser/mod.rs", - "vendor/clap-4.1.4/src/parser/parser.rs", - "vendor/clap-4.1.4/src/parser/validator.rs", - "vendor/clap-4.1.4/src/util/color.rs", - "vendor/clap-4.1.4/src/util/flat_map.rs", - "vendor/clap-4.1.4/src/util/flat_set.rs", - "vendor/clap-4.1.4/src/util/graph.rs", - "vendor/clap-4.1.4/src/util/id.rs", - "vendor/clap-4.1.4/src/util/mod.rs", - "vendor/clap-4.1.4/src/util/str_to_bool.rs", - ], +http_archive( + name = "clap-4.6.6.crate", + sha256 = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca", + strip_prefix = "clap-4.6.6", + urls = ["https://static.crates.io/crates/clap/4.6.6/download"], + visibility = [], +) + +cargo.rust_library( + name = "clap-4", + srcs = [":clap-4.6.6.crate"], crate = "clap", - crate_root = "vendor/clap-4.1.4/src/lib.rs", - edition = "2021", + crate_root = "clap-4.6.6.crate/src/lib.rs", + edition = "2024", + features = [ + "error-context", + "help", + "std", + "usage", + ], + visibility = [], + deps = [":clap_builder-4"], +) + +http_archive( + name = "clap_builder-4.6.6.crate", + sha256 = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889", + strip_prefix = "clap_builder-4.6.6", + urls = ["https://static.crates.io/crates/clap_builder/4.6.6/download"], + visibility = [], +) + +cargo.rust_library( + name = "clap_builder-4", + srcs = [":clap_builder-4.6.6.crate"], + crate = "clap_builder", + crate_root = "clap_builder-4.6.6.crate/src/lib.rs", + edition = "2024", features = [ "error-context", "help", "std", "usage", ], - rustc_flags = ["--cap-lints=allow"], visibility = [], deps = [ - ":bitflags-1.3.2", - ":clap_lex-0.3.1", + ":anstyle-1", + ":clap_lex-1", ], ) -rust_library( - name = "clap_lex-0.3.1", - srcs = ["vendor/clap_lex-0.3.1/src/lib.rs"], +http_archive( + name = "clap_lex-1.1.0.crate", + sha256 = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9", + strip_prefix = "clap_lex-1.1.0", + urls = ["https://static.crates.io/crates/clap_lex/1.1.0/download"], + visibility = [], +) + +cargo.rust_library( + name = "clap_lex-1", + srcs = [":clap_lex-1.1.0.crate"], crate = "clap_lex", - crate_root = "vendor/clap_lex-0.3.1/src/lib.rs", - edition = "2021", - rustc_flags = ["--cap-lints=allow"], + crate_root = "clap_lex-1.1.0.crate/src/lib.rs", + edition = "2024", visibility = [], - deps = [":os_str_bytes-6.4.1"], ) alias( name = "codespan-reporting", - actual = ":codespan-reporting-0.11.1", + actual = ":codespan-reporting-0.13", 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", - ], +http_archive( + name = "codespan-reporting-0.13.1.crate", + sha256 = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681", + strip_prefix = "codespan-reporting-0.13.1", + urls = ["https://static.crates.io/crates/codespan-reporting/0.13.1/download"], + visibility = [], +) + +cargo.rust_library( + name = "codespan-reporting-0.13", + srcs = [":codespan-reporting-0.13.1.crate"], crate = "codespan_reporting", - crate_root = "vendor/codespan-reporting-0.11.1/src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], + crate_root = "codespan-reporting-0.13.1.crate/src/lib.rs", + edition = "2021", + features = [ + "default", + "std", + "termcolor", + ], visibility = [], deps = [ - ":termcolor-1.2.0", - ":unicode-width-0.1.10", + ":termcolor-1", + ":unicode-width-0.2", ], ) +http_archive( + name = "equivalent-1.0.2.crate", + sha256 = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f", + strip_prefix = "equivalent-1.0.2", + urls = ["https://static.crates.io/crates/equivalent/1.0.2/download"], + visibility = [], +) + +cargo.rust_library( + name = "equivalent-1", + srcs = [":equivalent-1.0.2.crate"], + crate = "equivalent", + crate_root = "equivalent-1.0.2.crate/src/lib.rs", + edition = "2015", + visibility = [], +) + +http_archive( + name = "find-msvc-tools-0.1.10.crate", + sha256 = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de", + strip_prefix = "find-msvc-tools-0.1.10", + urls = ["https://static.crates.io/crates/find-msvc-tools/0.1.10/download"], + visibility = [], +) + +cargo.rust_library( + name = "find-msvc-tools-0.1", + srcs = [":find-msvc-tools-0.1.10.crate"], + crate = "find_msvc_tools", + crate_root = "find-msvc-tools-0.1.10.crate/src/lib.rs", + edition = "2021", + visibility = [], +) + alias( - name = "once_cell", - actual = ":once_cell-1.17.0", + name = "foldhash", + actual = ":foldhash-0.2", visibility = ["PUBLIC"], ) -rust_library( - name = "once_cell-1.17.0", - srcs = [ - "vendor/once_cell-1.17.0/src/imp_cs.rs", - "vendor/once_cell-1.17.0/src/imp_pl.rs", - "vendor/once_cell-1.17.0/src/imp_std.rs", - "vendor/once_cell-1.17.0/src/lib.rs", - "vendor/once_cell-1.17.0/src/race.rs", - ], - crate = "once_cell", - crate_root = "vendor/once_cell-1.17.0/src/lib.rs", +http_archive( + name = "foldhash-0.2.0.crate", + sha256 = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb", + strip_prefix = "foldhash-0.2.0", + urls = ["https://static.crates.io/crates/foldhash/0.2.0/download"], + visibility = [], +) + +cargo.rust_library( + name = "foldhash-0.2", + srcs = [":foldhash-0.2.0.crate"], + crate = "foldhash", + crate_root = "foldhash-0.2.0.crate/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", + visibility = [], +) + +http_archive( + name = "hashbrown-0.17.1.crate", + sha256 = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a", + strip_prefix = "hashbrown-0.17.1", + urls = ["https://static.crates.io/crates/hashbrown/0.17.1/download"], + visibility = [], +) + +cargo.rust_library( + name = "hashbrown-0.17", + srcs = [":hashbrown-0.17.1.crate"], + crate = "hashbrown", + crate_root = "hashbrown-0.17.1.crate/src/lib.rs", + edition = "2024", + visibility = [], +) + +alias( + name = "indexmap", + actual = ":indexmap-2", + visibility = ["PUBLIC"], +) + +http_archive( + name = "indexmap-2.14.0.crate", + sha256 = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9", + strip_prefix = "indexmap-2.14.0", + urls = ["https://static.crates.io/crates/indexmap/2.14.0/download"], + visibility = [], +) + +cargo.rust_library( + name = "indexmap-2", + srcs = [":indexmap-2.14.0.crate"], + crate = "indexmap", + crate_root = "indexmap-2.14.0.crate/src/lib.rs", + edition = "2024", + features = [ + "default", + "std", ], - 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 = [], + deps = [ + ":equivalent-1", + ":hashbrown-0.17", + ], ) alias( name = "proc-macro2", - actual = ":proc-macro2-1.0.51", + actual = ":proc-macro2-1", visibility = ["PUBLIC"], ) -rust_library( - name = "proc-macro2-1.0.51", - srcs = [ - "vendor/proc-macro2-1.0.51/src/detection.rs", - "vendor/proc-macro2-1.0.51/src/fallback.rs", - "vendor/proc-macro2-1.0.51/src/lib.rs", - "vendor/proc-macro2-1.0.51/src/location.rs", - "vendor/proc-macro2-1.0.51/src/marker.rs", - "vendor/proc-macro2-1.0.51/src/parse.rs", - "vendor/proc-macro2-1.0.51/src/rcvec.rs", - "vendor/proc-macro2-1.0.51/src/wrapper.rs", - ], +http_archive( + name = "proc-macro2-1.0.107.crate", + sha256 = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9", + strip_prefix = "proc-macro2-1.0.107", + urls = ["https://static.crates.io/crates/proc-macro2/1.0.107/download"], + visibility = [], +) + +cargo.rust_library( + name = "proc-macro2-1", + srcs = [":proc-macro2-1.0.107.crate"], crate = "proc_macro2", - crate_root = "vendor/proc-macro2-1.0.51/src/lib.rs", - edition = "2018", + crate_root = "proc-macro2-1.0.107.crate/src/lib.rs", + edition = "2021", + env = { + "OUT_DIR": "$(location :proc-macro2-1-build-script-run[out_dir])", + }, features = [ "default", "proc-macro", "span-locations", ], - rustc_flags = [ - "--cap-lints=allow", - "@$(location :proc-macro2-1.0.51-build-script-build-args)", - ], + rustc_flags = ["@$(location :proc-macro2-1-build-script-run[rustc_flags])"], visibility = [], - deps = [":unicode-ident-1.0.6"], + deps = [":unicode-ident-1"], ) -rust_binary( - name = "proc-macro2-1.0.51-build-script-build", - srcs = ["vendor/proc-macro2-1.0.51/build.rs"], +cargo.rust_binary( + name = "proc-macro2-1-build-script-build", + srcs = [":proc-macro2-1.0.107.crate"], crate = "build_script_build", - crate_root = "vendor/proc-macro2-1.0.51/build.rs", - edition = "2018", + crate_root = "proc-macro2-1.0.107.crate/build.rs", + edition = "2021", features = [ "default", "proc-macro", "span-locations", ], - rustc_flags = ["--cap-lints=allow"], visibility = [], ) -buildscript_args( - name = "proc-macro2-1.0.51-build-script-build-args", +buildscript_run( + name = "proc-macro2-1-build-script-run", package_name = "proc-macro2", - buildscript_rule = ":proc-macro2-1.0.51-build-script-build", + buildscript_rule = ":proc-macro2-1-build-script-build", features = [ "default", "proc-macro", "span-locations", ], - outfile = "args.txt", - version = "1.0.51", + version = "1.0.107", ) alias( name = "quote", - actual = ":quote-1.0.23", + actual = ":quote-1", visibility = ["PUBLIC"], ) -rust_library( - name = "quote-1.0.23", - srcs = [ - "vendor/quote-1.0.23/src/ext.rs", - "vendor/quote-1.0.23/src/format.rs", - "vendor/quote-1.0.23/src/ident_fragment.rs", - "vendor/quote-1.0.23/src/lib.rs", - "vendor/quote-1.0.23/src/runtime.rs", - "vendor/quote-1.0.23/src/spanned.rs", - "vendor/quote-1.0.23/src/to_tokens.rs", - ], +http_archive( + name = "quote-1.0.47.crate", + sha256 = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001", + strip_prefix = "quote-1.0.47", + urls = ["https://static.crates.io/crates/quote/1.0.47/download"], + visibility = [], +) + +cargo.rust_library( + name = "quote-1", + srcs = [":quote-1.0.47.crate"], crate = "quote", - crate_root = "vendor/quote-1.0.23/src/lib.rs", - edition = "2018", + crate_root = "quote-1.0.47.crate/src/lib.rs", + edition = "2021", + env = { + "OUT_DIR": "$(location :quote-1-build-script-run[out_dir])", + }, features = [ "default", "proc-macro", ], - rustc_flags = [ - "--cap-lints=allow", - "@$(location :quote-1.0.23-build-script-build-args)", - ], + rustc_flags = ["@$(location :quote-1-build-script-run[rustc_flags])"], visibility = [], - deps = [":proc-macro2-1.0.51"], + deps = [":proc-macro2-1"], ) -rust_binary( - name = "quote-1.0.23-build-script-build", - srcs = ["vendor/quote-1.0.23/build.rs"], +cargo.rust_binary( + name = "quote-1-build-script-build", + srcs = [":quote-1.0.47.crate"], crate = "build_script_build", - crate_root = "vendor/quote-1.0.23/build.rs", - edition = "2018", + crate_root = "quote-1.0.47.crate/build.rs", + edition = "2021", features = [ "default", "proc-macro", ], - rustc_flags = ["--cap-lints=allow"], visibility = [], ) -buildscript_args( - name = "quote-1.0.23-build-script-build-args", +buildscript_run( + name = "quote-1-build-script-run", package_name = "quote", - buildscript_rule = ":quote-1.0.23-build-script-build", + buildscript_rule = ":quote-1-build-script-build", features = [ "default", "proc-macro", ], - outfile = "args.txt", + version = "1.0.47", +) + +alias( + name = "rustversion", + actual = ":rustversion-1", + visibility = ["PUBLIC"], +) + +http_archive( + name = "rustversion-1.0.23.crate", + sha256 = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f", + strip_prefix = "rustversion-1.0.23", + urls = ["https://static.crates.io/crates/rustversion/1.0.23/download"], + visibility = [], +) + +cargo.rust_library( + name = "rustversion-1", + srcs = [":rustversion-1.0.23.crate"], + crate = "rustversion", + crate_root = "rustversion-1.0.23.crate/src/lib.rs", + edition = "2018", + env = { + "OUT_DIR": "$(location :rustversion-1-build-script-run[out_dir])", + }, + proc_macro = True, + rustc_flags = ["@$(location :rustversion-1-build-script-run[rustc_flags])"], + visibility = [], +) + +cargo.rust_binary( + name = "rustversion-1-build-script-build", + srcs = [":rustversion-1.0.23.crate"], + crate = "build_script_build", + crate_root = "rustversion-1.0.23.crate/build/build.rs", + edition = "2018", + visibility = [], +) + +buildscript_run( + name = "rustversion-1-build-script-run", + package_name = "rustversion", + buildscript_rule = ":rustversion-1-build-script-build", version = "1.0.23", ) alias( name = "scratch", - actual = ":scratch-1.0.3", + actual = ":scratch-1", visibility = ["PUBLIC"], ) -rust_library( - name = "scratch-1.0.3", - srcs = ["vendor/scratch-1.0.3/src/lib.rs"], +http_archive( + name = "scratch-1.0.9.crate", + sha256 = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2", + strip_prefix = "scratch-1.0.9", + urls = ["https://static.crates.io/crates/scratch/1.0.9/download"], + visibility = [], +) + +cargo.rust_library( + name = "scratch-1", + srcs = [":scratch-1.0.9.crate"], crate = "scratch", - crate_root = "vendor/scratch-1.0.3/src/lib.rs", + crate_root = "scratch-1.0.9.crate/src/lib.rs", edition = "2015", env = { - "OUT_DIR": "generated", + "OUT_DIR": "$(location :scratch-1-build-script-run[out_dir])", }, - rustc_flags = ["--cap-lints=allow"], + rustc_flags = ["@$(location :scratch-1-build-script-run[rustc_flags])"], visibility = [], ) +cargo.rust_binary( + name = "scratch-1-build-script-build", + srcs = [":scratch-1.0.9.crate"], + crate = "build_script_build", + crate_root = "scratch-1.0.9.crate/build.rs", + edition = "2015", + visibility = [], +) + +buildscript_run( + name = "scratch-1-build-script-run", + package_name = "scratch", + buildscript_rule = ":scratch-1-build-script-build", + version = "1.0.9", +) + alias( - name = "syn", - actual = ":syn-1.0.107", + name = "serde", + actual = ":serde-1", visibility = ["PUBLIC"], ) -rust_library( - name = "syn-1.0.107", - srcs = [ - "vendor/syn-1.0.107/src/attr.rs", - "vendor/syn-1.0.107/src/await.rs", - "vendor/syn-1.0.107/src/bigint.rs", - "vendor/syn-1.0.107/src/buffer.rs", - "vendor/syn-1.0.107/src/custom_keyword.rs", - "vendor/syn-1.0.107/src/custom_punctuation.rs", - "vendor/syn-1.0.107/src/data.rs", - "vendor/syn-1.0.107/src/derive.rs", - "vendor/syn-1.0.107/src/discouraged.rs", - "vendor/syn-1.0.107/src/drops.rs", - "vendor/syn-1.0.107/src/error.rs", - "vendor/syn-1.0.107/src/export.rs", - "vendor/syn-1.0.107/src/expr.rs", - "vendor/syn-1.0.107/src/ext.rs", - "vendor/syn-1.0.107/src/file.rs", - "vendor/syn-1.0.107/src/gen/clone.rs", - "vendor/syn-1.0.107/src/gen/debug.rs", - "vendor/syn-1.0.107/src/gen/eq.rs", - "vendor/syn-1.0.107/src/gen/fold.rs", - "vendor/syn-1.0.107/src/gen/hash.rs", - "vendor/syn-1.0.107/src/gen/visit.rs", - "vendor/syn-1.0.107/src/gen/visit_mut.rs", - "vendor/syn-1.0.107/src/gen_helper.rs", - "vendor/syn-1.0.107/src/generics.rs", - "vendor/syn-1.0.107/src/group.rs", - "vendor/syn-1.0.107/src/ident.rs", - "vendor/syn-1.0.107/src/item.rs", - "vendor/syn-1.0.107/src/lib.rs", - "vendor/syn-1.0.107/src/lifetime.rs", - "vendor/syn-1.0.107/src/lit.rs", - "vendor/syn-1.0.107/src/lookahead.rs", - "vendor/syn-1.0.107/src/mac.rs", - "vendor/syn-1.0.107/src/macros.rs", - "vendor/syn-1.0.107/src/op.rs", - "vendor/syn-1.0.107/src/parse.rs", - "vendor/syn-1.0.107/src/parse_macro_input.rs", - "vendor/syn-1.0.107/src/parse_quote.rs", - "vendor/syn-1.0.107/src/pat.rs", - "vendor/syn-1.0.107/src/path.rs", - "vendor/syn-1.0.107/src/print.rs", - "vendor/syn-1.0.107/src/punctuated.rs", - "vendor/syn-1.0.107/src/reserved.rs", - "vendor/syn-1.0.107/src/sealed.rs", - "vendor/syn-1.0.107/src/span.rs", - "vendor/syn-1.0.107/src/spanned.rs", - "vendor/syn-1.0.107/src/stmt.rs", - "vendor/syn-1.0.107/src/thread.rs", - "vendor/syn-1.0.107/src/token.rs", - "vendor/syn-1.0.107/src/tt.rs", - "vendor/syn-1.0.107/src/ty.rs", - "vendor/syn-1.0.107/src/verbatim.rs", - "vendor/syn-1.0.107/src/whitespace.rs", +http_archive( + name = "serde-1.0.229.crate", + sha256 = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba", + strip_prefix = "serde-1.0.229", + urls = ["https://static.crates.io/crates/serde/1.0.229/download"], + visibility = [], +) + +cargo.rust_library( + name = "serde-1", + srcs = [":serde-1.0.229.crate"], + crate = "serde", + crate_root = "serde-1.0.229.crate/src/lib.rs", + edition = "2021", + env = { + "CARGO_PKG_VERSION_PATCH": "229", + "OUT_DIR": "$(location :serde-1-build-script-run[out_dir])", + }, + features = [ + "default", + "derive", + "serde_derive", + "std", ], - crate = "syn", - crate_root = "vendor/syn-1.0.107/src/lib.rs", - edition = "2018", + rustc_flags = ["@$(location :serde-1-build-script-run[rustc_flags])"], + visibility = [], + deps = [ + ":serde_core-1", + ":serde_derive-1", + ], +) + +cargo.rust_binary( + name = "serde-1-build-script-build", + srcs = [":serde-1.0.229.crate"], + crate = "build_script_build", + crate_root = "serde-1.0.229.crate/build.rs", + edition = "2021", + env = { + "CARGO_PKG_VERSION_PATCH": "229", + }, features = [ - "clone-impls", "default", "derive", - "full", - "parsing", - "printing", - "proc-macro", - "quote", + "serde_derive", + "std", ], - rustc_flags = [ - "--cap-lints=allow", - "@$(location :syn-1.0.107-build-script-build-args)", + visibility = [], +) + +buildscript_run( + name = "serde-1-build-script-run", + package_name = "serde", + buildscript_rule = ":serde-1-build-script-build", + env = { + "CARGO_PKG_VERSION_PATCH": "229", + }, + features = [ + "default", + "derive", + "serde_derive", + "std", ], + version = "1.0.229", +) + +http_archive( + name = "serde_core-1.0.229.crate", + sha256 = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48", + strip_prefix = "serde_core-1.0.229", + urls = ["https://static.crates.io/crates/serde_core/1.0.229/download"], visibility = [], - deps = [ - ":proc-macro2-1.0.51", - ":quote-1.0.23", - ":unicode-ident-1.0.6", +) + +cargo.rust_library( + name = "serde_core-1", + srcs = [":serde_core-1.0.229.crate"], + crate = "serde_core", + crate_root = "serde_core-1.0.229.crate/src/lib.rs", + edition = "2021", + env = { + "CARGO_PKG_VERSION_PATCH": "229", + "OUT_DIR": "$(location :serde_core-1-build-script-run[out_dir])", + }, + features = [ + "result", + "std", ], + rustc_flags = ["@$(location :serde_core-1-build-script-run[rustc_flags])"], + visibility = [], ) -rust_binary( - name = "syn-1.0.107-build-script-build", - srcs = ["vendor/syn-1.0.107/build.rs"], +cargo.rust_binary( + name = "serde_core-1-build-script-build", + srcs = [":serde_core-1.0.229.crate"], crate = "build_script_build", - crate_root = "vendor/syn-1.0.107/build.rs", + crate_root = "serde_core-1.0.229.crate/build.rs", + edition = "2021", + env = { + "CARGO_PKG_VERSION_PATCH": "229", + }, + features = [ + "result", + "std", + ], + visibility = [], +) + +buildscript_run( + name = "serde_core-1-build-script-run", + package_name = "serde_core", + buildscript_rule = ":serde_core-1-build-script-build", + env = { + "CARGO_PKG_VERSION_PATCH": "229", + }, + features = [ + "result", + "std", + ], + version = "1.0.229", +) + +http_archive( + name = "serde_derive-1.0.229.crate", + sha256 = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348", + strip_prefix = "serde_derive-1.0.229", + urls = ["https://static.crates.io/crates/serde_derive/1.0.229/download"], + visibility = [], +) + +cargo.rust_library( + name = "serde_derive-1", + srcs = [":serde_derive-1.0.229.crate"], + crate = "serde_derive", + crate_root = "serde_derive-1.0.229.crate/src/lib.rs", + edition = "2021", + env = { + "CARGO_PKG_VERSION_PATCH": "229", + }, + features = ["default"], + proc_macro = True, + visibility = [], + deps = [ + ":proc-macro2-1", + ":quote-1", + ":syn-3", + ], +) + +http_archive( + name = "shlex-2.0.1.crate", + sha256 = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba", + strip_prefix = "shlex-2.0.1", + urls = ["https://static.crates.io/crates/shlex/2.0.1/download"], + visibility = [], +) + +cargo.rust_library( + name = "shlex-2", + srcs = [":shlex-2.0.1.crate"], + crate = "shlex", + crate_root = "shlex-2.0.1.crate/src/lib.rs", edition = "2018", features = [ - "clone-impls", "default", - "derive", - "full", - "parsing", - "printing", - "proc-macro", - "quote", + "std", ], - rustc_flags = ["--cap-lints=allow"], visibility = [], ) -buildscript_args( - name = "syn-1.0.107-build-script-build-args", - package_name = "syn", - buildscript_rule = ":syn-1.0.107-build-script-build", +alias( + name = "syn", + actual = ":syn-3", + visibility = ["PUBLIC"], +) + +http_archive( + name = "syn-3.0.3.crate", + sha256 = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3", + strip_prefix = "syn-3.0.3", + urls = ["https://static.crates.io/crates/syn/3.0.3/download"], + visibility = [], +) + +cargo.rust_library( + name = "syn-3", + srcs = [":syn-3.0.3.crate"], + crate = "syn", + crate_root = "syn-3.0.3.crate/src/lib.rs", + edition = "2021", features = [ "clone-impls", "default", @@ -493,46 +672,139 @@ buildscript_args( "parsing", "printing", "proc-macro", - "quote", ], - outfile = "args.txt", - version = "1.0.107", + visibility = [], + deps = [ + ":proc-macro2-1", + ":quote-1", + ":unicode-ident-1", + ], ) -rust_library( - name = "termcolor-1.2.0", - srcs = ["vendor/termcolor-1.2.0/src/lib.rs"], +http_archive( + name = "termcolor-1.4.1.crate", + sha256 = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755", + strip_prefix = "termcolor-1.4.1", + urls = ["https://static.crates.io/crates/termcolor/1.4.1/download"], + visibility = [], +) + +cargo.rust_library( + name = "termcolor-1", + srcs = [":termcolor-1.4.1.crate"], crate = "termcolor", - crate_root = "vendor/termcolor-1.2.0/src/lib.rs", + crate_root = "termcolor-1.4.1.crate/src/lib.rs", edition = "2018", - rustc_flags = ["--cap-lints=allow"], + platform = { + "windows-gnu": dict( + deps = [":winapi-util-0.1"], + ), + "windows-msvc": dict( + deps = [":winapi-util-0.1"], + ), + }, visibility = [], ) -rust_library( - name = "unicode-ident-1.0.6", - srcs = [ - "vendor/unicode-ident-1.0.6/src/lib.rs", - "vendor/unicode-ident-1.0.6/src/tables.rs", - ], +http_archive( + name = "unicode-ident-1.0.24.crate", + sha256 = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75", + strip_prefix = "unicode-ident-1.0.24", + urls = ["https://static.crates.io/crates/unicode-ident/1.0.24/download"], + visibility = [], +) + +cargo.rust_library( + name = "unicode-ident-1", + srcs = [":unicode-ident-1.0.24.crate"], crate = "unicode_ident", - crate_root = "vendor/unicode-ident-1.0.6/src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], + crate_root = "unicode-ident-1.0.24.crate/src/lib.rs", + edition = "2021", visibility = [], ) -rust_library( - 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", - ], +http_archive( + name = "unicode-width-0.2.2.crate", + sha256 = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254", + strip_prefix = "unicode-width-0.2.2", + urls = ["https://static.crates.io/crates/unicode-width/0.2.2/download"], + visibility = [], +) + +cargo.rust_library( + name = "unicode-width-0.2", + srcs = [":unicode-width-0.2.2.crate"], crate = "unicode_width", - crate_root = "vendor/unicode-width-0.1.10/src/lib.rs", - edition = "2015", - features = ["default"], - rustc_flags = ["--cap-lints=allow"], + crate_root = "unicode-width-0.2.2.crate/src/lib.rs", + edition = "2021", + features = [ + "cjk", + "default", + ], + visibility = [], +) + +http_archive( + name = "winapi-util-0.1.11.crate", + sha256 = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22", + strip_prefix = "winapi-util-0.1.11", + urls = ["https://static.crates.io/crates/winapi-util/0.1.11/download"], + visibility = [], +) + +cargo.rust_library( + name = "winapi-util-0.1", + srcs = [":winapi-util-0.1.11.crate"], + crate = "winapi_util", + crate_root = "winapi-util-0.1.11.crate/src/lib.rs", + edition = "2021", + target_compatible_with = ["prelude//os:windows"], + visibility = [], + deps = [":windows-sys-0.61"], +) + +http_archive( + name = "windows-link-0.2.1.crate", + sha256 = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5", + strip_prefix = "windows-link-0.2.1", + urls = ["https://static.crates.io/crates/windows-link/0.2.1/download"], + visibility = [], +) + +cargo.rust_library( + name = "windows-link-0.2", + srcs = [":windows-link-0.2.1.crate"], + crate = "windows_link", + crate_root = "windows-link-0.2.1.crate/src/lib.rs", + edition = "2021", + visibility = [], +) + +http_archive( + name = "windows-sys-0.61.2.crate", + sha256 = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc", + strip_prefix = "windows-sys-0.61.2", + urls = ["https://static.crates.io/crates/windows-sys/0.61.2/download"], + visibility = [], +) + +cargo.rust_library( + name = "windows-sys-0.61", + srcs = [":windows-sys-0.61.2.crate"], + crate = "windows_sys", + crate_root = "windows-sys-0.61.2.crate/src/lib.rs", + edition = "2021", + features = [ + "Win32", + "Win32_Foundation", + "Win32_Storage", + "Win32_Storage_FileSystem", + "Win32_System", + "Win32_System_Console", + "Win32_System_SystemInformation", + "default", + ], + target_compatible_with = ["prelude//os:windows"], visibility = [], + deps = [":windows-link-0.2"], ) diff --git a/third-party/BUILD b/third-party/BUILD deleted file mode 100644 index 7fc2b0f2a..000000000 --- a/third-party/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -load("@rules_rust//crate_universe:defs.bzl", "crates_vendor") - -crates_vendor( - name = "vendor", - cargo_lockfile = "//third-party:Cargo.lock", - generate_build_scripts = True, - manifests = ["//third-party:Cargo.toml"], - mode = "remote", - tags = ["manual"], - vendor_path = "bazel", -) - -[ - alias( - name = name, - actual = "//third-party/bazel:{}".format(name), - visibility = ["//visibility:public"], - ) - for name in [ - "cc", - "clap", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn", - ] -] diff --git a/third-party/BUILD.bazel b/third-party/BUILD.bazel new file mode 100644 index 000000000..e095556f9 --- /dev/null +++ b/third-party/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_rust//crate_universe:defs.bzl", "crates_vendor") + +crates_vendor( + name = "vendor", + cargo_lockfile = "//third-party:Cargo.lock", + generate_build_scripts = True, + manifests = ["//third-party:Cargo.toml"], + mode = "remote", + tags = ["manual"], + vendor_path = "bazel", +) diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock index 6a6be41f8..d03db159f 100644 --- a/third-party/Cargo.lock +++ b/third-party/Cargo.lock @@ -1,89 +1,164 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "bitflags" -version = "1.3.2" +name = "anstyle" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "cc" -version = "1.0.79" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] name = "clap" -version = "4.1.4" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ - "bitflags", - "clap_lex", + "clap_builder", ] [[package]] -name = "clap_lex" -version = "0.3.1" +name = "clap_builder" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ - "os_str_bytes", + "anstyle", + "clap_lex", ] +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + [[package]] name = "codespan-reporting" -version = "0.11.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ + "serde", "termcolor", "unicode-width", ] [[package]] -name = "once_cell" -version = "1.17.0" +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "find-msvc-tools" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de" + +[[package]] +name = "foldhash" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] -name = "os_str_bytes" -version = "6.4.1" +name = "hashbrown" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + [[package]] name = "scratch" -version = "1.0.3" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" +checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2" + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "syn" -version = "1.0.107" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" dependencies = [ "proc-macro2", "quote", @@ -92,9 +167,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -106,52 +181,48 @@ dependencies = [ "cc", "clap", "codespan-reporting", - "once_cell", + "foldhash", + "indexmap", "proc-macro2", "quote", + "rustversion", "scratch", + "serde", "syn", ] [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] -name = "winapi" -version = "0.3.9" +name = "winapi-util" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-sys", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "winapi-util" -version = "0.1.5" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "winapi", + "windows-link", ] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/third-party/Cargo.toml b/third-party/Cargo.toml index 84657de58..20cafdfc8 100644 --- a/third-party/Cargo.toml +++ b/third-party/Cargo.toml @@ -2,17 +2,19 @@ [package] name = "third-party" version = "0.0.0" +edition = "2024" publish = false - -[lib] -path = "/dev/null" +rust-version = "1.88" [dependencies] -cc = "1.0.49" +cc = "1.0.101" 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"] } +codespan-reporting = "0.13.1" +foldhash = "0.2" +indexmap = "2.9.0" +proc-macro2 = { version = "1.0.58", features = ["span-locations"] } quote = "1.0.4" +rustversion = "1" scratch = "1" -syn = { version = "1.0.95", features = ["full"] } +serde = { version = "1", features = ["derive"] } +syn = { version = "3", features = ["full"] } diff --git a/third-party/bazel/BUILD.anstyle-1.0.14.bazel b/third-party/bazel/BUILD.anstyle-1.0.14.bazel new file mode 100644 index 000000000..7d2decd4b --- /dev/null +++ b/third-party/bazel/BUILD.anstyle-1.0.14.bazel @@ -0,0 +1,114 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "anstyle", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "std", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=anstyle", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.14", +) diff --git a/third-party/bazel/BUILD.bazel b/third-party/bazel/BUILD.bazel index 244795bc4..dedcb7e6e 100644 --- a/third-party/bazel/BUILD.bazel +++ b/third-party/bazel/BUILD.bazel @@ -3,7 +3,7 @@ # DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To # regenerate this file, run the following: # -# bazel run @//third-party:vendor +# bazel run @@//third-party:vendor ############################################################################### package(default_visibility = ["//visibility:public"]) @@ -13,62 +13,152 @@ exports_files( "cargo-bazel.json", "crates.bzl", "defs.bzl", - ] + glob(["*.bazel"]), + ] + glob( + include = ["*.bazel"], + allow_empty = True, + ), ) filegroup( name = "srcs", - srcs = glob([ - "*.bazel", - "*.bzl", - ]), + srcs = glob( + include = [ + "*.bazel", + "*.bzl", + ], + allow_empty = True, + ), ) # Workspace Member Dependencies +alias( + name = "cc-1.4.2", + actual = "@vendor__cc-1.4.2//:cc", + tags = ["manual"], +) + alias( name = "cc", - actual = "@vendor__cc-1.0.79//:cc", + actual = "@vendor__cc-1.4.2//:cc", + tags = ["manual"], +) + +alias( + name = "clap-4.6.6", + actual = "@vendor__clap-4.6.6//:clap", tags = ["manual"], ) alias( name = "clap", - actual = "@vendor__clap-4.1.4//:clap", + actual = "@vendor__clap-4.6.6//:clap", + tags = ["manual"], +) + +alias( + name = "codespan-reporting-0.13.1", + actual = "@vendor__codespan-reporting-0.13.1//:codespan_reporting", tags = ["manual"], ) alias( name = "codespan-reporting", - actual = "@vendor__codespan-reporting-0.11.1//:codespan_reporting", + actual = "@vendor__codespan-reporting-0.13.1//:codespan_reporting", + tags = ["manual"], +) + +alias( + name = "foldhash-0.2.0", + actual = "@vendor__foldhash-0.2.0//:foldhash", + tags = ["manual"], +) + +alias( + name = "foldhash", + actual = "@vendor__foldhash-0.2.0//:foldhash", + tags = ["manual"], +) + +alias( + name = "indexmap-2.14.0", + actual = "@vendor__indexmap-2.14.0//:indexmap", + tags = ["manual"], +) + +alias( + name = "indexmap", + actual = "@vendor__indexmap-2.14.0//:indexmap", tags = ["manual"], ) alias( - name = "once_cell", - actual = "@vendor__once_cell-1.17.0//:once_cell", + name = "proc-macro2-1.0.107", + actual = "@vendor__proc-macro2-1.0.107//:proc_macro2", tags = ["manual"], ) alias( name = "proc-macro2", - actual = "@vendor__proc-macro2-1.0.51//:proc_macro2", + actual = "@vendor__proc-macro2-1.0.107//:proc_macro2", + tags = ["manual"], +) + +alias( + name = "quote-1.0.47", + actual = "@vendor__quote-1.0.47//:quote", tags = ["manual"], ) alias( name = "quote", - actual = "@vendor__quote-1.0.23//:quote", + actual = "@vendor__quote-1.0.47//:quote", + tags = ["manual"], +) + +alias( + name = "rustversion-1.0.23", + actual = "@vendor__rustversion-1.0.23//:rustversion", + tags = ["manual"], +) + +alias( + name = "rustversion", + actual = "@vendor__rustversion-1.0.23//:rustversion", + tags = ["manual"], +) + +alias( + name = "scratch-1.0.9", + actual = "@vendor__scratch-1.0.9//:scratch", tags = ["manual"], ) alias( name = "scratch", - actual = "@vendor__scratch-1.0.3//:scratch", + actual = "@vendor__scratch-1.0.9//:scratch", + tags = ["manual"], +) + +alias( + name = "serde-1.0.229", + actual = "@vendor__serde-1.0.229//:serde", + tags = ["manual"], +) + +alias( + name = "serde", + actual = "@vendor__serde-1.0.229//:serde", + tags = ["manual"], +) + +alias( + name = "syn-3.0.3", + actual = "@vendor__syn-3.0.3//:syn", tags = ["manual"], ) alias( name = "syn", - actual = "@vendor__syn-1.0.107//:syn", + actual = "@vendor__syn-3.0.3//:syn", tags = ["manual"], ) diff --git a/third-party/bazel/BUILD.bitflags-1.3.2.bazel b/third-party/bazel/BUILD.bitflags-1.3.2.bazel deleted file mode 100644 index 39360f23c..000000000 --- a/third-party/bazel/BUILD.bitflags-1.3.2.bazel +++ /dev/null @@ -1,44 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT/Apache-2.0 -# ]) - -rust_library( - name = "bitflags", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "default", - ], - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=bitflags", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.3.2", -) diff --git a/third-party/bazel/BUILD.cc-1.0.79.bazel b/third-party/bazel/BUILD.cc-1.0.79.bazel deleted file mode 100644 index 102bc5d12..000000000 --- a/third-party/bazel/BUILD.cc-1.0.79.bazel +++ /dev/null @@ -1,41 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "cc", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=cc", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.79", -) diff --git a/third-party/bazel/BUILD.cc-1.4.2.bazel b/third-party/bazel/BUILD.cc-1.4.2.bazel new file mode 100644 index 000000000..43848d8a1 --- /dev/null +++ b/third-party/bazel/BUILD.cc-1.4.2.bazel @@ -0,0 +1,114 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "cc", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=cc", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.4.2", + deps = [ + "@vendor__find-msvc-tools-0.1.10//:find_msvc_tools", + "@vendor__shlex-2.0.1//:shlex", + ], +) diff --git a/third-party/bazel/BUILD.clap-4.1.4.bazel b/third-party/bazel/BUILD.clap-4.1.4.bazel deleted file mode 100644 index 9386cfbbe..000000000 --- a/third-party/bazel/BUILD.clap-4.1.4.bazel +++ /dev/null @@ -1,51 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "clap", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "error-context", - "help", - "std", - "usage", - ], - crate_root = "src/lib.rs", - edition = "2021", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=clap", - "manual", - "noclippy", - "norustfmt", - ], - version = "4.1.4", - deps = [ - "@vendor__bitflags-1.3.2//:bitflags", - "@vendor__clap_lex-0.3.1//:clap_lex", - ], -) diff --git a/third-party/bazel/BUILD.clap-4.6.6.bazel b/third-party/bazel/BUILD.clap-4.6.6.bazel new file mode 100644 index 000000000..9ed3ab981 --- /dev/null +++ b/third-party/bazel/BUILD.clap-4.6.6.bazel @@ -0,0 +1,119 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "clap", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "error-context", + "help", + "std", + "usage", + ], + crate_root = "src/lib.rs", + edition = "2024", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=clap", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "4.6.6", + deps = [ + "@vendor__clap_builder-4.6.6//:clap_builder", + ], +) diff --git a/third-party/bazel/BUILD.clap_builder-4.6.6.bazel b/third-party/bazel/BUILD.clap_builder-4.6.6.bazel new file mode 100644 index 000000000..8e0c34dab --- /dev/null +++ b/third-party/bazel/BUILD.clap_builder-4.6.6.bazel @@ -0,0 +1,120 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "clap_builder", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "error-context", + "help", + "std", + "usage", + ], + crate_root = "src/lib.rs", + edition = "2024", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=clap_builder", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "4.6.6", + deps = [ + "@vendor__anstyle-1.0.14//:anstyle", + "@vendor__clap_lex-1.1.0//:clap_lex", + ], +) diff --git a/third-party/bazel/BUILD.clap_lex-0.3.1.bazel b/third-party/bazel/BUILD.clap_lex-0.3.1.bazel deleted file mode 100644 index fe85b7b63..000000000 --- a/third-party/bazel/BUILD.clap_lex-0.3.1.bazel +++ /dev/null @@ -1,44 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "clap_lex", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2021", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=clap_lex", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.3.1", - deps = [ - "@vendor__os_str_bytes-6.4.1//:os_str_bytes", - ], -) diff --git a/third-party/bazel/BUILD.clap_lex-1.1.0.bazel b/third-party/bazel/BUILD.clap_lex-1.1.0.bazel new file mode 100644 index 000000000..3f5dcca9b --- /dev/null +++ b/third-party/bazel/BUILD.clap_lex-1.1.0.bazel @@ -0,0 +1,110 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "clap_lex", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2024", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=clap_lex", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.1.0", +) diff --git a/third-party/bazel/BUILD.codespan-reporting-0.11.1.bazel b/third-party/bazel/BUILD.codespan-reporting-0.11.1.bazel deleted file mode 100644 index a75a13690..000000000 --- a/third-party/bazel/BUILD.codespan-reporting-0.11.1.bazel +++ /dev/null @@ -1,45 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # Apache-2.0 -# ]) - -rust_library( - name = "codespan_reporting", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=codespan-reporting", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.11.1", - deps = [ - "@vendor__termcolor-1.2.0//:termcolor", - "@vendor__unicode-width-0.1.10//:unicode_width", - ], -) diff --git a/third-party/bazel/BUILD.codespan-reporting-0.13.1.bazel b/third-party/bazel/BUILD.codespan-reporting-0.13.1.bazel new file mode 100644 index 000000000..ebacd825a --- /dev/null +++ b/third-party/bazel/BUILD.codespan-reporting-0.13.1.bazel @@ -0,0 +1,119 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "codespan_reporting", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "std", + "termcolor", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=codespan-reporting", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.13.1", + deps = [ + "@vendor__termcolor-1.4.1//:termcolor", + "@vendor__unicode-width-0.2.2//:unicode_width", + ], +) diff --git a/third-party/bazel/BUILD.equivalent-1.0.2.bazel b/third-party/bazel/BUILD.equivalent-1.0.2.bazel new file mode 100644 index 000000000..45ae27495 --- /dev/null +++ b/third-party/bazel/BUILD.equivalent-1.0.2.bazel @@ -0,0 +1,110 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "equivalent", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2015", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=equivalent", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.2", +) diff --git a/third-party/bazel/BUILD.find-msvc-tools-0.1.10.bazel b/third-party/bazel/BUILD.find-msvc-tools-0.1.10.bazel new file mode 100644 index 000000000..41cd92d8b --- /dev/null +++ b/third-party/bazel/BUILD.find-msvc-tools-0.1.10.bazel @@ -0,0 +1,110 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "find_msvc_tools", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=find-msvc-tools", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.1.10", +) diff --git a/third-party/bazel/BUILD.foldhash-0.2.0.bazel b/third-party/bazel/BUILD.foldhash-0.2.0.bazel new file mode 100644 index 000000000..ac344701e --- /dev/null +++ b/third-party/bazel/BUILD.foldhash-0.2.0.bazel @@ -0,0 +1,114 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "foldhash", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "std", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=foldhash", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.2.0", +) diff --git a/third-party/bazel/BUILD.hashbrown-0.17.1.bazel b/third-party/bazel/BUILD.hashbrown-0.17.1.bazel new file mode 100644 index 000000000..6b7fe065c --- /dev/null +++ b/third-party/bazel/BUILD.hashbrown-0.17.1.bazel @@ -0,0 +1,110 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "hashbrown", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2024", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=hashbrown", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.17.1", +) diff --git a/third-party/bazel/BUILD.indexmap-2.14.0.bazel b/third-party/bazel/BUILD.indexmap-2.14.0.bazel new file mode 100644 index 000000000..e1083b75d --- /dev/null +++ b/third-party/bazel/BUILD.indexmap-2.14.0.bazel @@ -0,0 +1,118 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "indexmap", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "std", + ], + crate_root = "src/lib.rs", + edition = "2024", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=indexmap", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "2.14.0", + deps = [ + "@vendor__equivalent-1.0.2//:equivalent", + "@vendor__hashbrown-0.17.1//:hashbrown", + ], +) diff --git a/third-party/bazel/BUILD.once_cell-1.17.0.bazel b/third-party/bazel/BUILD.once_cell-1.17.0.bazel deleted file mode 100644 index 8636f3b6b..000000000 --- a/third-party/bazel/BUILD.once_cell-1.17.0.bazel +++ /dev/null @@ -1,47 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "once_cell", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "alloc", - "default", - "race", - "std", - ], - crate_root = "src/lib.rs", - edition = "2021", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=once_cell", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.17.0", -) diff --git a/third-party/bazel/BUILD.os_str_bytes-6.4.1.bazel b/third-party/bazel/BUILD.os_str_bytes-6.4.1.bazel deleted file mode 100644 index 2510ac168..000000000 --- a/third-party/bazel/BUILD.os_str_bytes-6.4.1.bazel +++ /dev/null @@ -1,44 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "os_str_bytes", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "raw_os_str", - ], - crate_root = "src/lib.rs", - edition = "2021", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=os_str_bytes", - "manual", - "noclippy", - "norustfmt", - ], - version = "6.4.1", -) diff --git a/third-party/bazel/BUILD.proc-macro2-1.0.107.bazel b/third-party/bazel/BUILD.proc-macro2-1.0.107.bazel new file mode 100644 index 000000000..0b81b13b7 --- /dev/null +++ b/third-party/bazel/BUILD.proc-macro2-1.0.107.bazel @@ -0,0 +1,190 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "proc_macro2", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "proc-macro", + "span-locations", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=proc-macro2", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.107", + deps = [ + ":build_script_build", + "@vendor__unicode-ident-1.0.24//:unicode_ident", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + build_script_env_files = [ + ":cargo_toml_env_vars", + ], + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "proc-macro", + "span-locations", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2021", + emit_warnings = False, + pkg_name = "proc-macro2", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=proc-macro2", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.107", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/third-party/bazel/BUILD.proc-macro2-1.0.51.bazel b/third-party/bazel/BUILD.proc-macro2-1.0.51.bazel deleted file mode 100644 index 0ec6426f4..000000000 --- a/third-party/bazel/BUILD.proc-macro2-1.0.51.bazel +++ /dev/null @@ -1,92 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//cargo:defs.bzl", "cargo_build_script") -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "proc_macro2", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "default", - "proc-macro", - "span-locations", - ], - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=proc-macro2", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.51", - deps = [ - "@vendor__proc-macro2-1.0.51//:build_script_build", - "@vendor__unicode-ident-1.0.6//:unicode_ident", - ], -) - -cargo_build_script( - name = "proc-macro2_build_script", - srcs = glob(["**/*.rs"]), - crate_features = [ - "default", - "proc-macro", - "span-locations", - ], - crate_name = "build_script_build", - crate_root = "build.rs", - data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - edition = "2018", - rustc_flags = [ - "--cap-lints=allow", - ], - tags = [ - "cargo-bazel", - "crate-name=proc-macro2", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.51", - visibility = ["//visibility:private"], -) - -alias( - name = "build_script_build", - actual = "proc-macro2_build_script", - tags = ["manual"], -) diff --git a/third-party/bazel/BUILD.quote-1.0.23.bazel b/third-party/bazel/BUILD.quote-1.0.23.bazel deleted file mode 100644 index 133fdc92d..000000000 --- a/third-party/bazel/BUILD.quote-1.0.23.bazel +++ /dev/null @@ -1,90 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//cargo:defs.bzl", "cargo_build_script") -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "quote", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "default", - "proc-macro", - ], - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=quote", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.23", - deps = [ - "@vendor__proc-macro2-1.0.51//:proc_macro2", - "@vendor__quote-1.0.23//:build_script_build", - ], -) - -cargo_build_script( - name = "quote_build_script", - srcs = glob(["**/*.rs"]), - crate_features = [ - "default", - "proc-macro", - ], - crate_name = "build_script_build", - crate_root = "build.rs", - data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - edition = "2018", - rustc_flags = [ - "--cap-lints=allow", - ], - tags = [ - "cargo-bazel", - "crate-name=quote", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.23", - visibility = ["//visibility:private"], -) - -alias( - name = "build_script_build", - actual = "quote_build_script", - tags = ["manual"], -) diff --git a/third-party/bazel/BUILD.quote-1.0.47.bazel b/third-party/bazel/BUILD.quote-1.0.47.bazel new file mode 100644 index 000000000..4c2aae63c --- /dev/null +++ b/third-party/bazel/BUILD.quote-1.0.47.bazel @@ -0,0 +1,188 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "quote", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "proc-macro", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=quote", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.47", + deps = [ + ":build_script_build", + "@vendor__proc-macro2-1.0.107//:proc_macro2", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + build_script_env_files = [ + ":cargo_toml_env_vars", + ], + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "proc-macro", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2021", + emit_warnings = False, + pkg_name = "quote", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=quote", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.47", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/third-party/bazel/BUILD.rustversion-1.0.23.bazel b/third-party/bazel/BUILD.rustversion-1.0.23.bazel new file mode 100644 index 000000000..48b4e8cbd --- /dev/null +++ b/third-party/bazel/BUILD.rustversion-1.0.23.bazel @@ -0,0 +1,179 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_proc_macro") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_proc_macro( + name = "rustversion", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2018", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=rustversion", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.23", + deps = [ + ":build_script_build", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + build_script_env_files = [ + ":cargo_toml_env_vars", + ], + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_name = "build_script_build", + crate_root = "build/build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2018", + emit_warnings = False, + pkg_name = "rustversion", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=rustversion", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.23", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/third-party/bazel/BUILD.scratch-1.0.3.bazel b/third-party/bazel/BUILD.scratch-1.0.3.bazel deleted file mode 100644 index 56b0365cd..000000000 --- a/third-party/bazel/BUILD.scratch-1.0.3.bazel +++ /dev/null @@ -1,81 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//cargo:defs.bzl", "cargo_build_script") -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "scratch", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2015", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=scratch", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.3", - deps = [ - "@vendor__scratch-1.0.3//:build_script_build", - ], -) - -cargo_build_script( - name = "scratch_build_script", - srcs = glob(["**/*.rs"]), - crate_name = "build_script_build", - crate_root = "build.rs", - data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - edition = "2015", - rustc_flags = [ - "--cap-lints=allow", - ], - tags = [ - "cargo-bazel", - "crate-name=scratch", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.3", - visibility = ["//visibility:private"], -) - -alias( - name = "build_script_build", - actual = "scratch_build_script", - tags = ["manual"], -) diff --git a/third-party/bazel/BUILD.scratch-1.0.9.bazel b/third-party/bazel/BUILD.scratch-1.0.9.bazel new file mode 100644 index 000000000..27874e5eb --- /dev/null +++ b/third-party/bazel/BUILD.scratch-1.0.9.bazel @@ -0,0 +1,179 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "scratch", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2015", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=scratch", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.9", + deps = [ + ":build_script_build", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + build_script_env_files = [ + ":cargo_toml_env_vars", + ], + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2015", + emit_warnings = False, + pkg_name = "scratch", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=scratch", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.9", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/third-party/bazel/BUILD.serde-1.0.229.bazel b/third-party/bazel/BUILD.serde-1.0.229.bazel new file mode 100644 index 000000000..a009a5eac --- /dev/null +++ b/third-party/bazel/BUILD.serde-1.0.229.bazel @@ -0,0 +1,195 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "serde", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "derive", + "serde_derive", + "std", + ], + crate_root = "src/lib.rs", + edition = "2021", + proc_macro_deps = [ + "@vendor__serde_derive-1.0.229//:serde_derive", + ], + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.229", + deps = [ + ":build_script_build", + "@vendor__serde_core-1.0.229//:serde_core", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + build_script_env_files = [ + ":cargo_toml_env_vars", + ], + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "derive", + "serde_derive", + "std", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2021", + emit_warnings = False, + pkg_name = "serde", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.229", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/third-party/bazel/BUILD.serde_core-1.0.229.bazel b/third-party/bazel/BUILD.serde_core-1.0.229.bazel new file mode 100644 index 000000000..8459fd29d --- /dev/null +++ b/third-party/bazel/BUILD.serde_core-1.0.229.bazel @@ -0,0 +1,187 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "serde_core", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "result", + "std", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde_core", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.229", + deps = [ + ":build_script_build", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + build_script_env_files = [ + ":cargo_toml_env_vars", + ], + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "result", + "std", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2021", + emit_warnings = False, + pkg_name = "serde_core", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde_core", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.229", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/third-party/bazel/BUILD.serde_derive-1.0.229.bazel b/third-party/bazel/BUILD.serde_derive-1.0.229.bazel new file mode 100644 index 000000000..12905b16e --- /dev/null +++ b/third-party/bazel/BUILD.serde_derive-1.0.229.bazel @@ -0,0 +1,118 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_proc_macro") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_proc_macro( + name = "serde_derive", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde_derive", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.229", + deps = [ + "@vendor__proc-macro2-1.0.107//:proc_macro2", + "@vendor__quote-1.0.47//:quote", + "@vendor__syn-3.0.3//:syn", + ], +) diff --git a/third-party/bazel/BUILD.shlex-2.0.1.bazel b/third-party/bazel/BUILD.shlex-2.0.1.bazel new file mode 100644 index 000000000..6692f6c09 --- /dev/null +++ b/third-party/bazel/BUILD.shlex-2.0.1.bazel @@ -0,0 +1,114 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "shlex", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "std", + ], + crate_root = "src/lib.rs", + edition = "2018", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=shlex", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "2.0.1", +) diff --git a/third-party/bazel/BUILD.syn-1.0.107.bazel b/third-party/bazel/BUILD.syn-1.0.107.bazel deleted file mode 100644 index 1eb43c28c..000000000 --- a/third-party/bazel/BUILD.syn-1.0.107.bazel +++ /dev/null @@ -1,104 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//cargo:defs.bzl", "cargo_build_script") -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT OR Apache-2.0 -# ]) - -rust_library( - name = "syn", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "clone-impls", - "default", - "derive", - "full", - "parsing", - "printing", - "proc-macro", - "quote", - ], - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=syn", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.107", - deps = [ - "@vendor__proc-macro2-1.0.51//:proc_macro2", - "@vendor__quote-1.0.23//:quote", - "@vendor__syn-1.0.107//:build_script_build", - "@vendor__unicode-ident-1.0.6//:unicode_ident", - ], -) - -cargo_build_script( - name = "syn_build_script", - srcs = glob(["**/*.rs"]), - crate_features = [ - "clone-impls", - "default", - "derive", - "full", - "parsing", - "printing", - "proc-macro", - "quote", - ], - crate_name = "build_script_build", - crate_root = "build.rs", - data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - edition = "2018", - rustc_flags = [ - "--cap-lints=allow", - ], - tags = [ - "cargo-bazel", - "crate-name=syn", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.107", - visibility = ["//visibility:private"], -) - -alias( - name = "build_script_build", - actual = "syn_build_script", - tags = ["manual"], -) diff --git a/third-party/bazel/BUILD.syn-3.0.3.bazel b/third-party/bazel/BUILD.syn-3.0.3.bazel new file mode 100644 index 000000000..b10ac66bc --- /dev/null +++ b/third-party/bazel/BUILD.syn-3.0.3.bazel @@ -0,0 +1,124 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "syn", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "clone-impls", + "default", + "derive", + "full", + "parsing", + "printing", + "proc-macro", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=syn", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "3.0.3", + deps = [ + "@vendor__proc-macro2-1.0.107//:proc_macro2", + "@vendor__quote-1.0.47//:quote", + "@vendor__unicode-ident-1.0.24//:unicode_ident", + ], +) diff --git a/third-party/bazel/BUILD.termcolor-1.2.0.bazel b/third-party/bazel/BUILD.termcolor-1.2.0.bazel deleted file mode 100644 index fa7481ea0..000000000 --- a/third-party/bazel/BUILD.termcolor-1.2.0.bazel +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # Unlicense OR MIT -# ]) - -rust_library( - name = "termcolor", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=termcolor", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.2.0", - deps = select({ - "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [ - "@vendor__winapi-util-0.1.5//:winapi_util", # cfg(windows) - ], - "@rules_rust//rust/platform:i686-pc-windows-msvc": [ - "@vendor__winapi-util-0.1.5//:winapi_util", # cfg(windows) - ], - "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [ - "@vendor__winapi-util-0.1.5//:winapi_util", # cfg(windows) - ], - "//conditions:default": [], - }), -) diff --git a/third-party/bazel/BUILD.termcolor-1.4.1.bazel b/third-party/bazel/BUILD.termcolor-1.4.1.bazel new file mode 100644 index 000000000..1b6f39ad7 --- /dev/null +++ b/third-party/bazel/BUILD.termcolor-1.4.1.bazel @@ -0,0 +1,122 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "termcolor", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2018", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=termcolor", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.4.1", + deps = select({ + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [ + "@vendor__winapi-util-0.1.11//:winapi_util", # cfg(windows) + ], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [ + "@vendor__winapi-util-0.1.11//:winapi_util", # cfg(windows) + ], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [ + "@vendor__winapi-util-0.1.11//:winapi_util", # cfg(windows) + ], + "//conditions:default": [], + }), +) diff --git a/third-party/bazel/BUILD.unicode-ident-1.0.24.bazel b/third-party/bazel/BUILD.unicode-ident-1.0.24.bazel new file mode 100644 index 000000000..86f873377 --- /dev/null +++ b/third-party/bazel/BUILD.unicode-ident-1.0.24.bazel @@ -0,0 +1,110 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "unicode_ident", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=unicode-ident", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.24", +) diff --git a/third-party/bazel/BUILD.unicode-ident-1.0.6.bazel b/third-party/bazel/BUILD.unicode-ident-1.0.6.bazel deleted file mode 100644 index 5347f03e8..000000000 --- a/third-party/bazel/BUILD.unicode-ident-1.0.6.bazel +++ /dev/null @@ -1,41 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # (MIT OR Apache-2.0) AND Unicode-DFS-2016 -# ]) - -rust_library( - name = "unicode_ident", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=unicode-ident", - "manual", - "noclippy", - "norustfmt", - ], - version = "1.0.6", -) diff --git a/third-party/bazel/BUILD.unicode-width-0.1.10.bazel b/third-party/bazel/BUILD.unicode-width-0.1.10.bazel deleted file mode 100644 index 103a2036f..000000000 --- a/third-party/bazel/BUILD.unicode-width-0.1.10.bazel +++ /dev/null @@ -1,44 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT/Apache-2.0 -# ]) - -rust_library( - name = "unicode_width", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "default", - ], - crate_root = "src/lib.rs", - edition = "2015", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=unicode-width", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.1.10", -) diff --git a/third-party/bazel/BUILD.unicode-width-0.2.2.bazel b/third-party/bazel/BUILD.unicode-width-0.2.2.bazel new file mode 100644 index 000000000..a21c7ad62 --- /dev/null +++ b/third-party/bazel/BUILD.unicode-width-0.2.2.bazel @@ -0,0 +1,114 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "unicode_width", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "cjk", + "default", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=unicode-width", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.2.2", +) diff --git a/third-party/bazel/BUILD.winapi-0.3.9.bazel b/third-party/bazel/BUILD.winapi-0.3.9.bazel deleted file mode 100644 index 7af60b17b..000000000 --- a/third-party/bazel/BUILD.winapi-0.3.9.bazel +++ /dev/null @@ -1,105 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//cargo:defs.bzl", "cargo_build_script") -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT/Apache-2.0 -# ]) - -rust_library( - name = "winapi", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_features = [ - "consoleapi", - "errhandlingapi", - "fileapi", - "minwindef", - "processenv", - "std", - "winbase", - "wincon", - "winerror", - "winnt", - ], - crate_root = "src/lib.rs", - edition = "2015", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=winapi", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.3.9", - deps = [ - "@vendor__winapi-0.3.9//:build_script_build", - ], -) - -cargo_build_script( - name = "winapi_build_script", - srcs = glob(["**/*.rs"]), - crate_features = [ - "consoleapi", - "errhandlingapi", - "fileapi", - "minwindef", - "processenv", - "std", - "winbase", - "wincon", - "winerror", - "winnt", - ], - crate_name = "build_script_build", - crate_root = "build.rs", - data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - edition = "2015", - rustc_flags = [ - "--cap-lints=allow", - ], - tags = [ - "cargo-bazel", - "crate-name=winapi", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.3.9", - visibility = ["//visibility:private"], -) - -alias( - name = "build_script_build", - actual = "winapi_build_script", - tags = ["manual"], -) diff --git a/third-party/bazel/BUILD.winapi-i686-pc-windows-gnu-0.4.0.bazel b/third-party/bazel/BUILD.winapi-i686-pc-windows-gnu-0.4.0.bazel deleted file mode 100644 index ae3de3147..000000000 --- a/third-party/bazel/BUILD.winapi-i686-pc-windows-gnu-0.4.0.bazel +++ /dev/null @@ -1,81 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//cargo:defs.bzl", "cargo_build_script") -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT/Apache-2.0 -# ]) - -rust_library( - name = "winapi_i686_pc_windows_gnu", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2015", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=winapi-i686-pc-windows-gnu", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.4.0", - deps = [ - "@vendor__winapi-i686-pc-windows-gnu-0.4.0//:build_script_build", - ], -) - -cargo_build_script( - name = "winapi-i686-pc-windows-gnu_build_script", - srcs = glob(["**/*.rs"]), - crate_name = "build_script_build", - crate_root = "build.rs", - data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - edition = "2015", - rustc_flags = [ - "--cap-lints=allow", - ], - tags = [ - "cargo-bazel", - "crate-name=winapi-i686-pc-windows-gnu", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.4.0", - visibility = ["//visibility:private"], -) - -alias( - name = "build_script_build", - actual = "winapi-i686-pc-windows-gnu_build_script", - tags = ["manual"], -) diff --git a/third-party/bazel/BUILD.winapi-util-0.1.11.bazel b/third-party/bazel/BUILD.winapi-util-0.1.11.bazel new file mode 100644 index 000000000..d4cf25395 --- /dev/null +++ b/third-party/bazel/BUILD.winapi-util-0.1.11.bazel @@ -0,0 +1,122 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "winapi_util", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=winapi-util", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.1.11", + deps = select({ + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [ + "@vendor__windows-sys-0.61.2//:windows_sys", # cfg(windows) + ], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [ + "@vendor__windows-sys-0.61.2//:windows_sys", # cfg(windows) + ], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [ + "@vendor__windows-sys-0.61.2//:windows_sys", # cfg(windows) + ], + "//conditions:default": [], + }), +) diff --git a/third-party/bazel/BUILD.winapi-util-0.1.5.bazel b/third-party/bazel/BUILD.winapi-util-0.1.5.bazel deleted file mode 100644 index 6ca7e9a74..000000000 --- a/third-party/bazel/BUILD.winapi-util-0.1.5.bazel +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # Unlicense/MIT -# ]) - -rust_library( - name = "winapi_util", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2018", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=winapi-util", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.1.5", - deps = select({ - "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [ - "@vendor__winapi-0.3.9//:winapi", # cfg(windows) - ], - "@rules_rust//rust/platform:i686-pc-windows-msvc": [ - "@vendor__winapi-0.3.9//:winapi", # cfg(windows) - ], - "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [ - "@vendor__winapi-0.3.9//:winapi", # cfg(windows) - ], - "//conditions:default": [], - }), -) diff --git a/third-party/bazel/BUILD.winapi-x86_64-pc-windows-gnu-0.4.0.bazel b/third-party/bazel/BUILD.winapi-x86_64-pc-windows-gnu-0.4.0.bazel deleted file mode 100644 index c145846bb..000000000 --- a/third-party/bazel/BUILD.winapi-x86_64-pc-windows-gnu-0.4.0.bazel +++ /dev/null @@ -1,81 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @//third-party:vendor -############################################################################### - -load("@rules_rust//cargo:defs.bzl", "cargo_build_script") -load("@rules_rust//rust:defs.bzl", "rust_library") - -package(default_visibility = ["//visibility:public"]) - -# licenses([ -# "TODO", # MIT/Apache-2.0 -# ]) - -rust_library( - name = "winapi_x86_64_pc_windows_gnu", - srcs = glob(["**/*.rs"]), - compile_data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - crate_root = "src/lib.rs", - edition = "2015", - rustc_flags = ["--cap-lints=allow"], - tags = [ - "cargo-bazel", - "crate-name=winapi-x86_64-pc-windows-gnu", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.4.0", - deps = [ - "@vendor__winapi-x86_64-pc-windows-gnu-0.4.0//:build_script_build", - ], -) - -cargo_build_script( - name = "winapi-x86_64-pc-windows-gnu_build_script", - srcs = glob(["**/*.rs"]), - crate_name = "build_script_build", - crate_root = "build.rs", - data = glob( - include = ["**"], - exclude = [ - "**/* *", - "BUILD", - "BUILD.bazel", - "WORKSPACE", - "WORKSPACE.bazel", - ], - ), - edition = "2015", - rustc_flags = [ - "--cap-lints=allow", - ], - tags = [ - "cargo-bazel", - "crate-name=winapi-x86_64-pc-windows-gnu", - "manual", - "noclippy", - "norustfmt", - ], - version = "0.4.0", - visibility = ["//visibility:private"], -) - -alias( - name = "build_script_build", - actual = "winapi-x86_64-pc-windows-gnu_build_script", - tags = ["manual"], -) diff --git a/third-party/bazel/BUILD.windows-link-0.2.1.bazel b/third-party/bazel/BUILD.windows-link-0.2.1.bazel new file mode 100644 index 000000000..01ebdf7ee --- /dev/null +++ b/third-party/bazel/BUILD.windows-link-0.2.1.bazel @@ -0,0 +1,110 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "windows_link", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=windows-link", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.2.1", +) diff --git a/third-party/bazel/BUILD.windows-sys-0.61.2.bazel b/third-party/bazel/BUILD.windows-sys-0.61.2.bazel new file mode 100644 index 000000000..9008b0e84 --- /dev/null +++ b/third-party/bazel/BUILD.windows-sys-0.61.2.bazel @@ -0,0 +1,123 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "windows_sys", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "Win32", + "Win32_Foundation", + "Win32_Storage", + "Win32_Storage_FileSystem", + "Win32_System", + "Win32_System_Console", + "Win32_System_SystemInformation", + "default", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=windows-sys", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-macabi": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-none": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:arm-unknown-linux-musleabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:loongarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:mips-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imac-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:sparc64-unknown-netbsd": [], + "@rules_rust//rust/platform:sparc64-unknown-openbsd": [], + "@rules_rust//rust/platform:thumbv6m-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv7em-none-eabihf": [], + "@rules_rust//rust/platform:thumbv7m-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabihf": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-apple-ios-macabi": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.61.2", + deps = [ + "@vendor__windows-link-0.2.1//:windows_link", + ], +) diff --git a/third-party/bazel/alias_rules.bzl b/third-party/bazel/alias_rules.bzl new file mode 100644 index 000000000..14b04c127 --- /dev/null +++ b/third-party/bazel/alias_rules.bzl @@ -0,0 +1,47 @@ +"""Alias that transitions its target to `compilation_mode=opt`. Use `transition_alias="opt"` to enable.""" + +load("@rules_cc//cc:defs.bzl", "CcInfo") +load("@rules_rust//rust:rust_common.bzl", "COMMON_PROVIDERS") + +def _transition_alias_impl(ctx): + # `ctx.attr.actual` is a list of 1 item due to the transition + providers = [ctx.attr.actual[0][provider] for provider in COMMON_PROVIDERS] + if CcInfo in ctx.attr.actual[0]: + providers.append(ctx.attr.actual[0][CcInfo]) + return providers + +def _change_compilation_mode(compilation_mode): + def _change_compilation_mode_impl(_settings, _attr): + return { + "//command_line_option:compilation_mode": compilation_mode, + } + + return transition( + implementation = _change_compilation_mode_impl, + inputs = [], + outputs = [ + "//command_line_option:compilation_mode", + ], + ) + +def _transition_alias_rule(compilation_mode): + return rule( + implementation = _transition_alias_impl, + provides = COMMON_PROVIDERS, + attrs = { + "actual": attr.label( + mandatory = True, + doc = "`rust_library()` target to transition to `compilation_mode=opt`.", + providers = COMMON_PROVIDERS, + cfg = _change_compilation_mode(compilation_mode), + ), + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + }, + doc = "Transitions a Rust library crate to the `compilation_mode=opt`.", + ) + +transition_alias_dbg = _transition_alias_rule("dbg") +transition_alias_fastbuild = _transition_alias_rule("fastbuild") +transition_alias_opt = _transition_alias_rule("opt") diff --git a/third-party/bazel/cc-1.4.2/BUILD.bazel b/third-party/bazel/cc-1.4.2/BUILD.bazel new file mode 100644 index 000000000..e66508506 --- /dev/null +++ b/third-party/bazel/cc-1.4.2/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "cc-1.4.2", + actual = "@vendor__cc-1.4.2//:cc", + tags = ["manual"], +) diff --git a/third-party/bazel/cc/BUILD.bazel b/third-party/bazel/cc/BUILD.bazel new file mode 100644 index 000000000..dfbbf3a2c --- /dev/null +++ b/third-party/bazel/cc/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "cc", + actual = "@vendor__cc-1.4.2//:cc", + tags = ["manual"], +) diff --git a/third-party/bazel/clap-4.6.6/BUILD.bazel b/third-party/bazel/clap-4.6.6/BUILD.bazel new file mode 100644 index 000000000..1583387d9 --- /dev/null +++ b/third-party/bazel/clap-4.6.6/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "clap-4.6.6", + actual = "@vendor__clap-4.6.6//:clap", + tags = ["manual"], +) diff --git a/third-party/bazel/clap/BUILD.bazel b/third-party/bazel/clap/BUILD.bazel new file mode 100644 index 000000000..5a046535f --- /dev/null +++ b/third-party/bazel/clap/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "clap", + actual = "@vendor__clap-4.6.6//:clap", + tags = ["manual"], +) diff --git a/third-party/bazel/codespan-reporting-0.13.1/BUILD.bazel b/third-party/bazel/codespan-reporting-0.13.1/BUILD.bazel new file mode 100644 index 000000000..6febde893 --- /dev/null +++ b/third-party/bazel/codespan-reporting-0.13.1/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "codespan-reporting-0.13.1", + actual = "@vendor__codespan-reporting-0.13.1//:codespan_reporting", + tags = ["manual"], +) diff --git a/third-party/bazel/codespan-reporting/BUILD.bazel b/third-party/bazel/codespan-reporting/BUILD.bazel new file mode 100644 index 000000000..6d9ac27d3 --- /dev/null +++ b/third-party/bazel/codespan-reporting/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "codespan-reporting", + actual = "@vendor__codespan-reporting-0.13.1//:codespan_reporting", + tags = ["manual"], +) diff --git a/third-party/bazel/crates.bzl b/third-party/bazel/crates.bzl index 6d61f64a5..5002dc9f8 100644 --- a/third-party/bazel/crates.bzl +++ b/third-party/bazel/crates.bzl @@ -1,25 +1,743 @@ ############################################################################### # @generated -# This file is auto-generated by the cargo-bazel tool. +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: # -# DO NOT MODIFY: Local changes may be replaced in future executions. +# bazel run @@//third-party:vendor ############################################################################### -"""Rules for defining repositories for remote `crates_vendor` repositories""" +""" +# `crates_repository` API +- [aliases](#aliases) +- [crate_edition](#crate_edition) +- [crate_deps](#crate_deps) +- [all_crate_deps](#all_crate_deps) +- [crate_repositories](#crate_repositories) + +""" + +load("@bazel_skylib//lib:selects.bzl", "selects") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +load("@rules_rust//crate_universe:defs.bzl", "crates_vendor_remote_repository") + +############################################################################### +# MACROS API +############################################################################### + +# An identifier that represent common dependencies (unconditional). +_COMMON_CONDITION = "" + +def _flatten_dependency_maps(all_dependency_maps): + """Flatten a list of dependency maps into one dictionary. + + Dependency maps have the following structure: + + ```python + DEPENDENCIES_MAP = { + # The first key in the map is a Bazel package + # name of the workspace this file is defined in. + "workspace_member_package": { + + # Not all dependencies are supported for all platforms. + # the condition key is the condition required to be true + # on the host platform. + "condition": { + + # An alias to a crate target. # The label of the crate target the + # Aliases are only crate names. # package name refers to. + "package_name": "@full//:label", + } + } + } + ``` + + Args: + all_dependency_maps (list): A list of dicts as described above + + Returns: + dict: A dictionary as described above + """ + dependencies = {} + + for workspace_deps_map in all_dependency_maps: + for pkg_name, conditional_deps_map in workspace_deps_map.items(): + if pkg_name not in dependencies: + non_frozen_map = dict() + for key, values in conditional_deps_map.items(): + non_frozen_map.update({key: dict(values.items())}) + dependencies.setdefault(pkg_name, non_frozen_map) + continue + + for condition, deps_map in conditional_deps_map.items(): + # If the condition has not been recorded, do so and continue + if condition not in dependencies[pkg_name]: + dependencies[pkg_name].setdefault(condition, dict(deps_map.items())) + continue + + # Alert on any miss-matched dependencies + inconsistent_entries = [] + for crate_name, crate_label in deps_map.items(): + existing = dependencies[pkg_name][condition].get(crate_name) + if existing and existing != crate_label: + inconsistent_entries.append((crate_name, existing, crate_label)) + dependencies[pkg_name][condition].update({crate_name: crate_label}) + + return dependencies + +def crate_deps(deps, package_name = None): + """Finds the fully qualified label of the requested crates for the package where this macro is called. + + Args: + deps (list): The desired list of crate targets. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()`. + + Returns: + list: A list of labels to generated rust targets (str) + """ + + if not deps: + return [] + + if package_name == None: + package_name = native.package_name() + + # Join both sets of dependencies + dependencies = _flatten_dependency_maps([ + _NORMAL_DEPENDENCIES, + _NORMAL_DEV_DEPENDENCIES, + _PROC_MACRO_DEPENDENCIES, + _PROC_MACRO_DEV_DEPENDENCIES, + _BUILD_DEPENDENCIES, + _BUILD_PROC_MACRO_DEPENDENCIES, + ]).pop(package_name, {}) + + # Combine all conditional packages so we can easily index over a flat list + # TODO: Perhaps this should actually return select statements and maintain + # the conditionals of the dependencies + flat_deps = {} + for deps_set in dependencies.values(): + for crate_name, crate_label in deps_set.items(): + flat_deps.update({crate_name: crate_label}) + + missing_crates = [] + crate_targets = [] + for crate_target in deps: + if crate_target not in flat_deps: + missing_crates.append(crate_target) + else: + crate_targets.append(flat_deps[crate_target]) + + if missing_crates: + fail("Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`".format( + missing_crates, + package_name, + dependencies, + )) + + return crate_targets + +def crate_edition(package_name = None): + """Finds the Rust edition for the package where this macro is called. + + Args: + package_name (str, optional): The package name whose edition should be + looked up. Defaults to `native.package_name()` when unset. + + Returns: + str: The Rust edition declared by the package's Cargo.toml file. + """ + if package_name == None: + package_name = native.package_name() + + if package_name not in _CRATE_EDITIONS: + fail("Tried to get crate_edition for package " + package_name + " but that package had no Cargo.toml file") + + return _CRATE_EDITIONS[package_name] + +def all_crate_deps( + normal = False, + normal_dev = False, + proc_macro = False, + proc_macro_dev = False, + build = False, + build_proc_macro = False, + package_name = None): + """Finds the fully qualified label of all requested direct crate dependencies \ + for the package where this macro is called. + + If no parameters are set, all normal dependencies are returned. Setting any one flag will + otherwise impact the contents of the returned list. + + Args: + normal (bool, optional): If True, normal dependencies are included in the + output list. + normal_dev (bool, optional): If True, normal dev dependencies will be + included in the output list. + proc_macro (bool, optional): If True, proc_macro dependencies are included + in the output list. + proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are + included in the output list. + build (bool, optional): If True, build dependencies are included + in the output list. + build_proc_macro (bool, optional): If True, build proc_macro dependencies are + included in the output list. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()` when unset. + + Returns: + list: A list of labels to generated rust targets (str) + """ + + if package_name == None: + package_name = native.package_name() + + # Determine the relevant maps to use + all_dependency_maps = [] + if normal: + all_dependency_maps.append(_NORMAL_DEPENDENCIES) + if normal_dev: + all_dependency_maps.append(_NORMAL_DEV_DEPENDENCIES) + if proc_macro: + all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES) + if proc_macro_dev: + all_dependency_maps.append(_PROC_MACRO_DEV_DEPENDENCIES) + if build: + all_dependency_maps.append(_BUILD_DEPENDENCIES) + if build_proc_macro: + all_dependency_maps.append(_BUILD_PROC_MACRO_DEPENDENCIES) -# buildifier: disable=bzl-visibility -load("@cxx.rs//third-party/bazel:defs.bzl", _crate_repositories = "crate_repositories") + # Default to always using normal dependencies + if not all_dependency_maps: + all_dependency_maps.append(_NORMAL_DEPENDENCIES) -# buildifier: disable=bzl-visibility -load("@rules_rust//crate_universe/private:crates_vendor.bzl", "crates_vendor_remote_repository") + dependencies = _flatten_dependency_maps(all_dependency_maps).pop(package_name, None) + + if not dependencies: + if dependencies == None: + fail("Tried to get all_crate_deps for package " + package_name + " but that package had no Cargo.toml file") + else: + return [] + + crate_deps = list(dependencies.pop(_COMMON_CONDITION, {}).values()) + for condition, deps in dependencies.items(): + crate_deps += selects.with_or({ + tuple(_CONDITIONS[condition]): deps.values(), + "//conditions:default": [], + }) + + return crate_deps + +def aliases( + normal = False, + normal_dev = False, + proc_macro = False, + proc_macro_dev = False, + build = False, + build_proc_macro = False, + package_name = None): + """Produces a map of Crate alias names to their original label + + If no dependency kinds are specified, `normal` and `proc_macro` are used by default. + Setting any one flag will otherwise determine the contents of the returned dict. + + Args: + normal (bool, optional): If True, normal dependencies are included in the + output list. + normal_dev (bool, optional): If True, normal dev dependencies will be + included in the output list.. + proc_macro (bool, optional): If True, proc_macro dependencies are included + in the output list. + proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are + included in the output list. + build (bool, optional): If True, build dependencies are included + in the output list. + build_proc_macro (bool, optional): If True, build proc_macro dependencies are + included in the output list. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()` when unset. + + Returns: + dict: The aliases of all associated packages + """ + if package_name == None: + package_name = native.package_name() + + # Determine the relevant maps to use + all_aliases_maps = [] + if normal: + all_aliases_maps.append(_NORMAL_ALIASES) + if normal_dev: + all_aliases_maps.append(_NORMAL_DEV_ALIASES) + if proc_macro: + all_aliases_maps.append(_PROC_MACRO_ALIASES) + if proc_macro_dev: + all_aliases_maps.append(_PROC_MACRO_DEV_ALIASES) + if build: + all_aliases_maps.append(_BUILD_ALIASES) + if build_proc_macro: + all_aliases_maps.append(_BUILD_PROC_MACRO_ALIASES) + + # Default to always using normal aliases + if not all_aliases_maps: + all_aliases_maps.append(_NORMAL_ALIASES) + all_aliases_maps.append(_PROC_MACRO_ALIASES) + + aliases = _flatten_dependency_maps(all_aliases_maps).pop(package_name, None) + + if not aliases: + return dict() + + common_items = aliases.pop(_COMMON_CONDITION, {}).items() + + # If there are only common items in the dictionary, immediately return them + if not len(aliases.keys()) == 1: + return dict(common_items) + + # Build a single select statement where each conditional has accounted for the + # common set of aliases. + crate_aliases = {"//conditions:default": dict(common_items)} + for condition, deps in aliases.items(): + condition_triples = _CONDITIONS[condition] + for triple in condition_triples: + if triple in crate_aliases: + crate_aliases[triple].update(deps) + else: + crate_aliases.update({triple: dict(deps.items() + common_items)}) + + return select(crate_aliases) + +############################################################################### +# WORKSPACE MEMBER DEPS, ALIASES, AND EDITIONS +############################################################################### + +_CRATE_EDITIONS = { + "third-party": "2024", +} + +_NORMAL_DEPENDENCIES = { + "third-party": { + _COMMON_CONDITION: { + "cc": Label("@vendor//cc-1.4.2"), + "clap": Label("@vendor//clap-4.6.6"), + "codespan-reporting": Label("@vendor//codespan-reporting-0.13.1"), + "foldhash": Label("@vendor//foldhash-0.2.0"), + "indexmap": Label("@vendor//indexmap-2.14.0"), + "proc-macro2": Label("@vendor//proc-macro2-1.0.107"), + "quote": Label("@vendor//quote-1.0.47"), + "scratch": Label("@vendor//scratch-1.0.9"), + "serde": Label("@vendor//serde-1.0.229"), + "syn": Label("@vendor//syn-3.0.3"), + }, + }, +} + +_NORMAL_ALIASES = { + "third-party": { + _COMMON_CONDITION: { + }, + }, +} + +_NORMAL_DEV_DEPENDENCIES = { + "third-party": { + }, +} + +_NORMAL_DEV_ALIASES = { + "third-party": { + }, +} + +_PROC_MACRO_DEPENDENCIES = { + "third-party": { + _COMMON_CONDITION: { + "rustversion": Label("@vendor//rustversion-1.0.23"), + }, + }, +} + +_PROC_MACRO_ALIASES = { + "third-party": { + }, +} + +_PROC_MACRO_DEV_DEPENDENCIES = { + "third-party": { + }, +} + +_PROC_MACRO_DEV_ALIASES = { + "third-party": { + }, +} + +_BUILD_DEPENDENCIES = { + "third-party": { + }, +} + +_BUILD_ALIASES = { + "third-party": { + }, +} + +_BUILD_PROC_MACRO_DEPENDENCIES = { + "third-party": { + }, +} + +_BUILD_PROC_MACRO_ALIASES = { + "third-party": { + }, +} + +_CONDITIONS = { + "aarch64-apple-darwin": ["@rules_rust//rust/platform:aarch64-apple-darwin"], + "aarch64-apple-ios": ["@rules_rust//rust/platform:aarch64-apple-ios"], + "aarch64-apple-ios-macabi": ["@rules_rust//rust/platform:aarch64-apple-ios-macabi"], + "aarch64-apple-ios-sim": ["@rules_rust//rust/platform:aarch64-apple-ios-sim"], + "aarch64-linux-android": ["@rules_rust//rust/platform:aarch64-linux-android"], + "aarch64-pc-windows-msvc": ["@rules_rust//rust/platform:aarch64-pc-windows-msvc"], + "aarch64-unknown-fuchsia": ["@rules_rust//rust/platform:aarch64-unknown-fuchsia"], + "aarch64-unknown-linux-gnu": ["@rules_rust//rust/platform:aarch64-unknown-linux-gnu"], + "aarch64-unknown-nixos-gnu": ["@rules_rust//rust/platform:aarch64-unknown-nixos-gnu"], + "aarch64-unknown-none": ["@rules_rust//rust/platform:aarch64-unknown-none"], + "aarch64-unknown-nto-qnx710": ["@rules_rust//rust/platform:aarch64-unknown-nto-qnx710"], + "aarch64-unknown-uefi": ["@rules_rust//rust/platform:aarch64-unknown-uefi"], + "arm-unknown-linux-gnueabi": ["@rules_rust//rust/platform:arm-unknown-linux-gnueabi"], + "arm-unknown-linux-musleabi": ["@rules_rust//rust/platform:arm-unknown-linux-musleabi"], + "armv7-linux-androideabi": ["@rules_rust//rust/platform:armv7-linux-androideabi"], + "armv7-unknown-linux-gnueabi": ["@rules_rust//rust/platform:armv7-unknown-linux-gnueabi"], + "cfg(any())": [], + "cfg(windows)": ["@rules_rust//rust/platform:aarch64-pc-windows-msvc", "@rules_rust//rust/platform:i686-pc-windows-msvc", "@rules_rust//rust/platform:x86_64-pc-windows-msvc"], + "i686-apple-darwin": ["@rules_rust//rust/platform:i686-apple-darwin"], + "i686-linux-android": ["@rules_rust//rust/platform:i686-linux-android"], + "i686-pc-windows-msvc": ["@rules_rust//rust/platform:i686-pc-windows-msvc"], + "i686-unknown-freebsd": ["@rules_rust//rust/platform:i686-unknown-freebsd"], + "i686-unknown-linux-gnu": ["@rules_rust//rust/platform:i686-unknown-linux-gnu"], + "loongarch64-unknown-linux-gnu": ["@rules_rust//rust/platform:loongarch64-unknown-linux-gnu"], + "mips-unknown-linux-gnu": ["@rules_rust//rust/platform:mips-unknown-linux-gnu"], + "powerpc-unknown-linux-gnu": ["@rules_rust//rust/platform:powerpc-unknown-linux-gnu"], + "riscv32imac-unknown-none-elf": ["@rules_rust//rust/platform:riscv32imac-unknown-none-elf"], + "riscv32imc-unknown-none-elf": ["@rules_rust//rust/platform:riscv32imc-unknown-none-elf"], + "riscv64gc-unknown-linux-gnu": ["@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu"], + "riscv64gc-unknown-none-elf": ["@rules_rust//rust/platform:riscv64gc-unknown-none-elf"], + "s390x-unknown-linux-gnu": ["@rules_rust//rust/platform:s390x-unknown-linux-gnu"], + "sparc64-unknown-linux-gnu": ["@rules_rust//rust/platform:sparc64-unknown-linux-gnu"], + "sparc64-unknown-netbsd": ["@rules_rust//rust/platform:sparc64-unknown-netbsd"], + "sparc64-unknown-openbsd": ["@rules_rust//rust/platform:sparc64-unknown-openbsd"], + "thumbv6m-none-eabi": ["@rules_rust//rust/platform:thumbv6m-none-eabi"], + "thumbv7em-none-eabi": ["@rules_rust//rust/platform:thumbv7em-none-eabi"], + "thumbv7em-none-eabihf": ["@rules_rust//rust/platform:thumbv7em-none-eabihf"], + "thumbv7m-none-eabi": ["@rules_rust//rust/platform:thumbv7m-none-eabi"], + "thumbv8m.main-none-eabi": ["@rules_rust//rust/platform:thumbv8m.main-none-eabi"], + "thumbv8m.main-none-eabihf": ["@rules_rust//rust/platform:thumbv8m.main-none-eabihf"], + "wasm32-unknown-emscripten": ["@rules_rust//rust/platform:wasm32-unknown-emscripten"], + "wasm32-unknown-unknown": ["@rules_rust//rust/platform:wasm32-unknown-unknown"], + "wasm32-wasip1": ["@rules_rust//rust/platform:wasm32-wasip1"], + "wasm32-wasip1-threads": ["@rules_rust//rust/platform:wasm32-wasip1-threads"], + "wasm32-wasip2": ["@rules_rust//rust/platform:wasm32-wasip2"], + "x86_64-apple-darwin": ["@rules_rust//rust/platform:x86_64-apple-darwin"], + "x86_64-apple-ios": ["@rules_rust//rust/platform:x86_64-apple-ios"], + "x86_64-apple-ios-macabi": ["@rules_rust//rust/platform:x86_64-apple-ios-macabi"], + "x86_64-linux-android": ["@rules_rust//rust/platform:x86_64-linux-android"], + "x86_64-pc-windows-msvc": ["@rules_rust//rust/platform:x86_64-pc-windows-msvc"], + "x86_64-unknown-freebsd": ["@rules_rust//rust/platform:x86_64-unknown-freebsd"], + "x86_64-unknown-fuchsia": ["@rules_rust//rust/platform:x86_64-unknown-fuchsia"], + "x86_64-unknown-linux-gnu": ["@rules_rust//rust/platform:x86_64-unknown-linux-gnu"], + "x86_64-unknown-nixos-gnu": ["@rules_rust//rust/platform:x86_64-unknown-nixos-gnu"], + "x86_64-unknown-none": ["@rules_rust//rust/platform:x86_64-unknown-none"], + "x86_64-unknown-uefi": ["@rules_rust//rust/platform:x86_64-unknown-uefi"], +} + +############################################################################### def crate_repositories(): + """A macro for defining repositories for all generated crates. + + Returns: + A list of repos visible to the module through the module extension. + """ maybe( crates_vendor_remote_repository, name = "vendor", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.bazel"), - defs_module = Label("@cxx.rs//third-party/bazel:defs.bzl"), + # Lean interface: just point at `crates.bzl`; the repo rule + # derives the sibling `BUILD.bazel` and `defs.bzl`. + crates_module = Label("//third-party/bazel:crates.bzl"), + ) + maybe( + http_archive, + name = "vendor__anstyle-1.0.14", + sha256 = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000", + type = "tar.gz", + urls = ["https://static.crates.io/crates/anstyle/1.0.14/download"], + strip_prefix = "anstyle-1.0.14", + build_file = Label("//third-party/bazel:BUILD.anstyle-1.0.14.bazel"), + ) + + maybe( + http_archive, + name = "vendor__cc-1.4.2", + sha256 = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e", + type = "tar.gz", + urls = ["https://static.crates.io/crates/cc/1.4.2/download"], + strip_prefix = "cc-1.4.2", + build_file = Label("//third-party/bazel:BUILD.cc-1.4.2.bazel"), + ) + + maybe( + http_archive, + name = "vendor__clap-4.6.6", + sha256 = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca", + type = "tar.gz", + urls = ["https://static.crates.io/crates/clap/4.6.6/download"], + strip_prefix = "clap-4.6.6", + build_file = Label("//third-party/bazel:BUILD.clap-4.6.6.bazel"), + ) + + maybe( + http_archive, + name = "vendor__clap_builder-4.6.6", + sha256 = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889", + type = "tar.gz", + urls = ["https://static.crates.io/crates/clap_builder/4.6.6/download"], + strip_prefix = "clap_builder-4.6.6", + build_file = Label("//third-party/bazel:BUILD.clap_builder-4.6.6.bazel"), + ) + + maybe( + http_archive, + name = "vendor__clap_lex-1.1.0", + sha256 = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9", + type = "tar.gz", + urls = ["https://static.crates.io/crates/clap_lex/1.1.0/download"], + strip_prefix = "clap_lex-1.1.0", + build_file = Label("//third-party/bazel:BUILD.clap_lex-1.1.0.bazel"), + ) + + maybe( + http_archive, + name = "vendor__codespan-reporting-0.13.1", + sha256 = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681", + type = "tar.gz", + urls = ["https://static.crates.io/crates/codespan-reporting/0.13.1/download"], + strip_prefix = "codespan-reporting-0.13.1", + build_file = Label("//third-party/bazel:BUILD.codespan-reporting-0.13.1.bazel"), + ) + + maybe( + http_archive, + name = "vendor__equivalent-1.0.2", + sha256 = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f", + type = "tar.gz", + urls = ["https://static.crates.io/crates/equivalent/1.0.2/download"], + strip_prefix = "equivalent-1.0.2", + build_file = Label("//third-party/bazel:BUILD.equivalent-1.0.2.bazel"), + ) + + maybe( + http_archive, + name = "vendor__find-msvc-tools-0.1.10", + sha256 = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de", + type = "tar.gz", + urls = ["https://static.crates.io/crates/find-msvc-tools/0.1.10/download"], + strip_prefix = "find-msvc-tools-0.1.10", + build_file = Label("//third-party/bazel:BUILD.find-msvc-tools-0.1.10.bazel"), + ) + + maybe( + http_archive, + name = "vendor__foldhash-0.2.0", + sha256 = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb", + type = "tar.gz", + urls = ["https://static.crates.io/crates/foldhash/0.2.0/download"], + strip_prefix = "foldhash-0.2.0", + build_file = Label("//third-party/bazel:BUILD.foldhash-0.2.0.bazel"), + ) + + maybe( + http_archive, + name = "vendor__hashbrown-0.17.1", + sha256 = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a", + type = "tar.gz", + urls = ["https://static.crates.io/crates/hashbrown/0.17.1/download"], + strip_prefix = "hashbrown-0.17.1", + build_file = Label("//third-party/bazel:BUILD.hashbrown-0.17.1.bazel"), + ) + + maybe( + http_archive, + name = "vendor__indexmap-2.14.0", + sha256 = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9", + type = "tar.gz", + urls = ["https://static.crates.io/crates/indexmap/2.14.0/download"], + strip_prefix = "indexmap-2.14.0", + build_file = Label("//third-party/bazel:BUILD.indexmap-2.14.0.bazel"), + ) + + maybe( + http_archive, + name = "vendor__proc-macro2-1.0.107", + sha256 = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9", + type = "tar.gz", + urls = ["https://static.crates.io/crates/proc-macro2/1.0.107/download"], + strip_prefix = "proc-macro2-1.0.107", + build_file = Label("//third-party/bazel:BUILD.proc-macro2-1.0.107.bazel"), + ) + + maybe( + http_archive, + name = "vendor__quote-1.0.47", + sha256 = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001", + type = "tar.gz", + urls = ["https://static.crates.io/crates/quote/1.0.47/download"], + strip_prefix = "quote-1.0.47", + build_file = Label("//third-party/bazel:BUILD.quote-1.0.47.bazel"), + ) + + maybe( + http_archive, + name = "vendor__rustversion-1.0.23", + sha256 = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f", + type = "tar.gz", + urls = ["https://static.crates.io/crates/rustversion/1.0.23/download"], + strip_prefix = "rustversion-1.0.23", + build_file = Label("//third-party/bazel:BUILD.rustversion-1.0.23.bazel"), + ) + + maybe( + http_archive, + name = "vendor__scratch-1.0.9", + sha256 = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2", + type = "tar.gz", + urls = ["https://static.crates.io/crates/scratch/1.0.9/download"], + strip_prefix = "scratch-1.0.9", + build_file = Label("//third-party/bazel:BUILD.scratch-1.0.9.bazel"), + ) + + maybe( + http_archive, + name = "vendor__serde-1.0.229", + sha256 = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba", + type = "tar.gz", + urls = ["https://static.crates.io/crates/serde/1.0.229/download"], + strip_prefix = "serde-1.0.229", + build_file = Label("//third-party/bazel:BUILD.serde-1.0.229.bazel"), + ) + + maybe( + http_archive, + name = "vendor__serde_core-1.0.229", + sha256 = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48", + type = "tar.gz", + urls = ["https://static.crates.io/crates/serde_core/1.0.229/download"], + strip_prefix = "serde_core-1.0.229", + build_file = Label("//third-party/bazel:BUILD.serde_core-1.0.229.bazel"), + ) + + maybe( + http_archive, + name = "vendor__serde_derive-1.0.229", + sha256 = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348", + type = "tar.gz", + urls = ["https://static.crates.io/crates/serde_derive/1.0.229/download"], + strip_prefix = "serde_derive-1.0.229", + build_file = Label("//third-party/bazel:BUILD.serde_derive-1.0.229.bazel"), + ) + + maybe( + http_archive, + name = "vendor__shlex-2.0.1", + sha256 = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba", + type = "tar.gz", + urls = ["https://static.crates.io/crates/shlex/2.0.1/download"], + strip_prefix = "shlex-2.0.1", + build_file = Label("//third-party/bazel:BUILD.shlex-2.0.1.bazel"), + ) + + maybe( + http_archive, + name = "vendor__syn-3.0.3", + sha256 = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3", + type = "tar.gz", + urls = ["https://static.crates.io/crates/syn/3.0.3/download"], + strip_prefix = "syn-3.0.3", + build_file = Label("//third-party/bazel:BUILD.syn-3.0.3.bazel"), + ) + + maybe( + http_archive, + name = "vendor__termcolor-1.4.1", + sha256 = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755", + type = "tar.gz", + urls = ["https://static.crates.io/crates/termcolor/1.4.1/download"], + strip_prefix = "termcolor-1.4.1", + build_file = Label("//third-party/bazel:BUILD.termcolor-1.4.1.bazel"), + ) + + maybe( + http_archive, + name = "vendor__unicode-ident-1.0.24", + sha256 = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75", + type = "tar.gz", + urls = ["https://static.crates.io/crates/unicode-ident/1.0.24/download"], + strip_prefix = "unicode-ident-1.0.24", + build_file = Label("//third-party/bazel:BUILD.unicode-ident-1.0.24.bazel"), + ) + + maybe( + http_archive, + name = "vendor__unicode-width-0.2.2", + sha256 = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254", + type = "tar.gz", + urls = ["https://static.crates.io/crates/unicode-width/0.2.2/download"], + strip_prefix = "unicode-width-0.2.2", + build_file = Label("//third-party/bazel:BUILD.unicode-width-0.2.2.bazel"), + ) + + maybe( + http_archive, + name = "vendor__winapi-util-0.1.11", + sha256 = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22", + type = "tar.gz", + urls = ["https://static.crates.io/crates/winapi-util/0.1.11/download"], + strip_prefix = "winapi-util-0.1.11", + build_file = Label("//third-party/bazel:BUILD.winapi-util-0.1.11.bazel"), + ) + + maybe( + http_archive, + name = "vendor__windows-link-0.2.1", + sha256 = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5", + type = "tar.gz", + urls = ["https://static.crates.io/crates/windows-link/0.2.1/download"], + strip_prefix = "windows-link-0.2.1", + build_file = Label("//third-party/bazel:BUILD.windows-link-0.2.1.bazel"), + ) + + maybe( + http_archive, + name = "vendor__windows-sys-0.61.2", + sha256 = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc", + type = "tar.gz", + urls = ["https://static.crates.io/crates/windows-sys/0.61.2/download"], + strip_prefix = "windows-sys-0.61.2", + build_file = Label("//third-party/bazel:BUILD.windows-sys-0.61.2.bazel"), ) - _crate_repositories() + return [ + struct(repo = "vendor", is_dev_dep = False), + struct(repo = "vendor__cc-1.4.2", is_dev_dep = False), + struct(repo = "vendor__clap-4.6.6", is_dev_dep = False), + struct(repo = "vendor__codespan-reporting-0.13.1", is_dev_dep = False), + struct(repo = "vendor__foldhash-0.2.0", is_dev_dep = False), + struct(repo = "vendor__indexmap-2.14.0", is_dev_dep = False), + struct(repo = "vendor__proc-macro2-1.0.107", is_dev_dep = False), + struct(repo = "vendor__quote-1.0.47", is_dev_dep = False), + struct(repo = "vendor__rustversion-1.0.23", is_dev_dep = False), + struct(repo = "vendor__scratch-1.0.9", is_dev_dep = False), + struct(repo = "vendor__serde-1.0.229", is_dev_dep = False), + struct(repo = "vendor__syn-3.0.3", is_dev_dep = False), + ] diff --git a/third-party/bazel/defs.bzl b/third-party/bazel/defs.bzl index d1fa4b63f..8fb3314b2 100644 --- a/third-party/bazel/defs.bzl +++ b/third-party/bazel/defs.bzl @@ -3,549 +3,21 @@ # DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To # regenerate this file, run the following: # -# bazel run @//third-party:vendor +# bazel run @@//third-party:vendor ############################################################################### -""" -# `crates_repository` API - -- [aliases](#aliases) -- [crate_deps](#crate_deps) -- [all_crate_deps](#all_crate_deps) -- [crate_repositories](#crate_repositories) - -""" - -load("@bazel_skylib//lib:selects.bzl", "selects") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") - -############################################################################### -# MACROS API -############################################################################### - -# An identifier that represent common dependencies (unconditional). -_COMMON_CONDITION = "" - -def _flatten_dependency_maps(all_dependency_maps): - """Flatten a list of dependency maps into one dictionary. - - Dependency maps have the following structure: - - ```python - DEPENDENCIES_MAP = { - # The first key in the map is a Bazel package - # name of the workspace this file is defined in. - "workspace_member_package": { - - # Not all dependnecies are supported for all platforms. - # the condition key is the condition required to be true - # on the host platform. - "condition": { - - # An alias to a crate target. # The label of the crate target the - # Aliases are only crate names. # package name refers to. - "package_name": "@full//:label", - } - } - } - ``` - - Args: - all_dependency_maps (list): A list of dicts as described above - - Returns: - dict: A dictionary as described above - """ - dependencies = {} - - for workspace_deps_map in all_dependency_maps: - for pkg_name, conditional_deps_map in workspace_deps_map.items(): - if pkg_name not in dependencies: - non_frozen_map = dict() - for key, values in conditional_deps_map.items(): - non_frozen_map.update({key: dict(values.items())}) - dependencies.setdefault(pkg_name, non_frozen_map) - continue - - for condition, deps_map in conditional_deps_map.items(): - # If the condition has not been recorded, do so and continue - if condition not in dependencies[pkg_name]: - dependencies[pkg_name].setdefault(condition, dict(deps_map.items())) - continue - - # Alert on any miss-matched dependencies - inconsistent_entries = [] - for crate_name, crate_label in deps_map.items(): - existing = dependencies[pkg_name][condition].get(crate_name) - if existing and existing != crate_label: - inconsistent_entries.append((crate_name, existing, crate_label)) - dependencies[pkg_name][condition].update({crate_name: crate_label}) - - return dependencies - -def crate_deps(deps, package_name = None): - """Finds the fully qualified label of the requested crates for the package where this macro is called. - - Args: - deps (list): The desired list of crate targets. - package_name (str, optional): The package name of the set of dependencies to look up. - Defaults to `native.package_name()`. - - Returns: - list: A list of labels to generated rust targets (str) - """ - - if not deps: - return [] - - if package_name == None: - package_name = native.package_name() - - # Join both sets of dependencies - dependencies = _flatten_dependency_maps([ - _NORMAL_DEPENDENCIES, - _NORMAL_DEV_DEPENDENCIES, - _PROC_MACRO_DEPENDENCIES, - _PROC_MACRO_DEV_DEPENDENCIES, - _BUILD_DEPENDENCIES, - _BUILD_PROC_MACRO_DEPENDENCIES, - ]).pop(package_name, {}) - - # Combine all conditional packages so we can easily index over a flat list - # TODO: Perhaps this should actually return select statements and maintain - # the conditionals of the dependencies - flat_deps = {} - for deps_set in dependencies.values(): - for crate_name, crate_label in deps_set.items(): - flat_deps.update({crate_name: crate_label}) - - missing_crates = [] - crate_targets = [] - for crate_target in deps: - if crate_target not in flat_deps: - missing_crates.append(crate_target) - else: - crate_targets.append(flat_deps[crate_target]) - - if missing_crates: - fail("Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`".format( - missing_crates, - package_name, - dependencies, - )) - - return crate_targets - -def all_crate_deps( - normal = False, - normal_dev = False, - proc_macro = False, - proc_macro_dev = False, - build = False, - build_proc_macro = False, - package_name = None): - """Finds the fully qualified label of all requested direct crate dependencies \ - for the package where this macro is called. - - If no parameters are set, all normal dependencies are returned. Setting any one flag will - otherwise impact the contents of the returned list. - - Args: - normal (bool, optional): If True, normal dependencies are included in the - output list. - normal_dev (bool, optional): If True, normal dev dependencies will be - included in the output list.. - proc_macro (bool, optional): If True, proc_macro dependencies are included - in the output list. - proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are - included in the output list. - build (bool, optional): If True, build dependencies are included - in the output list. - build_proc_macro (bool, optional): If True, build proc_macro dependencies are - included in the output list. - package_name (str, optional): The package name of the set of dependencies to look up. - Defaults to `native.package_name()` when unset. - - Returns: - list: A list of labels to generated rust targets (str) - """ - - if package_name == None: - package_name = native.package_name() - - # Determine the relevant maps to use - all_dependency_maps = [] - if normal: - all_dependency_maps.append(_NORMAL_DEPENDENCIES) - if normal_dev: - all_dependency_maps.append(_NORMAL_DEV_DEPENDENCIES) - if proc_macro: - all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES) - if proc_macro_dev: - all_dependency_maps.append(_PROC_MACRO_DEV_DEPENDENCIES) - if build: - all_dependency_maps.append(_BUILD_DEPENDENCIES) - if build_proc_macro: - all_dependency_maps.append(_BUILD_PROC_MACRO_DEPENDENCIES) - - # Default to always using normal dependencies - if not all_dependency_maps: - all_dependency_maps.append(_NORMAL_DEPENDENCIES) - - dependencies = _flatten_dependency_maps(all_dependency_maps).pop(package_name, None) - - if not dependencies: - if dependencies == None: - fail("Tried to get all_crate_deps for package " + package_name + " but that package had no Cargo.toml file") - else: - return [] - - crate_deps = list(dependencies.pop(_COMMON_CONDITION, {}).values()) - for condition, deps in dependencies.items(): - crate_deps += selects.with_or({_CONDITIONS[condition]: deps.values()}) - - return crate_deps - -def aliases( - normal = False, - normal_dev = False, - proc_macro = False, - proc_macro_dev = False, - build = False, - build_proc_macro = False, - package_name = None): - """Produces a map of Crate alias names to their original label - - If no dependency kinds are specified, `normal` and `proc_macro` are used by default. - Setting any one flag will otherwise determine the contents of the returned dict. - - Args: - normal (bool, optional): If True, normal dependencies are included in the - output list. - normal_dev (bool, optional): If True, normal dev dependencies will be - included in the output list.. - proc_macro (bool, optional): If True, proc_macro dependencies are included - in the output list. - proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are - included in the output list. - build (bool, optional): If True, build dependencies are included - in the output list. - build_proc_macro (bool, optional): If True, build proc_macro dependencies are - included in the output list. - package_name (str, optional): The package name of the set of dependencies to look up. - Defaults to `native.package_name()` when unset. - - Returns: - dict: The aliases of all associated packages - """ - if package_name == None: - package_name = native.package_name() - - # Determine the relevant maps to use - all_aliases_maps = [] - if normal: - all_aliases_maps.append(_NORMAL_ALIASES) - if normal_dev: - all_aliases_maps.append(_NORMAL_DEV_ALIASES) - if proc_macro: - all_aliases_maps.append(_PROC_MACRO_ALIASES) - if proc_macro_dev: - all_aliases_maps.append(_PROC_MACRO_DEV_ALIASES) - if build: - all_aliases_maps.append(_BUILD_ALIASES) - if build_proc_macro: - all_aliases_maps.append(_BUILD_PROC_MACRO_ALIASES) - - # Default to always using normal aliases - if not all_aliases_maps: - all_aliases_maps.append(_NORMAL_ALIASES) - all_aliases_maps.append(_PROC_MACRO_ALIASES) - - aliases = _flatten_dependency_maps(all_aliases_maps).pop(package_name, None) - - if not aliases: - return dict() - - common_items = aliases.pop(_COMMON_CONDITION, {}).items() - - # If there are only common items in the dictionary, immediately return them - if not len(aliases.keys()) == 1: - return dict(common_items) - - # Build a single select statement where each conditional has accounted for the - # common set of aliases. - crate_aliases = {"//conditions:default": common_items} - for condition, deps in aliases.items(): - condition_triples = _CONDITIONS[condition] - if condition_triples in crate_aliases: - crate_aliases[condition_triples].update(deps) - else: - crate_aliases.update({_CONDITIONS[condition]: dict(deps.items() + common_items)}) - - return selects.with_or(crate_aliases) - -############################################################################### -# WORKSPACE MEMBER DEPS AND ALIASES -############################################################################### - -_NORMAL_DEPENDENCIES = { - "third-party": { - _COMMON_CONDITION: { - "cc": "@vendor__cc-1.0.79//:cc", - "clap": "@vendor__clap-4.1.4//:clap", - "codespan-reporting": "@vendor__codespan-reporting-0.11.1//:codespan_reporting", - "once_cell": "@vendor__once_cell-1.17.0//:once_cell", - "proc-macro2": "@vendor__proc-macro2-1.0.51//:proc_macro2", - "quote": "@vendor__quote-1.0.23//:quote", - "scratch": "@vendor__scratch-1.0.3//:scratch", - "syn": "@vendor__syn-1.0.107//:syn", - }, - }, -} - -_NORMAL_ALIASES = { - "third-party": { - _COMMON_CONDITION: { - }, - }, -} - -_NORMAL_DEV_DEPENDENCIES = { - "third-party": { - }, -} - -_NORMAL_DEV_ALIASES = { - "third-party": { - }, -} - -_PROC_MACRO_DEPENDENCIES = { - "third-party": { - }, -} - -_PROC_MACRO_ALIASES = { - "third-party": { - }, -} - -_PROC_MACRO_DEV_DEPENDENCIES = { - "third-party": { - }, -} - -_PROC_MACRO_DEV_ALIASES = { - "third-party": { - }, -} - -_BUILD_DEPENDENCIES = { - "third-party": { - }, -} - -_BUILD_ALIASES = { - "third-party": { - }, -} - -_BUILD_PROC_MACRO_DEPENDENCIES = { - "third-party": { - }, -} - -_BUILD_PROC_MACRO_ALIASES = { - "third-party": { - }, -} - -_CONDITIONS = { - "cfg(windows)": ["aarch64-pc-windows-msvc", "i686-pc-windows-msvc", "x86_64-pc-windows-msvc"], - "i686-pc-windows-gnu": [], - "x86_64-pc-windows-gnu": [], -} - -############################################################################### - -def crate_repositories(): - """A macro for defining repositories for all generated crates""" - maybe( - http_archive, - name = "vendor__bitflags-1.3.2", - sha256 = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/bitflags/1.3.2/download"], - strip_prefix = "bitflags-1.3.2", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.bitflags-1.3.2.bazel"), - ) - - maybe( - http_archive, - name = "vendor__cc-1.0.79", - sha256 = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/cc/1.0.79/download"], - strip_prefix = "cc-1.0.79", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.cc-1.0.79.bazel"), - ) - - maybe( - http_archive, - name = "vendor__clap-4.1.4", - sha256 = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/clap/4.1.4/download"], - strip_prefix = "clap-4.1.4", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.clap-4.1.4.bazel"), - ) - - maybe( - http_archive, - name = "vendor__clap_lex-0.3.1", - sha256 = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/clap_lex/0.3.1/download"], - strip_prefix = "clap_lex-0.3.1", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.clap_lex-0.3.1.bazel"), - ) - - maybe( - http_archive, - name = "vendor__codespan-reporting-0.11.1", - sha256 = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/codespan-reporting/0.11.1/download"], - strip_prefix = "codespan-reporting-0.11.1", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.codespan-reporting-0.11.1.bazel"), - ) - - maybe( - http_archive, - name = "vendor__once_cell-1.17.0", - sha256 = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/once_cell/1.17.0/download"], - strip_prefix = "once_cell-1.17.0", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.once_cell-1.17.0.bazel"), - ) - - maybe( - http_archive, - name = "vendor__os_str_bytes-6.4.1", - sha256 = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/os_str_bytes/6.4.1/download"], - strip_prefix = "os_str_bytes-6.4.1", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.os_str_bytes-6.4.1.bazel"), - ) - - maybe( - http_archive, - name = "vendor__proc-macro2-1.0.51", - sha256 = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/proc-macro2/1.0.51/download"], - strip_prefix = "proc-macro2-1.0.51", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.proc-macro2-1.0.51.bazel"), - ) - - maybe( - http_archive, - name = "vendor__quote-1.0.23", - sha256 = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/quote/1.0.23/download"], - strip_prefix = "quote-1.0.23", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.quote-1.0.23.bazel"), - ) - - maybe( - http_archive, - name = "vendor__scratch-1.0.3", - sha256 = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/scratch/1.0.3/download"], - strip_prefix = "scratch-1.0.3", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.scratch-1.0.3.bazel"), - ) - - maybe( - http_archive, - name = "vendor__syn-1.0.107", - sha256 = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/syn/1.0.107/download"], - strip_prefix = "syn-1.0.107", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.syn-1.0.107.bazel"), - ) - - maybe( - http_archive, - name = "vendor__termcolor-1.2.0", - sha256 = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/termcolor/1.2.0/download"], - strip_prefix = "termcolor-1.2.0", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.termcolor-1.2.0.bazel"), - ) - - maybe( - http_archive, - name = "vendor__unicode-ident-1.0.6", - sha256 = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/unicode-ident/1.0.6/download"], - strip_prefix = "unicode-ident-1.0.6", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.unicode-ident-1.0.6.bazel"), - ) - - maybe( - http_archive, - name = "vendor__unicode-width-0.1.10", - sha256 = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/unicode-width/0.1.10/download"], - strip_prefix = "unicode-width-0.1.10", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.unicode-width-0.1.10.bazel"), - ) - - maybe( - http_archive, - name = "vendor__winapi-0.3.9", - sha256 = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/winapi/0.3.9/download"], - strip_prefix = "winapi-0.3.9", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.winapi-0.3.9.bazel"), - ) - - maybe( - http_archive, - name = "vendor__winapi-i686-pc-windows-gnu-0.4.0", - sha256 = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/winapi-i686-pc-windows-gnu/0.4.0/download"], - strip_prefix = "winapi-i686-pc-windows-gnu-0.4.0", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.winapi-i686-pc-windows-gnu-0.4.0.bazel"), - ) - - maybe( - http_archive, - name = "vendor__winapi-util-0.1.5", - sha256 = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/winapi-util/0.1.5/download"], - strip_prefix = "winapi-util-0.1.5", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.winapi-util-0.1.5.bazel"), - ) - - maybe( - http_archive, - name = "vendor__winapi-x86_64-pc-windows-gnu-0.4.0", - sha256 = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f", - type = "tar.gz", - urls = ["https://crates.io/api/v1/crates/winapi-x86_64-pc-windows-gnu/0.4.0/download"], - strip_prefix = "winapi-x86_64-pc-windows-gnu-0.4.0", - build_file = Label("@cxx.rs//third-party/bazel:BUILD.winapi-x86_64-pc-windows-gnu-0.4.0.bazel"), - ) +"""Deprecated: re-exports the crate_universe macros from `:crates.bzl`.""" + +load( + ":crates.bzl", + _aliases = "aliases", + _all_crate_deps = "all_crate_deps", + _crate_deps = "crate_deps", + _crate_edition = "crate_edition", + _crate_repositories = "crate_repositories", +) + +aliases = _aliases +all_crate_deps = _all_crate_deps +crate_deps = _crate_deps +crate_edition = _crate_edition +crate_repositories = _crate_repositories diff --git a/third-party/bazel/foldhash-0.2.0/BUILD.bazel b/third-party/bazel/foldhash-0.2.0/BUILD.bazel new file mode 100644 index 000000000..9c6490b06 --- /dev/null +++ b/third-party/bazel/foldhash-0.2.0/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "foldhash-0.2.0", + actual = "@vendor__foldhash-0.2.0//:foldhash", + tags = ["manual"], +) diff --git a/third-party/bazel/foldhash/BUILD.bazel b/third-party/bazel/foldhash/BUILD.bazel new file mode 100644 index 000000000..b9b8f2d21 --- /dev/null +++ b/third-party/bazel/foldhash/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "foldhash", + actual = "@vendor__foldhash-0.2.0//:foldhash", + tags = ["manual"], +) diff --git a/third-party/bazel/indexmap-2.14.0/BUILD.bazel b/third-party/bazel/indexmap-2.14.0/BUILD.bazel new file mode 100644 index 000000000..f21b78668 --- /dev/null +++ b/third-party/bazel/indexmap-2.14.0/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "indexmap-2.14.0", + actual = "@vendor__indexmap-2.14.0//:indexmap", + tags = ["manual"], +) diff --git a/third-party/bazel/indexmap/BUILD.bazel b/third-party/bazel/indexmap/BUILD.bazel new file mode 100644 index 000000000..4cfe6345c --- /dev/null +++ b/third-party/bazel/indexmap/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "indexmap", + actual = "@vendor__indexmap-2.14.0//:indexmap", + tags = ["manual"], +) diff --git a/third-party/bazel/proc-macro2-1.0.107/BUILD.bazel b/third-party/bazel/proc-macro2-1.0.107/BUILD.bazel new file mode 100644 index 000000000..625f71763 --- /dev/null +++ b/third-party/bazel/proc-macro2-1.0.107/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "proc-macro2-1.0.107", + actual = "@vendor__proc-macro2-1.0.107//:proc_macro2", + tags = ["manual"], +) diff --git a/third-party/bazel/proc-macro2/BUILD.bazel b/third-party/bazel/proc-macro2/BUILD.bazel new file mode 100644 index 000000000..deca00a06 --- /dev/null +++ b/third-party/bazel/proc-macro2/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "proc-macro2", + actual = "@vendor__proc-macro2-1.0.107//:proc_macro2", + tags = ["manual"], +) diff --git a/third-party/bazel/quote-1.0.47/BUILD.bazel b/third-party/bazel/quote-1.0.47/BUILD.bazel new file mode 100644 index 000000000..25bc2e0da --- /dev/null +++ b/third-party/bazel/quote-1.0.47/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "quote-1.0.47", + actual = "@vendor__quote-1.0.47//:quote", + tags = ["manual"], +) diff --git a/third-party/bazel/quote/BUILD.bazel b/third-party/bazel/quote/BUILD.bazel new file mode 100644 index 000000000..f3af24371 --- /dev/null +++ b/third-party/bazel/quote/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "quote", + actual = "@vendor__quote-1.0.47//:quote", + tags = ["manual"], +) diff --git a/third-party/bazel/rustversion-1.0.23/BUILD.bazel b/third-party/bazel/rustversion-1.0.23/BUILD.bazel new file mode 100644 index 000000000..1525395ea --- /dev/null +++ b/third-party/bazel/rustversion-1.0.23/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "rustversion-1.0.23", + actual = "@vendor__rustversion-1.0.23//:rustversion", + tags = ["manual"], +) diff --git a/third-party/bazel/rustversion/BUILD.bazel b/third-party/bazel/rustversion/BUILD.bazel new file mode 100644 index 000000000..8a9657394 --- /dev/null +++ b/third-party/bazel/rustversion/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "rustversion", + actual = "@vendor__rustversion-1.0.23//:rustversion", + tags = ["manual"], +) diff --git a/third-party/bazel/scratch-1.0.9/BUILD.bazel b/third-party/bazel/scratch-1.0.9/BUILD.bazel new file mode 100644 index 000000000..6ffe25d28 --- /dev/null +++ b/third-party/bazel/scratch-1.0.9/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "scratch-1.0.9", + actual = "@vendor__scratch-1.0.9//:scratch", + tags = ["manual"], +) diff --git a/third-party/bazel/scratch/BUILD.bazel b/third-party/bazel/scratch/BUILD.bazel new file mode 100644 index 000000000..204b52d86 --- /dev/null +++ b/third-party/bazel/scratch/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "scratch", + actual = "@vendor__scratch-1.0.9//:scratch", + tags = ["manual"], +) diff --git a/third-party/bazel/serde-1.0.229/BUILD.bazel b/third-party/bazel/serde-1.0.229/BUILD.bazel new file mode 100644 index 000000000..6e8bc9ad7 --- /dev/null +++ b/third-party/bazel/serde-1.0.229/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "serde-1.0.229", + actual = "@vendor__serde-1.0.229//:serde", + tags = ["manual"], +) diff --git a/third-party/bazel/serde/BUILD.bazel b/third-party/bazel/serde/BUILD.bazel new file mode 100644 index 000000000..36383c7f8 --- /dev/null +++ b/third-party/bazel/serde/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "serde", + actual = "@vendor__serde-1.0.229//:serde", + tags = ["manual"], +) diff --git a/third-party/bazel/syn-3.0.3/BUILD.bazel b/third-party/bazel/syn-3.0.3/BUILD.bazel new file mode 100644 index 000000000..e9056b3f3 --- /dev/null +++ b/third-party/bazel/syn-3.0.3/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "syn-3.0.3", + actual = "@vendor__syn-3.0.3//:syn", + tags = ["manual"], +) diff --git a/third-party/bazel/syn/BUILD.bazel b/third-party/bazel/syn/BUILD.bazel new file mode 100644 index 000000000..2097a7d99 --- /dev/null +++ b/third-party/bazel/syn/BUILD.bazel @@ -0,0 +1,15 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//third-party:vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "syn", + actual = "@vendor__syn-3.0.3//:syn", + tags = ["manual"], +) diff --git a/third-party/fixups/cc/fixups.toml b/third-party/fixups/cc/fixups.toml deleted file mode 100644 index e148831c2..000000000 --- a/third-party/fixups/cc/fixups.toml +++ /dev/null @@ -1 +0,0 @@ -omit_targets = ["gcc-shim"] diff --git a/third-party/fixups/clap/fixups.toml b/third-party/fixups/clap/fixups.toml deleted file mode 100644 index 36ad30f5e..000000000 --- a/third-party/fixups/clap/fixups.toml +++ /dev/null @@ -1,2 +0,0 @@ -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 index 5e026f75e..89f3cd5db 100644 --- a/third-party/fixups/proc-macro2/fixups.toml +++ b/third-party/fixups/proc-macro2/fixups.toml @@ -1,2 +1 @@ -[[buildscript]] -[buildscript.rustc_flags] +buildscript.run = true diff --git a/third-party/fixups/quote/fixups.toml b/third-party/fixups/quote/fixups.toml index 5e026f75e..89f3cd5db 100644 --- a/third-party/fixups/quote/fixups.toml +++ b/third-party/fixups/quote/fixups.toml @@ -1,2 +1 @@ -[[buildscript]] -[buildscript.rustc_flags] +buildscript.run = true diff --git a/third-party/fixups/rustversion/fixups.toml b/third-party/fixups/rustversion/fixups.toml new file mode 100644 index 000000000..89f3cd5db --- /dev/null +++ b/third-party/fixups/rustversion/fixups.toml @@ -0,0 +1 @@ +buildscript.run = true diff --git a/third-party/fixups/scratch/fixups.toml b/third-party/fixups/scratch/fixups.toml index 72f4bdd0c..89f3cd5db 100644 --- a/third-party/fixups/scratch/fixups.toml +++ b/third-party/fixups/scratch/fixups.toml @@ -1,4 +1 @@ -buildscript = [] - -[env] -OUT_DIR = "generated" +buildscript.run = true diff --git a/third-party/fixups/serde/fixups.toml b/third-party/fixups/serde/fixups.toml new file mode 100644 index 000000000..0324ae4e5 --- /dev/null +++ b/third-party/fixups/serde/fixups.toml @@ -0,0 +1,2 @@ +buildscript.run = true +cargo_env = ["CARGO_PKG_VERSION_PATCH"] diff --git a/third-party/fixups/serde_core/fixups.toml b/third-party/fixups/serde_core/fixups.toml new file mode 100644 index 000000000..0324ae4e5 --- /dev/null +++ b/third-party/fixups/serde_core/fixups.toml @@ -0,0 +1,2 @@ +buildscript.run = true +cargo_env = ["CARGO_PKG_VERSION_PATCH"] diff --git a/third-party/fixups/serde_derive/fixups.toml b/third-party/fixups/serde_derive/fixups.toml new file mode 100644 index 000000000..aaf0dabe3 --- /dev/null +++ b/third-party/fixups/serde_derive/fixups.toml @@ -0,0 +1 @@ +cargo_env = ["CARGO_PKG_VERSION_PATCH"] diff --git a/third-party/fixups/syn/fixups.toml b/third-party/fixups/syn/fixups.toml deleted file mode 100644 index 5e026f75e..000000000 --- a/third-party/fixups/syn/fixups.toml +++ /dev/null @@ -1,2 +0,0 @@ -[[buildscript]] -[buildscript.rustc_flags] diff --git a/third-party/fixups/winapi-util/fixups.toml b/third-party/fixups/winapi-util/fixups.toml new file mode 100644 index 000000000..ab7ae28af --- /dev/null +++ b/third-party/fixups/winapi-util/fixups.toml @@ -0,0 +1 @@ +target_compatible_with = ["prelude//os:windows"] diff --git a/third-party/fixups/windows-sys/fixups.toml b/third-party/fixups/windows-sys/fixups.toml new file mode 100644 index 000000000..ab7ae28af --- /dev/null +++ b/third-party/fixups/windows-sys/fixups.toml @@ -0,0 +1 @@ +target_compatible_with = ["prelude//os:windows"] diff --git a/third-party/reindeer.toml b/third-party/reindeer.toml deleted file mode 100644 index eb65857c3..000000000 --- a/third-party/reindeer.toml +++ /dev/null @@ -1,13 +0,0 @@ -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/third-party/src/lib.rs b/third-party/src/lib.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/third-party/src/lib.rs @@ -0,0 +1 @@ + diff --git a/tools/bazel/BUILD b/tools/bazel/BUILD deleted file mode 100644 index d42fc71c8..000000000 --- a/tools/bazel/BUILD +++ /dev/null @@ -1,7 +0,0 @@ -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") - -bzl_library( - name = "bzl_srcs", - srcs = glob(["**/*.bzl"]), - visibility = ["//visibility:public"], -) diff --git a/tools/bazel/BUILD.bazel b/tools/bazel/BUILD.bazel new file mode 100644 index 000000000..2a7849f95 --- /dev/null +++ b/tools/bazel/BUILD.bazel @@ -0,0 +1,21 @@ +load("@apple_support//xcode:xcode_config.bzl", "xcode_config") +load("@apple_support//xcode:xcode_version.bzl", "xcode_version") +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +bzl_library( + name = "bzl_srcs", + srcs = glob(["**/*.bzl"]), + visibility = ["//visibility:public"], +) + +xcode_version( + name = "github_actions_xcode_26_2_0", + default_macos_sdk_version = "26.2", + version = "26.2", +) + +xcode_config( + name = "github_actions_xcodes", + default = ":github_actions_xcode_26_2_0", + versions = [":github_actions_xcode_26_2_0"], +) diff --git a/tools/bazel/extension.bzl b/tools/bazel/extension.bzl new file mode 100644 index 000000000..e74e08100 --- /dev/null +++ b/tools/bazel/extension.bzl @@ -0,0 +1,30 @@ +"""CXX bzlmod extensions""" + +load("@bazel_features//:features.bzl", "bazel_features") +load("//third-party/bazel:crates.bzl", _crate_repositories = "crate_repositories") + +def _crates_vendor_remote_repository_impl(repository_ctx): + repository_ctx.symlink(repository_ctx.attr.build_file, "BUILD.bazel") + +_crates_vendor_remote_repository = repository_rule( + implementation = _crates_vendor_remote_repository_impl, + attrs = { + "build_file": attr.label(mandatory = True), + }, +) + +def _crate_repositories_impl(module_ctx): + _crate_repositories() + _crates_vendor_remote_repository( + name = "crates.io", + build_file = "//third-party/bazel:BUILD.bazel", + ) + + metadata_kwargs = {} + if bazel_features.external_deps.extension_metadata_has_reproducible: + metadata_kwargs["reproducible"] = True + return module_ctx.extension_metadata(**metadata_kwargs) + +crate_repositories = module_extension( + implementation = _crate_repositories_impl, +) diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl index c7d07e8a1..9aa2dd546 100644 --- a/tools/bazel/rust_cxx_bridge.bzl +++ b/tools/bazel/rust_cxx_bridge.bzl @@ -1,23 +1,27 @@ -# buildifier: disable=module-docstring +"""CXX Bridge rules.""" + load("@bazel_skylib//rules:run_binary.bzl", "run_binary") load("@rules_cc//cc:defs.bzl", "cc_library") -def rust_cxx_bridge(name, src, deps = []): +def rust_cxx_bridge(name, src, deps = [], linkstatic = True, **kwargs): """A macro defining a cxx bridge library Args: name (string): The name of the new target src (string): The rust source file to generate a bridge for deps (list, optional): A list of dependencies for the underlying cc_library. Defaults to []. + **kwargs: Common arguments to pass through to underlying rules. """ native.alias( name = "%s/header" % name, actual = src + ".h", + **kwargs ) native.alias( name = "%s/source" % name, actual = src + ".cc", + **kwargs ) run_binary( @@ -28,22 +32,26 @@ def rust_cxx_bridge(name, src, deps = []): src + ".cc", ], args = [ - "$(location %s)" % src, + "$(execpath %s)" % src, "-o", - "$(location %s.h)" % src, + "$(execpath %s.h)" % src, "-o", - "$(location %s.cc)" % src, + "$(execpath %s.cc)" % src, ], tool = "@cxx.rs//:codegen", + **kwargs ) cc_library( name = name, srcs = [src + ".cc"], deps = deps + [":%s/include" % name], + linkstatic = linkstatic, + **kwargs ) cc_library( name = "%s/include" % name, hdrs = [src + ".h"], + **kwargs ) diff --git a/tools/buck/buildscript.bzl b/tools/buck/buildscript.bzl deleted file mode 100644 index e4d5e1e4e..000000000 --- a/tools/buck/buildscript.bzl +++ /dev/null @@ -1,17 +0,0 @@ -def buildscript_args( - name: str.type, - package_name: str.type, - buildscript_rule: str.type, - outfile: str.type, - version: str.type, - cfgs: [str.type] = [], - features: [str.type] = []): - _ = package_name - _ = version - _ = cfgs - _ = features - 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/prelude b/tools/buck/prelude deleted file mode 160000 index 37752b6ec..000000000 --- a/tools/buck/prelude +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 37752b6ec36a68c169053cb3f7ba359b677a22b6 diff --git a/tools/buck/rust_cxx_bridge.bzl b/tools/buck/rust_cxx_bridge.bzl index 18bb24585..1dce39505 100644 --- a/tools/buck/rust_cxx_bridge.bzl +++ b/tools/buck/rust_cxx_bridge.bzl @@ -1,23 +1,26 @@ def rust_cxx_bridge( - name: str.type, - src: str.type, - deps: [str.type] = []): - native.genrule( + name: str, + src: str, + deps: list[str] = []): + native.export_file( name = "%s/header" % name, + src = ":%s/generated[generated.h]" % name, out = src + ".h", - cmd = "cp $(location :%s/generated)/generated.h ${OUT}" % name, ) - native.genrule( + native.export_file( name = "%s/source" % name, + src = ":%s/generated[generated.cc]" % name, out = src + ".cc", - cmd = "cp $(location :%s/generated)/generated.cc ${OUT}" % name, ) native.genrule( name = "%s/generated" % name, srcs = [src], - out = ".", + outs = { + "generated.cc": ["generated.cc"], + "generated.h": ["generated.h"], + }, cmd = "$(exe //:codegen) ${SRCS} -o ${OUT}/generated.h -o ${OUT}/generated.cc", type = "cxxbridge", ) diff --git a/tools/buck/toolchains/BUCK b/tools/buck/toolchains/BUCK index 7036bc4d3..89b38ec79 100644 --- a/tools/buck/toolchains/BUCK +++ b/tools/buck/toolchains/BUCK @@ -1,9 +1,27 @@ +load("@prelude//tests:test_toolchain.bzl", "noop_test_toolchain") load("@prelude//toolchains:cxx.bzl", "system_cxx_toolchain") +load("@prelude//toolchains:genrule.bzl", "system_genrule_toolchain") load("@prelude//toolchains:python.bzl", "system_python_bootstrap_toolchain") +load("@prelude//toolchains:remote_test_execution.bzl", "remote_test_execution_toolchain") load("@prelude//toolchains:rust.bzl", "system_rust_toolchain") system_cxx_toolchain( name = "cxx", + cxx_flags = select({ + "config//os:linux": ["-std=c++17"], + "config//os:macos": ["-std=c++17"], + "config//os:windows": ["/EHsc"], + }), + link_flags = select({ + "config//os:linux": ["-lstdc++"], + "config//os:macos": ["-lc++"], + "config//os:windows": [], + }), + visibility = ["PUBLIC"], +) + +system_genrule_toolchain( + name = "genrule", visibility = ["PUBLIC"], ) @@ -15,5 +33,16 @@ system_python_bootstrap_toolchain( system_rust_toolchain( name = "rust", default_edition = None, + doctests = True, + visibility = ["PUBLIC"], +) + +noop_test_toolchain( + name = "test", + visibility = ["PUBLIC"], +) + +remote_test_execution_toolchain( + name = "remote_test_execution", visibility = ["PUBLIC"], ) diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs index 401c74186..1dd66b090 100644 --- a/tools/cargo/build.rs +++ b/tools/cargo/build.rs @@ -48,11 +48,15 @@ through crates.io. "; fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rustc-cfg=check_cfg"); + println!("cargo:rustc-check-cfg=cfg(check_cfg)"); + if Path::new("src/syntax/mod.rs").exists() { return; } - #[allow(unused_mut)] + #[cfg_attr(not(windows), expect(unused_mut))] let mut message = MISSING; #[cfg(windows)]