diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f659a1c3060c..4db0b6c6da44e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,7 @@ name: CI - try-perf - automation/bors/try - master + - solana-** pull_request: branches: - "**" @@ -42,26 +43,32 @@ jobs: CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" - SCCACHE_BUCKET: rust-lang-ci-sccache2 + SCCACHE_BUCKET: cached-ci-artifacts + SCCACHE_REGION: us-east-2 + SCCACHE_S3_NO_CREDENTIALS: 1 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" - CACHE_DOMAIN: ci-caches.rust-lang.org + CACHE_DOMAIN: cached-ci-artifacts.s3.us-east-2.amazonaws.com if: "github.event_name == 'pull_request'" continue-on-error: "${{ matrix.name == 'mingw-check-tidy' }}" strategy: matrix: include: - name: mingw-check - os: ubuntu-20.04-4core-16gb + os: ubuntu-latest env: {} - name: mingw-check-tidy - os: ubuntu-20.04-4core-16gb + os: ubuntu-latest env: {} - name: x86_64-gnu-llvm-15 env: ENABLE_GCC_CODEGEN: "1" - os: ubuntu-20.04-16core-64gb + os: ubuntu-latest + - name: sbf-solana-solana + tidy: false + os: ubuntu-latest + env: {} - name: x86_64-gnu-tools - os: ubuntu-20.04-16core-64gb + os: ubuntu-latest env: {} timeout-minutes: 600 runs-on: "${{ matrix.os }}" @@ -71,7 +78,7 @@ jobs: - name: checkout the source code uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 - name: configure the PR in which the error message will be posted run: "echo \"[CI_PR_NUMBER=$num]\"" env: @@ -85,8 +92,137 @@ jobs: - name: decide whether to skip this job run: src/ci/scripts/should-skip-this.sh if: success() && !env.SKIP_JOB - - name: ensure the channel matches the target branch - run: src/ci/scripts/verify-channel.sh + - name: collect CPU statistics + run: src/ci/scripts/collect-cpu-stats.sh + if: success() && !env.SKIP_JOB + - name: show the current environment + run: src/ci/scripts/dump-environment.sh + if: success() && !env.SKIP_JOB + - name: install awscli + run: src/ci/scripts/install-awscli.sh + if: success() && !env.SKIP_JOB + - name: install sccache + run: src/ci/scripts/install-sccache.sh + if: success() && !env.SKIP_JOB + - name: select Xcode + run: src/ci/scripts/select-xcode.sh + if: success() && !env.SKIP_JOB + - name: install clang + run: src/ci/scripts/install-clang.sh + if: success() && !env.SKIP_JOB + - name: install tidy + run: src/ci/scripts/install-tidy.sh + if: success() && !env.SKIP_JOB + - name: install WIX + run: src/ci/scripts/install-wix.sh + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + if: success() && !env.SKIP_JOB + - name: checkout submodules + run: src/ci/scripts/checkout-submodules.sh + if: success() && !env.SKIP_JOB + - name: install MSYS2 + run: src/ci/scripts/install-msys2.sh + if: success() && !env.SKIP_JOB + - name: install MinGW + run: src/ci/scripts/install-mingw.sh + if: success() && !env.SKIP_JOB + - name: install ninja + run: src/ci/scripts/install-ninja.sh + if: success() && !env.SKIP_JOB + - name: enable ipv6 on Docker + run: src/ci/scripts/enable-docker-ipv6.sh + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + if: success() && !env.SKIP_JOB + - name: ensure line endings are correct + run: src/ci/scripts/verify-line-endings.sh + if: success() && !env.SKIP_JOB + - name: ensure backported commits are in upstream branches + run: src/ci/scripts/verify-backported-commits.sh + if: success() && !env.SKIP_JOB + - name: ensure the stable version number is correct + run: src/ci/scripts/verify-stable-version-number.sh + env: + SKIP_JOB: 1 + if: success() && !env.SKIP_JOB + - name: run the build + run: src/ci/scripts/run-build-from-ci.sh + env: + AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" + TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" + if: success() && !env.SKIP_JOB + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + if: success() && !env.SKIP_JOB + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + name: "${{ env.DOC_ARTIFACT_NAME }}" + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + if: success() && !env.SKIP_JOB + - name: upload artifacts to S3 + run: src/ci/scripts/upload-artifacts.sh + env: + AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" + SKIP_JOB: 1 + if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" + push: + name: push + env: + CI_JOB_NAME: "${{ matrix.name }}" + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" + SCCACHE_BUCKET: cached-ci-artifacts + SCCACHE_REGION: us-east-2 + DEPLOY_BUCKET: rust-lang-ci2 + TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" + TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues" + TOOLSTATE_PUBLISH: 0 + CACHES_AWS_ACCESS_KEY_ID: AKIASSXOBJJGY5HRQO4U + ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 + AWS_REGION: us-west-1 + CACHE_DOMAIN: ci-caches.rust-lang.org + if: "github.event_name == 'push' && startsWith(github.ref, 'refs/heads/solana-') && github.repository == 'solana-labs/rust'" + strategy: + matrix: + include: + - name: mingw-check + os: ubuntu-latest + env: {} + - name: x86_64-gnu-llvm-12 + os: ubuntu-latest + env: {} + - name: sbf-solana-solana + os: ubuntu-latest + env: {} + timeout-minutes: 600 + runs-on: "${{ matrix.os }}" + steps: + - name: disable git crlf conversion + run: git config --global core.autocrlf false + - name: checkout the source code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: configure the PR in which the error message will be posted + run: "echo \"[CI_PR_NUMBER=$num]\"" + env: + num: "${{ github.event.number }}" + if: "success() && !env.SKIP_JOB && github.event_name == 'pull_request'" + - name: add extra environment variables + run: src/ci/scripts/setup-environment.sh + env: + EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" + if: success() && !env.SKIP_JOB + - name: decide whether to skip this job + run: src/ci/scripts/should-skip-this.sh if: success() && !env.SKIP_JOB - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh @@ -141,6 +277,8 @@ jobs: if: success() && !env.SKIP_JOB - name: ensure the stable version number is correct run: src/ci/scripts/verify-stable-version-number.sh + env: + SKIP_JOB: 1 if: success() && !env.SKIP_JOB - name: run the build run: src/ci/scripts/run-build-from-ci.sh @@ -165,6 +303,7 @@ jobs: env: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" + SKIP_JOB: 1 if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" auto: name: "auto - ${{ matrix.name }}" @@ -172,12 +311,13 @@ jobs: CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" - SCCACHE_BUCKET: rust-lang-ci-sccache2 + SCCACHE_BUCKET: cached-ci-artifacts + SCCACHE_REGION: us-east-2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL + TOOLSTATE_PUBLISH: 0 + CACHES_AWS_ACCESS_KEY_ID: AKIASSXOBJJGY5HRQO4U ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 AWS_REGION: us-west-1 CACHE_DOMAIN: ci-caches.rust-lang.org @@ -191,128 +331,128 @@ jobs: - ARM64 - linux - name: arm-android - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: armhf-gnu - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-aarch64-linux env: CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest - name: dist-android - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-arm-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-latest env: {} - name: dist-armhf-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-armv7-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-i586-gnu-i586-i686-musl - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-i686-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-loongarch64-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-powerpc-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-powerpc64-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-powerpc64le-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-riscv64-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-s390x-linux - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-various-1 - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-various-2 - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-x86_64-freebsd - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-x86_64-illumos - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: dist-x86_64-linux env: CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-16core-64gb + os: ubuntu-latest - name: dist-x86_64-linux-alt env: IMAGE: dist-x86_64-linux CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-16core-64gb + os: ubuntu-latest - name: dist-x86_64-musl env: CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest - name: dist-x86_64-netbsd - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: i686-gnu - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: i686-gnu-nopt - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: mingw-check - os: ubuntu-20.04-4core-16gb + os: ubuntu-latest env: {} - name: test-various - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: x86_64-gnu - os: ubuntu-20.04-4core-16gb + os: ubuntu-latest env: {} - name: x86_64-gnu-stable env: IMAGE: x86_64-gnu RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable CI_ONLY_WHEN_CHANNEL: nightly - os: ubuntu-20.04-4core-16gb + os: ubuntu-latest - name: x86_64-gnu-aux - os: ubuntu-20.04-4core-16gb + os: ubuntu-latest env: {} - name: x86_64-gnu-debug - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: x86_64-gnu-distcheck - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest env: {} - name: x86_64-gnu-llvm-17 env: RUST_BACKTRACE: 1 - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest - name: x86_64-gnu-llvm-16 env: RUST_BACKTRACE: 1 - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest - name: x86_64-gnu-llvm-15 env: RUST_BACKTRACE: 1 - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest - name: x86_64-gnu-nopt - os: ubuntu-20.04-4core-16gb + os: ubuntu-latest env: {} - name: x86_64-gnu-tools env: DEPLOY_TOOLSTATES_JSON: toolstates-linux.json - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest - name: dist-x86_64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin" @@ -464,7 +604,7 @@ jobs: - name: checkout the source code uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 - name: configure the PR in which the error message will be posted run: "echo \"[CI_PR_NUMBER=$num]\"" env: @@ -478,9 +618,6 @@ jobs: - name: decide whether to skip this job run: src/ci/scripts/should-skip-this.sh if: success() && !env.SKIP_JOB - - name: ensure the channel matches the target branch - run: src/ci/scripts/verify-channel.sh - if: success() && !env.SKIP_JOB - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh if: success() && !env.SKIP_JOB @@ -534,6 +671,8 @@ jobs: if: success() && !env.SKIP_JOB - name: ensure the stable version number is correct run: src/ci/scripts/verify-stable-version-number.sh + env: + SKIP_JOB: 1 if: success() && !env.SKIP_JOB - name: run the build run: src/ci/scripts/run-build-from-ci.sh @@ -558,6 +697,7 @@ jobs: env: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" + SKIP_JOB: 1 if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" try: name: "try - ${{ matrix.name }}" @@ -566,12 +706,13 @@ jobs: CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" - SCCACHE_BUCKET: rust-lang-ci-sccache2 + SCCACHE_BUCKET: cached-ci-artifacts + SCCACHE_REGION: us-east-2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL + TOOLSTATE_PUBLISH: 0 + CACHES_AWS_ACCESS_KEY_ID: AKIASSXOBJJGY5HRQO4U ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 AWS_REGION: us-west-1 CACHE_DOMAIN: ci-caches.rust-lang.org @@ -582,7 +723,7 @@ jobs: - name: dist-x86_64-linux env: CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-16core-64gb + os: ubuntu-latest timeout-minutes: 600 runs-on: "${{ matrix.os }}" steps: @@ -591,7 +732,7 @@ jobs: - name: checkout the source code uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 - name: configure the PR in which the error message will be posted run: "echo \"[CI_PR_NUMBER=$num]\"" env: @@ -605,9 +746,6 @@ jobs: - name: decide whether to skip this job run: src/ci/scripts/should-skip-this.sh if: success() && !env.SKIP_JOB - - name: ensure the channel matches the target branch - run: src/ci/scripts/verify-channel.sh - if: success() && !env.SKIP_JOB - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh if: success() && !env.SKIP_JOB @@ -661,6 +799,8 @@ jobs: if: success() && !env.SKIP_JOB - name: ensure the stable version number is correct run: src/ci/scripts/verify-stable-version-number.sh + env: + SKIP_JOB: 1 if: success() && !env.SKIP_JOB - name: run the build run: src/ci/scripts/run-build-from-ci.sh @@ -685,17 +825,19 @@ jobs: env: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" + SKIP_JOB: 1 if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" master: name: master runs-on: ubuntu-latest env: - SCCACHE_BUCKET: rust-lang-ci-sccache2 + SCCACHE_BUCKET: cached-ci-artifacts + SCCACHE_REGION: us-east-2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL + TOOLSTATE_PUBLISH: 0 + CACHES_AWS_ACCESS_KEY_ID: AKIASSXOBJJGY5HRQO4U ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 AWS_REGION: us-west-1 CACHE_DOMAIN: ci-caches.rust-lang.org @@ -704,7 +846,7 @@ jobs: - name: checkout the source code uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 - name: publish toolstate run: src/ci/publish_toolstate.sh shell: bash diff --git a/.gitignore b/.gitignore index 485968d9c56ff..1e81f0de3b287 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,6 @@ Session.vim !/tests/run-make/thumb-none-qemu/example/.cargo ## Configuration -/config.toml /Makefile config.mk config.stamp diff --git a/.gitmodules b/.gitmodules index 9bb68b37081f5..716ccb5c8c8af 100644 --- a/.gitmodules +++ b/.gitmodules @@ -32,8 +32,8 @@ shallow = true [submodule "src/llvm-project"] path = src/llvm-project - url = https://github.com/rust-lang/llvm-project.git - branch = rustc/17.0-2023-12-14 + url = https://github.com/solana-labs/llvm-project.git + branch = solana-rustc/17.0-2023-12-14 shallow = true [submodule "src/doc/embedded-book"] path = src/doc/embedded-book diff --git a/.reuse/dep5 b/.reuse/dep5 index 245ed2659f91f..dafee8ff6bb03 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -13,10 +13,12 @@ Files: compiler/* tests/* src/* .github/* + build.sh Cargo.lock Cargo.toml CODE_OF_CONDUCT.md config.example.toml + config.toml configure CONTRIBUTING.md COPYRIGHT diff --git a/Cargo.lock b/Cargo.lock index d3ecadf6e172f..dc44cb3685bc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -723,8 +723,7 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "compiler_builtins" version = "0.1.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242" +source = "git+https://github.com/solana-labs/compiler-builtins?tag=solana-tools-v1.40#81ef46f3fe1357095acdd089a700890fe4e13974" dependencies = [ "cc", "rustc-std-workspace-core", @@ -781,6 +780,7 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" name = "core" version = "0.0.0" dependencies = [ + "getrandom 0.1.16", "rand", "rand_xorshift", ] @@ -1591,6 +1591,17 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -1599,7 +1610,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -2523,7 +2534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -2544,7 +2555,7 @@ dependencies = [ "colored", "ctrlc", "env_logger 0.10.0", - "getrandom", + "getrandom 0.2.10", "lazy_static", "libc", "libffi", @@ -3175,7 +3186,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.10", ] [[package]] @@ -3240,7 +3251,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom", + "getrandom 0.2.10", "redox_syscall 0.2.16", "thiserror", ] @@ -5137,7 +5148,7 @@ dependencies = [ "rustc-demangle", "std_detect", "unwind", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -5963,7 +5974,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" dependencies = [ - "getrandom", + "getrandom 0.2.10", ] [[package]] @@ -6003,6 +6014,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 9b11ae8744b4f..9b1a4496e7879 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,6 +105,7 @@ miniz_oxide.debug = 0 object.debug = 0 [patch.crates-io] +compiler_builtins = { git = "https://github.com/solana-labs/compiler-builtins", tag = "solana-tools-v1.40" } # See comments in `library/rustc-std-workspace-core/README.md` for what's going on # here rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' } diff --git a/README.md b/README.md index a88ee4b8bf061..4f9520707f37a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,50 @@ +# Fork of the Rust Programming Language that supports Berkley Packet Filter (BPF) targets + +This fork of Rust contains changes that enable rustc to build BPF +modules. It depends on a customized +[fork](https://github.com/solana-labs/llvm-project) of Rust's LLVM +fork. + +Solana SDK does not depend directly on this repo. Instead [bpf-tools] +builds and releases binary packages that the Solana SDK pulls in. + +[bpf-tools]: https://github.com/solana-labs/bpf-tools + +BPF modules are built using target triple `bpfel-unknown-unknown` +which represents the little endian version of BPF. There is no +support for big endian at this time. + +Upgrading the compiler and standard library source tree +------------------------------------------------------- + +The source tree has two external dependencies +1. [compiler-builtins] +2. [llvm-project] + +If any of the depencies is changed or this repository is updated to +make a new release of the bpf-tools, tag the dependencies, and this +repository with a new bpf-tools-v1.x tag, so that all components of +the released bpf-tools have the same tag, e.g. bpf-tools-v1.6. Thus, +release of every version of the bpf-tools is fully specified by the +release version. + +The [llvm-project] is a submodule of this repository, therefore its +version is explicitly committed in this repository. However, +[compiler-builtins] is pulled in as a cargo package. Therefore, it is +necessary to update the `[patch.crates-io]` subsection of the +top-level `Cargo.toml` file, and specify which tag must be used to +pull the correct version of [compiler-builtins]. + +After this repository is tagged for a new release, update the +`bpf-tools/build.sh` in [bpf-tools] repository to pull the correct +version of the rust repository and make a new release tag in +[bpf-tools] repository. + +[compiler-builtins]: https://github.com/solana-labs/compiler-builtins +[llvm-project]: https://github.com/solana-labs/llvm-project + +--- + # The Rust Programming Language [![Rust Community](https://img.shields.io/badge/Rust_Community%20-Join_us-brightgreen?style=plastic&logo=rust)](https://www.rust-lang.org/community) diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000000..1dc775ba259d1 --- /dev/null +++ b/build.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -ex + +if [ "$1" == "--help" ] || [ "$1" == "-h" ]; then + echo "--llvm to rebuild llvm"; + exit; +fi + +unameOut="$(uname -s)-$(uname -m)" +case "${unameOut}" in + Linux-x86_64*) HOST_TRIPLE=x86_64-unknown-linux-gnu;; + Linux-aarch64*) HOST_TRIPLE=aarch64-unknown-linux-gnu;; + Darwin-x86_64*) HOST_TRIPLE=x86_64-apple-darwin;; + Darwin-arm64*) HOST_TRIPLE=aarch64-apple-darwin;; + MINGW*) HOST_TRIPLE=x86_64-pc-windows-msvc;; + *) HOST_TRIPLE=x86_64-unknown-linux-gnu +esac + +if [ "$1" == "--llvm" ]; then + rm -f build/${HOST_TRIPLE}/llvm/llvm-finished-building; +fi +./x.py build --stage 1 --target ${HOST_TRIPLE},bpfel-unknown-unknown,sbf-solana-solana diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index ba1cae03f3e41..0324e206b463e 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -14,7 +14,8 @@ use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ArgAbiMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; #[cfg(feature="master")] -use rustc_codegen_ssa::traits::{BaseTypeMethods, MiscMethods}; +use rustc_codegen_ssa::traits::MiscMethods; +use rustc_codegen_ssa::traits::BaseTypeMethods; use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_middle::bug; use rustc_middle::ty::{self, Instance, Ty}; diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 7a89fe81d3844..d30059eaaf5a8 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -26,10 +26,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } - pub fn type_void(&self) -> Type<'gcc> { - self.context.new_type::<()>() - } - pub fn type_size_t(&self) -> Type<'gcc> { self.context.new_type::() } @@ -126,6 +122,10 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.double_type } + fn type_void(&self) -> Type<'gcc> { + self.context.new_type::<()>() + } + fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> { self.context.new_function_pointer_type(None, return_type, params, false) } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index db5c1388ef846..d7d3a2563202f 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -83,13 +83,15 @@ pub(crate) unsafe fn codegen( let llval = llvm::LLVMConstInt(i8, val as u64, False); llvm::LLVMSetInitializer(ll_g, llval); - let name = NO_ALLOC_SHIM_IS_UNSTABLE; - let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); - if tcx.sess.target.default_hidden_visibility { - llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); + if tcx.sess.target.arch != "sbf" { + let name = NO_ALLOC_SHIM_IS_UNSTABLE; + let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); + if tcx.sess.target.default_hidden_visibility { + llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); + } + let llval = llvm::LLVMConstInt(i8, 0, False); + llvm::LLVMSetInitializer(ll_g, llval); } - let llval = llvm::LLVMConstInt(i8, 0, False); - llvm::LLVMSetInitializer(ll_g, llval); if tcx.sess.opts.debuginfo != DebugInfo::None { let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod); diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 06b7703672fe8..124fca73d34c3 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -164,6 +164,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMDoubleTypeInContext(self.llcx) } } + fn type_void(&self) -> &'ll Type { + unsafe { llvm::LLVMVoidTypeInContext(self.llcx) } + } + fn type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index dd9d277fb7757..b426bc0d00c26 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -46,7 +46,7 @@ use std::cell::OnceCell; use std::collections::BTreeSet; use std::ffi::OsString; use std::fs::{read, File, OpenOptions}; -use std::io::{BufWriter, Write}; +use std::io::{prelude::*, BufWriter, SeekFrom, Write}; use std::ops::Deref; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; @@ -310,6 +310,10 @@ fn link_rlib<'a>( let (metadata, metadata_position) = create_wrapper_file(sess, b".rmeta".to_vec(), codegen_results.metadata.raw_data()); let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME); + if sess.opts.cg.target_cpu.as_ref().unwrap_or( + &sess.target.cpu.as_ref().to_string()) == "sbfv2" { + patch_synthetic_object_file(sess, &metadata); + } match metadata_position { MetadataPosition::First => { // Most of the time metadata in rlib files is wrapped in a "dummy" object @@ -1798,7 +1802,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) cmd.args(&sess.opts.unstable_opts.pre_link_args); } -/// Add a link script embedded in the target, if applicable. +/// Add a link script embedded in the target, if applicable and not found in the command line. fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) { match (crate_type, &sess.target.link_script) { (CrateType::Cdylib | CrateType::Executable, Some(script)) => { @@ -1806,6 +1810,11 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty sess.emit_fatal(errors::LinkScriptUnavailable); } + if sess.opts.cg.link_args.contains(&String::from("--script")) + || sess.opts.cg.link_args.contains(&String::from("-T")) { + return; + } + let file_name = ["rustc", &sess.target.llvm_target, "linkfile.ld"].join("-"); let path = tmpdir.join(file_name); @@ -1936,9 +1945,24 @@ fn add_linked_symbol_object( if let Err(error) = result { sess.emit_fatal(errors::FailedToWrite { path, error }); } + if sess.opts.cg.target_cpu.as_ref().unwrap_or( + &sess.target.cpu.as_ref().to_string()) == "sbfv2" { + patch_synthetic_object_file(sess, &path); + } cmd.add_object(&path); } +fn patch_synthetic_object_file(sess: &Session, path: &PathBuf) { + const EM_SBF: [u8; 2] = [0x07, 0x01]; + if let Ok(mut sf) = fs::OpenOptions::new().write(true).open(path) { + if let Ok(_) = sf.seek(SeekFrom::Start(0x12)) { + sf.write(&EM_SBF).unwrap(); + } + } else { + sess.fatal(format!("failed to patch {}", path.display())); + } +} + /// Add object files containing code from the current crate. fn add_local_crate_regular_objects(cmd: &mut dyn Linker, codegen_results: &CodegenResults) { for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 09434513e31e9..f66d46f373b80 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -354,6 +354,17 @@ impl<'a> GccLinker<'a> { self.linker_arg(&format!("--out-implib={}", (*implib).to_str().unwrap())); } } + } else if self.sess.target.arch == "bpf" || self.sess.target.arch == "sbf" { + if self.sess.opts.test { + self.linker_arg("--entry=main"); + } else { + self.linker_arg("--entry=entrypoint"); + } + if self.sess.opts.cg.target_cpu.as_ref().unwrap_or(&self.sess.target.cpu.as_ref().to_string()) == "sbfv2" + { + self.linker_arg("--section-start=.text=0x100000000"); + self.linker_arg("--pack-dyn-relocs=relr"); + } } } } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index cb60ed729c1bf..07d1f3e888504 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -208,9 +208,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Architecture::Avr, "msp430" => Architecture::Msp430, "hexagon" => Architecture::Hexagon, - "bpf" => Architecture::Bpf, "loongarch64" => Architecture::LoongArch64, "csky" => Architecture::Csky, + "bpf" => Architecture::Bpf, + "sbf" => Architecture::Bpf, // Unsupported architecture. _ => return None, }; diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 2936f1de3cbf8..c9145999812b9 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -305,6 +305,10 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ const BPF_ALLOWED_FEATURES: &[(&str, Option)] = &[("alu32", Some(sym::bpf_target_feature))]; +const SBF_ALLOWED_FEATURES: &[(&str, Option)] = + &[("alu32", Some(sym::sbf_target_feature)), ("static-syscalls", Some(sym::sbf_target_feature))]; + + const CSKY_ALLOWED_FEATURES: &[(&str, Option)] = &[ // tidy-alphabetical-start ("10e60", Some(sym::csky_target_feature)), @@ -379,6 +383,7 @@ pub fn all_known_features() -> impl Iterator &'static [(&'static str, Opt "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, - "bpf" => BPF_ALLOWED_FEATURES, "csky" => CSKY_ALLOWED_FEATURES, "loongarch64" => LOONGARCH_ALLOWED_FEATURES, + "bpf" => BPF_ALLOWED_FEATURES, + "sbf" => SBF_ALLOWED_FEATURES, _ => &[], } } diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index b1fde8e4d8638..d3d2e5a69d217 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -23,6 +23,8 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn type_f64(&self) -> Self::Type; fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type; + fn type_void(&self) -> Self::Type; + fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type; fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type; fn type_kind(&self, ty: Self::Type) -> TypeKind; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index b11b190bdedad..4cd32b9ef4910 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -293,6 +293,7 @@ declare_features! ( (unstable, powerpc_target_feature, "1.27.0", Some(44839), None), (unstable, riscv_target_feature, "1.45.0", Some(44839), None), (unstable, rtm_target_feature, "1.35.0", Some(44839), None), + (unstable, sbf_target_feature, "1.54.0", Some(44839), None), (unstable, sse4a_target_feature, "1.27.0", Some(44839), None), (unstable, tbm_target_feature, "1.27.0", Some(44839), None), (unstable, wasm_target_feature, "1.30.0", Some(44839), None), diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 22d12793464a8..5dfcd6fc1ab78 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -404,6 +404,9 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { } fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { + let exe_only = (tcx.sess.target.arch != "bpf" && tcx.sess.target.arch != "sbf") || !tcx.sess.opts.test; let any_exe = tcx.crate_types().iter().any(|ty| *ty == CrateType::Executable); - if !any_exe { + if !any_exe && exe_only { // No need to find a main function. return None; } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f745bc390cadc..12196197cd955 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2977,9 +2977,10 @@ pub mod nightly_options { use crate::EarlyErrorHandler; use rustc_feature::UnstableFeatures; - pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool { - match_is_nightly_build(matches) - && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options") + pub fn is_unstable_enabled(_matches: &getopts::Matches) -> bool { + // Newer versions of Cargo might pass options that used to be nightly only + // Allow all nightly options on the Rust BPF compiler + true } pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 80a549b30f799..4f4b1341c15bd 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1244,7 +1244,21 @@ impl Session { // As a result 16 was chosen here! Mostly because it was a power of 2 // and most benchmarks agreed it was roughly a local optimum. Not very // scientific. - CodegenUnits::Default(16) + + if self.target.options.vendor == "solana" { + // Default to 1 for SBF programs. It makes a huge difference in + // terms of generated code size for us + // (https://github.com/rust-lang/rust/issues/47745) and compilation + // time isn't a huge concern (programs tend to be small). It's still + // possible to override this from the command line or from cargo + // profiles. + // + // Note that we don't set default_codegen_units in the target + // definition as that would break incremental compilation. + CodegenUnits::Default(1) + } else { + CodegenUnits::Default(16) + } } pub fn teach(&self, code: &DiagnosticId) -> bool { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f287862cc23c5..f2ce9ef742ef5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1447,6 +1447,7 @@ symbols! { saturating_add, saturating_div, saturating_sub, + sbf_target_feature, self_in_typedefs, self_struct_ctor, semitransparent, diff --git a/compiler/rustc_target/src/abi/call/bpf.rs b/compiler/rustc_target/src/abi/call/bpf.rs index 780e7df438373..d762c7fae9734 100644 --- a/compiler/rustc_target/src/abi/call/bpf.rs +++ b/compiler/rustc_target/src/abi/call/bpf.rs @@ -3,17 +3,21 @@ use crate::abi::call::{ArgAbi, FnAbi}; fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { if ret.layout.is_aggregate() || ret.layout.size.bits() > 64 { - ret.make_indirect(); + if ret.layout.size.bits() != 128 { + ret.make_indirect(); + } } else { - ret.extend_integer_width_to(32); + ret.extend_integer_width_to(64); } } fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { if arg.layout.is_aggregate() || arg.layout.size.bits() > 64 { - arg.make_indirect(); + if arg.layout.size.bits() != 128 { + arg.make_indirect(); + } } else { - arg.extend_integer_width_to(32); + arg.extend_integer_width_to(64); } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 5efd171b9dd76..084da59568a3a 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -22,6 +22,7 @@ mod powerpc; mod powerpc64; mod riscv; mod s390x; +mod sbf; mod sparc; mod sparc64; mod wasm; @@ -838,6 +839,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { } "asmjs" => wasm::compute_c_abi_info(cx, self), "bpf" => bpf::compute_abi_info(self), + "sbf" => sbf::compute_abi_info(self), arch => { return Err(AdjustForForeignAbiError::Unsupported { arch: Symbol::intern(arch), diff --git a/compiler/rustc_target/src/abi/call/sbf.rs b/compiler/rustc_target/src/abi/call/sbf.rs new file mode 100644 index 0000000000000..d762c7fae9734 --- /dev/null +++ b/compiler/rustc_target/src/abi/call/sbf.rs @@ -0,0 +1,35 @@ +// see https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/BPF/BPFCallingConv.td +use crate::abi::call::{ArgAbi, FnAbi}; + +fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { + if ret.layout.is_aggregate() || ret.layout.size.bits() > 64 { + if ret.layout.size.bits() != 128 { + ret.make_indirect(); + } + } else { + ret.extend_integer_width_to(64); + } +} + +fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { + if arg.layout.is_aggregate() || arg.layout.size.bits() > 64 { + if arg.layout.size.bits() != 128 { + arg.make_indirect(); + } + } else { + arg.extend_integer_width_to(64); + } +} + +pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { + if !fn_abi.ret.is_ignore() { + classify_ret(&mut fn_abi.ret); + } + + for arg in fn_abi.args.iter_mut() { + if arg.is_ignore() { + continue; + } + classify_arg(arg); + } +} diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index a11884bea268f..ce06a0040fe77 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -247,11 +247,12 @@ impl FromStr for InlineAsmArch { "spirv" => Ok(Self::SpirV), "wasm32" => Ok(Self::Wasm32), "wasm64" => Ok(Self::Wasm64), - "bpf" => Ok(Self::Bpf), "avr" => Ok(Self::Avr), "msp430" => Ok(Self::Msp430), "m68k" => Ok(Self::M68k), "csky" => Ok(Self::CSKY), + "bpf" => Ok(Self::Bpf), + "sbf" => Ok(Self::Bpf), _ => Err(()), } } diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index d137aaa535858..77e97ea58967d 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -22,6 +22,7 @@ pub(crate) mod netbsd; pub(crate) mod nto_qnx; pub(crate) mod openbsd; pub(crate) mod redox; +pub(crate) mod sbf_base; pub(crate) mod solaris; pub(crate) mod solid; pub(crate) mod teeos; diff --git a/compiler/rustc_target/src/spec/base/sbf_base.rs b/compiler/rustc_target/src/spec/base/sbf_base.rs new file mode 100644 index 0000000000000..50ffc6c883fc7 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/sbf_base.rs @@ -0,0 +1,65 @@ +use crate::abi::Endian; +use crate::spec::{Cc, cvs, LinkerFlavor, Lld, PanicStrategy, TargetOptions}; + +pub fn opts() -> TargetOptions { + let linker_script = r" +PHDRS +{ + text PT_LOAD ; + rodata PT_LOAD ; + data PT_LOAD ; + dynamic PT_DYNAMIC ; +} + +SECTIONS +{ + . = SIZEOF_HEADERS; + .text : { *(.text*) } :text + .rodata : { *(.rodata*) } :rodata + .data.rel.ro : { *(.data.rel.ro*) } :rodata + .dynamic : { *(.dynamic) } :dynamic + .dynsym : { *(.dynsym) } :data + .dynstr : { *(.dynstr) } :data + .rel.dyn : { *(.rel.dyn) } :data + /DISCARD/ : { + *(.eh_frame*) + *(.gnu.hash*) + *(.hash*) + } +} +"; + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::No, Lld::No), + &["--threads=1", "-z", "notext"], + ); + + TargetOptions { + allow_asm: true, + c_int_width: "64".into(), + default_hidden_visibility: true, + dll_prefix: "".into(), + dynamic_linking: true, + eh_frame_header: false, + emit_debug_gdb_scripts: false, + endian: Endian::Little, + env: "".into(), + executables: true, + features: "+solana".into(), + families: cvs!["solana"], + link_script: Some(linker_script.into()), + linker: Some("rust-lld".into()), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + main_needs_argc_argv: false, + max_atomic_width: Some(64), + no_default_libraries: true, + only_cdylib: true, + os: "solana".into(), + panic_strategy: PanicStrategy::Abort, + position_independent_executables: true, + pre_link_args, + requires_lto: false, + singlethread: true, + vendor: "solana".into(), + .. Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f04799482c831..bae5f1af122c9 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1691,6 +1691,8 @@ supported_targets! { ("bpfeb-unknown-none", bpfeb_unknown_none), ("bpfel-unknown-none", bpfel_unknown_none), + ("bpfel-unknown-unknown", bpfel_unknown_unknown), + ("sbf-solana-solana", sbf_solana_solana), ("armv6k-nintendo-3ds", armv6k_nintendo_3ds), diff --git a/compiler/rustc_target/src/spec/targets/bpfel_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/bpfel_unknown_unknown.rs new file mode 100644 index 0000000000000..6d28df29e797b --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/bpfel_unknown_unknown.rs @@ -0,0 +1,12 @@ +use crate::spec::Target; +use crate::spec::base::sbf_base; + +pub fn target() -> Target { + Target { + llvm_target: "bpfel".into(), + pointer_width: 64, + arch: "bpf".into(), + data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128".into(), + options: sbf_base::opts(), + } +} diff --git a/compiler/rustc_target/src/spec/targets/sbf_solana_solana.rs b/compiler/rustc_target/src/spec/targets/sbf_solana_solana.rs new file mode 100644 index 0000000000000..534b4f911257d --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/sbf_solana_solana.rs @@ -0,0 +1,12 @@ +use crate::spec::Target; +use crate::spec::base::sbf_base; + +pub fn target() -> Target { + Target { + llvm_target: "sbf".into(), + pointer_width: 64, + arch: "sbf".into(), + data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128".into(), + options: sbf_base::opts(), + } +} diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 257867b1b807b..4abea40c29557 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -27,7 +27,8 @@ impl Target { matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)) ); assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc)); - assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf)); + assert_eq!(self.arch == "bpf" && self.features != "+solana", + matches!(self.linker_flavor, LinkerFlavor::Bpf)); assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx)); for args in [ @@ -154,6 +155,7 @@ impl Target { fn can_use_os_unknown(&self) -> bool { self.llvm_target == "wasm32-unknown-unknown" || self.llvm_target == "wasm64-unknown-unknown" + || self.llvm_target == "bpf" || (self.env == "sgx" && self.vendor == "fortanix") } } diff --git a/config.toml b/config.toml new file mode 100644 index 0000000000000..9a195b3c27fb0 --- /dev/null +++ b/config.toml @@ -0,0 +1,531 @@ +changelog-seen = 2 +# Sample TOML configuration file for building Rust. +# +# To configure rustbuild, copy this file to the directory from which you will be +# running the build, and name it config.toml. +# +# All options are commented out by default in this file, and they're commented +# out with their default values. The build system by default looks for +# `config.toml` in the current directory of a build for build configuration, but +# a custom configuration file can also be specified with `--config` to the build +# system. + +# ============================================================================= +# Tweaking how LLVM is compiled +# ============================================================================= +[llvm] + +# Indicates whether the LLVM build is a Release or Debug build +optimize = true + +# Indicates whether LLVM should be built with ThinLTO. Note that this will +# only succeed if you use clang, lld, llvm-ar, and llvm-ranlib in your C/C++ +# toolchain (see the `cc`, `cxx`, `linker`, `ar`, and `ranlib` options below). +# More info at: https://clang.llvm.org/docs/ThinLTO.html#clang-bootstrap +#thin-lto = false + +# Indicates whether an LLVM Release build should include debug info +release-debuginfo = false + +# Indicates whether the LLVM assertions are enabled or not +assertions = false + +# Indicates whether ccache is used when building LLVM +#ccache = false +# or alternatively ... +#ccache = "/path/to/ccache" + +# If an external LLVM root is specified, we automatically check the version by +# default to make sure it's within the range that we're expecting, but setting +# this flag will indicate that this version check should not be done. +#version-check = true + +# Link libstdc++ statically into the librustc_llvm instead of relying on a +# dynamic version to be available. +#static-libstdcpp = false + +# Tell the LLVM build system to use Ninja instead of the platform default for +# the generated build system. This can sometimes be faster than make, for +# example. +#ninja = false + +# LLVM targets to build support for. +# Note: this is NOT related to Rust compilation targets. However, as Rust is +# dependent on LLVM for code generation, turning targets off here WILL lead to +# the resulting rustc being unable to compile for the disabled architectures. +# Also worth pointing out is that, in case support for new targets are added to +# LLVM, enabling them here doesn't mean Rust is automatically gaining said +# support. You'll need to write a target specification at least, and most +# likely, teach rustc about the C ABI of the target. Get in touch with the +# Rust team and file an issue if you need assistance in porting! +#targets = "AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86" +targets = "AArch64;X86" + +# LLVM experimental targets to build support for. These targets are specified in +# the same format as above, but since these targets are experimental, they are +# not built by default and the experimental Rust compilation targets that depend +# on them will not work unless the user opts in to building them. By default the +# `WebAssembly`, `RISCV`, and `BPF` targets are enabled when compiling LLVM from scratch. +experimental-targets = "BPF;SBF" + +# Cap the number of parallel linker invocations when compiling LLVM. +# This can be useful when building LLVM with debug info, which significantly +# increases the size of binaries and consequently the memory required by +# each linker process. +# If absent or 0, linker invocations are treated like any other job and +# controlled by rustbuild's -j parameter. +link-jobs = 2 + +# When invoking `llvm-config` this configures whether the `--shared` argument is +# passed to prefer linking to shared libraries. +link-shared = false + +# When building llvm, this configures what is being appended to the version. +# If absent, we let the version as-is. +#version-suffix = "-rust" + +# On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass +# with clang-cl, so this is special in that it only compiles LLVM with clang-cl +#clang-cl = '/path/to/clang-cl.exe' + +# Pass extra compiler and linker flags to the LLVM CMake build. +#cflags = "-fextra-flag" +#cxxflags = "-fextra-flag" +#ldflags = "-Wl,extra-flag" + +# Use libc++ when building LLVM instead of libstdc++. This is the default on +# platforms already use libc++ as the default C++ library, but this option +# allows you to use libc++ even on platforms when it's not. You need to ensure +# that your host compiler ships with libc++. +#use-libcxx = true + +# The value specified here will be passed as `-DLLVM_USE_LINKER` to CMake. +#use-linker = "lld" + +# Whether or not to specify `-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=YES` +#allow-old-toolchain = false + +# Which LLVM projects to build along with the LLVM base libraries/tools +enable-projects = "clang;lld;lldb" + +download-ci-llvm = false + +# ============================================================================= +# General build configuration options +# ============================================================================= +[build] + +# Build triple for the original snapshot compiler. This must be a compiler that +# nightlies are already produced for. The current platform must be able to run +# binaries of this build triple and the nightly will be used to bootstrap the +# first compiler. +#build = "x86_64-unknown-linux-gnu" # defaults to your host platform + +# In addition to the build triple, other triples to produce full compiler +# toolchains for. Each of these triples will be bootstrapped from the build +# triple and then will continue to bootstrap themselves. This platform must +# currently be able to run all of the triples provided here. +#host = ["x86_64-unknown-linux-gnu"] # defaults to just the build triple + +# In addition to all host triples, other triples to produce the standard library +# for. Each host triple will be used to produce a copy of the standard library +# for each target triple. +#target = ["x86_64-unknown-linux-gnu"] # defaults to just the build triple + +# Instead of downloading the src/stage0.txt version of Cargo specified, use +# this Cargo binary instead to build all Rust code +#cargo = "/path/to/bin/cargo" + +# Instead of downloading the src/stage0.txt version of the compiler +# specified, use this rustc binary instead as the stage0 snapshot compiler. +#rustc = "/path/to/bin/rustc" + +# Flag to specify whether any documentation is built. If false, rustdoc and +# friends will still be compiled but they will not be used to generate any +# documentation. +docs = false + +# Indicate whether the compiler should be documented in addition to the standard +# library and facade crates. +#compiler-docs = false + +# Indicate whether git submodules are managed and updated automatically. +#submodules = true + +# Update git submodules only when the checked out commit in the submodules differs +# from what is committed in the main rustc repo. +#fast-submodules = true + +# The path to (or name of) the GDB executable to use. This is only used for +# executing the debuginfo test suite. +#gdb = "gdb" + +# The node.js executable to use. Note that this is only used for the emscripten +# target when running tests, otherwise this can be omitted. +#nodejs = "node" + +# Python interpreter to use for various tasks throughout the build, notably +# rustdoc tests, the lldb python interpreter, and some dist bits and pieces. +# Note that Python 2 is currently required. +# +# Defaults to python2.7, then python2. If neither executable can be found, then +# it defaults to the Python interpreter used to execute x.py. +#python = "python2.7" + +# Force Cargo to check that Cargo.lock describes the precise dependency +# set that all the Cargo.toml files create, instead of updating it. +#locked-deps = false + +# Indicate whether the vendored sources are used for Rust dependencies or not +#vendor = false + +# Typically the build system will build the rust compiler twice. The second +# compiler, however, will simply use its own libraries to link against. If you +# would rather to perform a full bootstrap, compiling the compiler three times, +# then you can set this option to true. You shouldn't ever need to set this +# option to true. +#full-bootstrap = false + +# Enable a build of the extended rust tool set which is not only the compiler +# but also tools such as Cargo. This will also produce "combined installers" +# which are used to install Rust and Cargo together. This is disabled by +# default. +#extended = false + +# Installs chosen set of extended tools if enabled. By default builds all. +# If chosen tool failed to build the installation fails. +#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] + +# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose +#verbose = 0 + +# Build the sanitizer runtimes +#sanitizers = false + +# Build the profiler runtime +#profiler = false + +# Indicates whether the native libraries linked into Cargo will be statically +# linked or not. +#cargo-native-static = false + +# Run the build with low priority, by setting the process group's "nice" value +# to +10 on Unix platforms, and by using a "low priority" job object on Windows. +#low-priority = false + +# Arguments passed to the `./configure` script, used during distcheck. You +# probably won't fill this in but rather it's filled in by the `./configure` +# script. +#configure-args = [] + +# Indicates that a local rebuild is occurring instead of a full bootstrap, +# essentially skipping stage0 as the local compiler is recompiling itself again. +#local-rebuild = false + +# Print out how long each rustbuild step took (mostly intended for CI and +# tracking over time) +#print-step-timings = false + +# ============================================================================= +# General install configuration options +# ============================================================================= +[install] + +# Instead of installing to /usr/local, install to this path instead. +prefix = "opt/sbf-rust" + +# Where to install system configuration files +# If this is a relative path, it will get installed in `prefix` above +#sysconfdir = "/etc" + +# Where to install documentation in `prefix` above +#docdir = "share/doc/rust" + +# Where to install binaries in `prefix` above +#bindir = "bin" + +# Where to install libraries in `prefix` above +#libdir = "lib" + +# Where to install man pages in `prefix` above +#mandir = "share/man" + +# Where to install data in `prefix` above (currently unused) +#datadir = "share" + +# Where to install additional info in `prefix` above (currently unused) +#infodir = "share/info" + +# Where to install local state (currently unused) +# If this is a relative path, it will get installed in `prefix` above +#localstatedir = "/var/lib" + +# ============================================================================= +# Options for compiling Rust code itself +# ============================================================================= +[rust] + +# Whether or not to optimize the compiler and standard library. +# +# Note: the slowness of the non optimized compiler compiling itself usually +# outweighs the time gains in not doing optimizations, therefore a +# full bootstrap takes much more time with `optimize` set to false. +optimize = true + +# Indicates that the build should be configured for debugging Rust. A +# `debug`-enabled compiler and standard library will be somewhat +# slower (due to e.g. checking of debug assertions) but should remain +# usable. +# +# Note: If this value is set to `true`, it will affect a number of +# configuration options below as well, if they have been left +# unconfigured in this file. +# +# Note: changes to the `debug` setting do *not* affect `optimize` +# above. In theory, a "maximally debuggable" environment would +# set `optimize` to `false` above to assist the introspection +# facilities of debuggers like lldb and gdb. To recreate such an +# environment, explicitly set `optimize` to `false` and `debug` +# to `true`. In practice, everyone leaves `optimize` set to +# `true`, because an unoptimized rustc with debugging +# enabled becomes *unusably slow* (e.g. rust-lang/rust#24840 +# reported a 25x slowdown) and bootstrapping the supposed +# "maximally debuggable" environment (notably libstd) takes +# hours to build. +# +debug = false + +# Number of codegen units to use for each compiler invocation. A value of 0 +# means "the number of cores on this machine", and 1+ is passed through to the +# compiler. +#codegen-units = 1 + +# Sets the number of codegen units to build the standard library with, +# regardless of what the codegen-unit setting for the rest of the compiler is. +#codegen-units-std = 1 + +# Whether or not debug assertions are enabled for the compiler and standard +# library. +debug-assertions = false + +# Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`. +# `0` - no debug info +# `1` - line tables only +# `2` - full debug info with variable and type information +# Can be overriden for specific subsets of Rust code (rustc, std or tools). +# Debuginfo for tests run with compiletest is not controlled by this option +# and needs to be enabled separately with `debuginfo-level-tests`. +#debuginfo-level = if debug { 2 } else { 0 } + +# Debuginfo level for the compiler. +#debuginfo-level-rustc = debuginfo-level + +# Debuginfo level for the standard library. +#debuginfo-level-std = debuginfo-level + +# Debuginfo level for the tools. +#debuginfo-level-tools = debuginfo-level + +# Debuginfo level for the test suites run with compiletest. +# FIXME(#61117): Some tests fail when this option is enabled. +#debuginfo-level-tests = 0 + +# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) +#backtrace = true + +# Whether to always use incremental compilation when building rustc +#incremental = false + +# Build a multi-threaded rustc +#parallel-compiler = false + +# The default linker that will be hard-coded into the generated compiler for +# targets that don't specify linker explicitly in their target specifications. +# Note that this is not the linker used to link said compiler. +#default-linker = "cc" + +# The "channel" for the Rust build to produce. The stable/beta channels only +# allow using stable features, whereas the nightly and dev channels allow using +# nightly features +#channel = "dev" + +# By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix +# platforms to ensure that the compiler is usable by default from the build +# directory (as it links to a number of dynamic libraries). This may not be +# desired in distributions, for example. +#rpath = true + +# Emits extraneous output from tests to ensure that failures of the test +# harness are debuggable just from logfiles. +#verbose-tests = false + +# Flag indicating whether tests are compiled with optimizations (the -O flag). +#optimize-tests = true + +# Flag indicating whether codegen tests will be run or not. If you get an error +# saying that the FileCheck executable is missing, you may want to disable this. +# Also see the target's llvm-filecheck option. +#codegen-tests = true + +# Flag indicating whether git info will be retrieved from .git automatically. +# Having the git information can cause a lot of rebuilds during development. +# Note: If this attribute is not explicitly set (e.g. if left commented out) it +# will default to true if channel = "dev", but will default to false otherwise. +#ignore-git = true + +# When creating source tarballs whether or not to create a source tarball. +#dist-src = false + +# After building or testing extended tools (e.g. clippy and rustfmt), append the +# result (broken, compiling, testing) into this JSON file. +#save-toolstates = "/path/to/toolstates.json" + +# This is an array of the codegen backends that will be compiled for the rustc +# that's being compiled. The default is to only build the LLVM codegen backend, +# but you can also optionally enable the "emscripten" backend for asm.js or +# make this an empty array (but that probably won't get too far in the +# bootstrap) +#codegen-backends = ["llvm"] + +# This is the name of the directory in which codegen backends will get installed +#codegen-backends-dir = "codegen-backends" + +# Indicates whether LLD will be compiled and made available in the sysroot for +# rustc to execute. +lld = true + +# Indicates whether some LLVM tools, like llvm-objdump, will be made available in the +# sysroot. +#llvm-tools = false + +# Indicates whether LLDB will be made available in the sysroot. +# This is only built if LLVM is also being built. +#lldb = false + +# Whether to deny warnings in crates +#deny-warnings = true + +# Print backtrace on internal compiler errors during bootstrap +#backtrace-on-ice = false + +# Whether to verify generated LLVM IR +#verify-llvm-ir = false + +# Map all debuginfo paths for libstd and crates to `/rust/$sha/$crate/...`, +# generally only set for releases +#remap-debuginfo = false + +# Link the compiler against `jemalloc`, where on Linux and OSX it should +# override the default allocator for rustc and LLVM. +#jemalloc = false + +# Run tests in various test suites with the "nll compare mode" in addition to +# running the tests in normal mode. Largely only used on CI and during local +# development of NLL +#test-compare-mode = false + +# Use LLVM libunwind as the implementation for Rust's unwinder. +#llvm-libunwind = false + +# ============================================================================= +# Options for specific targets +# +# Each of the following options is scoped to the specific target triple in +# question and is used for determining how to compile each target. +# ============================================================================= +[target.x86_64-unknown-linux-gnu] + +# C compiler to be used to compiler C code. Note that the +# default value is platform specific, and if not specified it may also depend on +# what platform is crossing to what platform. +#cc = "cc" + +# C++ compiler to be used to compiler C++ code (e.g. LLVM and our LLVM shims). +# This is only used for host targets. +#cxx = "c++" + +# Archiver to be used to assemble static libraries compiled from C/C++ code. +# Note: an absolute path should be used, otherwise LLVM build will break. +#ar = "ar" + +# Ranlib to be used to assemble static libraries compiled from C/C++ code. +# Note: an absolute path should be used, otherwise LLVM build will break. +#ranlib = "ranlib" + +# Linker to be used to link Rust code. Note that the +# default value is platform specific, and if not specified it may also depend on +# what platform is crossing to what platform. +#linker = "cc" + +# Path to the `llvm-config` binary of the installation of a custom LLVM to link +# against. Note that if this is specified we don't compile LLVM at all for this +# target. +#llvm-config = "../path/to/llvm/root/bin/llvm-config" + +# Normally the build system can find LLVM's FileCheck utility, but if +# not, you can specify an explicit file name for it. +#llvm-filecheck = "/path/to/FileCheck" + +# If this target is for Android, this option will be required to specify where +# the NDK for the target lives. This is used to find the C compiler to link and +# build native code. +#android-ndk = "/path/to/ndk" + +# Force static or dynamic linkage of the standard library for this target. If +# this target is a host for rustc, this will also affect the linkage of the +# compiler itself. This is useful for building rustc on targets that normally +# only use static libraries. If unset, the target's default linkage is used. +#crt-static = false + +# The root location of the MUSL installation directory. The library directory +# will also need to contain libunwind.a for an unwinding implementation. Note +# that this option only makes sense for MUSL targets that produce statically +# linked binaries +#musl-root = "..." + +# The root location of the `wasm32-wasi` sysroot. +#wasi-root = "..." + +# Used in testing for configuring where the QEMU images are located, you +# probably don't want to use this. +#qemu-rootfs = "..." + +# ============================================================================= +# Distribution options +# +# These options are related to distribution, mostly for the Rust project itself. +# You probably won't need to concern yourself with any of these options +# ============================================================================= +[dist] + +# This is the folder of artifacts that the build system will sign. All files in +# this directory will be signed with the default gpg key using the system `gpg` +# binary. The `asc` and `sha256` files will all be output into the standard dist +# output folder (currently `build/dist`) +# +# This folder should be populated ahead of time before the build system is +# invoked. +#sign-folder = "path/to/folder/to/sign" + +# This is a file which contains the password of the default gpg key. This will +# be passed to `gpg` down the road when signing all files in `sign-folder` +# above. This should be stored in plaintext. +#gpg-password-file = "path/to/gpg/password" + +# The remote address that all artifacts will eventually be uploaded to. The +# build system generates manifests which will point to these urls, and for the +# manifests to be correct they'll have to have the right URLs encoded. +# +# Note that this address should not contain a trailing slash as file names will +# be appended to it. +#upload-addr = "https://example.com/folder" + +# Whether to build a plain source tarball to upload +# We disable that on Windows not to override the one already uploaded on S3 +# as the one built on Windows will contain backslashes in paths causing problems +# on linux +#src-tarball = true +# + +# Whether to allow failures when building tools +#missing-tools = false diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 2499f1053d860..bdb2cc4f714b7 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -36,6 +36,7 @@ extern "Rust" { #[rustc_nounwind] fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; + #[cfg(not(target_family = "solana"))] static __rust_no_alloc_shim_is_unstable: u8; } @@ -93,6 +94,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { unsafe { // Make sure we don't accidentally allow omitting the allocator shim in // stable code until it is actually stabilized. + #[cfg(not(target_family = "solana"))] core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable); __rust_alloc(layout.size(), layout.align()) @@ -405,6 +407,7 @@ pub mod __alloc_error_handler { // called via generated `__rust_alloc_error_handler` if there is no // `#[alloc_error_handler]`. #[rustc_std_internal_symbol] + #[cfg(not(target_family = "solana"))] pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. @@ -421,6 +424,14 @@ pub mod __alloc_error_handler { ) } } + + #[rustc_std_internal_symbol] + #[cfg(target_family = "solana")] + pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { + core::panicking::panic_nounwind_fmt(format_args!( + "memory allocation of {size} bytes failed" + ), /* force_no_backtrace */ false) + } } /// Specialize clones into pre-allocated, uninitialized memory. diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 3dc8c84e0bfde..6b74372a23ba5 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -27,6 +27,9 @@ test = true rand = { version = "0.8.5", default-features = false } rand_xorshift = { version = "0.3.0", default-features = false } +[target.bpfel-unknown-unknown.dev-dependencies] +getrandom = { version = "0.1.14", features = ["dummy"] } + [features] # Make panics and failed asserts immediately abort without formatting any message panic_immediate_abort = [] diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index 74ef0949b8af2..6ac4448931654 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -1,5 +1,5 @@ // wasm32 does not support benches (no time). -#![cfg(not(target_arch = "wasm32"))] +#![cfg(not(any(target_arch = "wasm32", target_family = "solana")))] #![feature(flt2dec)] #![feature(test)] #![feature(trusted_random_access)] diff --git a/library/core/benches/num/int_log/mod.rs b/library/core/benches/num/int_log/mod.rs index bb61224b5baad..7e98c0d623433 100644 --- a/library/core/benches/num/int_log/mod.rs +++ b/library/core/benches/num/int_log/mod.rs @@ -1,3 +1,4 @@ +#![cfg(not(target_family = "solana"))] use rand::Rng; use test::{black_box, Bencher}; diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 4f42f73ebbaff..fe80a7e3de320 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -467,13 +467,14 @@ mod imp { i8, u8, i16, u16, i32, u32, i64, u64, usize, isize as u64 via to_u64 named fmt_u64 ); + impl_Exp!( i8, u8, i16, u16, i32, u32, i64, u64, usize, isize as u64 via to_u64 named exp_u64 ); } -#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] +#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32", target_family = "solana")))] mod imp { use super::*; impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32); @@ -481,6 +482,7 @@ mod imp { impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32); impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64); } + impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128); /// Helper function for writing a u64 into `buf` going from last to first, with `curr`. diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 81da75d32a1c9..850eb850763a3 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -1,3 +1,4 @@ +#![cfg(not(target_family = "solana"))] use core::{array, assert_eq}; use core::convert::TryFrom; use core::num::NonZeroUsize; @@ -512,6 +513,7 @@ fn array_rsplit_array_mut_out_of_bounds() { } #[test] +#[cfg(not(target_family = "solana"))] fn array_intoiter_advance_by() { use std::cell::Cell; struct DropCounter<'a>(usize, &'a Cell); @@ -565,6 +567,7 @@ fn array_intoiter_advance_by() { } #[test] +#[cfg(not(target_family = "solana"))] fn array_intoiter_advance_back_by() { use std::cell::Cell; struct DropCounter<'a>(usize, &'a Cell); diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index a67a842d3407f..1e7cb8ccac45a 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -212,38 +212,42 @@ fn ptr_bitops_tagging() { assert_eq!(atom.load(SeqCst), ptr); } -static S_FALSE: AtomicBool = AtomicBool::new(false); -static S_TRUE: AtomicBool = AtomicBool::new(true); -static S_INT: AtomicIsize = AtomicIsize::new(0); -static S_UINT: AtomicUsize = AtomicUsize::new(0); - -#[test] -fn static_init() { - // Note that we're not really testing the mutability here but it's important - // on Android at the moment (#49775) - assert!(!S_FALSE.swap(true, SeqCst)); - assert!(S_TRUE.swap(false, SeqCst)); - assert!(S_INT.fetch_add(1, SeqCst) == 0); - assert!(S_UINT.fetch_add(1, SeqCst) == 0); +// SBF does not support mustable static data +#[cfg(not(target_family = "solana"))] +mod statik { + use super::*; + + static S_FALSE: AtomicBool = AtomicBool::new(false); + static S_TRUE: AtomicBool = AtomicBool::new(true); + static S_INT: AtomicIsize = AtomicIsize::new(0); + static S_UINT: AtomicUsize = AtomicUsize::new(0); + + #[test] + fn static_init() { + // Note that we're not really testing the mutability here but it's important + // on Android at the moment (#49775) + assert!(!S_FALSE.swap(true, SeqCst)); + assert!(S_TRUE.swap(false, SeqCst)); + assert!(S_INT.fetch_add(1, SeqCst) == 0); + assert!(S_UINT.fetch_add(1, SeqCst) == 0); + } } #[test] fn atomic_access_bool() { - static mut ATOMIC: AtomicBool = AtomicBool::new(false); - - unsafe { - assert_eq!(*ATOMIC.get_mut(), false); - ATOMIC.store(true, SeqCst); - assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_or(false, SeqCst); - assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_and(false, SeqCst); - assert_eq!(*ATOMIC.get_mut(), false); - ATOMIC.fetch_nand(true, SeqCst); - assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_xor(true, SeqCst); - assert_eq!(*ATOMIC.get_mut(), false); - } + let mut atomic: AtomicBool = AtomicBool::new(false); + + assert_eq!(*atomic.get_mut(), false); + atomic.store(true, SeqCst); + assert_eq!(*atomic.get_mut(), true); + atomic.fetch_or(false, SeqCst); + assert_eq!(*atomic.get_mut(), true); + atomic.fetch_and(false, SeqCst); + assert_eq!(*atomic.get_mut(), false); + atomic.fetch_nand(true, SeqCst); + assert_eq!(*atomic.get_mut(), true); + atomic.fetch_xor(true, SeqCst); + assert_eq!(*atomic.get_mut(), false); } #[test] @@ -284,26 +288,26 @@ fn atomic_alignment() { fn atomic_compare_exchange() { use Ordering::*; - static ATOMIC: AtomicIsize = AtomicIsize::new(0); - - ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, Acquire, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, Release, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, AcqRel, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok(); - ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok(); - ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok(); - ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok(); - ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, Acquire, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok(); - ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok(); - ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok(); - ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok(); + let atomic: AtomicIsize = AtomicIsize::new(0); + + atomic.compare_exchange(0, 1, Relaxed, Relaxed).ok(); + atomic.compare_exchange(0, 1, Acquire, Relaxed).ok(); + atomic.compare_exchange(0, 1, Release, Relaxed).ok(); + atomic.compare_exchange(0, 1, AcqRel, Relaxed).ok(); + atomic.compare_exchange(0, 1, SeqCst, Relaxed).ok(); + atomic.compare_exchange(0, 1, Acquire, Acquire).ok(); + atomic.compare_exchange(0, 1, AcqRel, Acquire).ok(); + atomic.compare_exchange(0, 1, SeqCst, Acquire).ok(); + atomic.compare_exchange(0, 1, SeqCst, SeqCst).ok(); + atomic.compare_exchange_weak(0, 1, Relaxed, Relaxed).ok(); + atomic.compare_exchange_weak(0, 1, Acquire, Relaxed).ok(); + atomic.compare_exchange_weak(0, 1, Release, Relaxed).ok(); + atomic.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok(); + atomic.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok(); + atomic.compare_exchange_weak(0, 1, Acquire, Acquire).ok(); + atomic.compare_exchange_weak(0, 1, AcqRel, Acquire).ok(); + atomic.compare_exchange_weak(0, 1, SeqCst, Acquire).ok(); + atomic.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok(); } /* FIXME(#110395) diff --git a/library/core/tests/future.rs b/library/core/tests/future.rs index db417256dd01e..04dac6fb72ff7 100644 --- a/library/core/tests/future.rs +++ b/library/core/tests/future.rs @@ -1,3 +1,4 @@ +#![cfg(not(target_family = "solana"))] use std::future::{join, Future}; use std::pin::Pin; use std::sync::Arc; diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs index 7f7f1f0058801..b5c8e5ce4d591 100644 --- a/library/core/tests/lazy.rs +++ b/library/core/tests/lazy.rs @@ -1,3 +1,4 @@ +#![allow(unused_imports)] use core::{ cell::{Cell, LazyCell, OnceCell}, sync::atomic::{AtomicUsize, Ordering::SeqCst}, @@ -23,6 +24,8 @@ fn once_cell_get_mut() { assert_eq!(c.get_mut(), Some(&mut 92)); } +// sbf doesn't have mutable static data +#[cfg(not(target_family = "solana"))] #[test] fn once_cell_drop() { static DROP_CNT: AtomicUsize = AtomicUsize::new(0); diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 3f3659ba837d5..b46835f68bcbd 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -30,6 +30,8 @@ mod bignum; mod const_from; mod dec2flt; +// sbf doesn't support floats +#[cfg(not(target_family = "solana"))] mod flt2dec; mod int_log; mod ops; diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index ee885adfeee61..319564c454635 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1,3 +1,4 @@ +#![allow(unused_imports)] use core::cell::RefCell; use core::mem::{self, MaybeUninit}; use core::num::NonZeroUsize; @@ -320,6 +321,8 @@ pub fn test_variadic_fnptr() { assert_eq!(p.hash(&mut s), q.hash(&mut s)); } +// sbf doesn't support thread locals +#[cfg(not(target_family = "solana"))] #[test] fn write_unaligned_drop() { thread_local! { diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 666452ead3f5a..c0ee96ad78d72 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1735,31 +1735,31 @@ fn test_iter_folds() { #[test] fn test_rotate_left() { const N: usize = 600; - let a: &mut [_] = &mut [0; N]; + let a: &mut [_] = &mut [0u8; N]; for i in 0..N { - a[i] = i; + a[i] = i as u8; } a.rotate_left(42); let k = N - 42; for i in 0..N { - assert_eq!(a[(i + k) % N], i); + assert_eq!(a[(i + k) % N], i as u8); } } #[test] fn test_rotate_right() { const N: usize = 600; - let a: &mut [_] = &mut [0; N]; + let a: &mut [_] = &mut [0u8; N]; for i in 0..N { - a[i] = i; + a[i] = i as u8; } a.rotate_right(42); for i in 0..N { - assert_eq!(a[(i + 42) % N], i); + assert_eq!(a[(i + 42) % N], i as u8); } } @@ -1802,7 +1802,7 @@ fn brute_force_rotate_test_1() { } #[test] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(any(target_arch = "wasm32", target_family = "solana")))] fn sort_unstable() { use core::cmp::Ordering::{Equal, Greater, Less}; use core::slice::heapsort; @@ -1876,7 +1876,7 @@ fn sort_unstable() { } #[test] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(any(target_arch = "wasm32", target_family = "solana")))] #[cfg_attr(miri, ignore)] // Miri is too slow fn select_nth_unstable() { use core::cmp::Ordering::{Equal, Greater, Less}; diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index f666b18887cb1..a7bd780465042 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -25,6 +25,8 @@ hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] } # Dependencies of the `backtrace` crate +[target.'cfg(not(target_family = "solana"))'.dependencies] +addr2line = { version = "0.21.0", optional = true, default-features = false } rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] } [target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] diff --git a/library/std/build.rs b/library/std/build.rs index ad0a82eab8ca1..cf2600039cc1a 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -35,6 +35,8 @@ fn main() { || target.contains("xous") || target.contains("hurd") || target.contains("uefi") + || target.contains("bpf") + || target.contains("sbf") // See src/bootstrap/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() { diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index bb786bd59dc84..55e4218491615 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -58,8 +58,11 @@ use core::intrinsics; use core::ptr::NonNull; +#[cfg(not(target_family = "solana"))] use core::sync::atomic::{AtomicPtr, Ordering}; -use core::{mem, ptr}; +#[cfg(not(target_family = "solana"))] +use core::mem; +use core::ptr; #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] @@ -286,6 +289,7 @@ unsafe impl Allocator for System { } } +#[cfg(not(target_family = "solana"))] static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// Registers a custom allocation error hook, replacing any that was previously registered. @@ -328,6 +332,7 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// set_alloc_error_hook(custom_alloc_error_hook); /// ``` #[unstable(feature = "alloc_error_hook", issue = "51245")] +#[cfg(not(target_family = "solana"))] pub fn set_alloc_error_hook(hook: fn(Layout)) { HOOK.store(hook as *mut (), Ordering::SeqCst); } @@ -338,11 +343,13 @@ pub fn set_alloc_error_hook(hook: fn(Layout)) { /// /// If no custom hook is registered, the default hook will be returned. #[unstable(feature = "alloc_error_hook", issue = "51245")] +#[cfg(not(target_family = "solana"))] pub fn take_alloc_error_hook() -> fn(Layout) { let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } } } +#[cfg(not(target_family = "solana"))] fn default_alloc_error_hook(layout: Layout) { extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. @@ -361,11 +368,18 @@ fn default_alloc_error_hook(layout: Layout) { #[doc(hidden)] #[alloc_error_handler] #[unstable(feature = "alloc_internals", issue = "none")] -pub fn rust_oom(layout: Layout) -> ! { - let hook = HOOK.load(Ordering::SeqCst); - let hook: fn(Layout) = - if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } }; - hook(layout); +pub fn rust_oom(_layout: Layout) -> ! { + #[cfg(not(target_family = "solana"))] + { + let hook = HOOK.load(Ordering::SeqCst); + let hook: fn(Layout) = + if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } }; + hook(_layout); + } + #[cfg(target_family = "solana")] + { + crate::sys::sol_log(b"Error: memory allocation failed, out of memory"); + } crate::process::abort() } diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index e7110aebdea16..9f9dc58b4a886 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -88,14 +88,22 @@ mod tests; // `Backtrace`, but that's a relatively small price to pay relative to capturing // a backtrace or actually symbolizing it. +#[cfg(not(target_family = "solana"))] use crate::backtrace_rs::{self, BytesOrWideString}; +#[cfg(not(target_family = "solana"))] use crate::env; +#[cfg(not(target_family = "solana"))] use crate::ffi::c_void; use crate::fmt; +#[cfg(not(target_family = "solana"))] use crate::panic::UnwindSafe; +#[cfg(not(target_family = "solana"))] use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +#[cfg(not(target_family = "solana"))] use crate::sync::LazyLock; +#[cfg(not(target_family = "solana"))] use crate::sys_common::backtrace::{lock, output_filename}; +#[cfg(not(target_family = "solana"))] use crate::vec::Vec; /// A captured OS thread stack backtrace. @@ -133,9 +141,11 @@ pub enum BacktraceStatus { enum Inner { Unsupported, Disabled, + #[cfg(not(target_family = "solana"))] Captured(LazyLock), } +#[cfg(not(target_family = "solana"))] struct Capture { actual_start: usize, frames: Vec, @@ -149,17 +159,21 @@ fn _assert_send_sync() { /// A single frame of a backtrace. #[unstable(feature = "backtrace_frames", issue = "79676")] pub struct BacktraceFrame { + #[cfg(not(target_family = "solana"))] frame: RawFrame, + #[cfg(not(target_family = "solana"))] symbols: Vec, } #[derive(Debug)] enum RawFrame { + #[cfg(not(target_family = "solana"))] Actual(backtrace_rs::Frame), #[cfg(test)] Fake, } +#[cfg(not(target_family = "solana"))] struct BacktraceSymbol { name: Option>, filename: Option, @@ -167,6 +181,7 @@ struct BacktraceSymbol { colno: Option, } +#[cfg(not(target_family = "solana"))] enum BytesOrWide { Bytes(Vec), Wide(Vec), @@ -174,6 +189,7 @@ enum BytesOrWide { #[stable(feature = "backtrace", since = "1.65.0")] impl fmt::Debug for Backtrace { + #[cfg(not(target_family = "solana"))] fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let capture = match &self.inner { Inner::Unsupported => return fmt.write_str(""), @@ -197,17 +213,29 @@ impl fmt::Debug for Backtrace { dbg.finish() } + + #[cfg(target_family = "solana")] + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "") + } } #[unstable(feature = "backtrace_frames", issue = "79676")] impl fmt::Debug for BacktraceFrame { + #[cfg(not(target_family = "solana"))] fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let mut dbg = fmt.debug_list(); dbg.entries(&self.symbols); dbg.finish() } + + #[cfg(target_family = "solana")] + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "") + } } +#[cfg(not(target_family = "solana"))] impl fmt::Debug for BacktraceSymbol { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // FIXME: improve formatting: https://github.com/rust-lang/rust/issues/65280 @@ -234,6 +262,7 @@ impl fmt::Debug for BacktraceSymbol { } } +#[cfg(not(target_family = "solana"))] impl fmt::Debug for BytesOrWide { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { output_filename( @@ -251,6 +280,7 @@ impl fmt::Debug for BytesOrWide { impl Backtrace { /// Returns whether backtrace captures are enabled through environment /// variables. + #[cfg(not(target_family = "solana"))] fn enabled() -> bool { // Cache the result of reading the environment variables to make // backtrace captures speedy, because otherwise reading environment @@ -272,6 +302,11 @@ impl Backtrace { enabled } + #[cfg(target_family = "solana")] + fn enabled() -> bool { + false + } + /// Capture a stack backtrace of the current thread. /// /// This function will capture a stack backtrace of the current OS thread of @@ -323,6 +358,7 @@ impl Backtrace { // Capture a backtrace which start just before the function addressed by // `ip` + #[cfg(not(target_family = "solana"))] fn create(ip: usize) -> Backtrace { let _lock = lock(); let mut frames = Vec::new(); @@ -355,6 +391,13 @@ impl Backtrace { Backtrace { inner } } + #[cfg(target_family = "solana")] + fn create(_ip: usize) -> Backtrace { + Backtrace { + inner: Inner::Unsupported + } + } + /// Returns the status of this backtrace, indicating whether this backtrace /// request was unsupported, disabled, or a stack trace was actually /// captured. @@ -364,6 +407,7 @@ impl Backtrace { match self.inner { Inner::Unsupported => BacktraceStatus::Unsupported, Inner::Disabled => BacktraceStatus::Disabled, + #[cfg(not(target_family = "solana"))] Inner::Captured(_) => BacktraceStatus::Captured, } } @@ -373,13 +417,23 @@ impl<'a> Backtrace { /// Returns an iterator over the backtrace frames. #[must_use] #[unstable(feature = "backtrace_frames", issue = "79676")] + #[cfg(not(target_family = "solana"))] pub fn frames(&'a self) -> &'a [BacktraceFrame] { if let Inner::Captured(c) = &self.inner { &c.frames } else { &[] } } + + /// Returns an iterator over the backtrace frames. + #[must_use] + #[unstable(feature = "backtrace_frames", issue = "79676")] + #[cfg(target_family = "solana")] + pub fn frames(&'a self) -> &'a [BacktraceFrame] { + &[] + } } #[stable(feature = "backtrace", since = "1.65.0")] impl fmt::Display for Backtrace { + #[cfg(not(target_family = "solana"))] fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let capture = match &self.inner { Inner::Unsupported => return fmt.write_str("unsupported backtrace"), @@ -426,10 +480,17 @@ impl fmt::Display for Backtrace { f.finish()?; Ok(()) } + + #[cfg(target_family = "solana")] + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "") + } } +#[cfg(not(target_family = "solana"))] type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe; +#[cfg(not(target_family = "solana"))] fn lazy_resolve(mut capture: Capture) -> LazyResolve { move || { // Use the global backtrace lock to synchronize this as it's a @@ -462,6 +523,7 @@ fn lazy_resolve(mut capture: Capture) -> LazyResolve { } } +#[cfg(not(target_family = "solana"))] impl RawFrame { fn ip(&self) -> *mut c_void { match self { diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4d109285d1645..a2f0bcf7aa278 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -3111,26 +3111,31 @@ impl RandomState { #[must_use] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn new() -> RandomState { - // Historically this function did not cache keys from the OS and instead - // simply always called `rand::thread_rng().gen()` twice. In #31356 it - // was discovered, however, that because we re-seed the thread-local RNG - // from the OS periodically that this can cause excessive slowdown when - // many hash maps are created on a thread. To solve this performance - // trap we cache the first set of randomly generated keys per-thread. - // - // Later in #36481 it was discovered that exposing a deterministic - // iteration order allows a form of DOS attack. To counter that we - // increment one of the seeds on every RandomState creation, giving - // every corresponding HashMap a different iteration order. - thread_local!(static KEYS: Cell<(u64, u64)> = { - Cell::new(sys::hashmap_random_keys()) - }); - - KEYS.with(|keys| { - let (k0, k1) = keys.get(); - keys.set((k0.wrapping_add(1), k1)); - RandomState { k0, k1 } - }) + if cfg!(target_family = "solana") { + // sbf doesn't support thread_local!() + RandomState { k0: 0, k1: 0 } + } else { + // Historically this function did not cache keys from the OS and instead + // simply always called `rand::thread_rng().gen()` twice. In #31356 it + // was discovered, however, that because we re-seed the thread-local RNG + // from the OS periodically that this can cause excessive slowdown when + // many hash maps are created on a thread. To solve this performance + // trap we cache the first set of randomly generated keys per-thread. + // + // Later in #36481 it was discovered that exposing a deterministic + // iteration order allows a form of DOS attack. To counter that we + // increment one of the seeds on every RandomState creation, giving + // every corresponding HashMap a different iteration order. + thread_local!(static KEYS: Cell<(u64, u64)> = { + Cell::new(sys::hashmap_random_keys()) + }); + + KEYS.with(|keys| { + let (k0, k1) = keys.get(); + keys.set((k0.wrapping_add(1), k1)); + RandomState { k0, k1 } + }) + } } } diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 375ff2d245044..b358fdcc56a7f 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -4,6 +4,7 @@ #[cfg(test)] mod tests; +#[cfg(not(target_family = "solana"))] use crate::backtrace::Backtrace; use crate::fmt::{self, Write}; @@ -457,6 +458,7 @@ impl Report where E: Error, { + #[cfg(not(target_family = "solana"))] fn backtrace(&self) -> Option<&Backtrace> { // have to grab the backtrace on the first error directly since that error may not be // 'static @@ -507,6 +509,7 @@ where } } + #[cfg(not(target_family = "solana"))] if self.show_backtrace { let backtrace = self.backtrace(); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 7d70a0bac24fd..a2eb9e758ed56 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -310,6 +310,7 @@ use crate::sys_common::memchr; pub use self::buffered::WriterPanicked; #[unstable(feature = "raw_os_error_ty", issue = "107792")] pub use self::error::RawOsError; +#[cfg(not(target_family = "solana"))] pub(crate) use self::stdio::attempt_print_to_stderr; #[unstable(feature = "internal_output_capture", issue = "none")] #[doc(no_inline, hidden)] @@ -344,6 +345,7 @@ mod util; const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; +#[cfg(not(target_family = "solana"))] pub(crate) use stdio::cleanup; struct Guard<'a> { diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 05b21eeb40f71..76e48322ad7e2 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -5,16 +5,25 @@ mod tests; use crate::io::prelude::*; +#[cfg(not(target_family = "solana"))] use crate::cell::{Cell, RefCell}; use crate::fmt; +#[cfg(not(target_family = "solana"))] use crate::fs::File; +#[cfg(not(target_family = "solana"))] use crate::io::{self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines}; +#[cfg(target_family = "solana")] +use crate::io::{self, BorrowedCursor, BufReader, IoSlice, IoSliceMut}; +#[cfg(not(target_family = "solana"))] use crate::sync::atomic::{AtomicBool, Ordering}; -use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard}; +use crate::sync::{Arc, Mutex, MutexGuard}; +#[cfg(not(target_family = "solana"))] +use crate::sync::{OnceLock, ReentrantMutex, ReentrantMutexGuard}; use crate::sys::stdio; type LocalStream = Arc>>; +#[cfg(not(target_family = "solana"))] thread_local! { /// Used by the test crate to capture the output of the print macros and panics. static OUTPUT_CAPTURE: Cell> = { @@ -34,6 +43,7 @@ thread_local! { /// have a consistent order between set_output_capture and print_to *within /// the same thread*. Within the same thread, things always have a perfectly /// consistent order. So Ordering::Relaxed is fine. +#[cfg(not(target_family = "solana"))] static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false); /// A handle to a raw instance of the standard input stream of this process. @@ -62,6 +72,7 @@ struct StderrRaw(stdio::Stderr); /// /// The returned handle has no external synchronization or buffering. #[unstable(feature = "libstd_sys_internals", issue = "none")] +#[cfg(not(target_family = "solana"))] const fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) } @@ -76,6 +87,7 @@ const fn stdin_raw() -> StdinRaw { /// The returned handle has no external synchronization or buffering layered on /// top. #[unstable(feature = "libstd_sys_internals", issue = "none")] +#[cfg(not(target_family = "solana"))] const fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) } @@ -88,6 +100,7 @@ const fn stdout_raw() -> StdoutRaw { /// The returned handle has no external synchronization or buffering layered on /// top. #[unstable(feature = "libstd_sys_internals", issue = "none")] +#[cfg(not(target_family = "solana"))] const fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) } @@ -230,6 +243,7 @@ fn handle_ebadf(r: io::Result, default: T) -> io::Result { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct Stdin { + #[cfg(not(target_family = "solana"))] inner: &'static Mutex>, } @@ -319,6 +333,7 @@ pub struct StdinLock<'a> { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] pub fn stdin() -> Stdin { static INSTANCE: OnceLock>> = OnceLock::new(); Stdin { @@ -328,6 +343,13 @@ pub fn stdin() -> Stdin { } } +/// SBF dummy +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +pub fn stdin() -> Stdin { + Stdin {} +} + impl Stdin { /// Locks this handle to the standard input stream, returning a readable /// guard. @@ -351,6 +373,7 @@ impl Stdin { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(target_family = "solana"))] pub fn lock(&self) -> StdinLock<'static> { // Locks this handle with 'static lifetime. This depends on the // implementation detail that the underlying `Mutex` is static. @@ -384,6 +407,7 @@ impl Stdin { /// in which case it will wait for the Enter key to be pressed before /// continuing #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(target_family = "solana"))] pub fn read_line(&self, buf: &mut String) -> io::Result { self.lock().read_line(buf) } @@ -405,6 +429,7 @@ impl Stdin { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "stdin_forwarders", since = "1.62.0")] + #[cfg(not(target_family = "solana"))] pub fn lines(self) -> Lines> { self.lock().lines() } @@ -418,6 +443,7 @@ impl fmt::Debug for Stdin { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] impl Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.lock().read(buf) @@ -443,6 +469,33 @@ impl Read for Stdin { } } +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +impl Read for Stdin { + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + Ok(0) + } + fn read_buf(&mut self, _buf: BorrowedCursor<'_>) -> io::Result<()> { + Ok(()) + } + fn read_vectored(&mut self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result { + Ok(0) + } + #[inline] + fn is_read_vectored(&self) -> bool { + false + } + fn read_to_end(&mut self, _buf: &mut Vec) -> io::Result { + Ok(0) + } + fn read_to_string(&mut self, _buf: &mut String) -> io::Result { + Ok(0) + } + fn read_exact(&mut self, _buf: &mut [u8]) -> io::Result<()> { + Ok(()) + } +} + // only used by platform-dependent io::copy specializations, i.e. unused on some platforms #[cfg(any(target_os = "linux", target_os = "android"))] impl StdinLock<'_> { @@ -536,6 +589,7 @@ pub struct Stdout { // FIXME: this should be LineWriter or BufWriter depending on the state of // stdout (tty or not). Note that if this is not line buffered it // should also flush-on-panic or some form of flush-on-abort. + #[cfg(not(target_family = "solana"))] inner: &'static ReentrantMutex>>, } @@ -557,10 +611,18 @@ pub struct Stdout { /// standard library or via raw Windows API calls, will fail. #[must_use = "if unused stdout will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] pub struct StdoutLock<'a> { inner: ReentrantMutexGuard<'a, RefCell>>, } +/// SBF dummy +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +pub struct StdoutLock { +} + +#[cfg(not(target_family = "solana"))] static STDOUT: OnceLock>>> = OnceLock::new(); /// Constructs a new handle to the standard output of the current process. @@ -612,6 +674,7 @@ static STDOUT: OnceLock>>> = OnceLo #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "io_stdout")] +#[cfg(not(target_family = "solana"))] pub fn stdout() -> Stdout { Stdout { inner: STDOUT @@ -619,9 +682,17 @@ pub fn stdout() -> Stdout { } } +/// Dummy stdout for SBF target +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +pub fn stdout() -> Stdout { + Stdout {} +} + // Flush the data and disable buffering during shutdown // by replacing the line writer by one with zero // buffering capacity. +#[cfg(not(target_family = "solana"))] pub fn cleanup() { let mut initialized = false; let stdout = STDOUT.get_or_init(|| { @@ -661,12 +732,23 @@ impl Stdout { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(target_family = "solana"))] pub fn lock(&self) -> StdoutLock<'static> { // Locks this handle with 'static lifetime. This depends on the // implementation detail that the underlying `ReentrantMutex` is // static. StdoutLock { inner: self.inner.lock() } } + + /// Dummy lock for SBF + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(target_family = "solana")] + pub fn lock(&self) -> StdoutLock { + // Locks this handle with 'static lifetime. This depends on the + // implementation detail that the underlying `ReentrantMutex` is + // static. + StdoutLock { } + } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -677,6 +759,7 @@ impl fmt::Debug for Stdout { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] impl Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { (&*self).write(buf) @@ -702,7 +785,37 @@ impl Write for Stdout { } } +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +impl Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + crate::sys::sol_log(buf); + Ok(buf.len()) + } + fn write_vectored(&mut self, _bufs: &[IoSlice<'_>]) -> io::Result { + Ok(0) + } + #[inline] + fn is_write_vectored(&self) -> bool { + false + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + crate::sys::sol_log(buf); + Ok(()) + } + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } +} + #[stable(feature = "write_mt", since = "1.48.0")] +#[cfg(not(target_family = "solana"))] impl Write for &Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { self.lock().write(buf) @@ -729,6 +842,7 @@ impl Write for &Stdout { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] impl Write for StdoutLock<'_> { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.borrow_mut().write(buf) @@ -751,13 +865,48 @@ impl Write for StdoutLock<'_> { } } +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +impl Write for StdoutLock { + fn write(&mut self, buf: &[u8]) -> io::Result { + crate::sys::sol_log(buf); + Ok(buf.len()) + } + fn write_vectored(&mut self, _bufs: &[IoSlice<'_>]) -> io::Result { + Ok(0) + } + #[inline] + fn is_write_vectored(&self) -> bool { + false + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + crate::sys::sol_log(buf); + Ok(()) + } + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } +} + #[stable(feature = "std_debug", since = "1.16.0")] +#[cfg(not(target_family = "solana"))] impl fmt::Debug for StdoutLock<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("StdoutLock").finish_non_exhaustive() } } +#[stable(feature = "std_debug", since = "1.16.0")] +#[cfg(target_family = "solana")] +impl fmt::Debug for StdoutLock { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("StdoutLock { .. }") + } +} + /// A handle to the standard error stream of a process. /// /// For more information, see the [`io::stderr`] method. @@ -777,6 +926,7 @@ impl fmt::Debug for StdoutLock<'_> { /// standard library or via raw Windows API calls, will fail. #[stable(feature = "rust1", since = "1.0.0")] pub struct Stderr { + #[cfg(not(target_family = "solana"))] inner: &'static ReentrantMutex>, } @@ -798,10 +948,17 @@ pub struct Stderr { /// standard library or via raw Windows API calls, will fail. #[must_use = "if unused stderr will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] pub struct StderrLock<'a> { inner: ReentrantMutexGuard<'a, RefCell>, } +/// SBF dummy +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +pub struct StderrLock { +} + /// Constructs a new handle to the standard error of the current process. /// /// This handle is not buffered. @@ -849,6 +1006,7 @@ pub struct StderrLock<'a> { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "io_stderr")] +#[cfg(not(target_family = "solana"))] pub fn stderr() -> Stderr { // Note that unlike `stdout()` we don't use `at_exit` here to register a // destructor. Stderr is not buffered, so there's no need to run a @@ -859,6 +1017,13 @@ pub fn stderr() -> Stderr { Stderr { inner: &INSTANCE } } +/// SBF dummy +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +pub fn stderr() -> Stderr { + Stderr {} +} + impl Stderr { /// Locks this handle to the standard error stream, returning a writable /// guard. @@ -881,6 +1046,7 @@ impl Stderr { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(target_family = "solana"))] pub fn lock(&self) -> StderrLock<'static> { // Locks this handle with 'static lifetime. This depends on the // implementation detail that the underlying `ReentrantMutex` is @@ -897,6 +1063,7 @@ impl fmt::Debug for Stderr { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] impl Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { (&*self).write(buf) @@ -922,7 +1089,37 @@ impl Write for Stderr { } } +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +impl Write for Stderr { + fn write(&mut self, buf: &[u8]) -> io::Result { + crate::sys::sol_log(buf); + Ok(buf.len()) + } + fn write_vectored(&mut self, _bufs: &[IoSlice<'_>]) -> io::Result { + Ok(0) + } + #[inline] + fn is_write_vectored(&self) -> bool { + false + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + crate::sys::sol_log(buf); + Ok(()) + } + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } +} + #[stable(feature = "write_mt", since = "1.48.0")] +#[cfg(not(target_family = "solana"))] impl Write for &Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { self.lock().write(buf) @@ -949,6 +1146,7 @@ impl Write for &Stderr { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] impl Write for StderrLock<'_> { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.borrow_mut().write(buf) @@ -972,13 +1170,23 @@ impl Write for StderrLock<'_> { } #[stable(feature = "std_debug", since = "1.16.0")] +#[cfg(not(target_family = "solana"))] impl fmt::Debug for StderrLock<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("StderrLock").finish_non_exhaustive() } } +#[stable(feature = "std_debug", since = "1.16.0")] +#[cfg(target_family = "solana")] +impl fmt::Debug for StderrLock { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("StderrLock { .. }") + } +} + /// Sets the thread-local output capture buffer and returns the old one. +#[cfg(not(target_family = "solana"))] #[unstable( feature = "internal_output_capture", reason = "this function is meant for use in the test crate \ @@ -995,6 +1203,19 @@ pub fn set_output_capture(sink: Option) -> Option { OUTPUT_CAPTURE.with(move |slot| slot.replace(sink)) } +/// Dummy version for satisfying test library dependencies when building the SBF target. +#[cfg(target_family = "solana")] +#[unstable( + feature = "internal_output_capture", + reason = "this function is meant for use in the test crate \ + and may disappear in the future", + issue = "none" +)] +#[doc(hidden)] +pub fn set_output_capture(_sink: Option) -> Option { + None +} + /// Write `args` to the capture buffer if enabled and possible, or `global_s` /// otherwise. `label` identifies the stream in a panic message. /// @@ -1008,6 +1229,7 @@ pub fn set_output_capture(sink: Option) -> Option { /// /// Writing to non-blocking stdout/stderr can cause an error, which will lead /// this function to panic. +#[cfg(not(target_family = "solana"))] fn print_to(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str) where T: Write, @@ -1022,6 +1244,7 @@ where } } +#[cfg(not(target_family = "solana"))] fn print_to_buffer_if_capture_used(args: fmt::Arguments<'_>) -> bool { OUTPUT_CAPTURE_USED.load(Ordering::Relaxed) && OUTPUT_CAPTURE.try_with(|s| { @@ -1038,6 +1261,7 @@ fn print_to_buffer_if_capture_used(args: fmt::Arguments<'_>) -> bool { /// Used by impl Termination for Result to print error after `main` or a test /// has returned. Should avoid panicking, although we can't help it if one of /// the Display impls inside args decides to. +#[cfg(not(target_family = "solana"))] pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) { if print_to_buffer_if_capture_used(args) { return; @@ -1069,6 +1293,7 @@ pub trait IsTerminal: crate::sealed::Sealed { fn is_terminal(&self) -> bool; } +#[cfg(not(target_family = "solana"))] macro_rules! impl_is_terminal { ($($t:ty),*$(,)?) => {$( #[unstable(feature = "sealed", issue = "none")] @@ -1084,6 +1309,7 @@ macro_rules! impl_is_terminal { )*} } +#[cfg(not(target_family = "solana"))] impl_is_terminal!(File, Stdin, StdinLock<'_>, Stdout, StdoutLock<'_>, Stderr, StderrLock<'_>); #[unstable( @@ -1093,10 +1319,21 @@ impl_is_terminal!(File, Stdin, StdinLock<'_>, Stdout, StdoutLock<'_>, Stderr, St )] #[doc(hidden)] #[cfg(not(test))] +#[cfg(not(target_family = "solana"))] pub fn _print(args: fmt::Arguments<'_>) { print_to(args, stdout, "stdout"); } +#[unstable( + feature = "print_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none")] +#[doc(hidden)] +#[cfg(not(test))] +#[cfg(target_family = "solana")] +pub fn _print(_args: fmt::Arguments<'_>) { +} + #[unstable( feature = "print_internals", reason = "implementation detail which may disappear or be replaced at any time", @@ -1104,9 +1341,20 @@ pub fn _print(args: fmt::Arguments<'_>) { )] #[doc(hidden)] #[cfg(not(test))] +#[cfg(not(target_family = "solana"))] pub fn _eprint(args: fmt::Arguments<'_>) { print_to(args, stderr, "stderr"); } +#[unstable( + feature = "print_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none")] +#[doc(hidden)] +#[cfg(not(test))] +#[cfg(target_family = "solana")] +pub fn _eprint(_args: fmt::Arguments<'_>) { +} + #[cfg(test)] pub use realstd::io::{_eprint, _print}; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 425890122577f..43cdd9a0a6ae2 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -432,6 +432,7 @@ extern crate unwind; not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))), feature = "miniz_oxide" ))] +#[cfg(all(not(target_family = "solana"), feature = "miniz_oxide"))] extern crate miniz_oxide; // During testing, this crate is not actually the "real" std library, but rather @@ -640,6 +641,7 @@ pub mod alloc; // Private support modules mod panicking; +#[cfg(not(target_family = "solana"))] #[path = "../../backtrace/src/lib.rs"] #[allow(dead_code, unused_attributes, fuzzy_provenance_casts)] mod backtrace_rs; diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 69a6f3e6d5ac4..956bd2e86f568 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -5,6 +5,7 @@ use crate::any::Any; use crate::collections; use crate::panicking; +#[cfg(not(target_family = "solana"))] use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::{Mutex, RwLock}; use crate::thread::Result; @@ -56,6 +57,7 @@ pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe}; /// accessed later using [`PanicInfo::payload`]. /// /// See the [`panic!`] macro for more information about panicking. +#[cfg(not(target_family = "solana"))] #[stable(feature = "panic_any", since = "1.51.0")] #[inline] #[track_caller] @@ -168,10 +170,19 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { /// } /// ``` #[stable(feature = "resume_unwind", since = "1.9.0")] +#[cfg(not(target_family = "solana"))] pub fn resume_unwind(payload: Box) -> ! { panicking::rust_panic_without_hook(payload) } +/// SBF version of resume_unwind +#[stable(feature = "resume_unwind", since = "1.9.0")] +#[cfg(target_family = "solana")] +pub fn resume_unwind(_payload: Box) -> ! { + // Only used by thread, redirect to plain old panic + panicking::begin_panic_fmt(&format_args!("unwind")) +} + /// Make all future panics abort directly without running the panic hook or unwinding. /// /// There is no way to undo this; the effect lasts until the process exits or @@ -210,6 +221,7 @@ pub fn always_abort() { /// The configuration for whether and how the default panic hook will capture /// and display the backtrace. +#[cfg(not(target_family = "solana"))] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[unstable(feature = "panic_backtrace_config", issue = "93346")] #[non_exhaustive] @@ -223,6 +235,7 @@ pub enum BacktraceStyle { Off, } +#[cfg(not(target_family = "solana"))] impl BacktraceStyle { pub(crate) fn full() -> Option { if cfg!(feature = "backtrace") { Some(BacktraceStyle::Full) } else { None } @@ -251,6 +264,7 @@ impl BacktraceStyle { // that backtrace. // // Internally stores equivalent of an Option. +#[cfg(not(target_family = "solana"))] static SHOULD_CAPTURE: AtomicUsize = AtomicUsize::new(0); /// Configure whether the default panic hook will capture and display a @@ -258,6 +272,7 @@ static SHOULD_CAPTURE: AtomicUsize = AtomicUsize::new(0); /// /// The default value for this setting may be set by the `RUST_BACKTRACE` /// environment variable; see the details in [`get_backtrace_style`]. +#[cfg(not(target_family = "solana"))] #[unstable(feature = "panic_backtrace_config", issue = "93346")] pub fn set_backtrace_style(style: BacktraceStyle) { if !cfg!(feature = "backtrace") { @@ -288,6 +303,7 @@ pub fn set_backtrace_style(style: BacktraceStyle) { /// the future /// /// Returns `None` if backtraces aren't currently supported. +#[cfg(not(target_family = "solana"))] #[unstable(feature = "panic_backtrace_config", issue = "93346")] pub fn get_backtrace_style() -> Option { if !cfg!(feature = "backtrace") { diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 55f4917a93705..3e3c871ad7f58 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -9,26 +9,38 @@ #![deny(unsafe_op_in_unsafe_fn)] +#[cfg(not(target_family = "solana"))] use crate::panic::BacktraceStyle; -use core::panic::{Location, PanicInfo, PanicPayload}; +#[cfg(not(target_family = "solana"))] +use core::panic::{PanicPayload}; +use core::panic::{Location, PanicInfo}; use crate::any::Any; use crate::fmt; use crate::intrinsics; -use crate::mem::{self, ManuallyDrop}; +use crate::mem::ManuallyDrop; +#[cfg(not(target_family = "solana"))] +use crate::mem; +#[cfg(not(target_family = "solana"))] use crate::process; +#[cfg(not(target_family = "solana"))] use crate::sync::atomic::{AtomicBool, Ordering}; +#[cfg(not(target_family = "solana"))] use crate::sync::{PoisonError, RwLock}; +#[cfg(not(target_family = "solana"))] use crate::sys::stdio::panic_output; +#[cfg(not(target_family = "solana"))] use crate::sys_common::backtrace; +#[cfg(not(target_family = "solana"))] use crate::sys_common::thread_info; +#[cfg(not(target_family = "solana"))] use crate::thread; -#[cfg(not(test))] +#[cfg(all(not(test), not(target_family = "solana")))] use crate::io::set_output_capture; // make sure to use the stderr output configured // by libtest in the real copy of std -#[cfg(test)] +#[cfg(all(test, not(target_family = "solana")))] use realstd::io::set_output_capture; // Binary interface to the panic runtime that the standard library depends on. @@ -49,13 +61,14 @@ extern "C" { extern "Rust" { /// `PanicPayload` lazily performs allocation only when needed (this avoids /// allocations when using the "abort" panic runtime). + #[cfg(not(target_family = "solana"))] fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32; } /// This function is called by the panic runtime if FFI code catches a Rust /// panic but doesn't rethrow it. We don't support this case since it messes /// with our panic count. -#[cfg(not(test))] +#[cfg(all(not(test), not(target_family = "solana")))] #[rustc_std_internal_symbol] extern "C" fn __rust_drop_panic() -> ! { rtabort!("Rust panics must be rethrown"); @@ -63,17 +76,19 @@ extern "C" fn __rust_drop_panic() -> ! { /// This function is called by the panic runtime if it catches an exception /// object which does not correspond to a Rust panic. -#[cfg(not(test))] +#[cfg(all(not(test), not(target_family = "solana")))] #[rustc_std_internal_symbol] extern "C" fn __rust_foreign_exception() -> ! { rtabort!("Rust cannot catch foreign exceptions"); } +#[cfg(not(target_family = "solana"))] enum Hook { Default, Custom(Box) + 'static + Sync + Send>), } +#[cfg(not(target_family = "solana"))] impl Hook { #[inline] fn into_box(self) -> Box) + 'static + Sync + Send> { @@ -84,6 +99,7 @@ impl Hook { } } +#[cfg(not(target_family = "solana"))] impl Default for Hook { #[inline] fn default() -> Hook { @@ -91,6 +107,7 @@ impl Default for Hook { } } +#[cfg(not(target_family = "solana"))] static HOOK: RwLock = RwLock::new(Hook::Default); /// Registers a custom panic hook, replacing the previously registered hook. @@ -129,6 +146,7 @@ static HOOK: RwLock = RwLock::new(Hook::Default); /// /// panic!("Normal panic"); /// ``` +#[cfg(not(target_family = "solana"))] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn set_hook(hook: Box) + 'static + Sync + Send>) { if thread::panicking() { @@ -144,6 +162,12 @@ pub fn set_hook(hook: Box) + 'static + Sync + Send>) { drop(old); } +/// Dummy version for satisfying library/test dependencies for SBF target +#[cfg(target_family = "solana")] +#[stable(feature = "panic_hooks", since = "1.10.0")] +pub fn set_hook(_hook: Box) + 'static + Sync + Send>) { +} + /// Unregisters the current panic hook and returns it, registering the default hook /// in its place. /// @@ -173,6 +197,7 @@ pub fn set_hook(hook: Box) + 'static + Sync + Send>) { /// panic!("Normal panic"); /// ``` #[must_use] +#[cfg(not(target_family = "solana"))] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn take_hook() -> Box) + 'static + Sync + Send> { if thread::panicking() { @@ -186,6 +211,13 @@ pub fn take_hook() -> Box) + 'static + Sync + Send> { old_hook.into_box() } +/// Dummy version for satisfying library/test dependencies for BPF target +#[cfg(target_family = "solana")] +#[stable(feature = "panic_hooks", since = "1.10.0")] +pub fn take_hook() -> Box) + 'static + Sync + Send> { + Box::new(default_hook) +} + /// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with /// a new panic handler that does something and then executes the old handler. /// @@ -217,6 +249,7 @@ pub fn take_hook() -> Box) + 'static + Sync + Send> { /// /// panic!("Custom and then normal"); /// ``` +#[cfg(not(target_family = "solana"))] #[unstable(feature = "panic_update_hook", issue = "92649")] pub fn update_hook(hook_fn: F) where @@ -234,7 +267,20 @@ where *hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info))); } +/// Dummy version for satisfying library/test dependencies for SBF target +#[cfg(target_family = "solana")] +#[unstable(feature = "panic_update_hook", issue = "92649")] +pub fn update_hook(_hook_fn: F) +where + F: Fn(&(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static), &PanicInfo<'_>) + + Sync + + Send + + 'static, +{ +} + /// The default panic handler. +#[cfg(not(target_family = "solana"))] fn default_hook(info: &PanicInfo<'_>) { // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. @@ -293,6 +339,10 @@ fn default_hook(info: &PanicInfo<'_>) { } } +#[cfg(target_family = "solana")] +fn default_hook(_info: &PanicInfo<'_>) { +} + #[cfg(not(test))] #[doc(hidden)] #[cfg(feature = "panic_immediate_abort")] @@ -338,6 +388,7 @@ pub mod panic_count { #[cfg(not(feature = "panic_immediate_abort"))] #[unstable(feature = "update_panic_count", issue = "none")] pub mod panic_count { + #[cfg(not(target_family = "solana"))] use crate::cell::Cell; use crate::sync::atomic::{AtomicUsize, Ordering}; @@ -352,6 +403,7 @@ pub mod panic_count { // Panic count for the current thread and whether a panic hook is currently // being executed.. + #[cfg(not(target_family = "solana"))] thread_local! { static LOCAL_PANIC_COUNT: Cell<(usize, bool)> = const { Cell::new((0, false)) } } @@ -388,6 +440,7 @@ pub mod panic_count { // // This also updates thread-local state to keep track of whether a panic // hook is currently executing. + #[cfg(not(target_family = "solana"))] pub fn increase(run_panic_hook: bool) -> Option { let global_count = GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed); if global_count & ALWAYS_ABORT_FLAG != 0 { @@ -404,6 +457,7 @@ pub mod panic_count { }) } + #[cfg(not(target_family = "solana"))] pub fn finished_panic_hook() { LOCAL_PANIC_COUNT.with(|c| { let (count, _) = c.get(); @@ -411,6 +465,7 @@ pub mod panic_count { }); } + #[cfg(not(target_family = "solana"))] pub fn decrease() { GLOBAL_PANIC_COUNT.fetch_sub(1, Ordering::Relaxed); LOCAL_PANIC_COUNT.with(|c| { @@ -425,12 +480,14 @@ pub mod panic_count { // Disregards ALWAYS_ABORT_FLAG #[must_use] + #[cfg(not(target_family = "solana"))] pub fn get_count() -> usize { LOCAL_PANIC_COUNT.with(|c| c.get().0) } // Disregards ALWAYS_ABORT_FLAG #[must_use] + #[cfg(not(target_family = "solana"))] #[inline] pub fn count_is_zero() -> bool { if GLOBAL_PANIC_COUNT.load(Ordering::Relaxed) & !ALWAYS_ABORT_FLAG == 0 { @@ -451,6 +508,7 @@ pub mod panic_count { // Slow path is in a separate function to reduce the amount of code // inlined from `count_is_zero`. + #[cfg(not(target_family = "solana"))] #[inline(never)] #[cold] fn is_zero_slow_path() -> bool { @@ -525,6 +583,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // optimizer (in most cases this function is not inlined even as a normal, // non-cold function, though, as of the writing of this comment). #[cold] + #[cfg(not(target_family = "solana"))] unsafe fn cleanup(payload: *mut u8) -> Box { // SAFETY: The whole unsafe block hinges on a correct implementation of // the panic handler `__rust_panic_cleanup`. As such we can only @@ -535,6 +594,17 @@ pub unsafe fn r#try R>(f: F) -> Result> obj } + #[cold] + #[cfg(target_family = "solana")] + unsafe fn cleanup(payload: *mut u8) -> Box { + // SAFETY: The whole unsafe block hinges on a correct implementation of + // the panic handler `__rust_panic_cleanup`. As such we can only + // assume it returns the correct thing for `Box::from_raw` to work + // without undefined behavior. + let obj = unsafe { Box::from_raw(__rust_panic_cleanup(payload)) }; + obj + } + // SAFETY: // data must be non-NUL, correctly aligned, and a pointer to a `Data` // Its must contains a valid `f` (type: F) value that can be use to fill @@ -582,13 +652,14 @@ pub unsafe fn r#try R>(f: F) -> Result> } /// Determines whether the current thread is unwinding because of panic. +#[cfg(not(target_family = "solana"))] #[inline] pub fn panicking() -> bool { !panic_count::count_is_zero() } /// Entry point of panics from the core crate (`panic_impl` lang item). -#[cfg(not(test))] +#[cfg(not(any(test, target_family = "solana")))] #[panic_handler] pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { struct FormatStringPayload<'a> { @@ -668,6 +739,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { /// This is the entry point of panicking for the non-format-string variants of /// panic!() and assert!(). In particular, this is the only entry point that supports /// arbitrary payloads, not just format strings. +#[cfg(not(target_family = "solana"))] #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")] #[cfg_attr(not(test), lang = "begin_panic")] // lang item for CTFE panic support @@ -731,6 +803,7 @@ pub const fn begin_panic(msg: M) -> ! { /// Executes the primary logic for a panic, including checking for recursive /// panics, panic hooks, and finally dispatching to the panic runtime to either /// abort or unwind. +#[cfg(not(target_family = "solana"))] fn rust_panic_with_hook( payload: &mut dyn PanicPayload, message: Option<&fmt::Arguments<'_>>, @@ -804,6 +877,7 @@ fn rust_panic_with_hook( /// This is the entry point for `resume_unwind`. /// It just forwards the payload to the panic runtime. #[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg(not(target_family = "solana"))] pub fn rust_panic_without_hook(payload: Box) -> ! { panic_count::increase(false); @@ -824,6 +898,7 @@ pub fn rust_panic_without_hook(payload: Box) -> ! { /// An unmangled function (through `rustc_std_internal_symbol`) on which to slap /// yer breakpoints. +#[cfg(not(target_family = "solana"))] #[inline(never)] #[cfg_attr(not(test), rustc_std_internal_symbol)] #[cfg(not(feature = "panic_immediate_abort"))] @@ -839,3 +914,67 @@ fn rust_panic(_: &mut dyn PanicPayload) -> ! { crate::intrinsics::abort(); } } + +// Note: The panicking functions have been stripped and rewritten +// in order to save space in SBF programs. Panic messages +// are not supported, just file, line, column. + +/// This function is called by the panic runtime if it catches an exception +/// object which does not correspond to a Rust panic. +#[cfg(all(not(test), target_family = "solana"))] +#[rustc_std_internal_symbol] +extern "C" fn __rust_foreign_exception() -> ! { + rtabort!("Rust cannot catch foreign exceptions"); +} + +/// Determines whether the current thread is unwinding because of panic. +#[cfg(target_family = "solana")] +pub fn panicking() -> bool { + true +} + +/// Entry point of panic from the libcore crate. +#[cfg(all(not(test), target_family = "solana"))] +#[panic_handler] +pub fn rust_begin_panic(info: &PanicInfo<'_>) -> ! { + crate::sys::panic(info); +} + +/// Entry point of panicking for panic!() and assert!() SBF version. +#[cfg(target_family = "solana")] +#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")] +#[cfg_attr(not(test), lang = "begin_panic")] +// lang item for CTFE panic support +// never inline unless panic_immediate_abort to avoid code +// bloat at the call sites as much as possible +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cold] +#[track_caller] +pub fn begin_panic(_msg: M) -> ! { + let info = PanicInfo::internal_constructor( + None, + Location::caller(), + false, + false, + ); + crate::sys::panic(&info); +} + +/// The entry point for panicking with a formatted message SBF version. +#[cfg(target_family = "solana")] +#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")] +#[cold] +// If panic_immediate_abort, inline the abort call, +// otherwise avoid inlining because of it is cold path. +#[cfg_attr(not(feature = "panic_immediate_abort"), track_caller)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! { + let info = PanicInfo::internal_constructor( + Some(msg), + Location::caller(), + false, + false, + ); + crate::sys::panic(&info); +} diff --git a/library/std/src/process.rs b/library/std/src/process.rs index af6bef1a76e69..510b4af13c8c5 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2207,6 +2207,7 @@ impl Child { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "process_exit")] pub fn exit(code: i32) -> ! { + #[cfg(not(target_family = "solana"))] crate::rt::cleanup(); crate::sys::os::exit(code) } @@ -2360,10 +2361,15 @@ impl Termination for Result { fn report(self) -> ExitCode { match self { Ok(val) => val.report(), + #[cfg(not(target_family = "solana"))] Err(err) => { io::attempt_print_to_stderr(format_args_nl!("Error: {err:?}")); ExitCode::FAILURE } + #[cfg(target_family = "solana")] + Err(_err) => { + ExitCode::FAILURE + } } } } diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 5c83f72f3c1a1..5bac2a8b942ec 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -16,15 +16,20 @@ #![deny(unsafe_op_in_unsafe_fn)] #![allow(unused_macros)] +#[cfg(not(target_family = "solana"))] use crate::ffi::CString; // Re-export some of our utilities which are expected by other crates. pub use crate::panicking::{begin_panic, panic_count}; pub use core::panicking::{panic_display, panic_fmt}; +#[cfg(not(target_family = "solana"))] use crate::sync::Once; +#[cfg(not(target_family = "solana"))] use crate::sys; +#[cfg(not(target_family = "solana"))] use crate::sys_common::thread_info; +#[cfg(not(target_family = "solana"))] use crate::thread::Thread; // Prints to the "panic output", depending on the platform this may be: @@ -92,6 +97,7 @@ macro_rules! rtunwrap { // Even though it is an `u8`, it only ever has 4 values. These are documented in // `compiler/rustc_session/src/config/sigpipe.rs`. #[cfg_attr(test, allow(dead_code))] +#[cfg(not(target_family = "solana"))] unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { unsafe { sys::init(argc, argv, sigpipe); @@ -109,6 +115,7 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { // One-time runtime cleanup. // Runs after `main` or at program exit. // NOTE: this is not guaranteed to run, for example when the program aborts. +#[cfg(not(target_family = "solana"))] pub(crate) fn cleanup() { static CLEANUP: Once = Once::new(); CLEANUP.call_once(|| unsafe { @@ -122,6 +129,7 @@ pub(crate) fn cleanup() { // To reduce the generated code of the new `lang_start`, this function is doing // the real work. #[cfg(not(test))] +#[cfg(not(target_family = "solana"))] fn lang_start_internal( main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe), argc: isize, @@ -156,6 +164,7 @@ fn lang_start_internal( #[cfg(not(test))] #[inline(never)] +#[cfg(not(target_family = "solana"))] #[lang = "start"] fn lang_start( main: fn() -> T, @@ -171,3 +180,15 @@ fn lang_start( ); v } + +#[cfg(not(test))] +#[cfg(target_family = "solana")] +#[lang = "start"] +fn lang_start( + main: fn() -> T, + _argc: isize, + _argv: *const *const u8, + _sigpipe: u8, +) -> isize { + main().report().to_i32() as isize +} diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index f6a7c0a9f7549..017a09f8915fc 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -180,6 +180,7 @@ pub use self::lazy_lock::LazyLock; #[stable(feature = "once_cell", since = "1.70.0")] pub use self::once_lock::OnceLock; +#[cfg(not(target_family = "solana"))] pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard}; pub mod mpsc; diff --git a/library/std/src/sync/mpmc/context.rs b/library/std/src/sync/mpmc/context.rs index bbfc6ce00ffc2..8cd1f60a57c9c 100644 --- a/library/std/src/sync/mpmc/context.rs +++ b/library/std/src/sync/mpmc/context.rs @@ -3,6 +3,7 @@ use super::select::Selected; use super::waker::current_thread_id; +#[cfg(not(target_family = "solana"))] use crate::cell::Cell; use crate::ptr; use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; @@ -34,6 +35,7 @@ struct Inner { impl Context { /// Creates a new context for the duration of the closure. + #[cfg(not(target_family = "solana"))] #[inline] pub fn with(f: F) -> R where @@ -63,6 +65,15 @@ impl Context { .unwrap_or_else(|_| f(&Context::new())) } + #[cfg(target_family = "solana")] + #[inline] + pub fn with(f: F) -> R + where + F: FnOnce(&Context) -> R, + { + f(&Context::new()) + } + /// Creates a new `Context`. #[cold] fn new() -> Context { @@ -77,6 +88,7 @@ impl Context { } /// Resets `select` and `packet`. + #[cfg(not(target_family = "solana"))] #[inline] fn reset(&self) { self.inner.select.store(Selected::Waiting.into(), Ordering::Release); diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs index 0cbc61160f7ee..9fb7e6672b3d4 100644 --- a/library/std/src/sync/mpmc/utils.rs +++ b/library/std/src/sync/mpmc/utils.rs @@ -3,6 +3,7 @@ use crate::ops::{Deref, DerefMut}; /// Pads and aligns a value to the length of a cache line. #[derive(Clone, Copy, Default, Hash, PartialEq, Eq)] +#[cfg_attr(target_family = "solana", repr(align(8)))] // Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache // lines at a time, so we have to align to 128 bytes rather than 64. // @@ -66,6 +67,7 @@ use crate::ops::{Deref, DerefMut}; target_arch = "mips64r6", target_arch = "riscv64", target_arch = "s390x", + target_family = "solana", )), repr(align(64)) )] diff --git a/library/std/src/sync/mpmc/waker.rs b/library/std/src/sync/mpmc/waker.rs index 9aab1b9417edb..21b1802f3464b 100644 --- a/library/std/src/sync/mpmc/waker.rs +++ b/library/std/src/sync/mpmc/waker.rs @@ -201,6 +201,7 @@ impl Drop for SyncWaker { } /// Returns a unique id for the current thread. +#[cfg(not(target_family = "solana"))] #[inline] pub fn current_thread_id() -> usize { // `u8` is not drop so this variable will be available during thread destruction, @@ -208,3 +209,10 @@ pub fn current_thread_id() -> usize { thread_local! { static DUMMY: u8 = 0 } DUMMY.with(|x| (x as *const u8).addr()) } + +/// Returns a unique id for the current thread. +#[cfg(target_family = "solana")] +#[inline] +pub fn current_thread_id() -> usize { + 0 +} diff --git a/library/std/src/sync/remutex.rs b/library/std/src/sync/remutex.rs index 0ced48d10b7c6..5d38a70dd2d5f 100644 --- a/library/std/src/sync/remutex.rs +++ b/library/std/src/sync/remutex.rs @@ -72,6 +72,7 @@ impl !Send for ReentrantMutexGuard<'_, T> {} impl ReentrantMutex { /// Creates a new reentrant mutex in an unlocked state. + #[cfg(not(target_family = "solana"))] pub const fn new(t: T) -> ReentrantMutex { ReentrantMutex { mutex: sys::Mutex::new(), @@ -93,6 +94,7 @@ impl ReentrantMutex { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. + #[cfg(not(target_family = "solana"))] pub fn lock(&self) -> ReentrantMutexGuard<'_, T> { let this_thread = current_thread_unique_ptr(); // Safety: We only touch lock_count when we own the lock. @@ -121,6 +123,7 @@ impl ReentrantMutex { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. + #[cfg(not(target_family = "solana"))] pub fn try_lock(&self) -> Option> { let this_thread = current_thread_unique_ptr(); // Safety: We only touch lock_count when we own the lock. @@ -139,6 +142,7 @@ impl ReentrantMutex { } } + #[cfg(not(target_family = "solana"))] unsafe fn increment_lock_count(&self) { *self.lock_count.get() = (*self.lock_count.get()) .checked_add(1) @@ -171,6 +175,7 @@ impl Drop for ReentrantMutexGuard<'_, T> { /// Get an address that is unique per running thread. /// /// This can be used as a non-null usize-sized ID. +#[cfg(not(target_family = "solana"))] pub fn current_thread_unique_ptr() -> usize { // Use a non-drop type to make sure it's still available during thread destruction. thread_local! { static X: u8 = const { 0 } } diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 159ffe7ac9635..528194fd99b58 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -35,6 +35,9 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "solid_asp3")] { mod solid; pub use self::solid::*; + } else if #[cfg(target_family = "solana")] { + mod sbf; + pub use self::sbf::*; } else if #[cfg(target_os = "hermit")] { mod hermit; pub use self::hermit::*; @@ -60,8 +63,9 @@ cfg_if::cfg_if! { } cfg_if::cfg_if! { + if #[cfg(target_family = "solana")] { // Fuchsia components default to full backtrace. - if #[cfg(target_os = "fuchsia")] { + } else if #[cfg(target_os = "fuchsia")] { pub const FULL_BACKTRACE_DEFAULT: bool = true; } else { pub const FULL_BACKTRACE_DEFAULT: bool = false; diff --git a/library/std/src/sys/sbf/alloc.rs b/library/std/src/sys/sbf/alloc.rs new file mode 100644 index 0000000000000..e6ef85d99adf5 --- /dev/null +++ b/library/std/src/sys/sbf/alloc.rs @@ -0,0 +1,46 @@ +//! This is an implementation of a global allocator on the SBF platform. +//! In that situation there's no actual runtime for us +//! to lean on for allocation, so instead we provide our own! +//! +//! The crate itself provides a global allocator which on SBF has no +//! synchronization as there are no threads! + +use crate::alloc::{GlobalAlloc, Layout, System}; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + sol_alloc_free_(layout.size() as u64, 0) + // 0 as *mut u8 + } + + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + sol_alloc_free_(layout.size() as u64, 0) + // 0 as *mut u8 + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + sol_alloc_free_(layout.size() as u64, ptr as u64); + } + + // #[inline] + // unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // sol_alloc_free_(layout.size() as u64, 0) + // // 0 as *mut u8 + // } +} + +#[cfg(not(target_feature = "static-syscalls"))] +extern "C" { + fn sol_alloc_free_(size: u64, ptr: u64) -> *mut u8; +} + +#[cfg(target_feature = "static-syscalls")] +fn sol_alloc_free_(size: u64, ptr: u64) -> *mut u8 { + let syscall: extern "C" fn(u64, u64) -> *mut u8 = + unsafe { core::mem::transmute(2213547663u64) }; // murmur32 hash of "sol_alloc_free_" + syscall(size, ptr) +} diff --git a/library/std/src/sys/sbf/args.rs b/library/std/src/sys/sbf/args.rs new file mode 100644 index 0000000000000..eaa943769e7dd --- /dev/null +++ b/library/std/src/sys/sbf/args.rs @@ -0,0 +1,48 @@ +use crate::ffi::OsString; +use crate::marker::PhantomData; +use crate::fmt; +use crate::vec; + +pub fn args() -> Args { + panic!(); +} + +pub struct Args { + iter: vec::IntoIter, + _dont_send_or_sync_me: PhantomData<*mut ()>, +} + +impl !Send for Args {} +impl !Sync for Args {} + +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.as_slice().fmt(f) + } +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +impl ExactSizeIterator for Args { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} diff --git a/library/std/src/sys/sbf/backtrace.rs b/library/std/src/sys/sbf/backtrace.rs new file mode 100644 index 0000000000000..7d56b298997aa --- /dev/null +++ b/library/std/src/sys/sbf/backtrace.rs @@ -0,0 +1,27 @@ +use crate::io; +use crate::sys::unsupported; +use crate::sys_common::backtrace::Frame; + +pub struct BacktraceContext; + +pub fn unwind_backtrace(_frames: &mut [Frame]) + -> io::Result<(usize, BacktraceContext)> +{ + unsupported() +} + +pub fn resolve_symname(_frame: Frame, + _callback: F, + _: &BacktraceContext) -> io::Result<()> + where F: FnOnce(Option<&str>) -> io::Result<()> +{ + unsupported() +} + +pub fn foreach_symbol_fileline(_: Frame, + _: F, + _: &BacktraceContext) -> io::Result + where F: FnMut(&[u8], u32) -> io::Result<()> +{ + unsupported() +} diff --git a/library/std/src/sys/sbf/cmath.rs b/library/std/src/sys/sbf/cmath.rs new file mode 100644 index 0000000000000..d8ef962c1ac20 --- /dev/null +++ b/library/std/src/sys/sbf/cmath.rs @@ -0,0 +1,33 @@ +// These symbols are all defined in `compiler-builtins` +extern { + pub fn acos(n: f64) -> f64; + pub fn acosf(n: f32) -> f32; + pub fn asin(n: f64) -> f64; + pub fn asinf(n: f32) -> f32; + pub fn atan(n: f64) -> f64; + pub fn atan2(a: f64, b: f64) -> f64; + pub fn atan2f(a: f32, b: f32) -> f32; + pub fn atanf(n: f32) -> f32; + pub fn cbrt(n: f64) -> f64; + pub fn cbrtf(n: f32) -> f32; + pub fn cosh(n: f64) -> f64; + pub fn coshf(n: f32) -> f32; + pub fn expm1(n: f64) -> f64; + pub fn expm1f(n: f32) -> f32; + pub fn fdim(a: f64, b: f64) -> f64; + pub fn fdimf(a: f32, b: f32) -> f32; + pub fn hypot(x: f64, y: f64) -> f64; + pub fn hypotf(x: f32, y: f32) -> f32; + pub fn log1p(n: f64) -> f64; + pub fn log1pf(n: f32) -> f32; + pub fn sinh(n: f64) -> f64; + pub fn sinhf(n: f32) -> f32; + pub fn tan(n: f64) -> f64; + pub fn tanf(n: f32) -> f32; + pub fn tanh(n: f64) -> f64; + pub fn tanhf(n: f32) -> f32; + pub fn tgamma(n: f64) -> f64; + pub fn tgammaf(n: f32) -> f32; + pub fn lgamma_r(n: f64, s: &mut i32) -> f64; + pub fn lgammaf_r(n: f32, s: &mut i32) -> f32; +} diff --git a/library/std/src/sys/sbf/condvar.rs b/library/std/src/sys/sbf/condvar.rs new file mode 100644 index 0000000000000..8905d07a4415b --- /dev/null +++ b/library/std/src/sys/sbf/condvar.rs @@ -0,0 +1,28 @@ +use crate::sys::mutex::Mutex; +use crate::time::Duration; + +pub struct Condvar { } + +pub type MovableCondvar = Condvar; + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { } + } + + #[inline] + pub unsafe fn notify_one(&self) { + } + + #[inline] + pub unsafe fn notify_all(&self) { + } + + pub unsafe fn wait(&self, _mutex: &Mutex) { + panic!("can't block with web assembly") + } + + pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + panic!("can't block with web assembly"); + } +} diff --git a/library/std/src/sys/sbf/condvar_atomics.rs b/library/std/src/sys/sbf/condvar_atomics.rs new file mode 100644 index 0000000000000..a9adf01ef89e8 --- /dev/null +++ b/library/std/src/sys/sbf/condvar_atomics.rs @@ -0,0 +1,48 @@ +use crate::cmp; +use crate::mem; +use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +use crate::sys::mutex::Mutex; +use crate::time::Duration; + +pub struct Condvar { + cnt: AtomicUsize, +} + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { cnt: AtomicUsize::new(0) } + } + + #[inline] + pub unsafe fn init(&mut self) { + // nothing to do... + } + + pub unsafe fn notify_one(&self) { + // nothing to do... + } + + #[inline] + pub unsafe fn notify_all(&self) { + // nothing to do... + } + + pub unsafe fn wait(&self, mutex: &Mutex) { + // nothing to do... + } + + pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + true + } + + #[inline] + pub unsafe fn destroy(&self) { + // nothing to do + } + + #[inline] + fn ptr(&self) -> *mut i32 { + assert_eq!(mem::size_of::(), mem::size_of::()); + &self.cnt as *const AtomicUsize as *mut i32 + } +} diff --git a/library/std/src/sys/sbf/env.rs b/library/std/src/sys/sbf/env.rs new file mode 100644 index 0000000000000..277aa067da2fd --- /dev/null +++ b/library/std/src/sys/sbf/env.rs @@ -0,0 +1,9 @@ +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = ""; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ".so"; + pub const EXE_EXTENSION: &str = "so"; +} diff --git a/library/std/src/sys/sbf/fs.rs b/library/std/src/sys/sbf/fs.rs new file mode 100644 index 0000000000000..54d4a18c2ed8b --- /dev/null +++ b/library/std/src/sys/sbf/fs.rs @@ -0,0 +1,328 @@ +use crate::ffi::OsString; +use crate::fmt; +use crate::hash::{Hash, Hasher}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; +use crate::path::{Path, PathBuf}; +use crate::sys::time::SystemTime; +use crate::sys::{unsupported, Void}; + +pub struct File(Void); + +pub struct FileAttr(Void); + +pub struct ReadDir(Void); + +pub struct DirEntry(Void); + +#[derive(Clone, Debug)] +pub struct OpenOptions { } + +pub struct FilePermissions(Void); + +#[derive(Copy, Clone, Debug, Default)] +pub struct FileTimes { } + +pub struct FileType(Void); + +#[derive(Debug)] +pub struct DirBuilder { } + +impl FileAttr { + pub fn size(&self) -> u64 { + match self.0 {} + } + + pub fn perm(&self) -> FilePermissions { + match self.0 {} + } + + pub fn file_type(&self) -> FileType { + match self.0 {} + } + + pub fn modified(&self) -> io::Result { + match self.0 {} + } + + pub fn accessed(&self) -> io::Result { + match self.0 {} + } + + pub fn created(&self) -> io::Result { + match self.0 {} + } +} + +impl Clone for FileAttr { + fn clone(&self) -> FileAttr { + match self.0 {} + } +} + +impl FilePermissions { + pub fn readonly(&self) -> bool { + match self.0 {} + } + + pub fn set_readonly(&mut self, _readonly: bool) { + match self.0 {} + } +} + +impl Clone for FilePermissions { + fn clone(&self) -> FilePermissions { + match self.0 {} + } +} + +impl PartialEq for FilePermissions { + fn eq(&self, _other: &FilePermissions) -> bool { + match self.0 {} + } +} + +impl Eq for FilePermissions { +} + +impl fmt::Debug for FilePermissions { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 {} + } +} + +impl FileTimes { + pub fn set_accessed(&mut self, _t: SystemTime) {} + pub fn set_modified(&mut self, _t: SystemTime) {} +} + +impl FileType { + pub fn is_dir(&self) -> bool { + match self.0 {} + } + + pub fn is_file(&self) -> bool { + match self.0 {} + } + + pub fn is_symlink(&self) -> bool { + match self.0 {} + } +} + +impl Clone for FileType { + fn clone(&self) -> FileType { + match self.0 {} + } +} + +impl Copy for FileType {} + +impl PartialEq for FileType { + fn eq(&self, _other: &FileType) -> bool { + match self.0 {} + } +} + +impl Eq for FileType { +} + +impl Hash for FileType { + fn hash(&self, _h: &mut H) { + match self.0 {} + } +} + +impl fmt::Debug for FileType { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 {} + } +} + +impl fmt::Debug for ReadDir { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 {} + } +} + +impl Iterator for ReadDir { + type Item = io::Result; + + fn next(&mut self) -> Option> { + match self.0 {} + } +} + +impl DirEntry { + pub fn path(&self) -> PathBuf { + match self.0 {} + } + + pub fn file_name(&self) -> OsString { + match self.0 {} + } + + pub fn metadata(&self) -> io::Result { + match self.0 {} + } + + pub fn file_type(&self) -> io::Result { + match self.0 {} + } +} + +impl OpenOptions { + pub fn new() -> OpenOptions { + OpenOptions { } + } + + pub fn read(&mut self, _read: bool) { } + pub fn write(&mut self, _write: bool) { } + pub fn append(&mut self, _append: bool) { } + pub fn truncate(&mut self, _truncate: bool) { } + pub fn create(&mut self, _create: bool) { } + pub fn create_new(&mut self, _create_new: bool) { } +} + +impl File { + pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result { + unsupported() + } + + pub fn file_attr(&self) -> io::Result { + match self.0 {} + } + + pub fn fsync(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn datasync(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn truncate(&self, _size: u64) -> io::Result<()> { + match self.0 {} + } + + pub fn read(&self, _buf: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result { + match self.0 {} + } + + #[inline] + pub fn is_read_vectored(&self) -> bool { + false + } + + pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { + match self.0 {} + } + + pub fn write(&self, _buf: &[u8]) -> io::Result { + match self.0 {} + } + + pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result { + match self.0 {} + } + + #[inline] + pub fn is_write_vectored(&self) -> bool { + false + } + + pub fn flush(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn seek(&self, _pos: SeekFrom) -> io::Result { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result { + match self.0 {} + } + + pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { + match self.0 {} + } + + pub fn set_times(&self, _times: FileTimes) -> io::Result<()> { + match self.0 {} + } +} + +impl DirBuilder { + pub fn new() -> DirBuilder { + DirBuilder { } + } + + pub fn mkdir(&self, _p: &Path) -> io::Result<()> { + unsupported() + } +} + +impl fmt::Debug for File { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 {} + } +} + +pub fn readdir(_p: &Path) -> io::Result { + unsupported() +} + +pub fn unlink(_p: &Path) -> io::Result<()> { + unsupported() +} + +pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { + unsupported() +} + +pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> { + match perm.0 {} +} + +pub fn rmdir(_p: &Path) -> io::Result<()> { + unsupported() +} + +pub fn remove_dir_all(_path: &Path) -> io::Result<()> { + unsupported() +} + +pub fn try_exists(_path: &Path) -> io::Result { + unsupported() +} + +pub fn readlink(_p: &Path) -> io::Result { + unsupported() +} + +pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { + unsupported() +} + +pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { + unsupported() +} + +pub fn stat(_p: &Path) -> io::Result { + unsupported() +} + +pub fn lstat(_p: &Path) -> io::Result { + unsupported() +} + +pub fn canonicalize(_p: &Path) -> io::Result { + unsupported() +} + +pub fn copy(_from: &Path, _to: &Path) -> io::Result { + unsupported() +} diff --git a/library/std/src/sys/sbf/futex.rs b/library/std/src/sys/sbf/futex.rs new file mode 100644 index 0000000000000..b8e83deb4f65a --- /dev/null +++ b/library/std/src/sys/sbf/futex.rs @@ -0,0 +1,14 @@ +use crate::sync::atomic::AtomicU32; +use crate::time::Duration; + +pub fn futex_wait(_futex: &AtomicU32, _expected: u32, _timeout: Option) -> bool { + false +} + +#[inline] +pub fn futex_wake(_futex: &AtomicU32) -> bool { + false +} + +#[inline] +pub fn futex_wake_all(_futex: &AtomicU32) {} diff --git a/library/std/src/sys/sbf/io.rs b/library/std/src/sys/sbf/io.rs new file mode 100644 index 0000000000000..84f13532f308b --- /dev/null +++ b/library/std/src/sys/sbf/io.rs @@ -0,0 +1,48 @@ +use crate::mem; + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct IoSlice<'a>(&'a [u8]); + +impl<'a> IoSlice<'a> { + #[inline] + pub fn new(buf: &'a [u8]) -> IoSlice<'a> { + IoSlice(buf) + } + + #[inline] + pub fn advance(&mut self, n: usize) { + self.0 = &self.0[n..] + } + + #[inline] + pub fn as_slice(&self) -> &[u8] { + self.0 + } +} + +pub struct IoSliceMut<'a>(&'a mut [u8]); + +impl<'a> IoSliceMut<'a> { + #[inline] + pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { + IoSliceMut(buf) + } + + #[inline] + pub fn advance(&mut self, n: usize) { + let slice = mem::replace(&mut self.0, &mut []); + let (_, remaining) = slice.split_at_mut(n); + self.0 = remaining; + } + + #[inline] + pub fn as_slice(&self) -> &[u8] { + self.0 + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [u8] { + self.0 + } +} diff --git a/library/std/src/sys/sbf/memchr.rs b/library/std/src/sys/sbf/memchr.rs new file mode 100644 index 0000000000000..9967482197eb3 --- /dev/null +++ b/library/std/src/sys/sbf/memchr.rs @@ -0,0 +1 @@ +pub use core::slice::memchr::{memchr, memrchr}; diff --git a/library/std/src/sys/sbf/mod.rs b/library/std/src/sys/sbf/mod.rs new file mode 100644 index 0000000000000..e9279d94d2382 --- /dev/null +++ b/library/std/src/sys/sbf/mod.rs @@ -0,0 +1,127 @@ +//! System bindings for the SBF platform +//! +//! This module contains the facade (aka platform-specific) implementations of +//! OS level functionality for SBF +//! +//! This is all super highly experimental and not actually intended for +//! wide/production use yet, it's still all in the experimental category. This +//! will likely change over time. +//! +//! Currently all functions here are basically stubs that immediately return +//! errors. The hope is that with a portability lint we can turn actually just +//! remove all this and just omit parts of the standard library if we're +//! compiling for SBF. That way it's a compile time error for something that's +//! guaranteed to be a runtime error! + +pub mod alloc; +pub mod args; +//#[cfg(feature = "backtrace")] +//pub mod backtrace; +pub mod cmath; +pub mod env; +pub mod fs; +pub mod futex; +pub mod io; +pub mod memchr; +pub mod net; +pub mod os; +pub mod path; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +#[path = "../unsupported/process.rs"] +pub mod process; +pub mod stdio; +pub mod thread; +#[path = "../unsupported/thread_local_dtor.rs"] +pub mod thread_local_dtor; +#[path = "../unsupported/thread_local_key.rs"] +pub mod thread_local_key; +#[path = "../unsupported/thread_parking.rs"] +pub mod thread_parking; +pub mod time; + +#[path = "../unix/os_str.rs"] +pub mod os_str; + +#[path = "../unix/locks"] +pub mod locks { + mod futex_condvar; + mod futex_mutex; + mod futex_rwlock; + pub(crate) use futex_condvar::Condvar; + pub(crate) use futex_mutex::Mutex; + pub(crate) use futex_rwlock::RwLock; +} + +#[cfg(not(target_feature = "static-syscalls"))] +extern "C" { + fn abort() -> !; + #[allow(improper_ctypes)] + fn custom_panic(info: &core::panic::PanicInfo<'_>); + fn sol_log_(message: *const u8, length: u64); +} + +#[cfg(target_feature = "static-syscalls")] +unsafe extern "C" fn abort() -> ! { + let syscall: extern "C" fn() -> ! = core::mem::transmute(3069975057u64); // murmur32 hash of "abort" + syscall() +} + +#[cfg(target_feature = "static-syscalls")] +unsafe extern "C" fn sol_log_(message: *const u8, length: u64) { + let syscall: extern "C" fn(*const u8, u64) = core::mem::transmute(544561597u64); // murmur32 hash of "sol_log_" + syscall(message, length) +} + +pub fn sol_log(message: &[u8]) { + unsafe { + sol_log_(message.as_ptr(), message.len() as u64); + } +} + +pub fn panic(info: &core::panic::PanicInfo<'_>) -> ! { + unsafe { + #[cfg(not(target_feature = "static-syscalls"))] + custom_panic(info); + + #[cfg(target_feature = "static-syscalls")] + sol_log(info.to_string().as_bytes()); + + abort(); + } +} + +pub fn unsupported() -> crate::io::Result { + Err(unsupported_err()) +} + +pub fn unsupported_err() -> crate::io::Error { + crate::io::Error::new(crate::io::ErrorKind::Other, "operation not supported on SBF yet") +} + +pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { + crate::io::ErrorKind::Other +} + +// This enum is used as the storage for a bunch of types which can't actually +// exist. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub enum Void {} + +pub fn abort_internal() -> ! { + unsafe { abort() } +} + +// We don't have randomness yet, but I totally used a random number generator to +// generate these numbers. +// +// More seriously though this is just for DOS protection in hash maps. It's ok +// if we don't do that on SBF just yet. +pub fn hashmap_random_keys() -> (u64, u64) { + (1, 2) +} + +#[inline] +pub fn is_interrupted(_errno: i32) -> bool { + false +} diff --git a/library/std/src/sys/sbf/mutex.rs b/library/std/src/sys/sbf/mutex.rs new file mode 100644 index 0000000000000..28916d8d53555 --- /dev/null +++ b/library/std/src/sys/sbf/mutex.rs @@ -0,0 +1,49 @@ +use crate::cell::UnsafeCell; +use crate::sys_common::lazy_box::{LazyBox, LazyInit}; + +pub struct Mutex { + inner: UnsafeCell, +} + +pub(crate) type MovableMutex = LazyBox; + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} // no threads on SBF + +impl LazyInit for Mutex { + fn init() -> Box { + Box::new(Self::new()) + } +} + +#[allow(dead_code)] // sys isn't exported yet +impl Mutex { + pub const fn new() -> Mutex { + Mutex { inner: UnsafeCell::new(false) } + } + #[inline] + pub unsafe fn init(&self) {} + #[inline] + pub unsafe fn lock(&self) { + let locked = self.inner.get(); + assert!(!*locked, "cannot recursively acquire mutex"); + *locked = true; + } + #[inline] + pub unsafe fn unlock(&self) { + *self.inner.get() = false; + } + #[inline] + pub unsafe fn try_lock(&self) -> bool { + let locked = self.inner.get(); + if *locked { + false + } else { + *locked = true; + true + } + } + #[inline] + pub unsafe fn destroy(&self) { + } +} diff --git a/library/std/src/sys/sbf/mutex_atomics.rs b/library/std/src/sys/sbf/mutex_atomics.rs new file mode 100644 index 0000000000000..a42da624ee2db --- /dev/null +++ b/library/std/src/sys/sbf/mutex_atomics.rs @@ -0,0 +1,92 @@ +// use crate::arch::SBF; +use crate::cell::UnsafeCell; +use crate::mem; +use crate::sync::atomic::{AtomicUsize, AtomicU32, Ordering::SeqCst}; +use crate::sys::thread; + +pub struct Mutex { + locked: AtomicUsize, +} + +impl Mutex { + pub const fn new() -> Mutex { + Mutex { locked: AtomicUsize::new(0) } + } + + #[inline] + pub unsafe fn init(&mut self) { + // nothing to do + } + + pub unsafe fn lock(&self) { + // nothing to do... + } + + pub unsafe fn unlock(&self) { + // nothing to do... + } + + #[inline] + pub unsafe fn try_lock(&self) -> bool { + true + } + + #[inline] + pub unsafe fn destroy(&self) { + // nothing to do + } + + #[inline] + fn ptr(&self) -> *mut i32 { + assert_eq!(mem::size_of::(), mem::size_of::()); + &self.locked as *const AtomicUsize as *mut isize as *mut i32 + } +} + +pub struct ReentrantMutex { + owner: AtomicU32, + recursions: UnsafeCell, +} + +unsafe impl Send for ReentrantMutex {} +unsafe impl Sync for ReentrantMutex {} + +impl ReentrantMutex { + pub unsafe fn uninitialized() -> ReentrantMutex { + ReentrantMutex { + owner: AtomicU32::new(0), + recursions: UnsafeCell::new(0), + } + } + + pub unsafe fn init(&mut self) { + // nothing to do... + } + + pub unsafe fn lock(&self) { + // nothing to do... + } + + #[inline] + pub unsafe fn try_lock(&self) -> bool { + // nothing to do... + } + + #[inline] + unsafe fn _try_lock(&self, id: u32) -> Result<(), u32> { + Ok(()) + } + + pub unsafe fn unlock(&self) { + // nothing to do... + } + + pub unsafe fn destroy(&self) { + // nothing to do... + } + + #[inline] + fn ptr(&self) -> *mut i32 { + &self.owner as *const AtomicU32 as *mut i32 + } +} diff --git a/library/std/src/sys/sbf/net.rs b/library/std/src/sys/sbf/net.rs new file mode 100644 index 0000000000000..9b3d7b86cb313 --- /dev/null +++ b/library/std/src/sys/sbf/net.rs @@ -0,0 +1,378 @@ +use crate::fmt; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; +use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr}; +use crate::time::Duration; +use crate::sys::{unsupported, Void}; +use crate::convert::TryFrom; + +pub struct TcpStream(Void); + +impl TcpStream { + pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { + unsupported() + } + + pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result { + unsupported() + } + + pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { + match self.0 {} + } + + pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { + match self.0 {} + } + + pub fn read_timeout(&self) -> io::Result> { + match self.0 {} + } + + pub fn write_timeout(&self) -> io::Result> { + match self.0 {} + } + + #[inline] + pub fn is_write_vectored(&self) -> bool { + false + } + + pub fn peek(&self, _: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn read(&self, _: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn read_buf(&self, _: BorrowedCursor<'_>) -> io::Result<()> { + match self.0 {} + } + + pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result { + match self.0 {} + } + + #[inline] + pub fn is_read_vectored(&self) -> bool { + false + } + + pub fn write(&self, _: &[u8]) -> io::Result { + match self.0 {} + } + + pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result { + match self.0 {} + } + + pub fn peer_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn socket_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result { + match self.0 {} + } + + pub fn set_linger(&self, _: Option) -> io::Result<()> { + unsupported() + } + + pub fn linger(&self) -> io::Result> { + unsupported() + } + + pub fn set_nodelay(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn nodelay(&self) -> io::Result { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for TcpStream { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 {} + } +} + +pub struct TcpListener(Void); + +impl TcpListener { + pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + unsupported() + } + + pub fn socket_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result { + match self.0 {} + } + + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn only_v6(&self) -> io::Result { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for TcpListener { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 {} + } +} + +pub struct UdpSocket(Void); + +impl UdpSocket { + pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + unsupported() + } + + pub fn peer_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn socket_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + match self.0 {} + } + + pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + match self.0 {} + } + + pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result { + match self.0 {} + } + + pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { + match self.0 {} + } + + pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { + match self.0 {} + } + + pub fn read_timeout(&self) -> io::Result> { + match self.0 {} + } + + pub fn write_timeout(&self) -> io::Result> { + match self.0 {} + } + + pub fn set_broadcast(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn broadcast(&self) -> io::Result { + match self.0 {} + } + + pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_loop_v4(&self) -> io::Result { + match self.0 {} + } + + pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_ttl_v4(&self) -> io::Result { + match self.0 {} + } + + pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_loop_v6(&self) -> io::Result { + match self.0 {} + } + + pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) + -> io::Result<()> { + match self.0 {} + } + + pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) + -> io::Result<()> { + match self.0 {} + } + + pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) + -> io::Result<()> { + match self.0 {} + } + + pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) + -> io::Result<()> { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn recv(&self, _: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn peek(&self, _: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn send(&self, _: &[u8]) -> io::Result { + match self.0 {} + } + + pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for UdpSocket { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 {} + } +} + +pub struct LookupHost(Void); + +impl LookupHost { + pub fn port(&self) -> u16 { + match self.0 {} + } +} + +impl Iterator for LookupHost { + type Item = SocketAddr; + fn next(&mut self) -> Option { + match self.0 {} + } +} + +impl TryFrom<&str> for LookupHost { + type Error = io::Error; + + fn try_from(_v: &str) -> io::Result { + unsupported() + } +} + +impl<'a> TryFrom<(&'a str, u16)> for LookupHost { + type Error = io::Error; + + fn try_from(_v: (&'a str, u16)) -> io::Result { + unsupported() + } +} + +#[allow(nonstandard_style)] +pub mod netc { + pub const AF_INET: u8 = 0; + pub const AF_INET6: u8 = 1; + pub type sa_family_t = u8; + + #[derive(Copy, Clone)] + pub struct in_addr { + pub s_addr: u32, + } + + #[derive(Copy, Clone)] + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: u16, + pub sin_addr: in_addr, + } + + #[derive(Copy, Clone)] + pub struct in6_addr { + pub s6_addr: [u8; 16], + } + + #[derive(Copy, Clone)] + pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: u16, + pub sin6_addr: in6_addr, + pub sin6_flowinfo: u32, + pub sin6_scope_id: u32, + } + + #[derive(Copy, Clone)] + pub struct sockaddr { + } +} diff --git a/library/std/src/sys/sbf/os.rs b/library/std/src/sys/sbf/os.rs new file mode 100644 index 0000000000000..c54c53d90442d --- /dev/null +++ b/library/std/src/sys/sbf/os.rs @@ -0,0 +1,110 @@ +use crate::error::Error as StdError; +use crate::ffi::{OsString, OsStr}; +use crate::fmt; +use crate::intrinsics; +use crate::io; +use crate::path::{self, PathBuf}; +use crate::str; +use crate::sys::{unsupported, Void}; + +pub fn errno() -> i32 { + 0 +} + +pub fn error_string(_errno: i32) -> String { + "operation successful".to_string() +} + +pub fn getcwd() -> io::Result { + unsupported() +} + +pub fn chdir(_: &path::Path) -> io::Result<()> { + unsupported() +} + +pub struct SplitPaths<'a>(&'a Void); + +pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { + panic!(); +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = PathBuf; + fn next(&mut self) -> Option { + match *self.0 {} + } +} + +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths(_paths: I) -> Result + where I: Iterator, T: AsRef +{ + Err(JoinPathsError) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "not supported on SBF yet".fmt(f) + } +} + +impl StdError for JoinPathsError { + fn description(&self) -> &str { + "not supported on SBF yet" + } +} + +pub fn current_exe() -> io::Result { + unsupported() +} + +#[derive(Debug)] +pub struct Env(Void); + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + match self.0 {} + } +} + +impl Env { + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + [OsString::new(), OsString::new()] + } +} + +pub fn env() -> Env { + panic!(); +} + +pub fn getenv(_k: &OsStr) -> Option { + None +} + +pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> { + unsupported() +} + +pub fn unsetenv(_k: &OsStr) -> io::Result<()> { + unsupported() +} + +pub fn temp_dir() -> PathBuf { + panic!(); +} + +pub fn home_dir() -> Option { + None +} + +pub fn exit(_code: i32) -> ! { + intrinsics::abort() +} + +pub fn getpid() -> u32 { + 0 +} diff --git a/library/std/src/sys/sbf/path.rs b/library/std/src/sys/sbf/path.rs new file mode 100644 index 0000000000000..c805c15e70245 --- /dev/null +++ b/library/std/src/sys/sbf/path.rs @@ -0,0 +1,25 @@ +use crate::ffi::OsStr; +use crate::io; +use crate::path::{Path, PathBuf, Prefix}; +use crate::sys::unsupported; + +#[inline] +pub fn is_sep_byte(b: u8) -> bool { + b == b'/' +} + +#[inline] +pub fn is_verbatim_sep(b: u8) -> bool { + b == b'/' +} + +pub fn parse_prefix(_: &OsStr) -> Option> { + None +} + +pub const MAIN_SEP_STR: &str = "/"; +pub const MAIN_SEP: char = '/'; + +pub(crate) fn absolute(_path: &Path) -> io::Result { + unsupported() +} diff --git a/library/std/src/sys/sbf/rwlock.rs b/library/std/src/sys/sbf/rwlock.rs new file mode 100644 index 0000000000000..35bcfc560b739 --- /dev/null +++ b/library/std/src/sys/sbf/rwlock.rs @@ -0,0 +1,70 @@ +use crate::cell::UnsafeCell; + +pub struct RwLock { + mode: UnsafeCell, +} + +pub type MovableRwLock = RwLock; + +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} // no threads on SBF + +impl RwLock { + pub const fn new() -> RwLock { + RwLock { + mode: UnsafeCell::new(0), + } + } + + #[inline] + pub unsafe fn read(&self) { + let mode = self.mode.get(); + if *mode >= 0 { + *mode += 1; + } else { + rtabort!("rwlock locked for writing"); + } + } + + #[inline] + pub unsafe fn try_read(&self) -> bool { + let mode = self.mode.get(); + if *mode >= 0 { + *mode += 1; + true + } else { + false + } + } + + #[inline] + pub unsafe fn write(&self) { + let mode = self.mode.get(); + if *mode == 0 { + *mode = -1; + } else { + rtabort!("rwlock locked for reading") + } + } + + #[inline] + pub unsafe fn try_write(&self) -> bool { + let mode = self.mode.get(); + if *mode == 0 { + *mode = -1; + true + } else { + false + } + } + + #[inline] + pub unsafe fn read_unlock(&self) { + *self.mode.get() -= 1; + } + + #[inline] + pub unsafe fn write_unlock(&self) { + *self.mode.get() += 1; + } +} diff --git a/library/std/src/sys/sbf/rwlock_atomics.rs b/library/std/src/sys/sbf/rwlock_atomics.rs new file mode 100644 index 0000000000000..c705568cec992 --- /dev/null +++ b/library/std/src/sys/sbf/rwlock_atomics.rs @@ -0,0 +1,151 @@ +use crate::cell::UnsafeCell; +use crate::sys::mutex::Mutex; +use crate::sys::condvar::Condvar; + +pub struct RWLock { + lock: Mutex, + cond: Condvar, + state: UnsafeCell, +} + +enum State { + Unlocked, + Reading(usize), + Writing, +} + +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} + +// This rwlock implementation is a relatively simple implementation which has a +// condition variable for readers/writers as well as a mutex protecting the +// internal state of the lock. A current downside of the implementation is that +// unlocking the lock will notify *all* waiters rather than just readers or just +// writers. This can cause lots of "thundering stampede" problems. While +// hopefully correct this implementation is very likely to want to be changed in +// the future. + +impl RWLock { + pub const fn new() -> RWLock { + RWLock { + lock: Mutex::new(), + cond: Condvar::new(), + state: UnsafeCell::new(State::Unlocked), + } + } + + #[inline] + pub unsafe fn read(&self) { + self.lock.lock(); + while !(*self.state.get()).inc_readers() { + self.cond.wait(&self.lock); + } + self.lock.unlock(); + } + + #[inline] + pub unsafe fn try_read(&self) -> bool { + self.lock.lock(); + let ok = (*self.state.get()).inc_readers(); + self.lock.unlock(); + return ok + } + + #[inline] + pub unsafe fn write(&self) { + self.lock.lock(); + while !(*self.state.get()).inc_writers() { + self.cond.wait(&self.lock); + } + self.lock.unlock(); + } + + #[inline] + pub unsafe fn try_write(&self) -> bool { + self.lock.lock(); + let ok = (*self.state.get()).inc_writers(); + self.lock.unlock(); + return ok + } + + #[inline] + pub unsafe fn read_unlock(&self) { + self.lock.lock(); + let notify = (*self.state.get()).dec_readers(); + self.lock.unlock(); + if notify { + // FIXME: should only wake up one of these some of the time + self.cond.notify_all(); + } + } + + #[inline] + pub unsafe fn write_unlock(&self) { + self.lock.lock(); + (*self.state.get()).dec_writers(); + self.lock.unlock(); + // FIXME: should only wake up one of these some of the time + self.cond.notify_all(); + } + + #[inline] + pub unsafe fn destroy(&self) { + self.lock.destroy(); + self.cond.destroy(); + } +} + +impl State { + fn inc_readers(&mut self) -> bool { + match *self { + State::Unlocked => { + *self = State::Reading(1); + true + } + State::Reading(ref mut cnt) => { + *cnt += 1; + true + } + State::Writing => false + } + } + + fn inc_writers(&mut self) -> bool { + match *self { + State::Unlocked => { + *self = State::Writing; + true + } + State::Reading(_) | + State::Writing => false + } + } + + fn dec_readers(&mut self) -> bool { + let zero = match *self { + State::Reading(ref mut cnt) => { + *cnt -= 1; + *cnt == 0 + } + State::Unlocked | + State::Writing => invalid(), + }; + if zero { + *self = State::Unlocked; + } + zero + } + + fn dec_writers(&mut self) { + match *self { + State::Writing => {} + State::Unlocked | + State::Reading(_) => invalid(), + } + *self = State::Unlocked; + } +} + +fn invalid() -> ! { + panic!("inconsistent rwlock"); +} diff --git a/library/std/src/sys/sbf/stdio.rs b/library/std/src/sys/sbf/stdio.rs new file mode 100644 index 0000000000000..1a66bc8cf6794 --- /dev/null +++ b/library/std/src/sys/sbf/stdio.rs @@ -0,0 +1,50 @@ +use crate::io; + +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; + +impl Stdin { +} + +impl io::Read for Stdin { + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + Ok(0) + } +} + +impl Stdout { +} + +impl io::Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + crate::sys::sol_log(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Stderr { +} + +impl io::Write for Stderr { + fn write(&mut self, buf: &[u8]) -> io::Result { + crate::sys::sol_log(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +pub fn is_ebadf(_err: &io::Error) -> bool { + true +} + +pub fn panic_output() -> Option { + None::> +} diff --git a/library/std/src/sys/sbf/thread.rs b/library/std/src/sys/sbf/thread.rs new file mode 100644 index 0000000000000..41dd0ace0920f --- /dev/null +++ b/library/std/src/sys/sbf/thread.rs @@ -0,0 +1,36 @@ +use crate::ffi::CStr; +use crate::io; +use crate::num::NonZeroUsize; +use crate::sys::{unsupported, Void}; +use crate::time::Duration; + +pub struct Thread(Void); + +impl Thread { + // unsafe: see thread::Builder::spawn_unchecked for safety requirements + pub unsafe fn new(_stack: usize, _p: Box) + -> io::Result + { + unsupported() + } + + pub fn yield_now() { + // do nothing + } + + pub fn set_name(_name: &CStr) { + // nope + } + + pub fn sleep(_dur: Duration) { + panic!("can't sleep"); + } + + pub fn join(self) { + match self.0 {} + } +} + +pub fn available_parallelism() -> io::Result { + unsupported() +} diff --git a/library/std/src/sys/sbf/thread_local_atomics.rs b/library/std/src/sys/sbf/thread_local_atomics.rs new file mode 100644 index 0000000000000..b408ad0d5c1f8 --- /dev/null +++ b/library/std/src/sys/sbf/thread_local_atomics.rs @@ -0,0 +1,61 @@ +use crate::sys::thread; +use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; + +const MAX_KEYS: usize = 128; +static NEXT_KEY: AtomicUsize = AtomicUsize::new(0); + +struct ThreadControlBlock { + keys: [*mut u8; MAX_KEYS], +} + +impl ThreadControlBlock { + fn new() -> ThreadControlBlock { + ThreadControlBlock { + keys: [0 as *mut u8; MAX_KEYS], + } + } + + fn get() -> *mut ThreadControlBlock { + let ptr = thread::tcb_get(); + if !ptr.is_null() { + return ptr as *mut ThreadControlBlock + } + let tcb = Box::into_raw(Box::new(ThreadControlBlock::new())); + thread::tcb_set(tcb as *mut u8); + tcb + } +} + +pub type Key = usize; + +pub unsafe fn create(dtor: Option) -> Key { + drop(dtor); // FIXME: need to figure out how to hook thread exit to run this + let key = NEXT_KEY.fetch_add(1, SeqCst); + if key >= MAX_KEYS { + NEXT_KEY.store(MAX_KEYS, SeqCst); + panic!("cannot allocate space for more TLS keys"); + } + // offset by 1 so we never hand out 0. This is currently required by + // `sys_common/thread_local.rs` where it can't cope with keys of value 0 + // because it messes up the atomic management. + return key + 1 +} + +pub unsafe fn set(key: Key, value: *mut u8) { + (*ThreadControlBlock::get()).keys[key - 1] = value; +} + +pub unsafe fn get(key: Key) -> *mut u8 { + (*ThreadControlBlock::get()).keys[key - 1] +} + +pub unsafe fn destroy(_key: Key) { + // FIXME: should implement this somehow, this isn't typically called but it + // can be called if two threads race to initialize a TLS slot and one ends + // up not being needed. +} + +#[inline] +pub fn requires_synchronized_create() -> bool { + false +} diff --git a/library/std/src/sys/sbf/time.rs b/library/std/src/sys/sbf/time.rs new file mode 100644 index 0000000000000..9db3b8bd85b9f --- /dev/null +++ b/library/std/src/sys/sbf/time.rs @@ -0,0 +1,46 @@ +use crate::time::Duration; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(Duration); + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct SystemTime(Duration); + +pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); + +impl Instant { + pub fn now() -> Instant { + Instant(Duration::from_secs(0)) + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option { + self.0.checked_sub(other.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_sub(*other)?)) + } +} + +impl SystemTime { + pub fn now() -> SystemTime { + panic!(); + } + + pub fn sub_time(&self, other: &SystemTime) + -> Result { + self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_sub(*other)?)) + } +} diff --git a/library/std/src/sys/unsupported/thread_local_dtor.rs b/library/std/src/sys/unsupported/thread_local_dtor.rs index 84660ea588156..858a227b8cb42 100644 --- a/library/std/src/sys/unsupported/thread_local_dtor.rs +++ b/library/std/src/sys/unsupported/thread_local_dtor.rs @@ -1,6 +1,7 @@ #![unstable(feature = "thread_local_internals", issue = "none")] -#[cfg_attr(target_family = "wasm", allow(unused))] // unused on wasm32-unknown-unknown + // unused on solana and wasm32-unknown-unknown +#[cfg_attr(any(target_family = "solana", target_family = "wasm"), allow(unused))] pub unsafe fn register_dtor(_t: *mut u8, _dtor: unsafe extern "C" fn(*mut u8)) { // FIXME: right now there is no concept of "thread exit", but this is likely // going to show up at some point in the form of an exported symbol that the diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index 84e2c5d8d7f70..2b8a67b2aac3a 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -1,3 +1,5 @@ +#![cfg(not(target_family = "solana"))] + use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt}; use crate::borrow::Cow; /// Common code for printing the backtrace in the same way across the different diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index e18638f2a5f54..86495e9597ac5 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -20,6 +20,7 @@ #[cfg(test)] mod tests; +#[cfg(feature = "backtrace")] pub mod backtrace; pub mod fs; pub mod io; @@ -45,6 +46,8 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(any(target_os = "l4re", target_os = "uefi", + target_arch = "bpf", + target_arch = "sbf", feature = "restricted-std", all(target_family = "wasm", not(target_os = "emscripten")), target_os = "xous", diff --git a/library/std/src/sys_common/once/mod.rs b/library/std/src/sys_common/once/mod.rs index 359697d831317..0821e0fb01fc3 100644 --- a/library/std/src/sys_common/once/mod.rs +++ b/library/std/src/sys_common/once/mod.rs @@ -17,6 +17,7 @@ cfg_if::cfg_if! { target_os = "dragonfly", target_os = "fuchsia", target_os = "hermit", + target_os = "solana", ))] { mod futex; pub use futex::{Once, OnceState}; diff --git a/library/std/src/sys_common/thread.rs b/library/std/src/sys_common/thread.rs index 76466b2b37beb..9f51c6c1affbe 100644 --- a/library/std/src/sys_common/thread.rs +++ b/library/std/src/sys_common/thread.rs @@ -1,7 +1,11 @@ +#[cfg(not(target_family = "solana"))] use crate::env; +#[cfg(not(target_family = "solana"))] use crate::sync::atomic::{self, Ordering}; +#[cfg(not(target_family = "solana"))] use crate::sys::thread as imp; +#[cfg(not(target_family = "solana"))] pub fn min_stack() -> usize { static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0); match MIN.load(Ordering::Relaxed) { @@ -16,3 +20,8 @@ pub fn min_stack() -> usize { MIN.store(amt + 1, Ordering::Relaxed); amt } + +#[cfg(target_family = "solana")] +pub fn min_stack() -> usize { + 0 +} diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs index 8d51732e03588..e92c857c045ed 100644 --- a/library/std/src/sys_common/thread_info.rs +++ b/library/std/src/sys_common/thread_info.rs @@ -1,3 +1,4 @@ +#![cfg(not(target_family = "solana"))] #![allow(dead_code)] // stack_guard isn't used right now on all platforms use crate::cell::OnceCell; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 4097eb5549efe..834a7bb3ed9aa 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -175,6 +175,7 @@ use crate::str; use crate::sync::Arc; use crate::sys::thread as imp; use crate::sys_common::thread; +#[cfg(not(target_family = "solana"))] use crate::sys_common::thread_info; use crate::sys_common::thread_parking::Parker; use crate::sys_common::{AsInner, IntoInner}; @@ -457,6 +458,7 @@ impl Builder { Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) } + #[cfg(not(target_family = "solana"))] unsafe fn spawn_unchecked_<'a, 'scope, F, T>( self, f: F, @@ -573,6 +575,67 @@ impl Builder { packet: my_packet, }) } + + /// SBF version of spawn_unchecked + #[cfg(target_family = "solana")] + unsafe fn spawn_unchecked_<'a, 'scope, F, T>( + self, + _f: F, + scope_data: Option>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'a, + T: Send + 'a, + 'scope: 'a, + { + let Builder { name, stack_size } = self; + let stack_size = stack_size.unwrap_or_else(thread::min_stack); + let my_thread = Thread::new(name.map(|name| { + CString::new(name).expect("thread name may not contain interior null bytes") + })); + let their_thread = my_thread.clone(); + let my_packet: Arc> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); + let main = move || { + if let Some(name) = their_thread.cname() { + imp::Thread::set_name(name); + } + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { + imp::Thread::new( + stack_size, + mem::transmute::, Box>( + Box::new(main), + ), + )? + }, + thread: my_thread, + packet: my_packet, + }) + } } //////////////////////////////////////////////////////////////////////////////// @@ -709,6 +772,7 @@ where /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_family = "solana"))] pub fn current() -> Thread { thread_info::current_thread().expect( "use of std::thread::current() is not possible \ @@ -716,6 +780,15 @@ pub fn current() -> Thread { ) } +/// SBF dummy version +/// +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_family = "solana")] +pub fn current() -> Thread { + Thread::new(None) +} + /// Cooperatively gives up a timeslice to the OS scheduler. /// /// This calls the underlying OS scheduler's yield primitive, signaling @@ -1176,12 +1249,13 @@ impl ThreadId { // Generate a new unique thread ID. fn new() -> ThreadId { #[cold] + #[cfg(not(target_family = "solana"))] fn exhausted() -> ! { panic!("failed to generate unique thread ID: bitspace exhausted") } cfg_if::cfg_if! { - if #[cfg(target_has_atomic = "64")] { + if #[cfg(all(target_has_atomic = "64", not(target_family = "solana")))] { use crate::sync::atomic::{AtomicU64, Ordering::Relaxed}; static COUNTER: AtomicU64 = AtomicU64::new(0); @@ -1197,7 +1271,7 @@ impl ThreadId { Err(id) => last = id, } } - } else { + } else if #[cfg(not(target_family = "solana"))] { use crate::sync::{Mutex, PoisonError}; static COUNTER: Mutex = Mutex::new(0); @@ -1213,6 +1287,11 @@ impl ThreadId { *counter = id; drop(counter); ThreadId(NonZeroU64::new(id).unwrap()) + } else { + // threads are not supported in sbf, so this isn't actually used + // anywhere. This branch of the if is only to avoid creating static + // mutable data. + ThreadId(NonZeroU64::new(1).unwrap()) } } } diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs index 6ac3b3eaa797b..6f3f18180ca88 100644 --- a/library/test/src/cli.rs +++ b/library/test/src/cli.rs @@ -1,10 +1,12 @@ //! Module converting command-line arguments into test configuration. +#[cfg(not(target_family = "solana"))] use std::env; use std::path::PathBuf; use super::options::{ColorConfig, Options, OutputFormat, RunIgnored}; use super::time::TestTimeOptions; +#[cfg(not(target_family = "solana"))] use std::io::{self, IsTerminal}; #[derive(Debug)] @@ -34,6 +36,7 @@ pub struct TestOpts { } impl TestOpts { + #[cfg(not(target_family = "solana"))] pub fn use_color(&self) -> bool { match self.color { ColorConfig::AutoColor => !self.nocapture && io::stdout().is_terminal(), @@ -41,11 +44,17 @@ impl TestOpts { ColorConfig::NeverColor => false, } } + + #[cfg(target_family = "solana")] + pub fn use_color(&self) -> bool { + false + } } /// Result of parsing the options. pub type OptRes = Result; /// Result of parsing the option part. +#[cfg(not(target_family = "solana"))] type OptPartRes = Result; fn optgroups() -> getopts::Options { @@ -221,6 +230,7 @@ pub fn parse_opts(args: &[String]) -> Option { } // Gets the option value and checks if unstable features are enabled. +#[cfg(not(target_family = "solana"))] macro_rules! unstable_optflag { ($matches:ident, $allow_unstable:ident, $option_name:literal) => {{ let opt = $matches.opt_present($option_name); @@ -236,6 +246,7 @@ macro_rules! unstable_optflag { } // Gets the option value and checks if unstable features are enabled. +#[cfg(not(target_family = "solana"))] macro_rules! unstable_optopt { ($matches:ident, $allow_unstable:ident, $option_name:literal) => {{ let opt = $matches.opt_str($option_name); @@ -252,6 +263,7 @@ macro_rules! unstable_optopt { // Implementation of `parse_opts` that doesn't care about help message // and returns a `Result`. +#[cfg(not(target_family = "solana"))] fn parse_opts_impl(matches: getopts::Matches) -> OptRes { let allow_unstable = get_allow_unstable(&matches)?; @@ -306,7 +318,35 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes { Ok(test_opts) } +#[cfg(target_family = "solana")] +fn parse_opts_impl(_matches: getopts::Matches) -> OptRes { + let test_opts = TestOpts { + list: false, + filters: Vec::new(), + filter_exact: false, + force_run_in_process: false, + exclude_should_panic: true, + run_ignored: RunIgnored::No, + run_tests: true, + bench_benchmarks: false, + logfile: None, + nocapture: true, + color: ColorConfig::NeverColor, + format: OutputFormat::Pretty, + shuffle: false, + shuffle_seed: None, + test_threads: Some(1), + skip: Vec::new(), + time_options: None, + options: Options::new(), + fail_fast: false, + }; + + Ok(test_opts) +} + // FIXME: Copied from librustc_ast until linkage errors are resolved. Issue #47566 +#[cfg(not(target_family = "solana"))] fn is_nightly() -> bool { // Whether this is a feature-staged build, i.e., on the beta or stable channel let disable_unstable_features = @@ -318,6 +358,7 @@ fn is_nightly() -> bool { } // Gets the CLI options associated with `report-time` feature. +#[cfg(not(target_family = "solana"))] fn get_time_options( matches: &getopts::Matches, allow_unstable: bool, @@ -336,6 +377,7 @@ fn get_time_options( Ok(options) } +#[cfg(not(target_family = "solana"))] fn get_shuffle(matches: &getopts::Matches, allow_unstable: bool) -> OptPartRes { let mut shuffle = unstable_optflag!(matches, allow_unstable, "shuffle"); if !shuffle && allow_unstable { @@ -348,6 +390,7 @@ fn get_shuffle(matches: &getopts::Matches, allow_unstable: bool) -> OptPartRes OptPartRes> { let mut shuffle_seed = match unstable_optopt!(matches, allow_unstable, "shuffle-seed") { Some(n_str) => match n_str.parse::() { @@ -375,6 +418,7 @@ fn get_shuffle_seed(matches: &getopts::Matches, allow_unstable: bool) -> OptPart Ok(shuffle_seed) } +#[cfg(not(target_family = "solana"))] fn get_test_threads(matches: &getopts::Matches) -> OptPartRes> { let test_threads = match matches.opt_str("test-threads") { Some(n_str) => match n_str.parse::() { @@ -393,6 +437,7 @@ fn get_test_threads(matches: &getopts::Matches) -> OptPartRes> { Ok(test_threads) } +#[cfg(not(target_family = "solana"))] fn get_format( matches: &getopts::Matches, quiet: bool, @@ -425,6 +470,7 @@ fn get_format( Ok(format) } +#[cfg(not(target_family = "solana"))] fn get_color_config(matches: &getopts::Matches) -> OptPartRes { let color = match matches.opt_str("color").as_deref() { Some("auto") | None => ColorConfig::AutoColor, @@ -442,6 +488,7 @@ fn get_color_config(matches: &getopts::Matches) -> OptPartRes { Ok(color) } +#[cfg(not(target_family = "solana"))] fn get_nocapture(matches: &getopts::Matches) -> OptPartRes { let mut nocapture = matches.opt_present("nocapture"); if !nocapture { @@ -454,6 +501,7 @@ fn get_nocapture(matches: &getopts::Matches) -> OptPartRes { Ok(nocapture) } +#[cfg(not(target_family = "solana"))] fn get_run_ignored(matches: &getopts::Matches, include_ignored: bool) -> OptPartRes { let run_ignored = match (include_ignored, matches.opt_present("ignored")) { (true, true) => { @@ -467,6 +515,7 @@ fn get_run_ignored(matches: &getopts::Matches, include_ignored: bool) -> OptPart Ok(run_ignored) } +#[cfg(not(target_family = "solana"))] fn get_allow_unstable(matches: &getopts::Matches) -> OptPartRes { let mut allow_unstable = false; @@ -488,6 +537,7 @@ fn get_allow_unstable(matches: &getopts::Matches) -> OptPartRes { Ok(allow_unstable) } +#[cfg(not(target_family = "solana"))] fn get_log_file(matches: &getopts::Matches) -> OptPartRes> { let logfile = matches.opt_str("logfile").map(|s| PathBuf::from(&s)); diff --git a/library/test/src/console.rs b/library/test/src/console.rs index bbeb944e8b11b..75cd81d0c7869 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -291,10 +291,13 @@ fn on_test_event( /// A simple console test runner. /// Runs provided tests reporting process and results to the stdout. pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Result { + #[cfg(not(target_family = "solana"))] let output = match term::stdout() { None => OutputLocation::Raw(io::stdout()), Some(t) => OutputLocation::Pretty(t), }; + #[cfg(target_family = "solana")] + let output = OutputLocation::Raw(io::stdout()); let max_name_len = tests .iter() diff --git a/library/test/src/helpers/concurrency.rs b/library/test/src/helpers/concurrency.rs index eb211157371b5..38f3fc190afdf 100644 --- a/library/test/src/helpers/concurrency.rs +++ b/library/test/src/helpers/concurrency.rs @@ -1,7 +1,9 @@ //! Helper module which helps to determine amount of threads to be used //! during tests execution. +#[cfg(not(target_family = "solana"))] use std::{env, num::NonZeroUsize, thread}; +#[cfg(not(target_family = "solana"))] pub fn get_concurrency() -> usize { if let Ok(value) = env::var("RUST_TEST_THREADS") { match value.parse::().ok() { @@ -12,3 +14,8 @@ pub fn get_concurrency() -> usize { thread::available_parallelism().map(|n| n.get()).unwrap_or(1) } } + +#[cfg(target_family = "solana")] +pub fn get_concurrency() -> usize { + 1 +} diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index bddf75dffbb62..a41ad66a7419b 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -14,6 +14,11 @@ // running tests while providing a base that other test frameworks may // build off of. +// N.B., this is also specified in this crate's Cargo.toml, but librustc_ast contains logic specific to +// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by +// cargo) to detect this crate. + +#![crate_name = "test"] #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] #![cfg_attr(not(bootstrap), doc(rust_logo))] @@ -57,7 +62,6 @@ use std::{ collections::VecDeque, env, io, io::prelude::Write, - mem::ManuallyDrop, panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo}, process::{self, Command, Termination}, sync::mpsc::{channel, Sender}, @@ -65,6 +69,8 @@ use std::{ thread, time::{Duration, Instant}, }; +#[cfg(not(target_family = "solana"))] +use std::mem::ManuallyDrop; pub mod bench; mod cli; @@ -117,6 +123,7 @@ pub fn test_main(args: &[String], tests: Vec, options: Option, options: Option>(); + #[cfg(target_family = "solana")] + let args: [String; 0] = []; let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect(); test_main(&args, owned_tests, None) } @@ -594,7 +604,7 @@ pub fn run_test( // If the platform is single-threaded we're just going to run // the test synchronously, regardless of the concurrency // level. - let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm"); + let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm") && !cfg!(target_family = "solana"); if supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); let mut runtest = Arc::new(Mutex::new(Some(runtest))); diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 7021a9543582d..f5f000d78201f 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -415,7 +415,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car if builder.no_std(target) == Some(true) { features += " compiler-builtins-mem"; - if !target.starts_with("bpf") { + if !target.starts_with("sbf") && !target.starts_with("bpf") { features.push_str(compiler_builtins_c_feature); } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index a1f6fac8a518a..d93386d77c6be 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -299,7 +299,7 @@ impl Step for Llvm { Some(s) => s, None => { "AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;\ - Sparc;SystemZ;WebAssembly;X86" + SBF;Sparc;SystemZ;WebAssembly;X86" } }; @@ -315,6 +315,7 @@ impl Step for Llvm { cfg.out_dir(&out_dir) .profile(profile) + .define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "ON") .define("LLVM_ENABLE_ASSERTIONS", assertions) .define("LLVM_UNREACHABLE_OPTIMIZE", "OFF") .define("LLVM_ENABLE_PLUGINS", plugins) @@ -378,6 +379,11 @@ impl Step for Llvm { // equally well everywhere. if builder.llvm_link_shared() { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); + } else { + cfg.define("LIBCLANG_BUILD_STATIC", "ON"); + cfg.define("CLANG_LINK_CLANG_DYLIB", "OFF"); + cfg.define("LLVM_BUILD_LLVM_DYLIB", "OFF"); + cfg.define("LLVM_LINK_LLVM_DYLIB", "OFF"); } if (target.starts_with("riscv") || target.starts_with("csky")) @@ -428,6 +434,12 @@ impl Step for Llvm { enabled_llvm_projects.push("clang"); } + if let Some(projects) = &builder.config.llvm_enable_projects { + for p in projects.split(';') { + enabled_llvm_projects.push(p); + } + } + // We want libxml to be disabled. // See https://github.com/rust-lang/rust/pull/50104 cfg.define("LLVM_ENABLE_LIBXML2", "OFF"); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 0a9175aa3ea5c..3b44270f729e0 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -197,6 +197,7 @@ pub struct Config { pub llvm_enable_warnings: bool, pub llvm_from_ci: bool, pub llvm_build_config: HashMap, + pub llvm_enable_projects: Option, pub use_lld: bool, pub lld_enabled: bool, @@ -847,6 +848,7 @@ define_config! { enable_warnings: Option = "enable-warnings", download_ci_llvm: Option = "download-ci-llvm", build_config: Option> = "build-config", + enable_projects: Option = "enable-projects", } } @@ -1520,6 +1522,7 @@ impl Config { config.llvm_link_jobs = llvm.link_jobs; config.llvm_version_suffix = llvm.version_suffix.clone(); config.llvm_clang_cl = llvm.clang_cl.clone(); + config.llvm_enable_projects = llvm.enable_projects.clone(); config.llvm_cflags = llvm.cflags.clone(); config.llvm_cxxflags = llvm.cxxflags.clone(); diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index eec3be66a1281..83b77b83dd11f 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -172,7 +172,9 @@ than building it. continue; } - if !build.config.dry_run() { + // sbf target relies on in-tree built llvm, + // which doesn't exist when this check runs + if !build.config.dry_run() && !target.contains("sbf") && !target.contains("bpf") { cmd_finder.must_have(build.cc(*target)); if let Some(ar) = build.ar(*target) { cmd_finder.must_have(ar); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 33b8f1a7ce720..62648218d4458 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -98,7 +98,9 @@ const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ /* Extra values not defined in the built-in targets yet, but used in std */ (Some(Mode::Std), "target_env", Some(&["libnx"])), // (Some(Mode::Std), "target_os", Some(&[])), - (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])), + (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "sbf", "xtensa"])), + (Some(Mode::Std), "target_family", Some(&["solana"])), + (Some(Mode::Std), "target_os", Some(&["solana"])), /* Extra names used by dependencies */ // FIXME: Used by serde_json, but we should not be triggering on external dependencies. (Some(Mode::Rustc), "no_btreemap_remove_entry", None), @@ -846,6 +848,17 @@ impl Build { } } + /// Returns the path to llvm/bin + fn llvm_bin(&self, target: TargetSelection) -> PathBuf { + let target_config = self.config.target_config.get(&target); + if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { + let llvm_bindir = output(Command::new(s).arg("--bindir")); + PathBuf::from(llvm_bindir.trim()) + } else { + self.llvm_out(self.config.build).join("bin") + } + } + /// Returns the path to `FileCheck` binary for the specified target fn llvm_filecheck(&self, target: TargetSelection) -> PathBuf { let target_config = self.config.target_config.get(&target); @@ -1212,6 +1225,13 @@ impl Build { base.push("-fno-omit-frame-pointer".into()); } + if &*target.triple == "bpfel-unknown-unknown" { + base.push("-Xclang".into()); + base.push("-target-feature".into()); + base.push("-Xclang".into()); + base.push("+solana".into()); + } + if let Some(map_to) = self.debuginfo_map_to(which) { let map = format!("{}={}", self.src.display(), map_to); let cc = self.cc(target); diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index 52b36ce75f343..057e568c6db3a 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -39,6 +39,10 @@ fn cc2ar(cc: &Path, target: TargetSelection) -> Option { Some(PathBuf::from(ar)) } else if let Some(ar) = env::var_os("AR") { Some(PathBuf::from(ar)) + } else if target.contains("sbf") || target.contains("bpf") { + let parent = cc.parent().unwrap(); + let file = PathBuf::from("llvm-ar"); + Some(parent.join(file)) } else if target.contains("msvc") { None } else if target.contains("musl") { @@ -216,6 +220,10 @@ fn default_compiler( } } + "bpfel-unknown-unknown" | "sbf-solana-solana" => { + Some(PathBuf::from(build.llvm_bin(target).join(compiler.clang()))) + } + t if t.contains("musl") && compiler == Language::C => { if let Some(root) = build.musl_root(target) { let guess = root.join("bin/musl-gcc"); diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 5bc81f2d983e8..8334fb10a999f 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -180,6 +180,7 @@ pub fn use_host_linker(target: TargetSelection) -> bool { || target.contains("fortanix") || target.contains("fuchsia") || target.contains("bpf") + || target.contains("sbf") || target.contains("switch")) } diff --git a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile index 3372baed999ac..68e51873c5381 100644 --- a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile @@ -104,6 +104,7 @@ ENV TARGETS=$TARGETS,armv7r-none-eabi ENV TARGETS=$TARGETS,armv7r-none-eabihf ENV TARGETS=$TARGETS,thumbv7neon-unknown-linux-gnueabihf ENV TARGETS=$TARGETS,armv7a-none-eabi +ENV TARGETS=$TARGETS,sbf-solana-solana # riscv targets currently do not need a C compiler, as compiler_builtins # doesn't currently have it enabled, and the riscv gcc compiler is not diff --git a/src/ci/docker/host-x86_64/sbf-solana-solana/Dockerfile b/src/ci/docker/host-x86_64/sbf-solana-solana/Dockerfile new file mode 100644 index 0000000000000..a30e321d14c96 --- /dev/null +++ b/src/ci/docker/host-x86_64/sbf-solana-solana/Dockerfile @@ -0,0 +1,45 @@ +FROM ubuntu:22.04 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + g++ \ + make \ + ninja-build \ + file \ + curl \ + ca-certificates \ + python3 \ + git \ + cmake \ + sudo \ + gdb \ + libssl-dev \ + pkg-config \ + xz-utils + +ENV RUSTUP_INIT_SKIP_PATH_CHECK="yes" +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + +RUN PATH="${HOME}/.cargo/bin:${PATH}" \ + cargo install --git https://github.com/solana-labs/cargo-run-solana-tests.git \ + --rev f7c1d109367c0ab4167d2eb41712777bcc66c9a4 \ + --bin cargo-run-solana-tests --root /usr/local + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# We are disabling CI LLVM since this builder is intentionally using a host +# LLVM, rather than the typical src/llvm-project LLVM. +ENV NO_DOWNLOAD_CI_LLVM 1 + +ENV RUST_CONFIGURE_ARGS \ + --set rust.lld \ + --set llvm.clang + +ENV SCRIPT CARGO_TARGET_BPFEL_UNKNOWN_UNKNOWN_RUNNER=\"cargo-run-solana-tests --heap-size 104857600\" \ + CARGO_TARGET_SBF_SOLANA_SOLANA_RUNNER=\"cargo-run-solana-tests --heap-size 104857600\" \ + LLVM_HOME=/checkout/obj/build/x86_64-unknown-linux-gnu/llvm \ + PATH="${HOME}/.cargo/bin:${PATH}" \ + python3 /checkout/x.py --stage 1 test --host='' --target bpfel-unknown-unknown,sbf-solana-solana \ + library/core diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index cedbc0390f8ff..27cd04b7c11e8 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -186,6 +186,7 @@ args= if [ "$SCCACHE_BUCKET" != "" ]; then args="$args --env SCCACHE_BUCKET" args="$args --env SCCACHE_REGION" + args="$args --env SCCACHE_S3_NO_CREDENTIALS" args="$args --env AWS_ACCESS_KEY_ID" args="$args --env AWS_SECRET_ACCESS_KEY" args="$args --env AWS_REGION" diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index 6c713e1f8611f..4ea5ab6ffa285 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -6,7 +6,7 @@ set -ex case "$(uname -m)" in x86_64) - url="https://ci-mirrors.rust-lang.org/rustc/2021-08-24-sccache-v0.2.15-x86_64-unknown-linux-musl" + url="https://cached-ci-artifacts.s3.us-east-2.amazonaws.com/sccache-5d2a373-x86_64-unknown-linux-musl" ;; aarch64) url="https://ci-mirrors.rust-lang.org/rustc/2021-08-25-sccache-v0.2.15-aarch64-unknown-linux-musl" diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index da29ffb8e5f9b..c7412b76e60f5 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -36,22 +36,25 @@ x--expand-yaml-anchors--remove: HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - &public-variables - SCCACHE_BUCKET: rust-lang-ci-sccache2 + SCCACHE_BUCKET: cached-ci-artifacts + SCCACHE_REGION: us-east-2 + SCCACHE_S3_NO_CREDENTIALS: 1 TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate - CACHE_DOMAIN: ci-caches.rust-lang.org + CACHE_DOMAIN: cached-ci-artifacts.s3.us-east-2.amazonaws.com - &prod-variables - SCCACHE_BUCKET: rust-lang-ci-sccache2 + SCCACHE_BUCKET: cached-ci-artifacts + SCCACHE_REGION: us-east-2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues - TOOLSTATE_PUBLISH: 1 + TOOLSTATE_PUBLISH: 0 # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named # AWS_SECRET_ACCESS_KEY_. Including the key id in the name allows to # rotate them in a single branch while keeping the old key in another # branch, which wouldn't be possible if the key was named with the kind # (caches, artifacts...). - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL + CACHES_AWS_ACCESS_KEY_ID: AKIASSXOBJJGY5HRQO4U ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 AWS_REGION: us-west-1 CACHE_DOMAIN: ci-caches.rust-lang.org @@ -76,15 +79,15 @@ x--expand-yaml-anchors--remove: env: {} - &job-linux-4c - os: ubuntu-20.04-4core-16gb + os: ubuntu-latest <<: *base-job - &job-linux-8c - os: ubuntu-20.04-8core-32gb + os: ubuntu-latest <<: *base-job - &job-linux-16c - os: ubuntu-20.04-16core-64gb + os: ubuntu-latest <<: *base-job - &job-macos-xl @@ -120,7 +123,7 @@ x--expand-yaml-anchors--remove: - name: checkout the source code uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 # Rust Log Analyzer can't currently detect the PR number of a GitHub # Actions build on its own, so a hint in the log message is needed to @@ -145,9 +148,9 @@ x--expand-yaml-anchors--remove: run: src/ci/scripts/should-skip-this.sh <<: *step - - name: ensure the channel matches the target branch - run: src/ci/scripts/verify-channel.sh - <<: *step + # - name: ensure the channel matches the target branch + # run: src/ci/scripts/verify-channel.sh + # <<: *step - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh @@ -224,6 +227,8 @@ x--expand-yaml-anchors--remove: - name: ensure the stable version number is correct run: src/ci/scripts/verify-stable-version-number.sh + env: + SKIP_JOB: 1 <<: *step - name: run the build @@ -253,6 +258,7 @@ x--expand-yaml-anchors--remove: env: AWS_ACCESS_KEY_ID: ${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }} + SKIP_JOB: 1 # Adding a condition on DEPLOY=1 or DEPLOY_ALT=1 is not needed as all deploy # builders *should* have the AWS credentials available. Still, explicitly # adding the condition is helpful as this way CI will not silently skip @@ -295,6 +301,7 @@ on: - try-perf - automation/bors/try - master + - solana-** pull_request: branches: - "**" @@ -339,9 +346,31 @@ jobs: ENABLE_GCC_CODEGEN: "1" <<: *job-linux-16c + - name: sbf-solana-solana + <<: *job-linux-16c + tidy: false + - name: x86_64-gnu-tools <<: *job-linux-16c + push: + <<: *base-ci-job + name: push + env: + <<: [*shared-ci-variables, *prod-variables] + if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/solana-') && github.repository == 'solana-labs/rust' + strategy: + matrix: + include: + - name: mingw-check + <<: *job-linux-16c + + - name: x86_64-gnu-llvm-12 + <<: *job-linux-16c + + - name: sbf-solana-solana + <<: *job-linux-16c + auto: <<: *base-ci-job name: auto - ${{ matrix.name }} @@ -745,7 +774,7 @@ jobs: - name: checkout the source code uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 - name: publish toolstate run: src/ci/publish_toolstate.sh diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 907e9c59f316c..64ad2aecc64f6 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -263,6 +263,7 @@ target | std | host | notes `bpfel-unknown-none` | * | | BPF (little endian) `csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian) `csky-unknown-linux-gnuabiv2hf` | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian) +`bpfel-unknown-unknown` | ✓ | | BPF `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI] [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI] @@ -325,6 +326,7 @@ target | std | host | notes [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 [`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) +`sbf-solana-solana` | ✓ | | SBF `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+ [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 diff --git a/src/llvm-project b/src/llvm-project index 2c4de6c2492d5..741642838f9c1 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 2c4de6c2492d5530de3f19f41d8f88ba984c2fe2 +Subproject commit 741642838f9c1df60956a0d2fd9810d5638dddba diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index aed6796fa13c4..3c37cc6e46aff 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -85,6 +85,7 @@ static TARGETS: &[&str] = &[ "asmjs-unknown-emscripten", "bpfeb-unknown-none", "bpfel-unknown-none", + "bpfel-unknown-unknown", "i386-apple-ios", "i586-pc-windows-msvc", "i586-unknown-linux-gnu", @@ -129,6 +130,7 @@ static TARGETS: &[&str] = &[ "riscv64gc-unknown-none-elf", "riscv64gc-unknown-linux-gnu", "s390x-unknown-linux-gnu", + "sbf-solana-solana", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", "sparc-unknown-none-elf", diff --git a/src/tools/clippy/clippy_lints/src/as_conversions.rs b/src/tools/clippy/clippy_lints/src/as_conversions.rs index b9dda49ca4124..2de205d80efcd 100644 --- a/src/tools/clippy/clippy_lints/src/as_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/as_conversions.rs @@ -48,11 +48,10 @@ declare_lint_pass!(AsConversions => [AS_CONVERSIONS]); impl<'tcx> LateLintPass<'tcx> for AsConversions { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if in_external_macro(cx.sess(), expr.span) || is_from_proc_macro(cx, expr) { - return; - } - - if let ExprKind::Cast(_, _) = expr.kind { + if let ExprKind::Cast(_, _) = expr.kind + && !in_external_macro(cx.sess(), expr.span) + && !is_from_proc_macro(cx, expr) + { span_lint_and_help( cx, AS_CONVERSIONS, diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs index 739ce8f67c236..a38269083262b 100644 --- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs +++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs @@ -49,69 +49,64 @@ declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]); impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) { - if_chain! { - if !e.span.from_expansion(); - if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind; - if !addrof_target.span.from_expansion(); - if let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind; - if !deref_target.span.from_expansion(); - if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) ); - let ref_ty = cx.typeck_results().expr_ty(deref_target); - if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind(); - if !is_from_proc_macro(cx, e); - then{ - - if let Some(parent_expr) = get_parent_expr(cx, e){ - if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) && - !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) { - return; - } + if !e.span.from_expansion() + && let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind + && !addrof_target.span.from_expansion() + && let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind + && !deref_target.span.from_expansion() + && !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..)) + && let ref_ty = cx.typeck_results().expr_ty(deref_target) + && let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind() + { + if let Some(parent_expr) = get_parent_expr(cx, e) { + if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) + && !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) + { + return; + } - // modification to `&mut &*x` is different from `&mut x` - if matches!(deref_target.kind, ExprKind::Path(..) - | ExprKind::Field(..) - | ExprKind::Index(..) - | ExprKind::Unary(UnOp::Deref, ..)) - && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) { - return; - } + // modification to `&mut &*x` is different from `&mut x` + if matches!( + deref_target.kind, + ExprKind::Path(..) | ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, ..) + ) && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) + { + return; } + } + if is_from_proc_macro(cx, e) { + return; + } - span_lint_and_then( - cx, - BORROW_DEREF_REF, - e.span, - "deref on an immutable reference", - |diag| { - diag.span_suggestion( - e.span, - "if you would like to reborrow, try removing `&*`", - snippet_opt(cx, deref_target.span).unwrap(), - Applicability::MachineApplicable - ); + span_lint_and_then( + cx, + BORROW_DEREF_REF, + e.span, + "deref on an immutable reference", + |diag| { + diag.span_suggestion( + e.span, + "if you would like to reborrow, try removing `&*`", + snippet_opt(cx, deref_target.span).unwrap(), + Applicability::MachineApplicable, + ); - // has deref trait -> give 2 help - // doesn't have deref trait -> give 1 help - if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait(){ - if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) { - return; - } + // has deref trait -> give 2 help + // doesn't have deref trait -> give 1 help + if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait() { + if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) { + return; } - - diag.span_suggestion( - e.span, - "if you would like to deref, try using `&**`", - format!( - "&**{}", - &snippet_opt(cx, deref_target.span).unwrap(), - ), - Applicability::MaybeIncorrect - ); - } - ); - } + diag.span_suggestion( + e.span, + "if you would like to deref, try using `&**`", + format!("&**{}", &snippet_opt(cx, deref_target.span).unwrap()), + Applicability::MaybeIncorrect, + ); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs index 62a2ab1ccb4c7..dd7fae79d9ba8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs @@ -9,7 +9,7 @@ use rustc_middle::ty; /// Checks for the `UNUSED_ENUMERATE_INDEX` lint. pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { - let PatKind::Tuple(tuple, _) = pat.kind else { + let PatKind::Tuple([index, elem], _) = pat.kind else { return; }; @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx let ty = cx.typeck_results().expr_ty(arg); - if !pat_is_wild(cx, &tuple[0].kind, body) { + if !pat_is_wild(cx, &index.kind, body) { return; } @@ -53,7 +53,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx diag, "remove the `.enumerate()` call", vec![ - (pat.span, snippet(cx, tuple[1].span, "..").into_owned()), + (pat.span, snippet(cx, elem.span, "..").into_owned()), (arg.span, base_iter.to_string()), ], ); diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index 0c4101ceb6bb3..f923e0ac82008 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -105,7 +105,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { // case somebody does that for some reason && (is_infinity(const_1) && is_neg_infinity(const_2) || is_neg_infinity(const_1) && is_infinity(const_2)) - && !is_from_proc_macro(cx, expr) && let Some(local_snippet) = snippet_opt(cx, first.span) { let variant = match (kind.node, lhs_kind.node, rhs_kind.node) { @@ -113,6 +112,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { (BinOpKind::And, BinOpKind::Ne, BinOpKind::Ne) => Variant::ManualIsFinite, _ => return, }; + if is_from_proc_macro(cx, expr) { + return; + } span_lint_and_then(cx, variant.lint(), expr.span, variant.msg(), |diag| { match variant { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 4a651396f14d0..4429f0326058a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -19,10 +19,6 @@ pub(super) fn check<'tcx>( arg: &'tcx hir::Expr<'_>, simplify_using: &str, ) { - if is_from_proc_macro(cx, expr) { - return; - } - let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option); let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); let is_bool = cx.typeck_results().expr_ty(recv).is_bool(); @@ -32,7 +28,7 @@ pub(super) fn check<'tcx>( let body = cx.tcx.hir().body(body); let body_expr = &body.value; - if usage::BindingUsageFinder::are_params_used(cx, body) { + if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) { return; } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 772686d93dd7e..7a50feff68ef1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -15,8 +15,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::{ - self, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, - TraitPredicate, Ty, + self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty, }; use rustc_span::{sym, Symbol}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -375,6 +374,7 @@ fn get_input_traits_and_projections<'tcx>( (trait_predicates, projection_predicates) } +#[expect(clippy::too_many_lines)] fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<'a>) -> bool { for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) { match node { @@ -403,22 +403,21 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< if let Some((callee_def_id, call_generic_args, recv, call_args)) = get_callee_generic_args_and_args(cx, parent_expr) { - // FIXME: the `instantiate_identity()` below seems incorrect, since we eventually - // call `tcx.try_instantiate_and_normalize_erasing_regions` further down - // (i.e., we are explicitly not in the identity context). - let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder(); + let bound_fn_sig = cx.tcx.fn_sig(callee_def_id); + let fn_sig = bound_fn_sig.skip_binder(); if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id) - && let Some(param_ty) = fn_sig.inputs().get(arg_index) - && let ty::Param(ParamTy { index: param_index , ..}) = param_ty.kind() + && let param_ty = fn_sig.input(arg_index).skip_binder() + && let ty::Param(ParamTy { index: param_index , ..}) = *param_ty.kind() // https://github.com/rust-lang/rust-clippy/issues/9504 and https://github.com/rust-lang/rust-clippy/issues/10021 - && (*param_index as usize) < call_generic_args.len() + && (param_index as usize) < call_generic_args.len() { if fn_sig + .skip_binder() .inputs() .iter() .enumerate() .filter(|(i, _)| *i != arg_index) - .any(|(_, ty)| ty.contains(*param_ty)) + .any(|(_, ty)| ty.contains(param_ty)) { return false; } @@ -430,7 +429,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< .iter() .filter(|predicate| { if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() - && trait_predicate.trait_ref.self_ty() == *param_ty + && trait_predicate.trait_ref.self_ty() == param_ty { true } else { @@ -441,7 +440,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let new_subst = cx .tcx .mk_args_from_iter(call_generic_args.iter().enumerate().map(|(i, t)| { - if i == (*param_index as usize) { + if i == param_index as usize { GenericArg::from(ty) } else { t @@ -449,7 +448,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< })); if trait_predicates.any(|predicate| { - let predicate = EarlyBinder::bind(predicate).instantiate(cx.tcx, new_subst); + let predicate = bound_fn_sig.rebind(predicate).instantiate(cx.tcx, new_subst); let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); !cx.tcx .infer_ctxt() @@ -459,12 +458,12 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< return false; } - let output_ty = fn_sig.output(); - if output_ty.contains(*param_ty) { + let output_ty = cx.tcx.erase_late_bound_regions(fn_sig.output()); + if output_ty.contains(param_ty) { if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions( new_subst, cx.param_env, - EarlyBinder::bind(output_ty), + bound_fn_sig.rebind(output_ty), ) { expr = parent_expr; ty = new_ty; diff --git a/src/tools/clippy/clippy_lints/src/needless_if.rs b/src/tools/clippy/clippy_lints/src/needless_if.rs index 1ed7ea6b32554..23aabc548a57d 100644 --- a/src/tools/clippy/clippy_lints/src/needless_if.rs +++ b/src/tools/clippy/clippy_lints/src/needless_if.rs @@ -44,7 +44,6 @@ impl LateLintPass<'_> for NeedlessIf { && block.stmts.is_empty() && block.expr.is_none() && !in_external_macro(cx.sess(), expr.span) - && !is_from_proc_macro(cx, expr) && let Some(then_snippet) = snippet_opt(cx, then.span) // Ignore // - empty macro expansions @@ -53,6 +52,7 @@ impl LateLintPass<'_> for NeedlessIf { // - #[cfg]'d out code && then_snippet.chars().all(|ch| matches!(ch, '{' | '}') || ch.is_ascii_whitespace()) && let Some(cond_snippet) = snippet_opt(cx, cond.span) + && !is_from_proc_macro(cx, expr) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index f7d9650b2f8db..4c6462b7747b4 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -132,7 +132,11 @@ impl ArithmeticSideEffects { } // Common entry-point to avoid code duplication. - fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { + fn issue_lint<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + if is_from_proc_macro(cx, expr) { + return; + } + let msg = "arithmetic operation that can potentially result in unexpected side-effects"; span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg); self.expr_span = Some(expr.span); @@ -160,10 +164,10 @@ impl ArithmeticSideEffects { fn manage_bin_ops<'tcx>( &mut self, cx: &LateContext<'tcx>, - expr: &hir::Expr<'tcx>, + expr: &'tcx hir::Expr<'_>, op: &Spanned, - lhs: &hir::Expr<'tcx>, - rhs: &hir::Expr<'tcx>, + lhs: &'tcx hir::Expr<'_>, + rhs: &'tcx hir::Expr<'_>, ) { if constant_simple(cx, cx.typeck_results(), expr).is_some() { return; @@ -236,10 +240,10 @@ impl ArithmeticSideEffects { /// provided input. fn manage_method_call<'tcx>( &mut self, - args: &[hir::Expr<'tcx>], + args: &'tcx [hir::Expr<'_>], cx: &LateContext<'tcx>, - ps: &hir::PathSegment<'tcx>, - receiver: &hir::Expr<'tcx>, + ps: &'tcx hir::PathSegment<'_>, + receiver: &'tcx hir::Expr<'_>, ) { let Some(arg) = args.first() else { return; @@ -264,8 +268,8 @@ impl ArithmeticSideEffects { fn manage_unary_ops<'tcx>( &mut self, cx: &LateContext<'tcx>, - expr: &hir::Expr<'tcx>, - un_expr: &hir::Expr<'tcx>, + expr: &'tcx hir::Expr<'_>, + un_expr: &'tcx hir::Expr<'_>, un_op: hir::UnOp, ) { let hir::UnOp::Neg = un_op else { @@ -287,14 +291,13 @@ impl ArithmeticSideEffects { fn should_skip_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool { is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id) - || is_from_proc_macro(cx, expr) || self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span)) } } impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if self.should_skip_expr(cx, expr) { return; } diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs index ae81e1198af26..0492df68daddc 100644 --- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs +++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs @@ -72,8 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for SingleCallFn { ) { if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) || in_external_macro(cx.sess(), span) - || is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span)) || is_in_test_function(cx.tcx, body.value.hir_id) + || is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span)) { return; } diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 3bac0626f8858..2f619a306fe02 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -12,14 +12,14 @@ //! code was written, and check if the span contains that text. Note this will only work correctly //! if the span is not from a `macro_rules` based macro. -use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, UintTy}; +use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, TraitObjectSyntax, UintTy}; use rustc_ast::token::CommentKind; use rustc_ast::AttrStyle; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId, Impl, ImplItem, - ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, TraitItemKind, Ty, - TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, + Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl, + ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, + TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, }; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; @@ -33,8 +33,6 @@ use rustc_target::spec::abi::Abi; pub enum Pat { /// A single string. Str(&'static str), - /// A single string. - OwnedStr(String), /// Any of the given strings. MultiStr(&'static [&'static str]), /// Any of the given strings. @@ -59,14 +57,12 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ','); (match start_pat { Pat::Str(text) => start_str.starts_with(text), - Pat::OwnedStr(text) => start_str.starts_with(&text), Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => start_str.starts_with(sym.as_str()), Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit), } && match end_pat { Pat::Str(text) => end_str.ends_with(text), - Pat::OwnedStr(text) => end_str.starts_with(&text), Pat::MultiStr(texts) => texts.iter().any(|s| start_str.ends_with(s)), Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => end_str.ends_with(sym.as_str()), @@ -125,6 +121,8 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) { fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { match e.kind { ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")), + // Parenthesis are trimmed from the text before the search patterns are matched. + // See: `span_matches_pat` ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1), ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat(tcx, e).1), @@ -286,23 +284,17 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { match attr.kind { AttrKind::Normal(..) => { - let mut pat = if matches!(attr.style, AttrStyle::Outer) { - (Pat::Str("#["), Pat::Str("]")) - } else { - (Pat::Str("#!["), Pat::Str("]")) - }; - - if let Some(ident) = attr.ident() - && let Pat::Str(old_pat) = pat.0 - { + if let Some(ident) = attr.ident() { // TODO: I feel like it's likely we can use `Cow` instead but this will require quite a bit of // refactoring // NOTE: This will likely have false positives, like `allow = 1` - pat.0 = Pat::OwnedMultiStr(vec![ident.to_string(), old_pat.to_owned()]); - pat.1 = Pat::Str(""); + ( + Pat::OwnedMultiStr(vec![ident.to_string(), "#".to_owned()]), + Pat::Str(""), + ) + } else { + (Pat::Str("#"), Pat::Str("]")) } - - pat }, AttrKind::DocComment(_kind @ CommentKind::Line, ..) => { if matches!(attr.style, AttrStyle::Outer) { @@ -324,32 +316,42 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { match ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), - TyKind::Ptr(MutTy { mutbl, ty }) => ( - if mutbl.is_mut() { - Pat::Str("*const") - } else { - Pat::Str("*mut") - }, - ty_search_pat(ty).1, - ), + TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), TyKind::BareFn(bare_fn) => ( - Pat::OwnedStr(format!("{}{} fn", bare_fn.unsafety.prefix_str(), bare_fn.abi.name())), - ty_search_pat(ty).1, + if bare_fn.unsafety == Unsafety::Unsafe { + Pat::Str("unsafe") + } else if bare_fn.abi != Abi::Rust { + Pat::Str("extern") + } else { + Pat::MultiStr(&["fn", "extern"]) + }, + match bare_fn.decl.output { + FnRetTy::DefaultReturn(_) => { + if let [.., ty] = bare_fn.decl.inputs { + ty_search_pat(ty).1 + } else { + Pat::Str("(") + } + }, + FnRetTy::Return(ty) => ty_search_pat(ty).1, + }, ), - TyKind::Never => (Pat::Str("!"), Pat::Str("")), - TyKind::Tup(..) => (Pat::Str("("), Pat::Str(")")), + TyKind::Never => (Pat::Str("!"), Pat::Str("!")), + // Parenthesis are trimmed from the text before the search patterns are matched. + // See: `span_matches_pat` + TyKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), + TyKind::Tup([ty]) => ty_search_pat(ty), + TyKind::Tup([head, .., tail]) => (ty_search_pat(head).0, ty_search_pat(tail).1), TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::Path(qpath) => qpath_search_pat(&qpath), - // NOTE: This is missing `TraitObject`. It will always return true then. + TyKind::Infer => (Pat::Str("_"), Pat::Str("_")), + TyKind::TraitObject(_, _, TraitObjectSyntax::Dyn) => (Pat::Str("dyn"), Pat::Str("")), + // NOTE: `TraitObject` is incomplete. It will always return true then. _ => (Pat::Str(""), Pat::Str("")), } } -fn ident_search_pat(ident: Ident) -> (Pat, Pat) { - (Pat::OwnedStr(ident.name.as_str().to_owned()), Pat::Str("")) -} - pub trait WithSearchPat<'cx> { type Context: LintContext; fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat); @@ -408,7 +410,7 @@ impl<'cx> WithSearchPat<'cx> for Ident { type Context = LateContext<'cx>; fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) { - ident_search_pat(*self) + (Pat::Sym(self.name), Pat::Sym(self.name)) } fn span(&self) -> Span { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 7eff93881b26e..842a206f96b35 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -1160,7 +1160,12 @@ pub fn make_normalized_projection<'tcx>( ) -> Option> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] - if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_late_bound_regions()) { + if let Some((i, arg)) = ty + .args + .iter() + .enumerate() + .find(|(_, arg)| arg.has_escaping_bound_vars()) + { debug_assert!( false, "args contain late-bound region at index `{i}` which can't be normalized.\n\ @@ -1233,7 +1238,12 @@ pub fn make_normalized_projection_with_regions<'tcx>( ) -> Option> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] - if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_late_bound_regions()) { + if let Some((i, arg)) = ty + .args + .iter() + .enumerate() + .find(|(_, arg)| arg.has_escaping_bound_vars()) + { debug_assert!( false, "args contain late-bound region at index `{i}` which can't be normalized.\n\ diff --git a/src/tools/clippy/tests/ui/crashes/ice-11230.rs b/src/tools/clippy/tests/ui/crashes/ice-11230.rs new file mode 100644 index 0000000000000..5761882273e00 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-11230.rs @@ -0,0 +1,6 @@ +/// Test for https://github.com/rust-lang/rust-clippy/issues/11230 + +fn main() { + const A: &[for<'a> fn(&'a ())] = &[]; + for v in A.iter() {} +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-11755.rs b/src/tools/clippy/tests/ui/crashes/ice-11755.rs new file mode 100644 index 0000000000000..367cb69985786 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-11755.rs @@ -0,0 +1,5 @@ +#![warn(clippy::unused_enumerate_index)] + +fn main() { + for () in [()].iter() {} +} diff --git a/src/tools/clippy/tests/ui/doc_unsafe.rs b/src/tools/clippy/tests/ui/doc_unsafe.rs index 0c8eac5ccffc3..f7f41c915e3f0 100644 --- a/src/tools/clippy/tests/ui/doc_unsafe.rs +++ b/src/tools/clippy/tests/ui/doc_unsafe.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, clippy::needless_pass_by_ref_mut)] extern crate proc_macros; use proc_macros::external; diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs index ea5e74c4c0067..bdb6d40d9f61a 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs @@ -302,6 +302,19 @@ fn filter_copy(predicate: &mut impl FnMut(T) -> bool) -> impl FnMut(&T) move |&item| predicate(item) } +// `is_from_proc_macro` stress tests +fn _empty_tup(x: &mut (())) {} +fn _single_tup(x: &mut ((i32,))) {} +fn _multi_tup(x: &mut ((i32, u32))) {} +fn _fn(x: &mut (fn())) {} +#[rustfmt::skip] +fn _extern_rust_fn(x: &mut extern "Rust" fn()) {} +fn _extern_c_fn(x: &mut extern "C" fn()) {} +fn _unsafe_fn(x: &mut unsafe fn()) {} +fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {} +fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {} +fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {} + fn main() { let mut u = 0; let mut v = vec![0]; diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr index aa937c3f6af2b..3e1415be08f82 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr @@ -139,5 +139,65 @@ LL | pub async fn closure4(n: &mut usize) { | = warning: changing this function will impact semver compatibility -error: aborting due to 21 previous errors +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:306:18 + | +LL | fn _empty_tup(x: &mut (())) {} + | ^^^^^^^^^ help: consider changing to: `&()` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:307:19 + | +LL | fn _single_tup(x: &mut ((i32,))) {} + | ^^^^^^^^^^^^^ help: consider changing to: `&(i32,)` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:308:18 + | +LL | fn _multi_tup(x: &mut ((i32, u32))) {} + | ^^^^^^^^^^^^^^^^^ help: consider changing to: `&(i32, u32)` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:309:11 + | +LL | fn _fn(x: &mut (fn())) {} + | ^^^^^^^^^^^ help: consider changing to: `&fn()` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:311:23 + | +LL | fn _extern_rust_fn(x: &mut extern "Rust" fn()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "Rust" fn()` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:312:20 + | +LL | fn _extern_c_fn(x: &mut extern "C" fn()) {} + | ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "C" fn()` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:313:18 + | +LL | fn _unsafe_fn(x: &mut unsafe fn()) {} + | ^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe fn()` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:314:25 + | +LL | fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn()` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:315:20 + | +LL | fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn(i32)` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:316:20 + | +LL | fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn() -> (i32)` + +error: aborting due to 31 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed index 67faabc53cb5e..2dd1d746626f3 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed @@ -1,4 +1,10 @@ -#![allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::ptr_arg)] +#![allow( + clippy::needless_borrow, + clippy::needless_borrows_for_generic_args, + clippy::ptr_arg, + clippy::manual_async_fn, + clippy::needless_lifetimes +)] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] use std::borrow::Cow; @@ -506,3 +512,18 @@ mod issue_10033 { } } } + +mod issue_11952 { + use core::future::{Future, IntoFuture}; + + fn foo<'a, T: AsRef<[u8]>>(x: T, y: &'a i32) -> impl 'a + Future> { + async move { + let _y = y; + Ok(()) + } + } + + fn bar() { + IntoFuture::into_future(foo([], &0)); + } +} diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs index 99f9136427d4d..17fad33402b58 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs @@ -1,4 +1,10 @@ -#![allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::ptr_arg)] +#![allow( + clippy::needless_borrow, + clippy::needless_borrows_for_generic_args, + clippy::ptr_arg, + clippy::manual_async_fn, + clippy::needless_lifetimes +)] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] use std::borrow::Cow; @@ -506,3 +512,18 @@ mod issue_10033 { } } } + +mod issue_11952 { + use core::future::{Future, IntoFuture}; + + fn foo<'a, T: AsRef<[u8]>>(x: T, y: &'a i32) -> impl 'a + Future> { + async move { + let _y = y; + Ok(()) + } + } + + fn bar() { + IntoFuture::into_future(foo([].to_vec(), &0)); + } +} diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr index d8971b51dcadd..ad6fa422b8cd2 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr @@ -1,11 +1,11 @@ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:148:64 + --> $DIR/unnecessary_to_owned.rs:154:64 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:148:20 + --> $DIR/unnecessary_to_owned.rs:154:20 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,55 +13,55 @@ LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()) = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: redundant clone - --> $DIR/unnecessary_to_owned.rs:149:40 + --> $DIR/unnecessary_to_owned.rs:155:40 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:149:21 + --> $DIR/unnecessary_to_owned.rs:155:21 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:150:48 + --> $DIR/unnecessary_to_owned.rs:156:48 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:150:19 + --> $DIR/unnecessary_to_owned.rs:156:19 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:151:35 + --> $DIR/unnecessary_to_owned.rs:157:35 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:151:18 + --> $DIR/unnecessary_to_owned.rs:157:18 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:152:39 + --> $DIR/unnecessary_to_owned.rs:158:39 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:152:20 + --> $DIR/unnecessary_to_owned.rs:158:20 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^^^^^^^^^ error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:57:36 + --> $DIR/unnecessary_to_owned.rs:63:36 | LL | require_c_str(&Cow::from(c_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this @@ -70,415 +70,415 @@ LL | require_c_str(&Cow::from(c_str).into_owned()); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:58:19 + --> $DIR/unnecessary_to_owned.rs:64:19 | LL | require_c_str(&c_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_os_string` - --> $DIR/unnecessary_to_owned.rs:60:20 + --> $DIR/unnecessary_to_owned.rs:66:20 | LL | require_os_str(&os_str.to_os_string()); | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:61:38 + --> $DIR/unnecessary_to_owned.rs:67:38 | LL | require_os_str(&Cow::from(os_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:62:20 + --> $DIR/unnecessary_to_owned.rs:68:20 | LL | require_os_str(&os_str.to_owned()); | ^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_path_buf` - --> $DIR/unnecessary_to_owned.rs:64:18 + --> $DIR/unnecessary_to_owned.rs:70:18 | LL | require_path(&path.to_path_buf()); | ^^^^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:65:34 + --> $DIR/unnecessary_to_owned.rs:71:34 | LL | require_path(&Cow::from(path).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:66:18 + --> $DIR/unnecessary_to_owned.rs:72:18 | LL | require_path(&path.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:68:17 + --> $DIR/unnecessary_to_owned.rs:74:17 | LL | require_str(&s.to_string()); | ^^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:69:30 + --> $DIR/unnecessary_to_owned.rs:75:30 | LL | require_str(&Cow::from(s).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:70:17 + --> $DIR/unnecessary_to_owned.rs:76:17 | LL | require_str(&s.to_owned()); | ^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:71:17 + --> $DIR/unnecessary_to_owned.rs:77:17 | LL | require_str(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:73:19 + --> $DIR/unnecessary_to_owned.rs:79:19 | LL | require_slice(&slice.to_vec()); | ^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:74:36 + --> $DIR/unnecessary_to_owned.rs:80:36 | LL | require_slice(&Cow::from(slice).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:75:19 + --> $DIR/unnecessary_to_owned.rs:81:19 | LL | require_slice(&array.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:76:19 + --> $DIR/unnecessary_to_owned.rs:82:19 | LL | require_slice(&array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:77:19 + --> $DIR/unnecessary_to_owned.rs:83:19 | LL | require_slice(&slice.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:80:42 + --> $DIR/unnecessary_to_owned.rs:86:42 | LL | require_x(&Cow::::Owned(x.clone()).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:83:25 + --> $DIR/unnecessary_to_owned.rs:89:25 | LL | require_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:84:26 + --> $DIR/unnecessary_to_owned.rs:90:26 | LL | require_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:85:24 + --> $DIR/unnecessary_to_owned.rs:91:24 | LL | require_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:86:23 + --> $DIR/unnecessary_to_owned.rs:92:23 | LL | require_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:87:25 + --> $DIR/unnecessary_to_owned.rs:93:25 | LL | require_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:89:30 + --> $DIR/unnecessary_to_owned.rs:95:30 | LL | require_impl_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:90:31 + --> $DIR/unnecessary_to_owned.rs:96:31 | LL | require_impl_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:91:29 + --> $DIR/unnecessary_to_owned.rs:97:29 | LL | require_impl_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:92:28 + --> $DIR/unnecessary_to_owned.rs:98:28 | LL | require_impl_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:93:30 + --> $DIR/unnecessary_to_owned.rs:99:30 | LL | require_impl_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:95:29 + --> $DIR/unnecessary_to_owned.rs:101:29 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:95:43 + --> $DIR/unnecessary_to_owned.rs:101:43 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:96:29 + --> $DIR/unnecessary_to_owned.rs:102:29 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:96:47 + --> $DIR/unnecessary_to_owned.rs:102:47 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:98:26 + --> $DIR/unnecessary_to_owned.rs:104:26 | LL | require_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:99:27 + --> $DIR/unnecessary_to_owned.rs:105:27 | LL | require_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:100:25 + --> $DIR/unnecessary_to_owned.rs:106:25 | LL | require_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:101:24 + --> $DIR/unnecessary_to_owned.rs:107:24 | LL | require_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:102:24 + --> $DIR/unnecessary_to_owned.rs:108:24 | LL | require_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:103:26 + --> $DIR/unnecessary_to_owned.rs:109:26 | LL | require_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:104:26 + --> $DIR/unnecessary_to_owned.rs:110:26 | LL | require_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:105:26 + --> $DIR/unnecessary_to_owned.rs:111:26 | LL | require_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:107:31 + --> $DIR/unnecessary_to_owned.rs:113:31 | LL | require_impl_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:108:32 + --> $DIR/unnecessary_to_owned.rs:114:32 | LL | require_impl_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:109:30 + --> $DIR/unnecessary_to_owned.rs:115:30 | LL | require_impl_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:110:29 + --> $DIR/unnecessary_to_owned.rs:116:29 | LL | require_impl_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:111:29 + --> $DIR/unnecessary_to_owned.rs:117:29 | LL | require_impl_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:112:31 + --> $DIR/unnecessary_to_owned.rs:118:31 | LL | require_impl_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:113:31 + --> $DIR/unnecessary_to_owned.rs:119:31 | LL | require_impl_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:114:31 + --> $DIR/unnecessary_to_owned.rs:120:31 | LL | require_impl_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:116:30 + --> $DIR/unnecessary_to_owned.rs:122:30 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:116:44 + --> $DIR/unnecessary_to_owned.rs:122:44 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:117:30 + --> $DIR/unnecessary_to_owned.rs:123:30 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:117:44 + --> $DIR/unnecessary_to_owned.rs:123:44 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:118:30 + --> $DIR/unnecessary_to_owned.rs:124:30 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:118:44 + --> $DIR/unnecessary_to_owned.rs:124:44 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:119:30 + --> $DIR/unnecessary_to_owned.rs:125:30 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:119:48 + --> $DIR/unnecessary_to_owned.rs:125:48 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:120:30 + --> $DIR/unnecessary_to_owned.rs:126:30 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:120:52 + --> $DIR/unnecessary_to_owned.rs:126:52 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:121:30 + --> $DIR/unnecessary_to_owned.rs:127:30 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:121:48 + --> $DIR/unnecessary_to_owned.rs:127:48 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:123:20 + --> $DIR/unnecessary_to_owned.rs:129:20 | LL | let _ = x.join(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:125:13 + --> $DIR/unnecessary_to_owned.rs:131:13 | LL | let _ = slice.to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:126:13 + --> $DIR/unnecessary_to_owned.rs:132:13 | LL | let _ = slice.to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:127:13 + --> $DIR/unnecessary_to_owned.rs:133:13 | LL | let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:128:13 + --> $DIR/unnecessary_to_owned.rs:134:13 | LL | let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:130:13 + --> $DIR/unnecessary_to_owned.rs:136:13 | LL | let _ = IntoIterator::into_iter(slice.to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:131:13 + --> $DIR/unnecessary_to_owned.rs:137:13 | LL | let _ = IntoIterator::into_iter(slice.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:132:13 + --> $DIR/unnecessary_to_owned.rs:138:13 | LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:133:13 + --> $DIR/unnecessary_to_owned.rs:139:13 | LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:195:14 + --> $DIR/unnecessary_to_owned.rs:201:14 | LL | for t in file_types.to_vec() { | ^^^^^^^^^^^^^^^^^^^ @@ -494,28 +494,34 @@ LL + let path = match get_file_path(t) { | error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:218:14 + --> $DIR/unnecessary_to_owned.rs:224:14 | LL | let _ = &["x"][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:223:14 + --> $DIR/unnecessary_to_owned.rs:229:14 | LL | let _ = &["x"][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:270:24 + --> $DIR/unnecessary_to_owned.rs:276:24 | LL | Box::new(build(y.to_string())) | ^^^^^^^^^^^^^ help: use: `y` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:378:12 + --> $DIR/unnecessary_to_owned.rs:384:12 | LL | id("abc".to_string()) | ^^^^^^^^^^^^^^^^^ help: use: `"abc"` -error: aborting due to 79 previous errors +error: unnecessary use of `to_vec` + --> $DIR/unnecessary_to_owned.rs:527:37 + | +LL | IntoFuture::into_future(foo([].to_vec(), &0)); + | ^^^^^^^^^^^ help: use: `[]` + +error: aborting due to 80 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs b/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs index 373b18470f695..5ad117eb8db6e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs +++ b/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, clippy::needless_pass_by_ref_mut)] #![warn(clippy::unnecessary_safety_doc)] extern crate proc_macros; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 63e8ba7c79f9f..282d8310b8ff8 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2191,9 +2191,10 @@ impl<'test> TestCx<'test> { || self.config.target.contains("wasm32") || self.config.target.contains("nvptx") || self.is_vxworks_pure_static() - || self.config.target.contains("bpf") || !self.config.target_cfg().dynamic_linking || matches!(self.config.mode, CoverageMap | CoverageRun) + || self.config.target.contains("bpf") + || self.config.target.contains("sbf") { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index 9b0a40c41b9cb..97f2b4ca02d45 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -20,8 +20,8 @@ use NaNKind::*; #[track_caller] fn check_all_outcomes(expected: HashSet, generate: impl Fn() -> T) { let mut seen = HashSet::new(); - // Let's give it 8x as many tries as we are expecting values. - let tries = expected.len() * 8; + // Let's give it 16x as many tries as we are expecting values. + let tries = expected.len() * 16; for _ in 0..tries { let val = generate(); assert!(expected.contains(&val), "got an unexpected value: {val}"); diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index ff71ca537256f..faeabd807b123 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -4,7 +4,8 @@ use std::fs; use std::path::Path; /// List of allowed sources for packages. -const ALLOWED_SOURCES: &[&str] = &["\"registry+https://github.com/rust-lang/crates.io-index\""]; +const ALLOWED_SOURCES: &[&str] = &["\"registry+https://github.com/rust-lang/crates.io-index\"", +"\"git+https://github.com/solana-labs/compiler-builtins?tag=solana-tools-v1.40#81ef46f3fe1357095acdd089a700890fe4e13974\""]; /// Checks for external package sources. `root` is the path to the directory that contains the /// workspace `Cargo.toml`. diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 5f6b63a67fda7..e3b5925a7358d 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -38,8 +38,25 @@ const EXCEPTION_PATHS: &[&str] = &[ "library/panic_abort", "library/panic_unwind", "library/unwind", - "library/rtstartup", // Not sure what to do about this. magic stuff for mingw - "library/test", // Probably should defer to unstable `std::sys` APIs. + "library/std/src/sys/", // Platform-specific code for std lives here. + // This has the trailing slash so that sys_common is not excepted. + "library/std/src/os", // Platform-specific public interfaces + "library/rtstartup", // Not sure what to do about this. magic stuff for mingw + // Integration test for platform-specific run-time feature detection: + "library/std/tests/run-time-detect.rs", + "library/std/src/net/test.rs", + "library/std/src/net/addr", + "library/std/src/net/udp", + "library/std/src/sys_common/backtrace.rs", + "library/std/src/sys_common/remutex.rs", + "library/std/src/sync/mutex.rs", + "library/std/src/sync/rwlock.rs", + "library/term", // Not sure how to make this crate portable, but test crate needs it. + "library/test", // Probably should defer to unstable `std::sys` APIs. + // std testing crates, okay for now at least + "library/core/tests", + "library/alloc/tests/lib.rs", + "library/alloc/benches/lib.rs", // The `VaList` implementation must have platform specific code. // The Windows implementation of a `va_list` is always a character // pointer regardless of the target architecture. As a result, @@ -123,7 +140,6 @@ fn check_cfgs( || cfg.contains("target_env") || cfg.contains("target_abi") || cfg.contains("target_vendor") - || cfg.contains("target_family") || cfg.contains("unix") || cfg.contains("windows"); diff --git a/tests/codegen/sbf-alu32.rs b/tests/codegen/sbf-alu32.rs new file mode 100644 index 0000000000000..47aaeb093dacd --- /dev/null +++ b/tests/codegen/sbf-alu32.rs @@ -0,0 +1,11 @@ +// only-sbf +#![crate_type = "lib"] +#![feature(sbf_target_feature)] +#![no_std] + +#[no_mangle] +#[target_feature(enable = "alu32")] +// CHECK: define i8 @foo(i8 returned %arg) unnamed_addr #0 { +pub unsafe fn foo(arg: u8) -> u8 { + arg +} diff --git a/tests/run-make/unstable-flag-required/Makefile b/tests/run-make/unstable-flag-required/Makefile index 17dd15b079c62..c95ec74a55d3a 100644 --- a/tests/run-make/unstable-flag-required/Makefile +++ b/tests/run-make/unstable-flag-required/Makefile @@ -1,4 +1,6 @@ include ../tools.mk +# only-thumb + all: $(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr index bb2f4915b5ef6..d7b2fa8f16ae3 100644 --- a/tests/ui/check-cfg/compact-values.stderr +++ b/tests/ui/check-cfg/compact-values.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value: `X` LL | #[cfg(target(os = "linux", arch = "X"))] | ^^^^^^^^^^ | - = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` + = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sbf`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/values-target-json.stderr b/tests/ui/check-cfg/values-target-json.stderr index e71149f337f58..ab04d953ad575 100644 --- a/tests/ui/check-cfg/values-target-json.stderr +++ b/tests/ui/check-cfg/values-target-json.stderr @@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")] | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solana`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 6877d8f5bb727..644df1fb0f7a1 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")] | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solana`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `0` diff --git a/tests/ui/linkage-attr/unstable-flavor.bpf.stderr b/tests/ui/linkage-attr/unstable-flavor.bpf.stderr deleted file mode 100644 index 819da2fb01788..0000000000000 --- a/tests/ui/linkage-attr/unstable-flavor.bpf.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the linker flavor `bpf` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values - diff --git a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr b/tests/ui/linkage-attr/unstable-flavor.ptx.stderr deleted file mode 100644 index 2ebdc1a903399..0000000000000 --- a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the linker flavor `ptx` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values - diff --git a/tests/ui/linkage-attr/unstable-flavor.rs b/tests/ui/linkage-attr/unstable-flavor.rs deleted file mode 100644 index c2c16b28bff10..0000000000000 --- a/tests/ui/linkage-attr/unstable-flavor.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Even though this test only checks 2 of the 10 or so unstable linker flavors, it exercizes the -// unique codepath checking all unstable options (see `LinkerFlavorCli::is_unstable` and its -// caller). If it passes, all the other unstable options are rejected as well. -// -// revisions: bpf ptx -// [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf --crate-type=rlib -// [bpf] error-pattern: linker flavor `bpf` is unstable, the `-Z unstable-options` flag -// [bpf] needs-llvm-components: -// [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx --crate-type=rlib -// [ptx] error-pattern: linker flavor `ptx` is unstable, the `-Z unstable-options` flag -// [ptx] needs-llvm-components: - -#![feature(no_core)] -#![no_core] diff --git a/tests/ui/native-library-link-flags/modifiers-override-2.rs b/tests/ui/native-library-link-flags/modifiers-override-2.rs deleted file mode 100644 index 333f6786b0fba..0000000000000 --- a/tests/ui/native-library-link-flags/modifiers-override-2.rs +++ /dev/null @@ -1,3 +0,0 @@ -// compile-flags:-lstatic:+whole-archive,-whole-archive=foo - -fn main() {} diff --git a/tests/ui/native-library-link-flags/modifiers-override-2.stderr b/tests/ui/native-library-link-flags/modifiers-override-2.stderr deleted file mode 100644 index aa5b59c5b6f9e..0000000000000 --- a/tests/ui/native-library-link-flags/modifiers-override-2.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: multiple `whole-archive` modifiers in a single `-l` option - diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 971a4654b4cec..fb6097551d029 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -19,6 +19,7 @@ // gate-test-aarch64_ver_target_feature // gate-test-csky_target_feature // gate-test-loongarch_target_feature +// gate-test-sbf_target_feature #[target_feature(enable = "avx512bw")] //~^ ERROR: currently unstable diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 0ec7427c3c456..8877b41c65049 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:23:18 + --> $DIR/gate.rs:24:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^