From c56c2b7a0db7e0c4a3d1c659af67386f0d1ad648 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 19 Aug 2024 15:20:02 +0200 Subject: [PATCH 001/139] Rename `is_like_osx` to `is_like_darwin` --- src/abi/mod.rs | 2 +- src/constant.rs | 2 +- src/debuginfo/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index e8076ce77abc..ddd119e0c610 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -641,7 +641,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( .flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()), ); - if fx.tcx.sess.target.is_like_osx && fx.tcx.sess.target.arch == "aarch64" { + if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == "aarch64" { // Add any padding arguments needed for Apple AArch64. // There's no need to pad the argument list unless variadic arguments are actually being // passed. diff --git a/src/constant.rs b/src/constant.rs index bcc70f4567fb..c8527c3a57df 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -391,7 +391,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant data.set_align(alloc.align.bytes()); if let Some(section_name) = section_name { - let (segment_name, section_name) = if tcx.sess.target.is_like_osx { + let (segment_name, section_name) = if tcx.sess.target.is_like_darwin { // See https://github.com/llvm/llvm-project/blob/main/llvm/lib/MC/MCSectionMachO.cpp let mut parts = section_name.as_str().split(','); let Some(segment_name) = parts.next() else { diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index bba6567774d7..286e02b986b3 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -58,7 +58,7 @@ impl DebugContext { // FIXME this should be configurable // macOS doesn't seem to support DWARF > 3 // 5 version is required for md5 file hash - version: if tcx.sess.target.is_like_osx { + version: if tcx.sess.target.is_like_darwin { 3 } else { // FIXME change to version 5 once the gdb and lldb shipping with the latest debian From 15dbafa81ee8dcf70ead827bb4991d5be8cd99de Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:43:48 +0000 Subject: [PATCH 002/139] Merge commit 'ba315abda789c9f59f2100102232bddb30b0d3d3' into sync_cg_clif-2025-03-30 --- .cirrus.yml | 41 +- .github/actions/github-release/README.md | 18 - .github/actions/github-release/action.yml | 13 - .github/actions/github-release/main.js | 162 ----- .../actions/github-release/package-lock.json | 571 ------------------ .github/actions/github-release/package.json | 11 - .github/workflows/abi-cafe.yml | 12 +- .github/workflows/main.yml | 43 +- .github/workflows/rustc.yml | 6 - .vscode/settings.json | 33 +- .zed/settings.json | 25 +- Cargo.lock | 89 +-- Cargo.toml | 24 +- Readme.md | 2 +- build_system/prepare.rs | 7 + build_system/tests.rs | 49 +- config.txt | 2 +- docs/usage.md | 11 +- ...root_tests-128bit-atomic-operations.patch} | 12 +- ...coretests-Disable-long-running-tests.patch | 48 -- ...oot_tests-Disable-long-running-tests.patch | 105 ++++ ...le-f16-and-f128-in-compiler-builtins.patch | 26 - patches/coretests-lock.toml | 35 -- rust-toolchain | 2 +- scripts/cargo-clif.rs | 14 +- scripts/filter_profile.rs | 2 +- scripts/rustup.sh | 2 +- scripts/setup_rust_fork.sh | 23 + scripts/test_rustc_tests.sh | 58 +- src/base.rs | 6 +- src/common.rs | 18 +- src/config.rs | 34 +- src/debuginfo/types.rs | 4 +- src/driver/aot.rs | 2 +- src/driver/jit.rs | 225 +------ src/inline_asm.rs | 48 +- src/intrinsics/llvm.rs | 8 + src/intrinsics/llvm_aarch64.rs | 123 +++- src/lib.rs | 24 +- src/num.rs | 8 +- src/value_and_place.rs | 6 +- 41 files changed, 533 insertions(+), 1419 deletions(-) delete mode 100644 .github/actions/github-release/README.md delete mode 100644 .github/actions/github-release/action.yml delete mode 100644 .github/actions/github-release/main.js delete mode 100644 .github/actions/github-release/package-lock.json delete mode 100644 .github/actions/github-release/package.json rename patches/{0027-coretests-128bit-atomic-operations.patch => 0027-sysroot_tests-128bit-atomic-operations.patch} (84%) delete mode 100644 patches/0028-coretests-Disable-long-running-tests.patch create mode 100644 patches/0028-sysroot_tests-Disable-long-running-tests.patch delete mode 100644 patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch delete mode 100644 patches/coretests-lock.toml diff --git a/.cirrus.yml b/.cirrus.yml index 1ec99eb3d17a..ee5de8b42f46 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,20 +1,21 @@ -task: - name: freebsd - freebsd_instance: - image: freebsd-13-2-release-amd64 - setup_rust_script: - - pkg install -y git-tiny binutils - - curl https://sh.rustup.rs -sSf --output rustup.sh - - sh rustup.sh --default-toolchain none -y --profile=minimal - target_cache: - folder: build/cg_clif - prepare_script: - - . $HOME/.cargo/env - - ./y.sh prepare - test_script: - - . $HOME/.cargo/env - # Disabling incr comp reduces cache size and incr comp doesn't save as much - # on CI anyway. - - export CARGO_BUILD_INCREMENTAL=false - # Skip rand as it fails on FreeBSD due to rust-random/rand#1355 - - ./y.sh test --skip-test test.rust-random/rand +# FIXME re-enable once https://github.com/rust-lang/rust/issues/134863 is fixed. +# task: +# name: freebsd +# freebsd_instance: +# image: freebsd-13-2-release-amd64 +# setup_rust_script: +# - pkg install -y git-tiny binutils +# - curl https://sh.rustup.rs -sSf --output rustup.sh +# - sh rustup.sh --default-toolchain none -y --profile=minimal +# target_cache: +# folder: build/cg_clif +# prepare_script: +# - . $HOME/.cargo/env +# - ./y.sh prepare +# test_script: +# - . $HOME/.cargo/env +# # Disabling incr comp reduces cache size and incr comp doesn't save as much +# # on CI anyway. +# - export CARGO_BUILD_INCREMENTAL=false +# # Skip rand as it fails on FreeBSD due to rust-random/rand#1355 +# - ./y.sh test --skip-test test.rust-random/rand diff --git a/.github/actions/github-release/README.md b/.github/actions/github-release/README.md deleted file mode 100644 index c70ba8f49538..000000000000 --- a/.github/actions/github-release/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# github-release - -An action used to publish GitHub releases for `wasmtime`. - -As of the time of this writing there's a few actions floating around which -perform github releases but they all tend to have their set of drawbacks. -Additionally nothing handles deleting releases which we need for our rolling -`dev` release. - -To handle all this this action rolls-its-own implementation using the -actions/toolkit repository and packages published there. These run in a Docker -container and take various inputs to orchestrate the release from the build. - -More comments can be found in `main.js`. - -Testing this is really hard. If you want to try though run `npm install` and -then `node main.js`. You'll have to configure a bunch of env vars though to get -anything reasonably working. diff --git a/.github/actions/github-release/action.yml b/.github/actions/github-release/action.yml deleted file mode 100644 index 36e5209f50c3..000000000000 --- a/.github/actions/github-release/action.yml +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -name: 'rustc_codegen_cranelift github releases' -description: 'rustc_codegen_cranelift github releases' -inputs: - token: - description: '' - required: true - files: - description: '' - required: true -runs: - using: 'node16' - main: 'main.js' diff --git a/.github/actions/github-release/main.js b/.github/actions/github-release/main.js deleted file mode 100644 index 1eb2b7f23b26..000000000000 --- a/.github/actions/github-release/main.js +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -const core = require('@actions/core'); -const path = require("path"); -const fs = require("fs"); -const github = require('@actions/github'); -const glob = require('glob'); - -function sleep(milliseconds) { - return new Promise(resolve => setTimeout(resolve, milliseconds)) -} - -async function runOnce() { - // Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*` - const files = core.getInput('files'); - const token = core.getInput('token'); - const slug = process.env.GITHUB_REPOSITORY; - const owner = slug.split('/')[0]; - const repo = slug.split('/')[1]; - const sha = process.env.GITHUB_SHA; - let name = 'dev'; - if (process.env.GITHUB_REF.startsWith('refs/tags/v')) { - name = process.env.GITHUB_REF.substring(10); - } - - core.info(`files: ${files}`); - core.info(`name: ${name}`); - core.info(`token: ${token}`); - - const octokit = github.getOctokit(token); - - // For the `dev` release we may need to update the tag to point to the new - // commit on this branch. All other names should already have tags associated - // with them. - if (name == 'dev') { - let tag = null; - try { - tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name }); - core.info(`found existing tag`); - console.log("tag: ", JSON.stringify(tag.data, null, 2)); - } catch (e) { - // ignore if this tag doesn't exist - core.info(`no existing tag found`); - } - - if (tag === null || tag.data.object.sha !== sha) { - core.info(`updating existing tag or creating new one`); - - try { - core.info(`updating dev tag`); - await octokit.rest.git.updateRef({ - owner, - repo, - ref: 'tags/dev', - sha, - force: true, - }); - } catch (e) { - console.log("ERROR: ", JSON.stringify(e.response, null, 2)); - core.info(`creating dev tag`); - try { - await octokit.rest.git.createRef({ - owner, - repo, - ref: 'refs/tags/dev', - sha, - }); - } catch (e) { - // we might race with others, so assume someone else has created the - // tag by this point. - console.log("failed to create tag: ", JSON.stringify(e.response, null, 2)); - } - } - - console.log("double-checking tag is correct"); - tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name }); - if (tag.data.object.sha !== sha) { - console.log("tag: ", JSON.stringify(tag.data, null, 2)); - throw new Error("tag didn't work"); - } - } else { - core.info(`existing tag works`); - } - } - - // Delete a previous release - try { - core.info(`fetching release`); - let release = await octokit.rest.repos.getReleaseByTag({ owner, repo, tag: name }); - console.log("found release: ", JSON.stringify(release.data, null, 2)); - await octokit.rest.repos.deleteRelease({ - owner, - repo, - release_id: release.data.id, - }); - console.log("deleted release"); - } catch (e) { - console.log("ERROR: ", JSON.stringify(e, null, 2)); - } - - console.log("creating a release"); - let release = await octokit.rest.repos.createRelease({ - owner, - repo, - tag_name: name, - prerelease: name === 'dev', - }); - - // Delete all assets from a previous run - for (const asset of release.data.assets) { - console.log(`deleting prior asset ${asset.id}`); - await octokit.rest.repos.deleteReleaseAsset({ - owner, - repo, - asset_id: asset.id, - }); - } - - // Upload all the relevant assets for this release as just general blobs. - for (const file of glob.sync(files)) { - const size = fs.statSync(file).size; - const name = path.basename(file); - core.info(`upload ${file}`); - await octokit.rest.repos.uploadReleaseAsset({ - data: fs.createReadStream(file), - headers: { 'content-length': size, 'content-type': 'application/octet-stream' }, - name, - url: release.data.upload_url, - }); - } -} - -async function run() { - const retries = 10; - for (let i = 0; i < retries; i++) { - try { - await runOnce(); - break; - } catch (e) { - if (i === retries - 1) - throw e; - logError(e); - console.log("RETRYING after 10s"); - await sleep(10000) - } - } -} - -function logError(e) { - console.log("ERROR: ", e.message); - try { - console.log(JSON.stringify(e, null, 2)); - } catch (e) { - // ignore json errors for now - } - console.log(e.stack); -} - -run().catch(err => { - logError(err); - core.setFailed(err.message); -}); diff --git a/.github/actions/github-release/package-lock.json b/.github/actions/github-release/package-lock.json deleted file mode 100644 index dd3b2a048f09..000000000000 --- a/.github/actions/github-release/package-lock.json +++ /dev/null @@ -1,571 +0,0 @@ -{ - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "dependencies": { - "@actions/core": "^1.9.1", - "@actions/github": "^5.1.0", - "glob": "^7.1.5" - } - }, - "node_modules/@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "dependencies": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" - } - }, - "node_modules/@actions/github": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", - "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", - "dependencies": { - "@actions/http-client": "^2.0.1", - "@octokit/core": "^3.6.0", - "@octokit/plugin-paginate-rest": "^2.17.0", - "@octokit/plugin-rest-endpoint-methods": "^5.13.0" - } - }, - "node_modules/@actions/http-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", - "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", - "dependencies": { - "tunnel": "^0.0.6" - } - }, - "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dependencies": { - "@octokit/types": "^6.0.3" - } - }, - "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dependencies": { - "@octokit/types": "^6.40.0" - }, - "peerDependencies": { - "@octokit/core": ">=2" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dependencies": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - }, - "dependencies": { - "@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "requires": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" - } - }, - "@actions/github": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", - "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", - "requires": { - "@actions/http-client": "^2.0.1", - "@octokit/core": "^3.6.0", - "@octokit/plugin-paginate-rest": "^2.17.0", - "@octokit/plugin-rest-endpoint-methods": "^5.13.0" - } - }, - "@actions/http-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", - "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", - "requires": { - "tunnel": "^0.0.6" - } - }, - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "requires": { - "@octokit/types": "^6.40.0" - } - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "requires": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - } - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - } -} diff --git a/.github/actions/github-release/package.json b/.github/actions/github-release/package.json deleted file mode 100644 index d9c23f8873ec..000000000000 --- a/.github/actions/github-release/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "license": "Apache-2.0 WITH LLVM-exception", - "main": "main.js", - "dependencies": { - "@actions/core": "^1.9.1", - "@actions/github": "^5.1.0", - "glob": "^7.1.5" - } -} diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index 30dc5cb16154..6ad041a796c9 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -25,7 +25,10 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-unknown-linux-gnu - - os: macos-latest + - os: ubuntu-24.04-arm + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu + - os: macos-13 env: TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest @@ -56,13 +59,6 @@ jobs: if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build run: ./y.sh build --sysroot none diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 61a4c1270c99..6fd288d195c0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,13 +53,12 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-unknown-linux-gnu - - os: macos-latest - env: - TARGET_TRIPLE: x86_64-apple-darwin - - os: ubuntu-latest + - os: ubuntu-24.04-arm env: TARGET_TRIPLE: aarch64-unknown-linux-gnu - apt_deps: gcc-aarch64-linux-gnu qemu-user + - os: macos-13 + env: + TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest env: TARGET_TRIPLE: aarch64-apple-darwin @@ -95,10 +94,6 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - name: Install toolchain and emulator if: matrix.apt_deps != null run: | @@ -170,9 +165,6 @@ jobs: sudo apt update sudo apt install -y hyperfine - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build run: ./y.sh build --sysroot none @@ -192,7 +184,10 @@ jobs: - os: ubuntu-22.04 env: TARGET_TRIPLE: x86_64-unknown-linux-gnu - - os: macos-latest + - os: ubuntu-24.04-arm + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu + - os: macos-13 env: TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest @@ -218,13 +213,6 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build backend run: ./y.sh build --sysroot none @@ -273,12 +261,9 @@ jobs: rmdir artifacts/ # verify all artifacts are represented in release/ ls -R release/ - - run: npm install --production - working-directory: .github/actions/github-release - - - name: Publish Release - uses: ./.github/actions/github-release - with: - files: "release/*" - token: ${{ github.token }} - continue-on-error: true + - name: Publish release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release delete --cleanup-tag -y dev || true + gh release create --target $GITHUB_SHA --prerelease dev release/* diff --git a/.github/workflows/rustc.yml b/.github/workflows/rustc.yml index 70c214ce8b14..9253ab96353c 100644 --- a/.github/workflows/rustc.yml +++ b/.github/workflows/rustc.yml @@ -22,9 +22,6 @@ jobs: path: build/cg_clif key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }} - - name: Prepare dependencies - run: ./y.sh prepare - - name: Test run: ./scripts/test_bootstrap.sh @@ -50,8 +47,5 @@ jobs: sudo apt update sudo apt install -y ripgrep - - name: Prepare dependencies - run: ./y.sh prepare - - name: Test run: ./scripts/test_rustc_tests.sh diff --git a/.vscode/settings.json b/.vscode/settings.json index 491646ce59bb..68bd93aea890 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,41 +1,40 @@ { "editor.formatOnSave": true, - // in case rustc.source is disabled for performance reasons; disable the errors about this - "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"], + "rust-analyzer.diagnostics.disabled": [ + "unresolved-extern-crate", + "unresolved-macro-call" + ], "rust-analyzer.rustc.source": "discover", "rust-analyzer.imports.granularity.enforce": true, "rust-analyzer.imports.granularity.group": "module", "rust-analyzer.imports.prefix": "crate", - "rust-analyzer.cargo.features": ["unstable-features"], + "rust-analyzer.cargo.features": [ + "unstable-features" + ], "rust-analyzer.linkedProjects": [ "./Cargo.toml", "./build_system/Cargo.toml", { + "sysroot_src": "./build/stdlib/library", "crates": [ { "root_module": "./example/mini_core.rs", - "edition": "2018", + "edition": "2015", "deps": [], "cfg": [], }, { "root_module": "./example/mini_core_hello_world.rs", - "edition": "2018", - "deps": [{ "crate": 0, "name": "mini_core" }], + "edition": "2015", + "deps": [ + { + "crate": 0, + "name": "mini_core" + } + ], "cfg": [], }, - { - "root_module": "./example/mod_bench.rs", - "edition": "2018", - "deps": [], - "cfg": [], - }, - ] - }, - { - "sysroot_src": "./build/stdlib/library", - "crates": [ { "root_module": "./example/std_example.rs", "edition": "2015", diff --git a/.zed/settings.json b/.zed/settings.json index e93bed369492..4338a3473311 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -5,7 +5,10 @@ "initialization_options": { "diagnostics": { // in case rustc.source is disabled for performance reasons; disable the errors about this - "disabled": ["unresolved-extern-crate", "unresolved-macro-call"] + "disabled": [ + "unresolved-extern-crate", + "unresolved-macro-call" + ] }, "rustc": { "source": "discover" @@ -18,22 +21,25 @@ "prefix": "crate" }, "cargo": { - "features": ["unstable-features"] + "features": [ + "unstable-features" + ] }, "linkedProjects": [ "./Cargo.toml", "./build_system/Cargo.toml", { + "sysroot_src": "./build/stdlib/library", "crates": [ { "root_module": "./example/mini_core.rs", - "edition": "2018", + "edition": "2015", "deps": [], "cfg": [] }, { "root_module": "./example/mini_core_hello_world.rs", - "edition": "2018", + "edition": "2015", "deps": [ { "crate": 0, @@ -42,17 +48,6 @@ ], "cfg": [] }, - { - "root_module": "./example/mod_bench.rs", - "edition": "2018", - "deps": [], - "cfg": [] - } - ] - }, - { - "sysroot_src": "./build/stdlib/library", - "crates": [ { "root_module": "./example/std_example.rs", "edition": "2015", diff --git a/Cargo.lock b/Cargo.lock index ca66ec5c6e93..e5f1896b9230 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,27 +42,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cranelift-bforest" -version = "0.116.1" +name = "cranelift-assembler-x64" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e15d04a0ce86cb36ead88ad68cf693ffd6cda47052b9e0ac114bc47fd9cd23c4" +checksum = "3e4b56ebe316895d3fa37775d0a87b0c889cc933f5c8b253dbcc7c7bcb7fe7e4" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95cabbc01dfbd7dcd6c329ca44f0212910309c221797ac736a67a5bc8857fe1b" + +[[package]] +name = "cranelift-bforest" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ffe46df300a45f1dc6f609dc808ce963f0e3a2e971682c479a2d13e3b9b8ef" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6e3969a7ce267259ce244b7867c5d3bc9e65b0a87e81039588dfdeaede9f34" +checksum = "b265bed7c51e1921fdae6419791d31af77d33662ee56d7b0fa0704dc8d231cab" [[package]] name = "cranelift-codegen" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c22032c4cb42558371cf516bb47f26cdad1819d3475c133e93c49f50ebf304e" +checksum = "e606230a7e3a6897d603761baee0d19f88d077f17b996bb5089488a29ae96e41" dependencies = [ "bumpalo", + "cranelift-assembler-x64", "cranelift-bforest", "cranelift-bitset", "cranelift-codegen-meta", @@ -71,7 +87,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.14.5", + "hashbrown", "log", "regalloc2", "rustc-hash", @@ -82,42 +98,43 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c904bc71c61b27fc57827f4a1379f29de64fe95653b620a3db77d59655eee0b8" +checksum = "8a63bffafc23bc60969ad528e138788495999d935f0adcfd6543cb151ca8637d" dependencies = [ + "cranelift-assembler-x64", "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40180f5497572f644ce88c255480981ae2ec1d7bb4d8e0c0136a13b87a2f2ceb" +checksum = "af50281b67324b58e843170a6a5943cf6d387c06f7eeacc9f5696e4ab7ae7d7e" [[package]] name = "cranelift-control" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d132c6d0bd8a489563472afc171759da0707804a65ece7ceb15a8c6d7dd5ef" +checksum = "8c20c1b38d1abfbcebb0032e497e71156c0e3b8dcb3f0a92b9863b7bcaec290c" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d0d9618275474fbf679dd018ac6e009acbd6ae6850f6a67be33fb3b00b323" +checksum = "0c2c67d95507c51b4a1ff3f3555fe4bfec36b9e13c1b684ccc602736f5d5f4a2" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fac41e16729107393174b0c9e3730fb072866100e1e64e80a1a963b2e484d57" +checksum = "4e002691cc69c38b54fc7ec93e5be5b744f627d027031d991cc845d1d512d0ce" dependencies = [ "cranelift-codegen", "log", @@ -127,15 +144,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca20d576e5070044d0a72a9effc2deacf4d6aa650403189d8ea50126483944d" +checksum = "e93588ed1796cbcb0e2ad160403509e2c5d330d80dd6e0014ac6774c7ebac496" [[package]] name = "cranelift-jit" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e65c42755a719b09662b00c700daaf76cc35d5ace1f5c002ad404b591ff1978" +checksum = "17f6682f0b193d6b7873cc8e7ed67e8776a8a26f50eeabf88534e9be618b9a03" dependencies = [ "anyhow", "cranelift-codegen", @@ -153,9 +170,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d55612bebcf16ff7306c8a6f5bdb6d45662b8aa1ee058ecce8807ad87db719b" +checksum = "ff19784c6de05116e63e6a34791012bd927b2a4eac56233039c46f1b6a4edac8" dependencies = [ "anyhow", "cranelift-codegen", @@ -164,9 +181,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dee82f3f1f2c4cba9177f1cc5e350fe98764379bcd29340caa7b01f85076c7" +checksum = "e5b09bdd6407bf5d89661b80cf926ce731c9e8cc184bf49102267a2369a8358e" dependencies = [ "cranelift-codegen", "libc", @@ -175,9 +192,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.116.1" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aad5a6d3e379493c3f8b35dc61c93d0bf5f27003bbe20614e0200b0ec372ef52" +checksum = "685e8661a30d1cb69509f589ac643adeee79c5f63c0da316431b9fad29e6d3b4" dependencies = [ "anyhow", "cranelift-codegen", @@ -226,12 +243,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "hashbrown" version = "0.15.2" @@ -248,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown", ] [[package]] @@ -295,7 +306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", - "hashbrown 0.15.2", + "hashbrown", "indexmap", "memchr", ] @@ -326,7 +337,7 @@ checksum = "145c1c267e14f20fb0f88aa76a1c5ffec42d592c1d28b3cd9148ae35916158d3" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown 0.15.2", + "hashbrown", "log", "rustc-hash", "smallvec", @@ -425,9 +436,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "wasmtime-jit-icache-coherence" -version = "29.0.1" +version = "31.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec5e8552e01692e6c2e5293171704fed8abdec79d1a6995a0870ab190e5747d1" +checksum = "a54f6c6c7e9d7eeee32dfcc10db7f29d505ee7dd28d00593ea241d5f70698e64" dependencies = [ "anyhow", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 670d6f4eef5c..08b60de14c1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.116.0", default-features = false, features = ["std", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.116.0" } -cranelift-module = { version = "0.116.0" } -cranelift-native = { version = "0.116.0" } -cranelift-jit = { version = "0.116.0", optional = true } -cranelift-object = { version = "0.116.0" } +cranelift-codegen = { version = "0.118.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.118.0" } +cranelift-module = { version = "0.118.0" } +cranelift-native = { version = "0.118.0" } +cranelift-jit = { version = "0.118.0", optional = true } +cranelift-object = { version = "0.118.0" } target-lexicon = "0.13" gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/Readme.md b/Readme.md index 18a840f8a50e..28edb5795ce3 100644 --- a/Readme.md +++ b/Readme.md @@ -49,13 +49,13 @@ If you want to build the backend manually, you can download it from GitHub and b ```bash $ git clone https://github.com/rust-lang/rustc_codegen_cranelift $ cd rustc_codegen_cranelift -$ ./y.sh prepare $ ./y.sh build ``` To run the test suite replace the last command with: ```bash +$ ./y.sh prepare # only needs to be run the first time $ ./test.sh ``` diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 11f73bdb61f9..ba5cc9a29f59 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -91,6 +91,13 @@ impl GitRepo { fn verify_checksum(&self, dirs: &Dirs) { let download_dir = self.download_dir(dirs); + if !download_dir.exists() { + eprintln!( + "Missing directory {download_dir}: Please run ./y.sh prepare to download.", + download_dir = download_dir.display(), + ); + std::process::exit(1); + } let actual_hash = format!("{:016x}", hash_dir(&download_dir)); if actual_hash != self.content_hash { eprintln!( diff --git a/build_system/tests.rs b/build_system/tests.rs index ea7e94c345ad..122b541fa35f 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -1,5 +1,4 @@ use std::ffi::OsStr; -use std::fs; use std::path::PathBuf; use std::process::Command; @@ -126,9 +125,9 @@ static PORTABLE_SIMD_SRC: RelPath = RelPath::build("portable-simd"); static PORTABLE_SIMD: CargoProject = CargoProject::new(&PORTABLE_SIMD_SRC, "portable-simd_target"); -static LIBCORE_TESTS_SRC: RelPath = RelPath::build("coretests"); +static SYSROOT_TESTS_SRC: RelPath = RelPath::build("sysroot_tests"); -static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "coretests_target"); +static SYSROOT_TESTS: CargoProject = CargoProject::new(&SYSROOT_TESTS_SRC, "sysroot_tests_target"); const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ TestCase::custom("test.rust-random/rand", &|runner| { @@ -147,28 +146,24 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::custom("test.libcore", &|runner| { + TestCase::custom("test.sysroot", &|runner| { apply_patches( &runner.dirs, - "coretests", - &runner.stdlib_source.join("library/coretests"), - &LIBCORE_TESTS_SRC.to_path(&runner.dirs), + "sysroot_tests", + &runner.stdlib_source.join("library"), + &SYSROOT_TESTS_SRC.to_path(&runner.dirs), ); - let source_lockfile = runner.dirs.source_dir.join("patches/coretests-lock.toml"); - let target_lockfile = LIBCORE_TESTS_SRC.to_path(&runner.dirs).join("Cargo.lock"); - fs::copy(source_lockfile, target_lockfile).unwrap(); - - LIBCORE_TESTS.clean(&runner.dirs); + SYSROOT_TESTS.clean(&runner.dirs); if runner.is_native { - let mut test_cmd = LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs); - test_cmd.arg("--").arg("-q"); + let mut test_cmd = SYSROOT_TESTS.test(&runner.target_compiler, &runner.dirs); + test_cmd.args(["-p", "coretests", "-p", "alloctests", "--", "-q"]); spawn_and_wait(test_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); - let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs); - build_cmd.arg("--tests"); + let mut build_cmd = SYSROOT_TESTS.build(&runner.target_compiler, &runner.dirs); + build_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests"]); spawn_and_wait(build_cmd); } }), @@ -330,10 +325,8 @@ impl<'a> TestRunner<'a> { target_compiler.rustflags.extend(rustflags_from_env("RUSTFLAGS")); target_compiler.rustdocflags.extend(rustflags_from_env("RUSTDOCFLAGS")); - let jit_supported = use_unstable_features - && is_native - && target_compiler.triple.contains("x86_64") - && !target_compiler.triple.contains("windows"); + let jit_supported = + use_unstable_features && is_native && !target_compiler.triple.contains("windows"); Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source } } @@ -374,21 +367,7 @@ impl<'a> TestRunner<'a> { TestCaseCmd::JitBin { source, args } => { let mut jit_cmd = self.rustc_command([ "-Zunstable-options", - "-Cllvm-args=mode=jit", - "-Cprefer-dynamic", - source, - "--cfg", - "jit", - ]); - if !args.is_empty() { - jit_cmd.env("CG_CLIF_JIT_ARGS", args); - } - spawn_and_wait(jit_cmd); - - eprintln!("[JIT-lazy] {testname}"); - let mut jit_cmd = self.rustc_command([ - "-Zunstable-options", - "-Cllvm-args=mode=jit-lazy", + "-Cllvm-args=jit-mode", "-Cprefer-dynamic", source, "--cfg", diff --git a/config.txt b/config.txt index f578cbef35e6..714414fe8d68 100644 --- a/config.txt +++ b/config.txt @@ -35,6 +35,6 @@ aot.raw-dylib testsuite.extended_sysroot test.rust-random/rand -test.libcore +test.sysroot test.regex test.portable-simd diff --git a/docs/usage.md b/docs/usage.md index 135a51ce392b..dbe36109f83e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -38,14 +38,7 @@ $ $cg_clif_dir/dist/cargo-clif jit or ```bash -$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs -``` - -There is also an experimental lazy jit mode. In this mode functions are only compiled once they are -first called. - -```bash -$ $cg_clif_dir/dist/cargo-clif lazy-jit +$ $cg_clif_dir/dist/rustc-clif -Cllvm-args=jit-mode -Cprefer-dynamic my_crate.rs ``` ## Shell @@ -54,7 +47,7 @@ These are a few functions that allow you to easily run rust code from the shell ```bash function jit_naked() { - echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic + echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode-Cprefer-dynamic } function jit() { diff --git a/patches/0027-coretests-128bit-atomic-operations.patch b/patches/0027-sysroot_tests-128bit-atomic-operations.patch similarity index 84% rename from patches/0027-coretests-128bit-atomic-operations.patch rename to patches/0027-sysroot_tests-128bit-atomic-operations.patch index 4a06dc3f7ef8..16c8488acdb5 100644 --- a/patches/0027-coretests-128bit-atomic-operations.patch +++ b/patches/0027-sysroot_tests-128bit-atomic-operations.patch @@ -10,20 +10,20 @@ Cranelift doesn't support them yet library/core/tests/atomic.rs | 4 --- 4 files changed, 4 insertions(+), 50 deletions(-) -diff --git a/tests/lib.rs b/tests/lib.rs +diff --git a/coretests/tests/lib.rs b/coretests/tests/lib.rs index 1e336bf..35e6f54 100644 ---- a/tests/lib.rs -+++ b/tests/lib.rs +--- a/coretests/tests/lib.rs ++++ b/coretests/tests/lib.rs @@ -2,5 +2,4 @@ // tidy-alphabetical-start -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] #![feature(array_chunks)] -diff --git a/tests/atomic.rs b/tests/atomic.rs +diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs index b735957..ea728b6 100644 ---- a/tests/atomic.rs -+++ b/tests/atomic.rs +--- a/coretests/tests/atomic.rs ++++ b/coretests/tests/atomic.rs @@ -185,10 +185,6 @@ fn atomic_alignment() { assert_eq!(align_of::(), size_of::()); #[cfg(target_has_atomic = "64")] diff --git a/patches/0028-coretests-Disable-long-running-tests.patch b/patches/0028-coretests-Disable-long-running-tests.patch deleted file mode 100644 index f5ae66c0eb13..000000000000 --- a/patches/0028-coretests-Disable-long-running-tests.patch +++ /dev/null @@ -1,48 +0,0 @@ -From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Fri, 3 Dec 2021 12:16:30 +0100 -Subject: [PATCH] Disable long running tests - ---- - library/core/tests/slice.rs | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/tests/slice.rs b/tests/slice.rs -index 8402833..84592e0 100644 ---- a/tests/slice.rs -+++ b/tests/slice.rs -@@ -1809,6 +1809,7 @@ fn sort_unstable() { - } - } - -+/* - #[test] - #[cfg(not(target_arch = "wasm32"))] - #[cfg_attr(miri, ignore)] // Miri is too slow -@@ -1914,6 +1915,7 @@ fn select_nth_unstable() { - v.select_nth_unstable(0); - assert!(v == [0xDEADBEEF]); - } -+*/ - - #[test] - #[should_panic(expected = "index 0 greater than length of slice")] -@@ -2462,6 +2462,7 @@ take_tests! { - #[cfg(not(miri))] // unused in Miri - const EMPTY_MAX: &'static [()] = &[(); usize::MAX]; - -+/* - // can't be a constant due to const mutability rules - #[cfg(not(miri))] // unused in Miri - macro_rules! empty_max_mut { -@@ -2485,6 +2486,7 @@ take_tests! { - (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), - (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), - } -+*/ - - #[test] - fn test_slice_from_ptr_range() { --- -2.26.2.7.g19db9cfb68 - diff --git a/patches/0028-sysroot_tests-Disable-long-running-tests.patch b/patches/0028-sysroot_tests-Disable-long-running-tests.patch new file mode 100644 index 000000000000..357b8d306cf6 --- /dev/null +++ b/patches/0028-sysroot_tests-Disable-long-running-tests.patch @@ -0,0 +1,105 @@ +From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Fri, 3 Dec 2021 12:16:30 +0100 +Subject: [PATCH] Disable long running tests + +--- + library/coretests/tests/slice.rs | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/coretests/tests/slice.rs b/coretests/tests/slice.rs +index 8402833..84592e0 100644 +--- a/coretests/tests/slice.rs ++++ b/coretests/tests/slice.rs +@@ -1809,6 +1809,7 @@ fn sort_unstable() { + } + } + ++/* + #[test] + #[cfg(not(target_arch = "wasm32"))] + #[cfg_attr(miri, ignore)] // Miri is too slow +@@ -1914,6 +1915,7 @@ fn select_nth_unstable() { + v.select_nth_unstable(0); + assert!(v == [0xDEADBEEF]); + } ++*/ + + #[test] + #[should_panic(expected = "index 0 greater than length of slice")] +@@ -2462,6 +2462,7 @@ take_tests! { + #[cfg(not(miri))] // unused in Miri + const EMPTY_MAX: &'static [()] = &[(); usize::MAX]; + ++/* + // can't be a constant due to const mutability rules + #[cfg(not(miri))] // unused in Miri + macro_rules! empty_max_mut { +@@ -2485,6 +2486,7 @@ take_tests! { + (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), + (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), + } ++*/ + + #[test] + fn test_slice_from_ptr_range() { +diff --git a/alloctests/tests/sort/tests.rs b/alloctests/tests/sort/tests.rs +index d321f8d..8b2040a 100644 +--- a/alloctests/tests/sort/tests.rs ++++ b/alloctests/tests/sort/tests.rs +@@ -1,3 +1,5 @@ ++#![cfg(any())] ++ + use std::cell::Cell; + use std::cmp::Ordering; + use std::fmt::Debug; +diff --git a/alloctests/tests/str.rs b/alloctests/tests/str.rs +index 906fa2d..b82fa99 100644 +--- a/alloctests/tests/str.rs ++++ b/alloctests/tests/str.rs +@@ -2234,7 +2234,7 @@ fn const_str_ptr() { + const C: *const u8 = B as *const u8; + + // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131) +- #[cfg(not(miri))] ++ #[cfg(any())] + { + let foo = &A as *const u8; + assert_eq!(foo, C); +diff --git a/alloctests/tests/task.rs b/alloctests/tests/task.rs +index 390dec1..87df6e6 100644 +--- a/alloctests/tests/task.rs ++++ b/alloctests/tests/task.rs +@@ -4,7 +4,7 @@ use alloc::task::{LocalWake, Wake}; + use core::task::{LocalWaker, Waker}; + + #[test] +-#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail ++#[ignore] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail + fn test_waker_will_wake_clone() { + struct NoopWaker; + +@@ -20,7 +20,7 @@ fn test_waker_will_wake_clone() { + } + + #[test] +-#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail ++#[ignore] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail + fn test_local_waker_will_wake_clone() { + struct NoopWaker; + +diff --git a/alloctests/tests/vec.rs b/alloctests/tests/vec.rs +index f430d97..cfbd3cb 100644 +--- a/alloctests/tests/vec.rs ++++ b/alloctests/tests/vec.rs +@@ -762,6 +762,7 @@ fn test_drain_inclusive_range() { + } + + #[test] ++#[ignore] + fn test_drain_max_vec_size() { + let mut v = Vec::<()>::with_capacity(usize::MAX); + unsafe { +-- +2.26.2.7.g19db9cfb68 + diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch deleted file mode 100644 index 34249ea48345..000000000000 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 175d52c5e1779764b66777db1e6f172c2dc365ff Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Fri, 9 Aug 2024 15:44:51 +0000 -Subject: [PATCH] Disable f16 and f128 in compiler-builtins - ---- - library/liballoc/Cargo.toml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/library/liballoc/Cargo.toml b/library/liballoc/Cargo.toml -index 7165c3e48af..968552ad435 100644 ---- a/library/alloc/Cargo.toml -+++ b/library/alloc/Cargo.toml -@@ -11,7 +11,7 @@ test = { path = "../test" } - bench = false - - [dependencies] - core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std', 'no-f16-f128'] } - - [features] - compiler-builtins-mem = ['compiler_builtins/mem'] --- -2.34.1 - diff --git a/patches/coretests-lock.toml b/patches/coretests-lock.toml deleted file mode 100644 index af8f28a193bc..000000000000 --- a/patches/coretests-lock.toml +++ /dev/null @@ -1,35 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "coretests" -version = "0.0.0" -dependencies = [ - "rand", - "rand_xorshift", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] diff --git a/rust-toolchain b/rust-toolchain index 481903c6afb2..ceff15b1180a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-15" +channel = "nightly-2025-03-30" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/scripts/cargo-clif.rs b/scripts/cargo-clif.rs index ebbb68796105..e6c63bf5e650 100644 --- a/scripts/cargo-clif.rs +++ b/scripts/cargo-clif.rs @@ -50,19 +50,7 @@ fn main() { .chain([ "--".to_string(), "-Zunstable-options".to_string(), - "-Cllvm-args=mode=jit".to_string(), - ]) - .collect() - } - Some("lazy-jit") => { - rustflags.push("-Cprefer-dynamic".to_owned()); - args.remove(0); - IntoIterator::into_iter(["rustc".to_string()]) - .chain(args) - .chain([ - "--".to_string(), - "-Zunstable-options".to_string(), - "-Cllvm-args=mode=jit-lazy".to_string(), + "-Cllvm-args=jit-mode".to_string(), ]) .collect() } diff --git a/scripts/filter_profile.rs b/scripts/filter_profile.rs index 0252d5b33403..4595063c032d 100755 --- a/scripts/filter_profile.rs +++ b/scripts/filter_profile.rs @@ -4,7 +4,7 @@ pushd $(dirname "$0")/../ RUSTC="$(pwd)/dist/rustc-clif" popd -PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0 +PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=jit-mode -Cprefer-dynamic $0 #*/ //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse diff --git a/scripts/rustup.sh b/scripts/rustup.sh index 355282911c25..152c243aa6ad 100755 --- a/scripts/rustup.sh +++ b/scripts/rustup.sh @@ -64,7 +64,7 @@ case $1 in cg_clif=$(pwd) pushd ../rust git fetch origin master - git checkout "$RUST_VERS" + git -c advice.detachedHead=false checkout "$RUST_VERS" "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust popd git merge sync_from_rust -m "Sync from rust $RUST_VERS" diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 54f6baff4fec..ca6426f2ba9d 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -43,8 +43,31 @@ verbose-tests = false # disabled bootstrap will crash trying to copy llvm tools for the bootstrap # compiler. llvm-tools = false +std-features = ["panic-unwind", "compiler-builtins-no-f16-f128"] EOF + +cat <128bits not yet supported # requires LTO rm -r tests/run-make/cdylib @@ -120,6 +118,7 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same rm tests/ui/consts/issue-33537.rs # same rm tests/ui/consts/const-mut-refs-crate.rs # same rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift +rm tests/ui/abi/simd-abi-checks-avx.rs # attempts to declare function with two different signatures # doesn't work due to the way the rustc test suite is invoked. # should work when using ./x.py test the way it is intended @@ -136,7 +135,6 @@ rm -r tests/run-make/incr-add-rust-src-component # ============ rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort -rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation warning for -Cinline-threshold # bugs in the test suite # ====================== @@ -150,48 +148,8 @@ rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist -cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/ -# prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by -# rustdoc-clif cat < Self { - #[track_caller] - pub fn new() -> Self { - let mut cmd = setup_common(); -- cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR")); - Self { cmd } - } - -diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs -index e7ae773ffa1d3..04bc2d7787da7 100644 ---- a/src/tools/compiletest/src/runtest/run_make.rs -+++ b/src/tools/compiletest/src/runtest/run_make.rs -@@ -329,7 +329,6 @@ impl TestCx<'_> { - .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) - .arg("--edition=2021") - .arg(&self.testpaths.file.join("rmake.rs")) -- .arg("-Cprefer-dynamic") - // Provide necessary library search paths for rustc. - .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap()); - diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 30387af428c..f7895b12961 100644 --- a/tests/run-make/linker-warning/rmake.rs @@ -205,7 +163,19 @@ index 30387af428c..f7895b12961 100644 regex::escape(run_make_support::build_root().to_str().unwrap()), "/build-root", ) - .run(); + .normalize(r#""[^"]*\/symbols.o""#, "\\"/symbols.o\\"") +diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs +index 073116933bd..c3e4578204d 100644 +--- a/src/tools/compiletest/src/runtest/run_make.rs ++++ b/src/tools/compiletest/src/runtest/run_make.rs +@@ -109,7 +109,6 @@ pub(super) fn run_rmake_test(&self) { + // library or compiler features. Here, we force the stage 0 rustc to consider itself as + // a stable-channel compiler via \`RUSTC_BOOTSTRAP=-1\` to prevent *any* unstable + // library/compiler usages, even if stage 0 rustc is *actually* a nightly rustc. +- .env("RUSTC_BOOTSTRAP", "-1") + .arg("-o") + .arg(&recipe_bin) + // Specify library search paths for \`run_make_support\`. EOF echo "[TEST] rustc test suite" diff --git a/src/base.rs b/src/base.rs index 125a9201831c..adaa754491e5 100644 --- a/src/base.rs +++ b/src/base.rs @@ -729,8 +729,10 @@ fn codegen_stmt<'tcx>( let to_ty = fx.monomorphize(to_ty); fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.builtin_deref(true) - .is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty)) + ty.builtin_deref(true).is_some_and(|pointee_ty| { + fx.tcx + .type_has_metadata(pointee_ty, ty::TypingEnv::fully_monomorphized()) + }) } if is_wide_ptr(fx, from_ty) { diff --git a/src/common.rs b/src/common.rs index 766278d87183..abe2972ba0cb 100644 --- a/src/common.rs +++ b/src/common.rs @@ -71,7 +71,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option pointer_ty(tcx), ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => { - if has_ptr_meta(tcx, *pointee_ty) { + if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) { return None; } else { pointer_ty(tcx) @@ -91,7 +91,7 @@ fn clif_pair_type_from_ty<'tcx>( (clif_type_from_ty(tcx, types[0])?, clif_type_from_ty(tcx, types[1])?) } ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => { - if has_ptr_meta(tcx, *pointee_ty) { + if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) { (pointer_ty(tcx), pointer_ty(tcx)) } else { return None; @@ -101,20 +101,6 @@ fn clif_pair_type_from_ty<'tcx>( }) } -/// Is a pointer to this type a wide ptr? -pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) { - return false; - } - - let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized()); - match tail.kind() { - ty::Foreign(..) => false, - ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, - _ => bug!("unexpected unsized tail: {:?}", tail), - } -} - pub(crate) fn codegen_icmp_imm( fx: &mut FunctionCx<'_, '_, '_>, intcc: IntCC, diff --git a/src/config.rs b/src/config.rs index d784f6e9d9eb..d328b33a704f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,21 +1,10 @@ -/// The mode to use for compilation. -#[derive(Copy, Clone, Debug)] -pub enum CodegenMode { - /// AOT compile the crate. This is the default. - Aot, - /// JIT compile and execute the crate. - Jit, - /// JIT compile and execute the crate, but only compile functions the first time they are used. - JitLazy, -} - /// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars. #[derive(Clone, Debug)] pub struct BackendConfig { /// Should the crate be AOT compiled or JIT executed. /// - /// Defaults to AOT compilation. Can be set using `-Cllvm-args=mode=...`. - pub codegen_mode: CodegenMode, + /// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`. + pub jit_mode: bool, /// When JIT mode is enable pass these arguments to the program. /// @@ -27,7 +16,7 @@ impl BackendConfig { /// Parse the configuration passed in using `-Cllvm-args`. pub fn from_opts(opts: &[String]) -> Result { let mut config = BackendConfig { - codegen_mode: CodegenMode::Aot, + jit_mode: false, jit_args: match std::env::var("CG_CLIF_JIT_ARGS") { Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(), Err(std::env::VarError::NotPresent) => vec![], @@ -43,20 +32,9 @@ impl BackendConfig { // testing cg_clif. continue; } - if let Some((name, value)) = opt.split_once('=') { - match name { - "mode" => { - config.codegen_mode = match value { - "aot" => CodegenMode::Aot, - "jit" => CodegenMode::Jit, - "jit-lazy" => CodegenMode::JitLazy, - _ => return Err(format!("Unknown codegen mode `{}`", value)), - }; - } - _ => return Err(format!("Unknown option `{}`", name)), - } - } else { - return Err(format!("Invalid option `{}`", opt)); + match &**opt { + "jit-mode" => config.jit_mode = true, + _ => return Err(format!("Unknown option `{}`", opt)), } } diff --git a/src/debuginfo/types.rs b/src/debuginfo/types.rs index 017d7784dc03..25b922c8be4c 100644 --- a/src/debuginfo/types.rs +++ b/src/debuginfo/types.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; -use crate::{DebugContext, FullyMonomorphizedLayoutCx, has_ptr_meta}; +use crate::{DebugContext, FullyMonomorphizedLayoutCx}; #[derive(Default)] pub(crate) struct TypeDebugContext<'tcx> { @@ -129,7 +129,7 @@ impl DebugContext { let name = type_names::compute_debuginfo_type_name(tcx, ptr_type, true); - if !has_ptr_meta(tcx, ptr_type) { + if !tcx.type_has_metadata(ptr_type, ty::TypingEnv::fully_monomorphized()) { let pointer_type_id = self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_pointer_type); let pointer_entry = self.dwarf.unit.get_mut(pointer_type_id); diff --git a/src/driver/aot.rs b/src/driver/aot.rs index fb7864ae6124..444dc4412868 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -331,7 +331,7 @@ fn produce_final_output_artifacts( } fn make_module(sess: &Session, name: String) -> UnwindModule { - let isa = crate::build_isa(sess); + let isa = crate::build_isa(sess, false); let mut builder = ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 57c88f4b0f9f..41f8bb9161ca 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -1,75 +1,27 @@ //! The JIT driver uses [`cranelift_jit`] to JIT execute programs without writing any object //! files. -use std::cell::RefCell; use std::ffi::CString; use std::os::raw::{c_char, c_int}; -use std::sync::{Mutex, OnceLock, mpsc}; -use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_jit::{JITBuilder, JITModule}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; use rustc_session::Session; use rustc_span::sym; +use crate::CodegenCx; use crate::debuginfo::TypeDebugContext; use crate::prelude::*; use crate::unwind_module::UnwindModule; -use crate::{CodegenCx, CodegenMode}; -struct JitState { - jit_module: UnwindModule, -} - -thread_local! { - static LAZY_JIT_STATE: RefCell> = const { RefCell::new(None) }; -} - -/// The Sender owned by the rustc thread -static GLOBAL_MESSAGE_SENDER: OnceLock>> = OnceLock::new(); - -/// A message that is sent from the jitted runtime to the rustc thread. -/// Senders are responsible for upholding `Send` semantics. -enum UnsafeMessage { - /// Request that the specified `Instance` be lazily jitted. - /// - /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after - /// this message is sent. - JitFn { - instance_ptr: *const Instance<'static>, - trampoline_ptr: *const u8, - tx: mpsc::Sender<*const u8>, - }, -} -unsafe impl Send for UnsafeMessage {} - -impl UnsafeMessage { - /// Send the message. - fn send(self) { - thread_local! { - /// The Sender owned by the local thread - static LOCAL_MESSAGE_SENDER: mpsc::Sender = - GLOBAL_MESSAGE_SENDER - .get().unwrap() - .lock().unwrap() - .clone(); - } - LOCAL_MESSAGE_SENDER.with(|sender| { - sender.send(self).expect("rustc thread hung up before lazy JIT request was sent") - }) - } -} - -fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule, CodegenCx) { +fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule, CodegenCx) { let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); - let isa = crate::build_isa(tcx.sess); + let isa = crate::build_isa(tcx.sess, true); let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); - jit_builder.hotswap(hotswap); crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info)); - jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8); let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false); let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); @@ -79,7 +31,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule (jit_module, cx) } -pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec) -> ! { +pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec) -> ! { if !tcx.sess.opts.output_types.should_codegen() { tcx.dcx().fatal("JIT mode doesn't work with `cargo check`"); } @@ -88,8 +40,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< tcx.dcx().fatal("can't jit non-executable crate"); } - let (mut jit_module, mut cx) = - create_jit_module(tcx, matches!(codegen_mode, CodegenMode::JitLazy)); + let (mut jit_module, mut cx) = create_jit_module(tcx); let mut cached_context = Context::new(); let cgus = tcx.collect_and_partition_mono_items(()).codegen_units; @@ -105,21 +56,15 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< super::predefine_mono_items(tcx, &mut jit_module, &mono_items); for (mono_item, _) in mono_items { match mono_item { - MonoItem::Fn(inst) => match codegen_mode { - CodegenMode::Aot => unreachable!(), - CodegenMode::Jit => { - codegen_and_compile_fn( - tcx, - &mut cx, - &mut cached_context, - &mut jit_module, - inst, - ); - } - CodegenMode::JitLazy => { - codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) - } - }, + MonoItem::Fn(inst) => { + codegen_and_compile_fn( + tcx, + &mut cx, + &mut cached_context, + &mut jit_module, + inst, + ); + } MonoItem::Static(def_id) => { crate::constant::codegen_static(tcx, &mut jit_module, def_id); } @@ -161,41 +106,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap(); let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id); - LAZY_JIT_STATE.with(|lazy_jit_state| { - let mut lazy_jit_state = lazy_jit_state.borrow_mut(); - assert!(lazy_jit_state.is_none()); - *lazy_jit_state = Some(JitState { jit_module }); - }); - let f: extern "C" fn(c_int, *const *const c_char) -> c_int = unsafe { ::std::mem::transmute(finalized_start) }; - let (tx, rx) = mpsc::channel(); - GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap(); + let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); - // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages - // (eg to lazily JIT further functions as required) - std::thread::spawn(move || { - let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); + // Push a null pointer as a terminating argument. This is required by POSIX and + // useful as some dynamic linkers use it as a marker to jump over. + argv.push(std::ptr::null()); - // Push a null pointer as a terminating argument. This is required by POSIX and - // useful as some dynamic linkers use it as a marker to jump over. - argv.push(std::ptr::null()); - - let ret = f(args.len() as c_int, argv.as_ptr()); - std::process::exit(ret); - }); - - // Handle messages - loop { - match rx.recv().unwrap() { - // lazy JIT compilation request - compile requested instance and return pointer to result - UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => { - tx.send(jit_fn(instance_ptr, trampoline_ptr)) - .expect("jitted runtime hung up before response to lazy JIT request was sent"); - } - } - } + let ret = f(args.len() as c_int, argv.as_ptr()); + std::process::exit(ret); } pub(crate) fn codegen_and_compile_fn<'tcx>( @@ -227,58 +148,6 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( }); } -extern "C" fn clif_jit_fn( - instance_ptr: *const Instance<'static>, - trampoline_ptr: *const u8, -) -> *const u8 { - // send the JIT request to the rustc thread, with a channel for the response - let (tx, rx) = mpsc::channel(); - UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }.send(); - - // block on JIT compilation result - rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request") -} - -fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 { - rustc_middle::ty::tls::with(|tcx| { - // lift is used to ensure the correct lifetime for instance. - let instance = tcx.lift(unsafe { *instance_ptr }).unwrap(); - - LAZY_JIT_STATE.with(|lazy_jit_state| { - let mut lazy_jit_state = lazy_jit_state.borrow_mut(); - let lazy_jit_state = lazy_jit_state.as_mut().unwrap(); - let jit_module = &mut lazy_jit_state.jit_module; - - let name = tcx.symbol_name(instance).name; - let sig = crate::abi::get_function_sig( - tcx, - jit_module.target_config().default_call_conv, - instance, - ); - let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap(); - - let current_ptr = jit_module.module.read_got_entry(func_id); - - // If the function's GOT entry has already been updated to point at something other - // than the shim trampoline, don't re-jit but just return the new pointer instead. - // This does not need synchronization as this code is executed only by a sole rustc - // thread. - if current_ptr != trampoline_ptr { - return current_ptr; - } - - jit_module.module.prepare_for_function_redefine(func_id).unwrap(); - - let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); - codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance); - - assert!(cx.global_asm.is_empty()); - jit_module.finalize_definitions(); - jit_module.module.get_finalized_function(func_id) - }) - }) -} - fn dep_symbol_lookup_fn( sess: &Session, crate_info: CrateInfo, @@ -326,57 +195,3 @@ fn dep_symbol_lookup_fn( None }) } - -fn codegen_shim<'tcx>( - tcx: TyCtxt<'tcx>, - cached_context: &mut Context, - module: &mut UnwindModule, - inst: Instance<'tcx>, -) { - let pointer_type = module.target_config().pointer_type(); - - let name = tcx.symbol_name(inst).name; - let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst); - let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap(); - - let instance_ptr = Box::into_raw(Box::new(inst)); - - let jit_fn = module - .declare_function( - "__clif_jit_fn", - Linkage::Import, - &Signature { - call_conv: module.target_config().default_call_conv, - params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)], - returns: vec![AbiParam::new(pointer_type)], - }, - ) - .unwrap(); - - let context = cached_context; - context.clear(); - let trampoline = &mut context.func; - trampoline.signature = sig.clone(); - - let mut builder_ctx = FunctionBuilderContext::new(); - let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx); - - let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func); - let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func); - let sig_ref = trampoline_builder.func.import_signature(sig); - - let entry_block = trampoline_builder.create_block(); - trampoline_builder.append_block_params_for_function_params(entry_block); - let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec(); - - trampoline_builder.switch_to_block(entry_block); - let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64); - let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn); - let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]); - let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0]; - let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args); - let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec(); - trampoline_builder.ins().return_(&ret_vals); - - module.define_function(func_id, context).unwrap(); -} diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 310b226814d4..fbc33a642853 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -612,6 +612,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { generated_asm.push_str(".att_syntax\n"); } + if self.arch == InlineAsmArch::AArch64 { + for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features { + if feature.name == sym::neon { + continue; + } + writeln!(generated_asm, ".arch_extension {}", feature.name).unwrap(); + } + } + // The actual inline asm for piece in self.template { match piece { @@ -652,6 +661,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { .emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier) .unwrap(), }, + InlineAsmArch::AArch64 => match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit( + &mut generated_asm, + InlineAsmArch::AArch64, + Some(modifier.unwrap_or('q')), + ) + .unwrap() + } + _ => reg + .emit(&mut generated_asm, InlineAsmArch::AArch64, *modifier) + .unwrap(), + }, _ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(), } } @@ -665,6 +688,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } generated_asm.push('\n'); + if self.arch == InlineAsmArch::AArch64 { + for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features { + if feature.name == sym::neon { + continue; + } + writeln!(generated_asm, ".arch_extension no{}", feature.name).unwrap(); + } + } + if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) { generated_asm.push_str(".intel_syntax noprefix\n"); } @@ -809,7 +841,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } InlineAsmArch::AArch64 => { generated_asm.push_str(" str "); - reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); + match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap() + } + _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(), + } writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } InlineAsmArch::RiscV64 => { @@ -851,7 +889,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } InlineAsmArch::AArch64 => { generated_asm.push_str(" ldr "); - reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); + match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap() + } + _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(), + } writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } InlineAsmArch::RiscV64 => { diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 720a0d8fbf59..eb0dfbb69c3b 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -54,6 +54,14 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( ); } + "llvm.fptosi.sat.v4i32.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { + fx.bcx.ins().fcvt_to_sint_sat(types::I32, lane) + }); + } + _ => { fx.tcx .dcx() diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index 4c59c81296ba..387c87d123a3 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -1,5 +1,9 @@ //! Emulate AArch64 LLVM intrinsics +use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_target::asm::*; + +use crate::inline_asm::{CInlineAsmOperand, codegen_inline_asm_inner}; use crate::intrinsics::*; use crate::prelude::*; @@ -17,7 +21,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( fx.bcx.ins().fence(); } - "llvm.aarch64.neon.ld1x4.v16i8.p0i8" => { + "llvm.aarch64.neon.ld1x4.v16i8.p0" => { intrinsic_args!(fx, args => (ptr); intrinsic); let ptr = ptr.load_scalar(fx); @@ -49,6 +53,121 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } + "llvm.aarch64.neon.fcvtns.v4i32.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + // Note: Using inline asm instead of fcvt_to_sint as the latter rounds to zero rather than to nearest + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + fcvtns v0.4s, v0.4s + str q0, [x1]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + + "llvm.aarch64.neon.frecpe.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + frecpe v0.4s, v0.4s + str q0, [x1]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + + "llvm.aarch64.neon.frecps.v4f32" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let b_ptr = b.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + ldr q1, [x1] + frecps v0.4s, v0.4s, v1.4s + str q0, [x2]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: b_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x2, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") || intrinsic.starts_with("llvm.aarch64.neon.uqadd.v") => { @@ -134,7 +253,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( } let res = CValue::by_val( fx.bcx.ins().uextend(types::I32, res_val), - fx.layout_of(fx.tcx.types.u32), + fx.layout_of(fx.tcx.types.i32), ); ret.write_cvalue(fx, res); } diff --git a/src/lib.rs b/src/lib.rs index ab3386a9b4cc..e7afaff3b428 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,6 @@ use std::sync::Arc; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::CodegenResults; -use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -214,15 +213,14 @@ impl CodegenBackend for CraneliftCodegenBackend { BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) .unwrap_or_else(|err| tcx.sess.dcx().fatal(err)) }); - match config.codegen_mode { - CodegenMode::Aot => driver::aot::run_aot(tcx, metadata, need_metadata_module), - CodegenMode::Jit | CodegenMode::JitLazy => { - #[cfg(feature = "jit")] - driver::jit::run_jit(tcx, config.codegen_mode, config.jit_args); + if config.jit_mode { + #[cfg(feature = "jit")] + driver::jit::run_jit(tcx, config.jit_args); - #[cfg(not(feature = "jit"))] - tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); - } + #[cfg(not(feature = "jit"))] + tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); + } else { + driver::aot::run_aot(tcx, metadata, need_metadata_module) } } @@ -247,21 +245,19 @@ fn enable_verifier(sess: &Session) -> bool { } fn target_triple(sess: &Session) -> target_lexicon::Triple { - // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS. - // See - match versioned_llvm_target(sess).parse() { + match sess.target.llvm_target.parse() { Ok(triple) => triple, Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)), } } -fn build_isa(sess: &Session) -> Arc { +fn build_isa(sess: &Session, jit: bool) -> Arc { use target_lexicon::BinaryFormat; let target_triple = crate::target_triple(sess); let mut flags_builder = settings::builder(); - flags_builder.enable("is_pic").unwrap(); + flags_builder.set("is_pic", if jit { "false" } else { "true" }).unwrap(); let enable_verifier = if enable_verifier(sess) { "true" } else { "false" }; flags_builder.set("enable_verifier", enable_verifier).unwrap(); flags_builder.set("regalloc_checker", enable_verifier).unwrap(); diff --git a/src/num.rs b/src/num.rs index f44e2459a784..2a4d1e3ae571 100644 --- a/src/num.rs +++ b/src/num.rs @@ -395,8 +395,12 @@ pub(crate) fn codegen_ptr_binop<'tcx>( in_lhs: CValue<'tcx>, in_rhs: CValue<'tcx>, ) -> CValue<'tcx> { - let is_thin_ptr = - in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true); + let is_thin_ptr = in_lhs + .layout() + .ty + .builtin_deref(true) + .map(|ty| !fx.tcx.type_has_metadata(ty, ty::TypingEnv::fully_monomorphized())) + .unwrap_or(true); if is_thin_ptr { match bin_op { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index cc739fefcd06..f8a19589fdd7 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -746,7 +746,7 @@ impl<'tcx> CPlace<'tcx> { }; let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field); - if has_ptr_meta(fx.tcx, field_layout.ty) { + if fx.tcx.type_has_metadata(field_layout.ty, ty::TypingEnv::fully_monomorphized()) { CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout) } else { CPlace::for_ptr(field_ptr, field_layout) @@ -832,7 +832,7 @@ impl<'tcx> CPlace<'tcx> { pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> { let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap()); - if has_ptr_meta(fx.tcx, inner_layout.ty) { + if fx.tcx.type_has_metadata(inner_layout.ty, ty::TypingEnv::fully_monomorphized()) { let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx); CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout) } else { @@ -845,7 +845,7 @@ impl<'tcx> CPlace<'tcx> { fx: &mut FunctionCx<'_, '_, 'tcx>, layout: TyAndLayout<'tcx>, ) -> CValue<'tcx> { - if has_ptr_meta(fx.tcx, self.layout().ty) { + if fx.tcx.type_has_metadata(self.layout().ty, ty::TypingEnv::fully_monomorphized()) { let (ptr, extra) = self.to_ptr_unsized(); CValue::by_val_pair(ptr.get_addr(fx), extra, layout) } else { From 625b8000f7897ab51312f1800fcae280cc3ac81b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:13:53 +0000 Subject: [PATCH 003/139] Allow formatting example/gen_block_iterate.rs --- example/gen_block_iterate.rs | 16 ++++++++++++---- rustfmt.toml | 4 ---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/example/gen_block_iterate.rs b/example/gen_block_iterate.rs index 25bfe542d228..de9a3d550ecc 100644 --- a/example/gen_block_iterate.rs +++ b/example/gen_block_iterate.rs @@ -6,16 +6,25 @@ #![feature(gen_blocks)] fn foo() -> impl Iterator { - gen { yield 42; for x in 3..6 { yield x } } + gen { + yield 42; + for x in 3..6 { + yield x + } + } } fn moved() -> impl Iterator { let mut x = "foo".to_string(); gen move { yield 42; - if x == "foo" { return } + if x == "foo" { + return; + } x.clear(); - for x in 3..6 { yield x } + for x in 3..6 { + yield x + } } } @@ -32,5 +41,4 @@ fn main() { let mut iter = moved(); assert_eq!(iter.next(), Some(42)); assert_eq!(iter.next(), None); - } diff --git a/rustfmt.toml b/rustfmt.toml index f31fa9c76abc..35c92663eb90 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,7 +1,3 @@ -ignore = [ - "example/gen_block_iterate.rs", # uses edition 2024 -] - # Matches rustfmt.toml of rustc style_edition = "2024" use_small_heuristics = "Max" From e58dd2568b5ba8524c3423495190313aa006ab53 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 31 Mar 2025 15:09:43 +0000 Subject: [PATCH 004/139] Unset RUSTC_WRAPPER in cg_clif's build system --- build_system/utils.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build_system/utils.rs b/build_system/utils.rs index c2114caf8692..f23997684596 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -105,7 +105,11 @@ impl CargoProject { .arg(self.manifest_path(dirs)) .arg("--target-dir") .arg(self.target_dir(dirs)) - .arg("--locked"); + .arg("--locked") + // bootstrap sets both RUSTC and RUSTC_WRAPPER to the same wrapper. RUSTC is already + // respected by the rustc-clif wrapper, but RUSTC_WRAPPER will misinterpret rustc-clif + // as filename, so we need to unset it. + .env_remove("RUSTC_WRAPPER"); if dirs.frozen { cmd.arg("--frozen"); From bb2b3d04c31648ebd737b0ebc47b9d90fc3b777a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 13:54:08 +0000 Subject: [PATCH 005/139] Run coretests and alloctests with cg_clif in CI --- build_system/tests.rs | 47 ++++++++++++++++++++++++------------------- config.txt | 2 +- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 122b541fa35f..eb15a3fc027e 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -99,6 +99,32 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ runner.run_out_command("gen_block_iterate", &[]); }), TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]), + TestCase::custom("test.sysroot", &|runner| { + apply_patches( + &runner.dirs, + "sysroot_tests", + &runner.stdlib_source.join("library"), + &SYSROOT_TESTS_SRC.to_path(&runner.dirs), + ); + + SYSROOT_TESTS.clean(&runner.dirs); + + // coretests and alloctests produce a bunch of warnings. When running + // in rust's CI warnings are denied, so we have to override that here. + let mut target_compiler = runner.target_compiler.clone(); + target_compiler.rustflags.push("--cap-lints=allow".to_owned()); + + if runner.is_native { + let mut test_cmd = SYSROOT_TESTS.test(&target_compiler, &runner.dirs); + test_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests", "--", "-q"]); + spawn_and_wait(test_cmd); + } else { + eprintln!("Cross-Compiling: Not running tests"); + let mut build_cmd = SYSROOT_TESTS.build(&target_compiler, &runner.dirs); + build_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests"]); + spawn_and_wait(build_cmd); + } + }), ]; pub(crate) static RAND_REPO: GitRepo = GitRepo::github( @@ -146,27 +172,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::custom("test.sysroot", &|runner| { - apply_patches( - &runner.dirs, - "sysroot_tests", - &runner.stdlib_source.join("library"), - &SYSROOT_TESTS_SRC.to_path(&runner.dirs), - ); - - SYSROOT_TESTS.clean(&runner.dirs); - - if runner.is_native { - let mut test_cmd = SYSROOT_TESTS.test(&runner.target_compiler, &runner.dirs); - test_cmd.args(["-p", "coretests", "-p", "alloctests", "--", "-q"]); - spawn_and_wait(test_cmd); - } else { - eprintln!("Cross-Compiling: Not running tests"); - let mut build_cmd = SYSROOT_TESTS.build(&runner.target_compiler, &runner.dirs); - build_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests"]); - spawn_and_wait(build_cmd); - } - }), TestCase::custom("test.regex", &|runner| { REGEX_REPO.patch(&runner.dirs); diff --git a/config.txt b/config.txt index 714414fe8d68..6ae4767adfdf 100644 --- a/config.txt +++ b/config.txt @@ -32,9 +32,9 @@ aot.issue-59326 aot.neon aot.gen_block_iterate aot.raw-dylib +test.sysroot testsuite.extended_sysroot test.rust-random/rand -test.sysroot test.regex test.portable-simd From e3a8d9c6a3ed67948cded5a3cbef65c15fd6b180 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:30:01 +0000 Subject: [PATCH 006/139] Fix testing with randomized layouts enabled --- build_system/tests.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index eb15a3fc027e..eec89c026b26 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -109,10 +109,12 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ SYSROOT_TESTS.clean(&runner.dirs); + let mut target_compiler = runner.target_compiler.clone(); // coretests and alloctests produce a bunch of warnings. When running // in rust's CI warnings are denied, so we have to override that here. - let mut target_compiler = runner.target_compiler.clone(); target_compiler.rustflags.push("--cap-lints=allow".to_owned()); + // The standard library may have been compiled with -Zrandomize-layout. + target_compiler.rustflags.extend(["--cfg".to_owned(), "randomized_layouts".to_owned()]); if runner.is_native { let mut test_cmd = SYSROOT_TESTS.test(&target_compiler, &runner.dirs); From 4807c29d0837c3ee0af94563b8a801f4f2c4c356 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 4 Apr 2025 10:30:15 +0000 Subject: [PATCH 007/139] Rustup to rustc 1.88.0-nightly (00095b3da 2025-04-03) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index ceff15b1180a..c03f08575698 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-30" +channel = "nightly-2025-04-04" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From b0c23f78c98b71f6a202983b4278386cf1703ce7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 4 Apr 2025 10:41:27 +0000 Subject: [PATCH 008/139] Fix rustc test suite --- scripts/test_rustc_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 95a4302b5e47..01c8b474a9d1 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -130,6 +130,7 @@ rm -r tests/run-make/translation # same rm -r tests/run-make/missing-unstable-trait-bound # This disables support for unstable features, but running cg_clif needs some unstable features rm -r tests/run-make/const-trait-stable-toolchain # same rm -r tests/run-make/incr-add-rust-src-component +rm tests/ui/errors/remap-path-prefix-sysroot.rs # different sysroot source path # genuine bugs # ============ From 829413d208d4dc71e5b16ab2d60c86b5934122e8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 4 Apr 2025 10:46:47 +0000 Subject: [PATCH 009/139] Tell rustfmt to use the 2024 edition --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6fd288d195c0..d92e0fdce99a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,9 +34,9 @@ jobs: - name: Rustfmt run: | cargo fmt --check - rustfmt --check build_system/main.rs - rustfmt --check example/* - rustfmt --check scripts/*.rs + rustfmt --check --edition 2024 build_system/main.rs + rustfmt --check --edition 2024 example/* + rustfmt --check --edition 2024 scripts/*.rs test: From 4a8026ce639f2e5e09d20320ca569fedcafcef6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Sun, 6 Apr 2025 15:10:23 +0200 Subject: [PATCH 010/139] update docs - src\doc\nomicon\src\ffi.md should also have its ABI list updated --- src/intrinsics/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 75f3a3c19724..d3f47ad72633 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1,5 +1,4 @@ -//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, -//! functions marked with the `#[rustc_intrinsic]` attribute +//! Codegen of intrinsics. This includes functions marked with the `#[rustc_intrinsic]` attribute //! and LLVM intrinsics that have symbol names starting with `llvm.`. macro_rules! intrinsic_args { From 25f263ded766cdbb916de3ff5724fe1cfb2fb803 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 7 Apr 2025 19:40:28 +0000 Subject: [PATCH 011/139] Rustup to rustc 1.88.0-nightly (2fa8b11f0 2025-04-06) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index c03f08575698..01cba7ac9e09 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-04-04" +channel = "nightly-2025-04-07" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 0e9a8540b011a8c0adb0e2c542cfb31c5aaf61a8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 7 Apr 2025 20:28:24 +0000 Subject: [PATCH 012/139] Preserve rustc_literal_escaper with --sysroot llvm --- build_system/build_sysroot.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index a73e3c87d43d..a6e956c51f13 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -168,7 +168,8 @@ fn build_llvm_sysroot_for_triple(compiler: Compiler) -> SysrootTarget { let file_name_str = file.file_name().unwrap().to_str().unwrap(); if (file_name_str.contains("rustc_") && !file_name_str.contains("rustc_std_workspace_") - && !file_name_str.contains("rustc_demangle")) + && !file_name_str.contains("rustc_demangle") + && !file_name_str.contains("rustc_literal_escaper")) || file_name_str.contains("chalk") || file_name_str.contains("tracing") || file_name_str.contains("regex") From ab84fe61ed38bf68e1502d580a22b14535c49d9f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Apr 2025 23:37:30 +0000 Subject: [PATCH 013/139] Simplify temp path creation a bit --- src/driver/aot.rs | 24 +++++++++--------------- src/global_asm.rs | 2 +- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 444dc4412868..4ac7b86f0856 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -169,8 +169,8 @@ fn produce_final_output_artifacts( if codegen_results.modules.len() == 1 { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let module_name = Some(&codegen_results.modules[0].name[..]); - let path = crate_output.temp_path(output_type, module_name); + let path = + crate_output.temp_path_for_cgu(output_type, &codegen_results.modules[0].name); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { sess.dcx() @@ -183,22 +183,16 @@ fn produce_final_output_artifacts( ensure_removed(sess.dcx(), &path); } } else { - let extension = crate_output - .temp_path(output_type, None) - .extension() - .unwrap() - .to_str() - .unwrap() - .to_owned(); - if crate_output.outputs.contains_explicit_name(&output_type) { // 2) Multiple codegen units, with `--emit foo=some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(ssa_errors::IgnoringEmitPath { extension }); + sess.dcx() + .emit_warn(ssa_errors::IgnoringEmitPath { extension: output_type.extension() }); } else if crate_output.single_output_file.is_some() { // 3) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(ssa_errors::IgnoringOutput { extension }); + sess.dcx() + .emit_warn(ssa_errors::IgnoringOutput { extension: output_type.extension() }); } else { // 4) Multiple codegen units, but no explicit name. We // just leave the `foo.0.x` files in place. @@ -409,7 +403,7 @@ fn emit_module( object.set_section_data(comment_section, producer, 1); } - let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name)); + let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name); let file = match File::create(&tmp_file) { Ok(file) => file, Err(err) => return Err(format!("error creating object file: {}", err)), @@ -450,7 +444,7 @@ fn reuse_workproduct_for_cgu( ) -> Result { let work_product = cgu.previous_work_product(tcx); let obj_out_regular = - tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); + tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, cgu.name().as_str()); let source_file_regular = rustc_incremental::in_incr_comp_dir_sess( &tcx.sess, &work_product.saved_files.get("o").expect("no saved object file in work product"), @@ -627,7 +621,7 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled .to_string(); let tmp_file = - tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); + tcx.output_filenames(()).temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name); let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name); diff --git a/src/global_asm.rs b/src/global_asm.rs index 9ea92c300f89..6e3b3677a7ff 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -146,7 +146,7 @@ pub(crate) fn compile_global_asm( global_asm.push('\n'); let global_asm_object_file = add_file_stem_postfix( - config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)), + config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name), ".asm", ); From 68dd8b344a7882738cf816949e238578c7c4cc63 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Apr 2025 23:50:16 +0000 Subject: [PATCH 014/139] Prepend temp files with a string per invocation of rustc --- src/driver/aot.rs | 35 +++++++++++++++++++++++++++-------- src/global_asm.rs | 3 ++- src/lib.rs | 2 ++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 4ac7b86f0856..0ea0dbfc44b6 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -169,8 +169,11 @@ fn produce_final_output_artifacts( if codegen_results.modules.len() == 1 { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let path = - crate_output.temp_path_for_cgu(output_type, &codegen_results.modules[0].name); + let path = crate_output.temp_path_for_cgu( + output_type, + &codegen_results.modules[0].name, + sess.invocation_temp.as_deref(), + ); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { sess.dcx() @@ -345,6 +348,7 @@ fn make_module(sess: &Session, name: String) -> UnwindModule { fn emit_cgu( output_filenames: &OutputFilenames, + invocation_temp: Option<&str>, prof: &SelfProfilerRef, name: String, module: UnwindModule, @@ -360,6 +364,7 @@ fn emit_cgu( let module_regular = emit_module( output_filenames, + invocation_temp, prof, product.object, ModuleKind::Regular, @@ -385,6 +390,7 @@ fn emit_cgu( fn emit_module( output_filenames: &OutputFilenames, + invocation_temp: Option<&str>, prof: &SelfProfilerRef, mut object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, @@ -403,7 +409,7 @@ fn emit_module( object.set_section_data(comment_section, producer, 1); } - let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name); + let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name, invocation_temp); let file = match File::create(&tmp_file) { Ok(file) => file, Err(err) => return Err(format!("error creating object file: {}", err)), @@ -443,8 +449,11 @@ fn reuse_workproduct_for_cgu( cgu: &CodegenUnit<'_>, ) -> Result { let work_product = cgu.previous_work_product(tcx); - let obj_out_regular = - tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, cgu.name().as_str()); + let obj_out_regular = tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Object, + cgu.name().as_str(), + tcx.sess.invocation_temp.as_deref(), + ); let source_file_regular = rustc_incremental::in_incr_comp_dir_sess( &tcx.sess, &work_product.saved_files.get("o").expect("no saved object file in work product"), @@ -589,13 +598,19 @@ fn module_codegen( let global_asm_object_file = profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| { - crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm) + crate::global_asm::compile_global_asm( + &global_asm_config, + &cgu_name, + &cx.global_asm, + cx.invocation_temp.as_deref(), + ) })?; let codegen_result = profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| { emit_cgu( &global_asm_config.output_filenames, + cx.invocation_temp.as_deref(), &profiler, cgu_name, module, @@ -620,8 +635,11 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled .as_str() .to_string(); - let tmp_file = - tcx.output_filenames(()).temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name); + let tmp_file = tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Metadata, + &metadata_cgu_name, + tcx.sess.invocation_temp.as_deref(), + ); let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name); @@ -651,6 +669,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option { match emit_module( tcx.output_filenames(()), + tcx.sess.invocation_temp.as_deref(), &tcx.sess.prof, product.object, ModuleKind::Allocator, diff --git a/src/global_asm.rs b/src/global_asm.rs index 6e3b3677a7ff..79cefb05de32 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -132,6 +132,7 @@ pub(crate) fn compile_global_asm( config: &GlobalAsmConfig, cgu_name: &str, global_asm: &str, + invocation_temp: Option<&str>, ) -> Result, String> { if global_asm.is_empty() { return Ok(None); @@ -146,7 +147,7 @@ pub(crate) fn compile_global_asm( global_asm.push('\n'); let global_asm_object_file = add_file_stem_postfix( - config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name), + config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp), ".asm", ); diff --git a/src/lib.rs b/src/lib.rs index e7afaff3b428..9d9e790289cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -124,6 +124,7 @@ impl String> Drop for PrintOnPanic { /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). struct CodegenCx { output_filenames: Arc, + invocation_temp: Option, should_write_ir: bool, global_asm: String, inline_asm_index: usize, @@ -142,6 +143,7 @@ impl CodegenCx { }; CodegenCx { output_filenames: tcx.output_filenames(()).clone(), + invocation_temp: tcx.sess.invocation_temp.clone(), should_write_ir: crate::pretty_clif::should_write_ir(tcx), global_asm: String::new(), inline_asm_index: 0, From b69a4787b4fc86a8d1cc2563d9d6aade092e83b5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:47:26 +0000 Subject: [PATCH 015/139] Rustup to rustc 1.88.0-nightly (e643f59f6 2025-04-07) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 01cba7ac9e09..4be668c7b848 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-04-07" +channel = "nightly-2025-04-08" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 6424f0a7ba84253c8db42d66d3e80ef74e65f92b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 8 Apr 2025 10:25:03 +0000 Subject: [PATCH 016/139] Replace trap_unimplemented calls with codegen_panic_nounwind This will show a backtrace. Also added a reference to rust-lang/rustc_codegen_cranelift#171 in the unimplemented intrinsic error message. --- src/intrinsics/llvm.rs | 7 ++++++- src/intrinsics/llvm_aarch64.rs | 7 ++++++- src/intrinsics/llvm_x86.rs | 7 ++++++- src/intrinsics/mod.rs | 12 +++++++++-- src/lib.rs | 1 - src/trap.rs | 38 ---------------------------------- 6 files changed, 28 insertions(+), 44 deletions(-) delete mode 100644 src/trap.rs diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index eb0dfbb69c3b..2e02e85a997d 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -66,7 +66,12 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( fx.tcx .dcx() .warn(format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); - crate::trap::trap_unimplemented(fx, intrinsic); + let msg = format!( + "{intrinsic} is not yet supported.\n\ + See https://github.com/rust-lang/rustc_codegen_cranelift/issues/171\n\ + Please open an issue at https://github.com/rust-lang/rustc_codegen_cranelift/issues" + ); + crate::base::codegen_panic_nounwind(fx, &msg, None); return; } } diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index 387c87d123a3..06e8663a8b77 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -507,7 +507,12 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( "unsupported AArch64 llvm intrinsic {}; replacing with trap", intrinsic )); - crate::trap::trap_unimplemented(fx, intrinsic); + let msg = format!( + "{intrinsic} is not yet supported.\n\ + See https://github.com/rust-lang/rustc_codegen_cranelift/issues/171\n\ + Please open an issue at https://github.com/rust-lang/rustc_codegen_cranelift/issues" + ); + crate::base::codegen_panic_nounwind(fx, &msg, None); return; } } diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index c02d31844e03..3adff1f749a8 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -1316,7 +1316,12 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx.tcx .dcx() .warn(format!("unsupported x86 llvm intrinsic {}; replacing with trap", intrinsic)); - crate::trap::trap_unimplemented(fx, intrinsic); + let msg = format!( + "{intrinsic} is not yet supported.\n\ + See https://github.com/rust-lang/rustc_codegen_cranelift/issues/171\n\ + Please open an issue at https://github.com/rust-lang/rustc_codegen_cranelift/issues" + ); + crate::base::codegen_panic_nounwind(fx, &msg, None); return; } } diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index d3f47ad72633..0048a3e8db5a 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -801,7 +801,11 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME implement 128bit atomics if fx.tcx.is_compiler_builtins(LOCAL_CRATE) { // special case for compiler-builtins to avoid having to patch it - crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported"); + crate::base::codegen_panic_nounwind( + fx, + "128bit atomics not yet supported", + None, + ); return Ok(()); } else { fx.tcx @@ -832,7 +836,11 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME implement 128bit atomics if fx.tcx.is_compiler_builtins(LOCAL_CRATE) { // special case for compiler-builtins to avoid having to patch it - crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported"); + crate::base::codegen_panic_nounwind( + fx, + "128bit atomics not yet supported", + None, + ); return Ok(()); } else { fx.tcx diff --git a/src/lib.rs b/src/lib.rs index e7afaff3b428..c0063a40d39f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,6 @@ mod optimize; mod pointer; mod pretty_clif; mod toolchain; -mod trap; mod unsize; mod unwind_module; mod value_and_place; diff --git a/src/trap.rs b/src/trap.rs deleted file mode 100644 index ac3f58ee1ee6..000000000000 --- a/src/trap.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! Helpers used to print a message and abort in case of certain panics and some detected UB. - -use crate::prelude::*; - -fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) { - let puts = fx - .module - .declare_function( - "puts", - Linkage::Import, - &Signature { - call_conv: fx.target_config.default_call_conv, - params: vec![AbiParam::new(fx.pointer_type)], - returns: vec![AbiParam::new(types::I32)], - }, - ) - .unwrap(); - let puts = fx.module.declare_func_in_func(puts, &mut fx.bcx.func); - if fx.clif_comments.enabled() { - fx.add_comment(puts, "puts"); - } - - let real_msg = format!("trap at {:?} ({}): {}\0", fx.instance, fx.symbol_name, msg); - let msg_ptr = fx.anonymous_str(&real_msg); - fx.bcx.ins().call(puts, &[msg_ptr]); -} - -/// Use this when something is unimplemented, but `libcore` or `libstd` requires it to codegen. -/// -/// Trap code: user65535 -pub(crate) fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef) { - codegen_print(fx, msg.as_ref()); - - let one = fx.bcx.ins().iconst(types::I32, 1); - fx.lib_call("exit", vec![AbiParam::new(types::I32)], vec![], &[one]); - - fx.bcx.ins().trap(TrapCode::user(3).unwrap()); -} From 420e44f57848e3b21d1b5dd983f77536a1b7d43b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 8 Apr 2025 18:41:42 +0000 Subject: [PATCH 017/139] Reduce visibility of a couple of functions --- src/driver/jit.rs | 2 +- src/intrinsics/llvm_aarch64.rs | 2 +- src/intrinsics/llvm_x86.rs | 2 +- src/num.rs | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 41f8bb9161ca..0e2e1f6fc0a8 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -119,7 +119,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec) -> ! { std::process::exit(ret); } -pub(crate) fn codegen_and_compile_fn<'tcx>( +fn codegen_and_compile_fn<'tcx>( tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx, cached_context: &mut Context, diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index 06e8663a8b77..d22483cf1776 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -7,7 +7,7 @@ use crate::inline_asm::{CInlineAsmOperand, codegen_inline_asm_inner}; use crate::intrinsics::*; use crate::prelude::*; -pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( +pub(super) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, args: &[Spanned>], diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 3adff1f749a8..e145eda60685 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -7,7 +7,7 @@ use crate::inline_asm::{CInlineAsmOperand, codegen_inline_asm_inner}; use crate::intrinsics::*; use crate::prelude::*; -pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( +pub(super) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, args: &[Spanned>], diff --git a/src/num.rs b/src/num.rs index 2a4d1e3ae571..90627f8060b8 100644 --- a/src/num.rs +++ b/src/num.rs @@ -2,7 +2,7 @@ use crate::prelude::*; -pub(crate) fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> IntCC { +fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> IntCC { use BinOp::*; use IntCC::*; match bin_op { @@ -109,7 +109,7 @@ pub(crate) fn codegen_binop<'tcx>( } } -pub(crate) fn codegen_bool_binop<'tcx>( +fn codegen_bool_binop<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, bin_op: BinOp, in_lhs: CValue<'tcx>, @@ -389,7 +389,7 @@ pub(crate) fn codegen_float_binop<'tcx>( CValue::by_val(res, in_lhs.layout()) } -pub(crate) fn codegen_ptr_binop<'tcx>( +fn codegen_ptr_binop<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, bin_op: BinOp, in_lhs: CValue<'tcx>, From ab514c95967a7c5d732aa1e3800afc4d9cb252f9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 9 Apr 2025 13:50:59 +0000 Subject: [PATCH 018/139] Pass UnwindAction to a couple of functions In preparation for future unwinding support. Part of rust-lang/rustc_codegen_cranelift#1567 --- src/abi/mod.rs | 20 +++++++++++++++----- src/abi/returning.rs | 12 +++++------- src/base.rs | 32 ++++++++++++++++++++++++++------ 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index ddd119e0c610..2c6dd851d4de 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -20,6 +20,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_target::callconv::{Conv, FnAbi, PassMode}; +use smallvec::SmallVec; use self::pass_mode::*; pub(crate) use self::returning::codegen_return; @@ -384,6 +385,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( args: &[Spanned>], destination: Place<'tcx>, target: Option, + _unwind: UnwindAction, ) { let func = codegen_operand(fx, func); let fn_sig = func.layout().ty.fn_sig(fx.tcx); @@ -588,12 +590,14 @@ pub(crate) fn codegen_terminator_call<'tcx>( with_no_trimmed_paths!(fx.add_comment(nop_inst, format!("abi: {:?}", fn_abi))); } - match func_ref { + let call_inst = match func_ref { CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), CallTarget::Indirect(sig, func_ptr) => { fx.bcx.ins().call_indirect(sig, func_ptr, &call_args) } - } + }; + + fx.bcx.func.dfg.inst_results(call_inst).iter().copied().collect::>() }); if let Some(dest) = target { @@ -703,14 +707,17 @@ pub(crate) fn codegen_drop<'tcx>( source_info: mir::SourceInfo, drop_place: CPlace<'tcx>, target: BasicBlock, + _unwind: UnwindAction, ) { let ty = drop_place.layout().ty; let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty); + let ret_block = fx.get_block(target); if let ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) = drop_instance.def { // we don't actually need to drop anything + fx.bcx.ins().jump(ret_block, &[]); } else { match ty.kind() { ty::Dynamic(_, _, ty::Dyn) => { @@ -747,7 +754,9 @@ pub(crate) fn codegen_drop<'tcx>( let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); + // FIXME implement cleanup on exceptions fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]); + fx.bcx.ins().jump(ret_block, &[]); } ty::Dynamic(_, _, ty::DynStar) => { // IN THIS ARM, WE HAVE: @@ -791,6 +800,8 @@ pub(crate) fn codegen_drop<'tcx>( let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); fx.bcx.ins().call_indirect(sig, drop_fn, &[data]); + // FIXME implement cleanup on exceptions + fx.bcx.ins().jump(ret_block, &[]); } _ => { assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _))); @@ -816,10 +827,9 @@ pub(crate) fn codegen_drop<'tcx>( let func_ref = fx.get_function_ref(drop_instance); fx.bcx.ins().call(func_ref, &call_args); + // FIXME implement cleanup on exceptions + fx.bcx.ins().jump(ret_block, &[]); } } } - - let target_block = fx.get_block(target); - fx.bcx.ins().jump(target_block, &[]); } diff --git a/src/abi/returning.rs b/src/abi/returning.rs index 9e048c7badb8..36087f96dd77 100644 --- a/src/abi/returning.rs +++ b/src/abi/returning.rs @@ -46,7 +46,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, ret_arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, ret_place: CPlace<'tcx>, - f: impl FnOnce(&mut FunctionCx<'_, '_, 'tcx>, Option) -> Inst, + f: impl FnOnce(&mut FunctionCx<'_, '_, 'tcx>, Option) -> SmallVec<[Value; 2]>, ) { let (ret_temp_place, return_ptr) = match ret_arg_abi.mode { PassMode::Ignore => (None, None), @@ -67,23 +67,21 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast { .. } => (None, None), }; - let call_inst = f(fx, return_ptr); + let results = f(fx, return_ptr); match ret_arg_abi.mode { PassMode::Ignore => {} PassMode::Direct(_) => { - let ret_val = fx.bcx.inst_results(call_inst)[0]; + let ret_val = results[0]; ret_place.write_cvalue(fx, CValue::by_val(ret_val, ret_arg_abi.layout)); } PassMode::Pair(_, _) => { - let ret_val_a = fx.bcx.inst_results(call_inst)[0]; - let ret_val_b = fx.bcx.inst_results(call_inst)[1]; + let ret_val_a = results[0]; + let ret_val_b = results[1]; ret_place .write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_arg_abi.layout)); } PassMode::Cast { ref cast, .. } => { - let results = - fx.bcx.inst_results(call_inst).iter().copied().collect::>(); let result = super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast); ret_place.write_cvalue(fx, result); diff --git a/src/base.rs b/src/base.rs index adaa754491e5..9d425a3b292a 100644 --- a/src/base.rs +++ b/src/base.rs @@ -372,7 +372,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { TerminatorKind::Return => { crate::abi::codegen_return(fx); } - TerminatorKind::Assert { cond, expected, msg, target, unwind: _ } => { + TerminatorKind::Assert { cond, expected, msg, target, unwind } => { if !fx.tcx.sess.overflow_checks() && msg.is_optional_overflow_check() { let target = fx.get_block(*target); fx.bcx.ins().jump(target, &[]); @@ -402,6 +402,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { fx, rustc_hir::LangItem::PanicBoundsCheck, &[index, len, location], + *unwind, Some(source_info.span), ); } @@ -414,6 +415,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { fx, rustc_hir::LangItem::PanicMisalignedPointerDereference, &[required, found, location], + *unwind, Some(source_info.span), ); } @@ -424,6 +426,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { fx, rustc_hir::LangItem::PanicNullPointerDereference, &[location], + *unwind, Some(source_info.span), ) } @@ -434,6 +437,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { fx, msg.panic_function(), &[location], + *unwind, Some(source_info.span), ); } @@ -492,7 +496,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { destination, target, fn_span, - unwind: _, + unwind, call_source: _, } => { fx.tcx.prof.generic_activity("codegen call").run(|| { @@ -503,6 +507,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { args, *destination, *target, + *unwind, ) }); } @@ -565,9 +570,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { | TerminatorKind::CoroutineDrop => { bug!("shouldn't exist at codegen {:?}", bb_data.terminator()); } - TerminatorKind::Drop { place, target, unwind: _, replace: _ } => { + TerminatorKind::Drop { place, target, unwind, replace: _ } => { let drop_place = codegen_place(fx, *place); - crate::abi::codegen_drop(fx, source_info, drop_place, *target); + crate::abi::codegen_drop(fx, source_info, drop_place, *target, *unwind); } }; } @@ -1089,7 +1094,13 @@ pub(crate) fn codegen_panic_nounwind<'tcx>( let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap()); let args = [msg_ptr, msg_len]; - codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, span); + codegen_panic_inner( + fx, + rustc_hir::LangItem::PanicNounwind, + &args, + UnwindAction::Terminate(UnwindTerminateReason::Abi), + span, + ); } pub(crate) fn codegen_unwind_terminate<'tcx>( @@ -1099,13 +1110,20 @@ pub(crate) fn codegen_unwind_terminate<'tcx>( ) { let args = []; - codegen_panic_inner(fx, reason.lang_item(), &args, Some(source_info.span)); + codegen_panic_inner( + fx, + reason.lang_item(), + &args, + UnwindAction::Terminate(UnwindTerminateReason::Abi), + Some(source_info.span), + ); } fn codegen_panic_inner<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, lang_item: rustc_hir::LangItem, args: &[Value], + _unwind: UnwindAction, span: Option, ) { fx.bcx.set_cold_block(fx.bcx.current_block().unwrap()); @@ -1121,6 +1139,8 @@ fn codegen_panic_inner<'tcx>( let symbol_name = fx.tcx.symbol_name(instance).name; + // FIXME implement cleanup on exceptions + fx.lib_call( symbol_name, args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(), From 9495eb517e5a2b76fcdb514eeec5aa4d8fd16320 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 9 Apr 2025 14:05:27 +0000 Subject: [PATCH 019/139] Pass Module to UnwindContext Once writing the LSDA, it will need access to the Module to get a reference to the personality function and to define a data object for the LSDA. Part of rust-lang/rustc_codegen_cranelift#1567 --- src/debuginfo/unwind.rs | 20 +++++++++++++------- src/unwind_module.rs | 8 ++++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/debuginfo/unwind.rs b/src/debuginfo/unwind.rs index 362333d35a41..74b82a7139ab 100644 --- a/src/debuginfo/unwind.rs +++ b/src/debuginfo/unwind.rs @@ -1,7 +1,6 @@ //! Unwind info generation (`.eh_frame`) use cranelift_codegen::ir::Endianness; -use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::isa::unwind::UnwindInfo; use cranelift_object::ObjectProduct; use gimli::RunTimeEndian; @@ -18,14 +17,14 @@ pub(crate) struct UnwindContext { } impl UnwindContext { - pub(crate) fn new(isa: &dyn TargetIsa, pic_eh_frame: bool) -> Self { - let endian = match isa.endianness() { + pub(crate) fn new(module: &mut dyn Module, pic_eh_frame: bool) -> Self { + let endian = match module.isa().endianness() { Endianness::Little => RunTimeEndian::Little, Endianness::Big => RunTimeEndian::Big, }; let mut frame_table = FrameTable::default(); - let cie_id = if let Some(mut cie) = isa.create_systemv_cie() { + let cie_id = if let Some(mut cie) = module.isa().create_systemv_cie() { if pic_eh_frame { cie.fde_address_encoding = gimli::DwEhPe(gimli::DW_EH_PE_pcrel.0 | gimli::DW_EH_PE_sdata4.0); @@ -38,8 +37,15 @@ impl UnwindContext { UnwindContext { endian, frame_table, cie_id } } - pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) { - if let target_lexicon::OperatingSystem::MacOSX { .. } = isa.triple().operating_system { + pub(crate) fn add_function( + &mut self, + module: &mut dyn Module, + func_id: FuncId, + context: &Context, + ) { + if let target_lexicon::OperatingSystem::MacOSX { .. } = + module.isa().triple().operating_system + { // The object crate doesn't currently support DW_GNU_EH_PE_absptr, which macOS // requires for unwinding tables. In addition on arm64 it currently doesn't // support 32bit relocations as we currently use for the unwinding table. @@ -48,7 +54,7 @@ impl UnwindContext { } let unwind_info = if let Some(unwind_info) = - context.compiled_code().unwrap().create_unwind_info(isa).unwrap() + context.compiled_code().unwrap().create_unwind_info(module.isa()).unwrap() { unwind_info } else { diff --git a/src/unwind_module.rs b/src/unwind_module.rs index b950aaa29ce0..f963dc79fbb5 100644 --- a/src/unwind_module.rs +++ b/src/unwind_module.rs @@ -17,8 +17,8 @@ pub(crate) struct UnwindModule { } impl UnwindModule { - pub(crate) fn new(module: T, pic_eh_frame: bool) -> Self { - let unwind_context = UnwindContext::new(module.isa(), pic_eh_frame); + pub(crate) fn new(mut module: T, pic_eh_frame: bool) -> Self { + let unwind_context = UnwindContext::new(&mut module, pic_eh_frame); UnwindModule { module, unwind_context } } } @@ -37,7 +37,7 @@ impl UnwindModule { self.module.finalize_definitions().unwrap(); let prev_unwind_context = std::mem::replace( &mut self.unwind_context, - UnwindContext::new(self.module.isa(), false), + UnwindContext::new(&mut self.module, false), ); unsafe { prev_unwind_context.register_jit(&self.module) }; } @@ -94,7 +94,7 @@ impl Module for UnwindModule { ctrl_plane: &mut ControlPlane, ) -> ModuleResult<()> { self.module.define_function_with_control_plane(func, ctx, ctrl_plane)?; - self.unwind_context.add_function(func, ctx, self.module.isa()); + self.unwind_context.add_function(&mut self.module, func, ctx); Ok(()) } From 547a31016d9725df7466f6064fdcf0e4fb031957 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 8 Apr 2025 12:23:07 +1000 Subject: [PATCH 020/139] Rename some `name` variables as `ident`. It bugs me when variables of type `Ident` are called `name`. It leads to silly things like `name.name`. `Ident` variables should be called `ident`, and `name` should be used for variables of type `Symbol`. This commit improves things by by doing `s/name/ident/` on a bunch of `Ident` variables. Not all of them, but a decent chunk. --- src/main_shim.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main_shim.rs b/src/main_shim.rs index 6d5df2b00437..3b48adb7e918 100644 --- a/src/main_shim.rs +++ b/src/main_shim.rs @@ -104,7 +104,7 @@ pub(crate) fn maybe_create_entry_wrapper( let termination_trait = tcx.require_lang_item(LangItem::Termination, None); let report = tcx .associated_items(termination_trait) - .find_by_name_and_kind( + .find_by_ident_and_kind( tcx, Ident::from_str("report"), AssocKind::Fn, From 180bc6c8f179cb192c98a08693802191452ee822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 27 Mar 2025 00:19:52 +0100 Subject: [PATCH 021/139] Remove the use of Rayon iterators --- src/driver/aot.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 444dc4412868..b1bc7e1707eb 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -728,26 +728,27 @@ pub(crate) fn run_aot( let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(todo_cgus.len())); - let modules = tcx.sess.time("codegen mono items", || { - let mut modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| { - let dep_node = cgu.codegen_dep_node(tcx); - tcx.dep_graph - .with_task( + let modules: Vec<_> = + tcx.sess.time("codegen mono items", || { + let modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| { + let dep_node = cgu.codegen_dep_node(tcx); + let (module, _) = tcx.dep_graph.with_task( dep_node, tcx, (global_asm_config.clone(), cgu.name(), concurrency_limiter.acquire(tcx.dcx())), module_codegen, Some(rustc_middle::dep_graph::hash_result), - ) - .0 - }); - modules.extend( - done_cgus + ); + IntoDynSyncSend(module) + }); + modules .into_iter() - .map(|(_, cgu)| OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))), - ); - modules - }); + .map(|module| module.0) + .chain(done_cgus.into_iter().map(|(_, cgu)| { + OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu)) + })) + .collect() + }); let allocator_module = emit_allocator_module(tcx); From bc9dacdf9a0f123377f6f97ab23f13f5777e4041 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 06:28:59 +1000 Subject: [PATCH 022/139] Move `has_self` field to `hir::AssocKind::Fn`. `hir::AssocItem` currently has a boolean `fn_has_self_parameter` field, which is misplaced, because it's only relevant for associated fns, not for associated consts or types. This commit moves it (and renames it) to the `AssocKind::Fn` variant, where it belongs. This requires introducing a new C-style enum, `AssocTag`, which is like `AssocKind` but without the fields. This is because `AssocKind` values are passed to various functions like `find_by_ident_and_kind` to indicate what kind of associated item should be searched for, and having to specify `has_self` isn't relevant there. New methods: - Predicates `AssocItem::is_fn` and `AssocItem::is_method`. - `AssocItem::as_tag` which converts `AssocItem::kind` to `AssocTag`. Removed `find_by_name_and_kinds`, which is unused. `AssocItem::descr` can now distinguish between methods and associated functions, which slightly improves some error messages. --- src/main_shim.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main_shim.rs b/src/main_shim.rs index 3b48adb7e918..6eef97c14dd2 100644 --- a/src/main_shim.rs +++ b/src/main_shim.rs @@ -1,6 +1,6 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use rustc_hir::LangItem; -use rustc_middle::ty::{AssocKind, GenericArg}; +use rustc_middle::ty::{AssocTag, GenericArg}; use rustc_session::config::EntryFnType; use rustc_span::{DUMMY_SP, Ident}; @@ -107,7 +107,7 @@ pub(crate) fn maybe_create_entry_wrapper( .find_by_ident_and_kind( tcx, Ident::from_str("report"), - AssocKind::Fn, + AssocTag::Fn, termination_trait, ) .unwrap(); From f99bdfef831f86e3d32c9aade7e41020b067d393 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 14 Apr 2025 08:47:01 +0000 Subject: [PATCH 023/139] Rustup to rustc 1.88.0-nightly (092a284ba 2025-04-13) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 4be668c7b848..1789b62917de 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-04-08" +channel = "nightly-2025-04-14" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 1afce7c3548ff31174cb060f3217b1994d982bed Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:13:37 +0000 Subject: [PATCH 024/139] Implement simd_insert_dyn and simd_extract_dyn intrinsics --- src/intrinsics/simd.rs | 28 ++++++++++++++++++++++++++++ src/value_and_place.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index dd6d8dbb6f5e..7a041469bccd 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -283,6 +283,20 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ret_lane.write_cvalue(fx, val); } + sym::simd_insert_dyn => { + intrinsic_args!(fx, args => (base, idx, val); intrinsic); + + if !base.layout().ty.is_simd() { + report_simd_type_validation_error(fx, intrinsic, span, base.layout().ty); + return; + } + + let idx = idx.load_scalar(fx); + + ret.write_cvalue(fx, base); + ret.write_lane_dyn(fx, idx, val); + } + sym::simd_extract => { let (v, idx) = match args { [v, idx] => (v, idx), @@ -318,6 +332,20 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ret.write_cvalue(fx, ret_lane); } + sym::simd_extract_dyn => { + intrinsic_args!(fx, args => (v, idx); intrinsic); + + if !v.layout().ty.is_simd() { + report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); + return; + } + + let idx = idx.load_scalar(fx); + + let ret_lane = v.value_lane_dyn(fx, idx); + ret.write_cvalue(fx, ret_lane); + } + sym::simd_neg | sym::simd_bswap | sym::simd_bitreverse diff --git a/src/value_and_place.rs b/src/value_and_place.rs index f8a19589fdd7..9fd71cd6f77f 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -806,6 +806,34 @@ impl<'tcx> CPlace<'tcx> { } } + /// Write a value to an individual lane in a SIMD vector. + pub(crate) fn write_lane_dyn( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + lane_idx: Value, + value: CValue<'tcx>, + ) { + let layout = self.layout(); + assert!(layout.ty.is_simd()); + let (_lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + assert_eq!(lane_layout, value.layout()); + + match self.inner { + CPlaceInner::Var(_, _) => unreachable!(), + CPlaceInner::VarPair(_, _, _) => unreachable!(), + CPlaceInner::Addr(ptr, None) => { + let field_offset = fx + .bcx + .ins() + .imul_imm(lane_idx, i64::try_from(lane_layout.size.bytes()).unwrap()); + let field_ptr = ptr.offset_value(fx, field_offset); + CPlace::for_ptr(field_ptr, lane_layout).write_cvalue(fx, value); + } + CPlaceInner::Addr(_, Some(_)) => unreachable!(), + } + } + pub(crate) fn place_index( self, fx: &mut FunctionCx<'_, '_, 'tcx>, From c02e496ecc4e60b3c39bb361de5fac57fef83846 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:31:20 +0000 Subject: [PATCH 025/139] Use cg_ssa's version of codegen_naked_asm in cg_clif --- src/base.rs | 39 +------ src/driver/aot.rs | 37 +++++-- src/driver/jit.rs | 12 ++- src/global_asm.rs | 254 ++++++++++++++++++++++++++++++++-------------- src/inline_asm.rs | 193 +++++++---------------------------- 5 files changed, 255 insertions(+), 280 deletions(-) diff --git a/src/base.rs b/src/base.rs index adaa754491e5..4acbd4b95598 100644 --- a/src/base.rs +++ b/src/base.rs @@ -8,8 +8,6 @@ use rustc_ast::InlineAsmOptions; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_index::IndexVec; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::InlineAsmMacro; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; @@ -18,7 +16,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use crate::constant::ConstantCx; use crate::debuginfo::{FunctionDebugContext, TypeDebugContext}; use crate::enable_verifier; -use crate::inline_asm::codegen_naked_asm; use crate::prelude::*; use crate::pretty_clif::CommentWriter; @@ -37,7 +34,7 @@ pub(crate) fn codegen_fn<'tcx>( cached_func: Function, module: &mut dyn Module, instance: Instance<'tcx>, -) -> Option { +) -> CodegenedFunction { debug_assert!(!instance.args.has_infer()); let symbol_name = tcx.symbol_name(instance).name.to_string(); @@ -54,38 +51,6 @@ pub(crate) fn codegen_fn<'tcx>( String::from_utf8_lossy(&buf).into_owned() }); - if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) { - assert_eq!(mir.basic_blocks.len(), 1); - assert!(mir.basic_blocks[START_BLOCK].statements.is_empty()); - - match &mir.basic_blocks[START_BLOCK].terminator().kind { - TerminatorKind::InlineAsm { - asm_macro: InlineAsmMacro::NakedAsm, - template, - operands, - options, - line_spans: _, - targets: _, - unwind: _, - } => { - codegen_naked_asm( - tcx, - cx, - module, - instance, - mir.basic_blocks[START_BLOCK].terminator().source_info.span, - &symbol_name, - template, - operands, - *options, - ); - } - _ => unreachable!(), - } - - return None; - } - // Declare function let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance); let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap(); @@ -166,7 +131,7 @@ pub(crate) fn codegen_fn<'tcx>( // Verify function verify_func(tcx, &clif_comments, &func); - Some(CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }) + CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx } } pub(crate) fn compile_fn( diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 00136ac4a574..1cb8f8bc4399 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -22,7 +22,10 @@ use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_metadata::EncodedMetadata; use rustc_metadata::fs::copy_to_stdout; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::mir::mono::{CodegenUnit, MonoItem}; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::mir::mono::{ + CodegenUnit, Linkage as RLinkage, MonoItem, MonoItemData, Visibility, +}; use rustc_session::Session; use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType}; @@ -30,7 +33,7 @@ use crate::CodegenCx; use crate::base::CodegenedFunction; use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken}; use crate::debuginfo::TypeDebugContext; -use crate::global_asm::GlobalAsmConfig; +use crate::global_asm::{GlobalAsmConfig, GlobalAsmContext}; use crate::prelude::*; use crate::unwind_module::UnwindModule; @@ -530,19 +533,35 @@ fn codegen_cgu_content( let mut type_dbg = TypeDebugContext::default(); super::predefine_mono_items(tcx, module, &mono_items); let mut codegened_functions = vec![]; - for (mono_item, _) in mono_items { + for (mono_item, item_data) in mono_items { match mono_item { - MonoItem::Fn(inst) => { - if let Some(codegened_function) = crate::base::codegen_fn( + MonoItem::Fn(instance) => { + if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) + { + rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm( + &mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm }, + instance, + MonoItemData { + linkage: RLinkage::External, + visibility: if item_data.linkage == RLinkage::Internal { + Visibility::Hidden + } else { + item_data.visibility + }, + ..item_data + }, + ); + continue; + } + let codegened_function = crate::base::codegen_fn( tcx, &mut cx, &mut type_dbg, Function::new(), module, - inst, - ) { - codegened_functions.push(codegened_function); - } + instance, + ); + codegened_functions.push(codegened_function); } MonoItem::Static(def_id) => { let data_id = crate::constant::codegen_static(tcx, module, def_id); diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 41f8bb9161ca..e368cf4386d0 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -126,6 +126,11 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( module: &mut dyn Module, instance: Instance<'tcx>, ) { + if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) { + tcx.dcx() + .span_fatal(tcx.def_span(instance.def_id()), "Naked asm is not supported in JIT mode"); + } + cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler( tcx.prof.clone(), ))); @@ -135,16 +140,15 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); - if let Some(codegened_func) = crate::base::codegen_fn( + let codegened_func = crate::base::codegen_fn( tcx, cx, &mut TypeDebugContext::default(), cached_func, module, instance, - ) { - crate::base::compile_fn(cx, &tcx.prof, cached_context, module, codegened_func); - } + ); + crate::base::compile_fn(cx, &tcx.prof, cached_context, module, codegened_func); }); } diff --git a/src/global_asm.rs b/src/global_asm.rs index 79cefb05de32..18944a3be276 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -7,102 +7,206 @@ use std::process::{Command, Stdio}; use std::sync::Arc; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_codegen_ssa::traits::{AsmCodegenMethods, GlobalAsmOperandRef}; use rustc_hir::{InlineAsmOperand, ItemId}; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, +}; use rustc_session::config::{OutputFilenames, OutputType}; use rustc_target::asm::InlineAsmArch; use crate::prelude::*; +pub(crate) struct GlobalAsmContext<'a, 'tcx> { + pub tcx: TyCtxt<'tcx>, + pub global_asm: &'a mut String, +} + +impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> { + fn codegen_global_asm( + &mut self, + template: &[InlineAsmTemplatePiece], + operands: &[GlobalAsmOperandRef<'tcx>], + options: InlineAsmOptions, + _line_spans: &[Span], + ) { + codegen_global_asm_inner(self.tcx, self.global_asm, template, operands, options); + } + + fn mangled_name(&self, instance: Instance<'tcx>) -> String { + self.tcx.symbol_name(instance).name.to_owned() + } +} + +impl<'tcx> LayoutOfHelpers<'tcx> for GlobalAsmContext<'_, 'tcx> { + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { + if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err { + self.tcx.sess.dcx().span_fatal(span, err.to_string()) + } else { + self.tcx + .sess + .dcx() + .span_fatal(span, format!("failed to get layout for `{}`: {}", ty, err)) + } + } +} + +impl<'tcx> FnAbiOfHelpers<'tcx> for GlobalAsmContext<'_, 'tcx> { + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + FullyMonomorphizedLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request) + } +} + +impl<'tcx> HasTyCtxt<'tcx> for GlobalAsmContext<'_, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.tcx + } +} + +impl<'tcx> rustc_abi::HasDataLayout for GlobalAsmContext<'_, 'tcx> { + fn data_layout(&self) -> &rustc_abi::TargetDataLayout { + &self.tcx.data_layout + } +} + +impl<'tcx> HasTypingEnv<'tcx> for GlobalAsmContext<'_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() + } +} + pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind { - let is_x86 = - matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); + let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind else { + bug!("Expected GlobalAsm found {:?}", item); + }; - if is_x86 { - if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { - global_asm.push_str("\n.intel_syntax noprefix\n"); - } else { - global_asm.push_str("\n.att_syntax\n"); + // Adapted from rustc_codegen_ssa::mono_items::MonoItem::define + let operands: Vec<_> = asm + .operands + .iter() + .map(|(op, op_sp)| match *op { + InlineAsmOperand::Const { ref anon_const } => { + match tcx.const_eval_poly(anon_const.def_id.to_def_id()) { + Ok(const_value) => { + let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + let string = rustc_codegen_ssa::common::asm_const_to_str( + tcx, + *op_sp, + const_value, + FullyMonomorphizedLayoutCx(tcx).layout_of(ty), + ); + GlobalAsmOperandRef::Const { string } + } + Err(ErrorHandled::Reported { .. }) => { + // An error has already been reported and + // compilation is guaranteed to fail if execution + // hits this path. So an empty string instead of + // a stringified constant value will suffice. + GlobalAsmOperandRef::Const { string: String::new() } + } + Err(ErrorHandled::TooGeneric(_)) => { + span_bug!(*op_sp, "asm const cannot be resolved; too generic") + } + } } + InlineAsmOperand::SymFn { expr } => { + if cfg!(not(feature = "inline_asm_sym")) { + tcx.dcx().span_err( + item.span, + "asm! and global_asm! sym operands are not yet supported", + ); + } + + let ty = tcx.typeck(item_id.owner_id).expr_ty(expr); + let instance = match ty.kind() { + &ty::FnDef(def_id, args) => Instance::new(def_id, args), + _ => span_bug!(*op_sp, "asm sym is not a function"), + }; + GlobalAsmOperandRef::SymFn { instance } + } + InlineAsmOperand::SymStatic { path: _, def_id } => { + GlobalAsmOperandRef::SymStatic { def_id } + } + InlineAsmOperand::In { .. } + | InlineAsmOperand::Out { .. } + | InlineAsmOperand::InOut { .. } + | InlineAsmOperand::SplitInOut { .. } + | InlineAsmOperand::Label { .. } => { + span_bug!(*op_sp, "invalid operand type for global_asm!") + } + }) + .collect(); + + codegen_global_asm_inner(tcx, global_asm, asm.template, &operands, asm.options); +} + +fn codegen_global_asm_inner<'tcx>( + tcx: TyCtxt<'tcx>, + global_asm: &mut String, + template: &[InlineAsmTemplatePiece], + operands: &[GlobalAsmOperandRef<'tcx>], + options: InlineAsmOptions, +) { + let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); + + if is_x86 { + if !options.contains(InlineAsmOptions::ATT_SYNTAX) { + global_asm.push_str("\n.intel_syntax noprefix\n"); + } else { + global_asm.push_str("\n.att_syntax\n"); } - for piece in asm.template { - match *piece { - InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s), - InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: op_sp } => { - match asm.operands[operand_idx].0 { - InlineAsmOperand::Const { ref anon_const } => { - match tcx.const_eval_poly(anon_const.def_id.to_def_id()) { - Ok(const_value) => { - let ty = tcx - .typeck_body(anon_const.body) - .node_type(anon_const.hir_id); - let string = rustc_codegen_ssa::common::asm_const_to_str( - tcx, - op_sp, - const_value, - FullyMonomorphizedLayoutCx(tcx).layout_of(ty), - ); - global_asm.push_str(&string); - } - Err(ErrorHandled::Reported { .. }) => { - // An error has already been reported and compilation is - // guaranteed to fail if execution hits this path. - } - Err(ErrorHandled::TooGeneric(_)) => { - span_bug!(op_sp, "asm const cannot be resolved; too generic"); - } - } + } + for piece in template { + match *piece { + InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s), + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { + match operands[operand_idx] { + GlobalAsmOperandRef::Const { ref string } => { + global_asm.push_str(string); + } + GlobalAsmOperandRef::SymFn { instance } => { + if cfg!(not(feature = "inline_asm_sym")) { + tcx.dcx().span_err( + span, + "asm! and global_asm! sym operands are not yet supported", + ); } - InlineAsmOperand::SymFn { expr } => { - if cfg!(not(feature = "inline_asm_sym")) { - tcx.dcx().span_err( - item.span, - "asm! and global_asm! sym operands are not yet supported", - ); - } - let ty = tcx.typeck(item_id.owner_id).expr_ty(expr); - let instance = match ty.kind() { - &ty::FnDef(def_id, args) => Instance::new(def_id, args), - _ => span_bug!(op_sp, "asm sym is not a function"), - }; - let symbol = tcx.symbol_name(instance); - // FIXME handle the case where the function was made private to the - // current codegen unit - global_asm.push_str(symbol.name); + let symbol = tcx.symbol_name(instance); + // FIXME handle the case where the function was made private to the + // current codegen unit + global_asm.push_str(symbol.name); + } + GlobalAsmOperandRef::SymStatic { def_id } => { + if cfg!(not(feature = "inline_asm_sym")) { + tcx.dcx().span_err( + span, + "asm! and global_asm! sym operands are not yet supported", + ); } - InlineAsmOperand::SymStatic { path: _, def_id } => { - if cfg!(not(feature = "inline_asm_sym")) { - tcx.dcx().span_err( - item.span, - "asm! and global_asm! sym operands are not yet supported", - ); - } - let instance = Instance::mono(tcx, def_id); - let symbol = tcx.symbol_name(instance); - global_asm.push_str(symbol.name); - } - InlineAsmOperand::In { .. } - | InlineAsmOperand::Out { .. } - | InlineAsmOperand::InOut { .. } - | InlineAsmOperand::SplitInOut { .. } - | InlineAsmOperand::Label { .. } => { - span_bug!(op_sp, "invalid operand type for global_asm!") - } + let instance = Instance::mono(tcx, def_id); + let symbol = tcx.symbol_name(instance); + global_asm.push_str(symbol.name); } } } } + } - global_asm.push('\n'); - if is_x86 { - global_asm.push_str(".att_syntax\n\n"); - } - } else { - bug!("Expected GlobalAsm found {:?}", item); + global_asm.push('\n'); + if is_x86 { + global_asm.push_str(".att_syntax\n\n"); } } diff --git a/src/inline_asm.rs b/src/inline_asm.rs index fbc33a642853..afee50955497 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -161,7 +161,6 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>( stack_slots_input: Vec::new(), stack_slots_output: Vec::new(), stack_slot_size: Size::from_bytes(0), - is_naked: false, }; asm_gen.allocate_registers(); asm_gen.allocate_stack_slots(); @@ -201,114 +200,6 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>( call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs); } -pub(crate) fn codegen_naked_asm<'tcx>( - tcx: TyCtxt<'tcx>, - cx: &mut crate::CodegenCx, - module: &mut dyn Module, - instance: Instance<'tcx>, - span: Span, - symbol_name: &str, - template: &[InlineAsmTemplatePiece], - operands: &[InlineAsmOperand<'tcx>], - options: InlineAsmOptions, -) { - // FIXME add .eh_frame unwind info directives - - let operands = operands - .iter() - .map(|operand| match *operand { - InlineAsmOperand::In { .. } - | InlineAsmOperand::Out { .. } - | InlineAsmOperand::InOut { .. } => { - span_bug!(span, "invalid operand type for naked asm") - } - InlineAsmOperand::Const { ref value } => { - let cv = instance.instantiate_mir_and_normalize_erasing_regions( - tcx, - ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(value.const_), - ); - let const_value = cv - .eval(tcx, ty::TypingEnv::fully_monomorphized(), value.span) - .expect("erroneous constant missed by mono item collection"); - - let value = rustc_codegen_ssa::common::asm_const_to_str( - tcx, - span, - const_value, - FullyMonomorphizedLayoutCx(tcx).layout_of(cv.ty()), - ); - CInlineAsmOperand::Const { value } - } - InlineAsmOperand::SymFn { ref value } => { - if cfg!(not(feature = "inline_asm_sym")) { - tcx.dcx() - .span_err(span, "asm! and global_asm! sym operands are not yet supported"); - } - - let const_ = instance.instantiate_mir_and_normalize_erasing_regions( - tcx, - ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(value.const_), - ); - if let ty::FnDef(def_id, args) = *const_.ty().kind() { - let instance = ty::Instance::resolve_for_fn_ptr( - tcx, - ty::TypingEnv::fully_monomorphized(), - def_id, - args, - ) - .unwrap(); - let symbol = tcx.symbol_name(instance); - - // Pass a wrapper rather than the function itself as the function itself may not - // be exported from the main codegen unit and may thus be unreachable from the - // object file created by an external assembler. - let wrapper_name = format!( - "__inline_asm_{}_wrapper_n{}", - cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), - cx.inline_asm_index - ); - cx.inline_asm_index += 1; - let sig = - get_function_sig(tcx, module.target_config().default_call_conv, instance); - create_wrapper_function(module, sig, &wrapper_name, symbol.name); - - CInlineAsmOperand::Symbol { symbol: wrapper_name } - } else { - span_bug!(span, "invalid type for asm sym (fn)"); - } - } - InlineAsmOperand::SymStatic { def_id } => { - assert!(tcx.is_static(def_id)); - let instance = Instance::mono(tcx, def_id); - CInlineAsmOperand::Symbol { symbol: tcx.symbol_name(instance).name.to_owned() } - } - InlineAsmOperand::Label { .. } => { - span_bug!(span, "asm! label operands are not yet supported"); - } - }) - .collect::>(); - - let asm_gen = InlineAssemblyGenerator { - tcx, - arch: tcx.sess.asm_arch.unwrap(), - enclosing_def_id: instance.def_id(), - template, - operands: &operands, - options, - registers: Vec::new(), - stack_slots_clobber: Vec::new(), - stack_slots_input: Vec::new(), - stack_slots_output: Vec::new(), - stack_slot_size: Size::from_bytes(0), - is_naked: true, - }; - - let generated_asm = asm_gen.generate_asm_wrapper(symbol_name); - cx.global_asm.push_str(&generated_asm); -} - struct InlineAssemblyGenerator<'a, 'tcx> { tcx: TyCtxt<'tcx>, arch: InlineAsmArch, @@ -321,13 +212,10 @@ struct InlineAssemblyGenerator<'a, 'tcx> { stack_slots_input: Vec>, stack_slots_output: Vec>, stack_slot_size: Size, - is_naked: bool, } impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { fn allocate_registers(&mut self) { - assert!(!self.is_naked); - let sess = self.tcx.sess; let map = allocatable_registers( self.arch, @@ -451,8 +339,6 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } fn allocate_stack_slots(&mut self) { - assert!(!self.is_naked); - let mut slot_size = Size::from_bytes(0); let mut slots_clobber = vec![None; self.operands.len()]; let mut slots_input = vec![None; self.operands.len()]; @@ -582,32 +468,31 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { if is_x86 { generated_asm.push_str(".intel_syntax noprefix\n"); } - if !self.is_naked { - Self::prologue(&mut generated_asm, self.arch); - // Save clobbered registers - if !self.options.contains(InlineAsmOptions::NORETURN) { - for (reg, slot) in self - .registers - .iter() - .zip(self.stack_slots_clobber.iter().copied()) - .filter_map(|(r, s)| r.zip(s)) - { - Self::save_register(&mut generated_asm, self.arch, reg, slot); - } - } + Self::prologue(&mut generated_asm, self.arch); - // Write input registers + // Save clobbered registers + if !self.options.contains(InlineAsmOptions::NORETURN) { for (reg, slot) in self .registers .iter() - .zip(self.stack_slots_input.iter().copied()) + .zip(self.stack_slots_clobber.iter().copied()) .filter_map(|(r, s)| r.zip(s)) { - Self::restore_register(&mut generated_asm, self.arch, reg, slot); + Self::save_register(&mut generated_asm, self.arch, reg, slot); } } + // Write input registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_input.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::restore_register(&mut generated_asm, self.arch, reg, slot); + } + if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) { generated_asm.push_str(".att_syntax\n"); } @@ -701,32 +586,30 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { generated_asm.push_str(".intel_syntax noprefix\n"); } - if !self.is_naked { - if !self.options.contains(InlineAsmOptions::NORETURN) { - // Read output registers - for (reg, slot) in self - .registers - .iter() - .zip(self.stack_slots_output.iter().copied()) - .filter_map(|(r, s)| r.zip(s)) - { - Self::save_register(&mut generated_asm, self.arch, reg, slot); - } - - // Restore clobbered registers - for (reg, slot) in self - .registers - .iter() - .zip(self.stack_slots_clobber.iter().copied()) - .filter_map(|(r, s)| r.zip(s)) - { - Self::restore_register(&mut generated_asm, self.arch, reg, slot); - } - - Self::epilogue(&mut generated_asm, self.arch); - } else { - Self::epilogue_noreturn(&mut generated_asm, self.arch); + if !self.options.contains(InlineAsmOptions::NORETURN) { + // Read output registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_output.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::save_register(&mut generated_asm, self.arch, reg, slot); } + + // Restore clobbered registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_clobber.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::restore_register(&mut generated_asm, self.arch, reg, slot); + } + + Self::epilogue(&mut generated_asm, self.arch); + } else { + Self::epilogue_noreturn(&mut generated_asm, self.arch); } if is_x86 { From b3b1eddc5b46da5482e5adb882791f239caffc5e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:01:09 +0000 Subject: [PATCH 026/139] Share part of the global_asm!() implementation between cg_ssa and cg_clif --- src/driver/aot.rs | 5 +++- src/global_asm.rs | 68 ----------------------------------------------- 2 files changed, 4 insertions(+), 69 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 1cb8f8bc4399..5d07c94859f3 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -570,7 +570,10 @@ fn codegen_cgu_content( } } MonoItem::GlobalAsm(item_id) => { - crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id); + rustc_codegen_ssa::base::codegen_global_asm( + &mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm }, + item_id, + ); } } } diff --git a/src/global_asm.rs b/src/global_asm.rs index 18944a3be276..eef5288027c3 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -8,8 +8,6 @@ use std::sync::Arc; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::traits::{AsmCodegenMethods, GlobalAsmOperandRef}; -use rustc_hir::{InlineAsmOperand, ItemId}; -use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, @@ -84,72 +82,6 @@ impl<'tcx> HasTypingEnv<'tcx> for GlobalAsmContext<'_, 'tcx> { } } -pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { - let item = tcx.hir_item(item_id); - let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind else { - bug!("Expected GlobalAsm found {:?}", item); - }; - - // Adapted from rustc_codegen_ssa::mono_items::MonoItem::define - let operands: Vec<_> = asm - .operands - .iter() - .map(|(op, op_sp)| match *op { - InlineAsmOperand::Const { ref anon_const } => { - match tcx.const_eval_poly(anon_const.def_id.to_def_id()) { - Ok(const_value) => { - let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); - let string = rustc_codegen_ssa::common::asm_const_to_str( - tcx, - *op_sp, - const_value, - FullyMonomorphizedLayoutCx(tcx).layout_of(ty), - ); - GlobalAsmOperandRef::Const { string } - } - Err(ErrorHandled::Reported { .. }) => { - // An error has already been reported and - // compilation is guaranteed to fail if execution - // hits this path. So an empty string instead of - // a stringified constant value will suffice. - GlobalAsmOperandRef::Const { string: String::new() } - } - Err(ErrorHandled::TooGeneric(_)) => { - span_bug!(*op_sp, "asm const cannot be resolved; too generic") - } - } - } - InlineAsmOperand::SymFn { expr } => { - if cfg!(not(feature = "inline_asm_sym")) { - tcx.dcx().span_err( - item.span, - "asm! and global_asm! sym operands are not yet supported", - ); - } - - let ty = tcx.typeck(item_id.owner_id).expr_ty(expr); - let instance = match ty.kind() { - &ty::FnDef(def_id, args) => Instance::new(def_id, args), - _ => span_bug!(*op_sp, "asm sym is not a function"), - }; - GlobalAsmOperandRef::SymFn { instance } - } - InlineAsmOperand::SymStatic { path: _, def_id } => { - GlobalAsmOperandRef::SymStatic { def_id } - } - InlineAsmOperand::In { .. } - | InlineAsmOperand::Out { .. } - | InlineAsmOperand::InOut { .. } - | InlineAsmOperand::SplitInOut { .. } - | InlineAsmOperand::Label { .. } => { - span_bug!(*op_sp, "invalid operand type for global_asm!") - } - }) - .collect(); - - codegen_global_asm_inner(tcx, global_asm, asm.template, &operands, asm.options); -} - fn codegen_global_asm_inner<'tcx>( tcx: TyCtxt<'tcx>, global_asm: &mut String, From c8c87421a5ef753edc27066a571fd0afcc066a6d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:42:32 +0000 Subject: [PATCH 027/139] Nicer formatting for verifier errors during define_function --- src/base.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/base.rs b/src/base.rs index 9d425a3b292a..6b850a9a6e69 100644 --- a/src/base.rs +++ b/src/base.rs @@ -228,6 +228,18 @@ pub(crate) fn compile_fn( name = codegened_func.symbol_name )); } + Err(ModuleError::Compilation(CodegenError::Verifier(err))) => { + let early_dcx = rustc_session::EarlyDiagCtxt::new( + rustc_session::config::ErrorOutputType::default(), + ); + let _ = early_dcx.early_err(format!("{:?}", err)); + let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error( + &context.func, + Some(Box::new(&clif_comments)), + err, + ); + early_dcx.early_fatal(format!("cranelift verify error:\n{}", pretty_error)); + } Err(err) => { panic!("Error while defining {name}: {err:?}", name = codegened_func.symbol_name); } From 49bfa1aaf5f7e68079e6ed9b0d23dacebf38bac9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 18 Apr 2025 10:30:37 +0000 Subject: [PATCH 028/139] Fix simd_insert_dyn and simd_extract_dyn intrinsics with non-pointer sized indices --- src/value_and_place.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 9fd71cd6f77f..4874a4ad9e0d 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -309,6 +309,7 @@ impl<'tcx> CValue<'tcx> { match self.0 { CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => unreachable!(), CValueInner::ByRef(ptr, None) => { + let lane_idx = clif_intcast(fx, lane_idx, fx.pointer_type, false); let field_offset = fx.bcx.ins().imul_imm(lane_idx, lane_layout.size.bytes() as i64); let field_ptr = ptr.offset_value(fx, field_offset); CValue::by_ref(field_ptr, lane_layout) @@ -823,6 +824,7 @@ impl<'tcx> CPlace<'tcx> { CPlaceInner::Var(_, _) => unreachable!(), CPlaceInner::VarPair(_, _, _) => unreachable!(), CPlaceInner::Addr(ptr, None) => { + let lane_idx = clif_intcast(fx, lane_idx, fx.pointer_type, false); let field_offset = fx .bcx .ins() From 59c5ed0ba84d9007d8957dc1056f46bed381c100 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 29 Mar 2025 17:30:11 +0100 Subject: [PATCH 029/139] Make `#[naked]` an unsafe attribute --- example/mini_core_hello_world.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 09d5b73fd3d9..0b3a7281d5a0 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -387,11 +387,9 @@ global_asm! { } #[cfg(all(not(jit), target_arch = "x86_64"))] -#[naked] +#[unsafe(naked)] extern "C" fn naked_test() { - unsafe { - naked_asm!("ret"); - } + naked_asm!("ret") } #[repr(C)] From 88ddf9e203291d085c9fa8bf8b3c574e7f41e174 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 18 Dec 2024 22:05:27 +0100 Subject: [PATCH 030/139] stabilize `naked_functions` --- example/mini_core_hello_world.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 0b3a7281d5a0..93ca2e0e4218 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -1,13 +1,4 @@ -#![feature( - no_core, - lang_items, - never_type, - linkage, - extern_types, - naked_functions, - thread_local, - repr_simd -)] +#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local, repr_simd)] #![no_core] #![allow(dead_code, non_camel_case_types, internal_features)] From d50c76974f7ff75afe4c4a84cee2934c3074b61a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Apr 2025 10:59:49 +0200 Subject: [PATCH 031/139] make abi_unsupported_vector_types a hard error --- example/std_example.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/example/std_example.rs b/example/std_example.rs index ffdc6a7d4849..2d9de2a5b8d6 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -8,9 +8,6 @@ unboxed_closures )] #![allow(internal_features)] -// FIXME once abi_unsupported_vector_types is a hard error disable the foo test when the respective -// target feature is not enabled. -#![allow(abi_unsupported_vector_types)] #[cfg(target_arch = "x86_64")] use std::arch::x86_64::*; From 4cfecfdfa6a432d72f5ee03c5a0904b5fbcca0a3 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 21 Apr 2025 10:37:10 +0000 Subject: [PATCH 032/139] Rustup to rustc 1.88.0-nightly (b8c54d635 2025-04-20) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 1789b62917de..93dfecedb6d6 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-04-14" +channel = "nightly-2025-04-21" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 91114bd289cf92c7b62b1d2d53f2467024d9cf07 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 21 Apr 2025 10:48:40 +0000 Subject: [PATCH 033/139] Fix rustc test suite --- scripts/test_rustc_tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 01c8b474a9d1..575467185c8b 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -96,6 +96,7 @@ rm -r tests/run-make/llvm-location-discriminator-limit-dummy-span # same rm tests/ui/abi/stack-protector.rs # requires stack protector support rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific +rm -r tests/ui/optimization-remark.rs # same rm -r tests/run-make/print-to-output # requires --print relocation-models # requires asm, llvm-ir and/or llvm-bc emit support @@ -129,6 +130,7 @@ rm -r tests/run-make/compiler-builtins # Expects lib/rustlib/src/rust to contain rm -r tests/run-make/translation # same rm -r tests/run-make/missing-unstable-trait-bound # This disables support for unstable features, but running cg_clif needs some unstable features rm -r tests/run-make/const-trait-stable-toolchain # same +rm -r tests/run-make/print-request-help-stable-unstable # same rm -r tests/run-make/incr-add-rust-src-component rm tests/ui/errors/remap-path-prefix-sysroot.rs # different sysroot source path From de372d3fff28d21e48e91b0ec7203d25158ff7fa Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 7 Apr 2025 19:59:49 +0000 Subject: [PATCH 034/139] Update to Cranelift 0.119 --- Cargo.lock | 80 +++++++++++++++++++++++++------------------- Cargo.toml | 24 ++++++------- src/unwind_module.rs | 9 +++-- 3 files changed, 61 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e5f1896b9230..066d5a61adde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,39 +43,42 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-assembler-x64" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4b56ebe316895d3fa37775d0a87b0c889cc933f5c8b253dbcc7c7bcb7fe7e4" +checksum = "263cc79b8a23c29720eb596d251698f604546b48c34d0d84f8fd2761e5bf8888" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95cabbc01dfbd7dcd6c329ca44f0212910309c221797ac736a67a5bc8857fe1b" +checksum = "5b4a113455f8c0e13e3b3222a9c38d6940b958ff22573108be083495c72820e1" +dependencies = [ + "cranelift-srcgen", +] [[package]] name = "cranelift-bforest" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ffe46df300a45f1dc6f609dc808ce963f0e3a2e971682c479a2d13e3b9b8ef" +checksum = "58f96dca41c5acf5d4312c1d04b3391e21a312f8d64ce31a2723a3bb8edd5d4d" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b265bed7c51e1921fdae6419791d31af77d33662ee56d7b0fa0704dc8d231cab" +checksum = "7d821ed698dd83d9c012447eb63a5406c1e9c23732a2f674fb5b5015afd42202" [[package]] name = "cranelift-codegen" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e606230a7e3a6897d603761baee0d19f88d077f17b996bb5089488a29ae96e41" +checksum = "06c52fdec4322cb8d5545a648047819aaeaa04e630f88d3a609c0d3c1a00e9a0" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -98,43 +101,44 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a63bffafc23bc60969ad528e138788495999d935f0adcfd6543cb151ca8637d" +checksum = "af2c215e0c9afa8069aafb71d22aa0e0dde1048d9a5c3c72a83cacf9b61fcf4a" dependencies = [ - "cranelift-assembler-x64", + "cranelift-assembler-x64-meta", "cranelift-codegen-shared", + "cranelift-srcgen", ] [[package]] name = "cranelift-codegen-shared" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af50281b67324b58e843170a6a5943cf6d387c06f7eeacc9f5696e4ab7ae7d7e" +checksum = "97524b2446fc26a78142132d813679dda19f620048ebc9a9fbb0ac9f2d320dcb" [[package]] name = "cranelift-control" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c20c1b38d1abfbcebb0032e497e71156c0e3b8dcb3f0a92b9863b7bcaec290c" +checksum = "8e32e900aee81f9e3cc493405ef667a7812cb5c79b5fc6b669e0a2795bda4b22" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2c67d95507c51b4a1ff3f3555fe4bfec36b9e13c1b684ccc602736f5d5f4a2" +checksum = "d16a2e28e0fa6b9108d76879d60fe1cc95ba90e1bcf52bac96496371044484ee" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e002691cc69c38b54fc7ec93e5be5b744f627d027031d991cc845d1d512d0ce" +checksum = "328181a9083d99762d85954a16065d2560394a862b8dc10239f39668df528b95" dependencies = [ "cranelift-codegen", "log", @@ -144,15 +148,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93588ed1796cbcb0e2ad160403509e2c5d330d80dd6e0014ac6774c7ebac496" +checksum = "e916f36f183e377e9a3ed71769f2721df88b72648831e95bb9fa6b0cd9b1c709" [[package]] name = "cranelift-jit" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6682f0b193d6b7873cc8e7ed67e8776a8a26f50eeabf88534e9be618b9a03" +checksum = "d6bb584ac927f1076d552504b0075b833b9d61e2e9178ba55df6b2d966b4375d" dependencies = [ "anyhow", "cranelift-codegen", @@ -170,9 +174,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff19784c6de05116e63e6a34791012bd927b2a4eac56233039c46f1b6a4edac8" +checksum = "40c18ccb8e4861cf49cec79998af73b772a2b47212d12d3d63bf57cc4293a1e3" dependencies = [ "anyhow", "cranelift-codegen", @@ -181,9 +185,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5b09bdd6407bf5d89661b80cf926ce731c9e8cc184bf49102267a2369a8358e" +checksum = "fc852cf04128877047dc2027aa1b85c64f681dc3a6a37ff45dcbfa26e4d52d2f" dependencies = [ "cranelift-codegen", "libc", @@ -192,9 +196,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.118.0" +version = "0.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685e8661a30d1cb69509f589ac643adeee79c5f63c0da316431b9fad29e6d3b4" +checksum = "14f6ad789197bda49f7c98280ee8d7ccd63a5a1cc67283f87798a2d61e089ce4" dependencies = [ "anyhow", "cranelift-codegen", @@ -205,6 +209,12 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cranelift-srcgen" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1a86340a16e74b4285cc86ac69458fa1c8e7aaff313da4a89d10efd3535ee" + [[package]] name = "crc32fast" version = "1.4.2" @@ -331,9 +341,9 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145c1c267e14f20fb0f88aa76a1c5ffec42d592c1d28b3cd9148ae35916158d3" +checksum = "6d4c3c15aa088eccea44550bffea9e9a5d0b14a264635323d23c6e6351acca98" dependencies = [ "allocator-api2", "bumpalo", @@ -436,9 +446,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "wasmtime-jit-icache-coherence" -version = "31.0.0" +version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a54f6c6c7e9d7eeee32dfcc10db7f29d505ee7dd28d00593ea241d5f70698e64" +checksum = "eb399eaabd7594f695e1159d236bf40ef55babcb3af97f97c027864ed2104db6" dependencies = [ "anyhow", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 08b60de14c1f..82fde4b838e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.118.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.118.0" } -cranelift-module = { version = "0.118.0" } -cranelift-native = { version = "0.118.0" } -cranelift-jit = { version = "0.118.0", optional = true } -cranelift-object = { version = "0.118.0" } +cranelift-codegen = { version = "0.119.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.119.0" } +cranelift-module = { version = "0.119.0" } +cranelift-native = { version = "0.119.0" } +cranelift-jit = { version = "0.119.0", optional = true } +cranelift-object = { version = "0.119.0" } target-lexicon = "0.13" gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/src/unwind_module.rs b/src/unwind_module.rs index f963dc79fbb5..0864bd8d84f6 100644 --- a/src/unwind_module.rs +++ b/src/unwind_module.rs @@ -1,10 +1,10 @@ +use cranelift_codegen::Context; use cranelift_codegen::control::ControlPlane; -use cranelift_codegen::ir::{Function, Signature}; +use cranelift_codegen::ir::Signature; use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa}; -use cranelift_codegen::{Context, FinalizedMachReloc}; use cranelift_module::{ DataDescription, DataId, FuncId, FuncOrDataId, Linkage, Module, ModuleDeclarations, - ModuleResult, + ModuleReloc, ModuleResult, }; use cranelift_object::{ObjectModule, ObjectProduct}; @@ -101,10 +101,9 @@ impl Module for UnwindModule { fn define_function_bytes( &mut self, _func_id: FuncId, - _func: &Function, _alignment: u64, _bytes: &[u8], - _relocs: &[FinalizedMachReloc], + _relocs: &[ModuleReloc], ) -> ModuleResult<()> { unimplemented!() } From 0103c583fa01dd21d49fa9d5b2009e4c217659e2 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 21 Apr 2025 22:19:19 +0200 Subject: [PATCH 035/139] support `-Zmin-function-alignment` (#1572) --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index b86a549f57b9..6292606aef2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -280,6 +280,12 @@ fn build_isa(sess: &Session, jit: bool) -> Arc { flags_builder.set("enable_llvm_abi_extensions", "true").unwrap(); + if let Some(align) = sess.opts.unstable_opts.min_function_alignment { + flags_builder + .set("log2_min_function_alignment", &align.bytes().ilog2().to_string()) + .unwrap(); + } + use rustc_session::config::OptLevel; match sess.opts.optimize { OptLevel::No => { From 00417de6b8b07af4d4355f69fef5fb7c5e11d893 Mon Sep 17 00:00:00 2001 From: bendn Date: Mon, 31 Mar 2025 15:50:56 +0700 Subject: [PATCH 036/139] Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc --- example/example.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/example.rs b/example/example.rs index 1ef2aa5dd8ea..aeb38331edb0 100644 --- a/example/example.rs +++ b/example/example.rs @@ -1,6 +1,6 @@ #![feature(no_core, unboxed_closures)] #![no_core] -#![allow(dead_code)] +#![allow(dead_code, unnecessary_transmutes)] extern crate mini_core; From eef57cb4e290ea44bae26a1320c37c76b13275b6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 24 Apr 2025 13:02:28 +0000 Subject: [PATCH 037/139] Pass Option to codegen_unwind_terminate In preparation for unwinding support. --- src/base.rs | 14 +++----------- src/compiler_builtins.rs | 1 - 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/base.rs b/src/base.rs index 6b850a9a6e69..7c02b3f48f9d 100644 --- a/src/base.rs +++ b/src/base.rs @@ -566,7 +566,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { ); } TerminatorKind::UnwindTerminate(reason) => { - codegen_unwind_terminate(fx, source_info, *reason); + codegen_unwind_terminate(fx, Some(source_info.span), *reason); } TerminatorKind::UnwindResume => { // FIXME implement unwinding @@ -1117,18 +1117,10 @@ pub(crate) fn codegen_panic_nounwind<'tcx>( pub(crate) fn codegen_unwind_terminate<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - source_info: mir::SourceInfo, + span: Option, reason: UnwindTerminateReason, ) { - let args = []; - - codegen_panic_inner( - fx, - reason.lang_item(), - &args, - UnwindAction::Terminate(UnwindTerminateReason::Abi), - Some(source_info.span), - ); + codegen_panic_inner(fx, reason.lang_item(), &[], UnwindAction::Unreachable, span); } fn codegen_panic_inner<'tcx>( diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index bf16e81a06f9..5b6d0ef6ddf7 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -67,5 +67,4 @@ builtin_functions! { fn malloc(size: size_t) -> *mut c_void; fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; fn free(p: *mut c_void) -> (); - } From 349430c08ecc4c98325f8231d3fafee69cc3ba29 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 24 Apr 2025 13:08:32 +0000 Subject: [PATCH 038/139] Avoid creating a second UnwindContext in finalize_definitions Once UnwindContext sets the personality function it will need to define a DW.ref.rust_eh_personality function which would cause a duplicate definition if UnwindContext is called a second time. --- src/driver/jit.rs | 4 ++-- src/unwind_module.rs | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 0e2e1f6fc0a8..6315935a221d 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -84,7 +84,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec) -> ! { tcx.dcx().abort_if_errors(); - jit_module.finalize_definitions(); + let mut jit_module = jit_module.finalize_definitions(); println!( "Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed" @@ -104,7 +104,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec) -> ! { call_conv: jit_module.target_config().default_call_conv, }; let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap(); - let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id); + let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id); let f: extern "C" fn(c_int, *const *const c_char) -> c_int = unsafe { ::std::mem::transmute(finalized_start) }; diff --git a/src/unwind_module.rs b/src/unwind_module.rs index 0864bd8d84f6..b4eb939cf256 100644 --- a/src/unwind_module.rs +++ b/src/unwind_module.rs @@ -33,13 +33,10 @@ impl UnwindModule { #[cfg(feature = "jit")] impl UnwindModule { - pub(crate) fn finalize_definitions(&mut self) { + pub(crate) fn finalize_definitions(mut self) -> cranelift_jit::JITModule { self.module.finalize_definitions().unwrap(); - let prev_unwind_context = std::mem::replace( - &mut self.unwind_context, - UnwindContext::new(&mut self.module, false), - ); - unsafe { prev_unwind_context.register_jit(&self.module) }; + unsafe { self.unwind_context.register_jit(&self.module) }; + self.module } } From b59f697ee989325f16a7c37658780d18d80b1a6d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 24 Apr 2025 13:16:21 +0000 Subject: [PATCH 039/139] Relocation improvements for .eh_frame This is necessary to handle LSDA references in the future once unwinding is supported. --- src/debuginfo/emit.rs | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs index ccdc347af660..0f4696b9337e 100644 --- a/src/debuginfo/emit.rs +++ b/src/debuginfo/emit.rs @@ -81,13 +81,36 @@ impl WriterRelocate { /// Perform the collected relocations to be usable for JIT usage. #[cfg(all(feature = "jit", not(windows)))] pub(super) fn relocate_for_jit(mut self, jit_module: &cranelift_jit::JITModule) -> Vec { + use cranelift_module::Module; + for reloc in self.relocs.drain(..) { match reloc.name { super::DebugRelocName::Section(_) => unreachable!(), super::DebugRelocName::Symbol(sym) => { - let addr = jit_module.get_finalized_function( - cranelift_module::FuncId::from_u32(sym.try_into().unwrap()), - ); + let addr = if sym & 1 << 31 == 0 { + let func_id = FuncId::from_u32(sym.try_into().unwrap()); + // FIXME make JITModule::get_address public and use it here instead. + // HACK rust_eh_personality is likely not defined in the same crate, + // so get_finalized_function won't work. Use the rust_eh_personality + // of cg_clif itself, which is likely ABI compatible. + if jit_module.declarations().get_function_decl(func_id).name.as_deref() + == Some("rust_eh_personality") + { + extern "C" { + fn rust_eh_personality() -> !; + } + rust_eh_personality as *const u8 + } else { + jit_module.get_finalized_function(func_id) + } + } else { + jit_module + .get_finalized_data(DataId::from_u32( + u32::try_from(sym).unwrap() & !(1 << 31), + )) + .0 + }; + let val = (addr as u64 as i64 + reloc.addend) as u64; self.writer.write_udata_at(reloc.offset as usize, val, reloc.size).unwrap(); } @@ -196,6 +219,16 @@ impl Writer for WriterRelocate { }); self.write_udata(0, size) } + gimli::DW_EH_PE_absptr => { + self.relocs.push(DebugReloc { + offset: self.len() as u32, + size: size.into(), + name: DebugRelocName::Symbol(symbol), + addend, + kind: object::RelocationKind::Absolute, + }); + self.write_udata(0, size.into()) + } _ => Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)), }, } From 6e2490ca9f476d8da0fe519caa8db688a3d3a78f Mon Sep 17 00:00:00 2001 From: Urgau <3616612+Urgau@users.noreply.github.com> Date: Sun, 27 Apr 2025 20:14:46 +0200 Subject: [PATCH 040/139] Merge pull request #1576 from Urgau/triagebot-issue-links-no-mentions Enable `[no-mentions]` and `[issue-links]` in `rustbot` --- triagebot.toml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 triagebot.toml diff --git a/triagebot.toml b/triagebot.toml new file mode 100644 index 000000000000..13da0a87def3 --- /dev/null +++ b/triagebot.toml @@ -0,0 +1,7 @@ +# Documentation at https://forge.rust-lang.org/triagebot/index.html + +# Prevents un-canonicalized issue links (to avoid wrong issues being linked in r-l/rust) +[issue-links] + +# Prevents mentions in commits to avoid users being spammed +[no-mentions] From daaae11f4dd49285ee5cebf8f02586606401c22a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 24 Apr 2025 22:11:23 +0000 Subject: [PATCH 041/139] Implement the internal feature `cfg_target_has_reliable_f16_f128` Support for `f16` and `f128` is varied across targets, backends, and backend versions. Eventually we would like to reach a point where all backends support these approximately equally, but until then we have to work around some of these nuances of support being observable. Introduce the `cfg_target_has_reliable_f16_f128` internal feature, which provides the following new configuration gates: * `cfg(target_has_reliable_f16)` * `cfg(target_has_reliable_f16_math)` * `cfg(target_has_reliable_f128)` * `cfg(target_has_reliable_f128_math)` `reliable_f16` and `reliable_f128` indicate that basic arithmetic for the type works correctly. The `_math` versions indicate that anything relying on `libm` works correctly, since sometimes this hits a separate class of codegen bugs. These options match configuration set by the build script at [1]. The logic for LLVM support is duplicated as-is from the same script. There are a few possible updates that will come as a follow up. The config introduced here is not planned to ever become stable, it is only intended to replace the build scripts for `std` tests and `compiler-builtins` that don't have any way to configure based on the codegen backend. MCP: https://github.com/rust-lang/compiler-team/issues/866 Closes: https://github.com/rust-lang/compiler-team/issues/866 [1]: https://github.com/rust-lang/rust/blob/555e1d0386f024a8359645c3217f4b3eae9be042/library/std/build.rs#L84-L186 --- src/lib.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9d9e790289cf..ab09a6f8b38e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,8 +41,8 @@ use std::sync::Arc; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; -use rustc_codegen_ssa::CodegenResults; use rustc_codegen_ssa::traits::CodegenBackend; +use rustc_codegen_ssa::{CodegenResults, TargetConfig}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::Session; @@ -178,7 +178,7 @@ impl CodegenBackend for CraneliftCodegenBackend { } } - fn target_features_cfg(&self, sess: &Session) -> (Vec, Vec) { + fn target_config(&self, sess: &Session) -> TargetConfig { // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" { // x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled @@ -197,7 +197,16 @@ impl CodegenBackend for CraneliftCodegenBackend { }; // FIXME do `unstable_target_features` properly let unstable_target_features = target_features.clone(); - (target_features, unstable_target_features) + + TargetConfig { + target_features, + unstable_target_features, + // Cranelift does not yet support f16 or f128 + has_reliable_f16: false, + has_reliable_f16_math: false, + has_reliable_f128: false, + has_reliable_f128_math: false, + } } fn print_version(&self) { From c179f96fa923514906361af40a956a5284685822 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Mon, 26 Aug 2024 16:45:15 +0300 Subject: [PATCH 042/139] AsyncDrop implementation using shim codegen of async_drop_in_place::{closure}, scoped async drop added. --- src/abi/mod.rs | 9 +++++---- src/base.rs | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index ddd119e0c610..5f631405a9a4 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -441,7 +441,9 @@ pub(crate) fn codegen_terminator_call<'tcx>( Err(instance) => Some(instance), } } - InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) => { + // We don't need AsyncDropGlueCtorShim here because it is not `noop func`, + // it is `func returning noop future` + InstanceKind::DropGlue(_, None) => { // empty drop glue - a nop. let dest = target.expect("Non terminating drop_in_place_real???"); let ret_block = fx.get_block(dest); @@ -707,9 +709,8 @@ pub(crate) fn codegen_drop<'tcx>( let ty = drop_place.layout().ty; let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty); - if let ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) = - drop_instance.def - { + // AsyncDropGlueCtorShim can't be here + if let ty::InstanceKind::DropGlue(_, None) = drop_instance.def { // we don't actually need to drop anything } else { match ty.kind() { diff --git a/src/base.rs b/src/base.rs index adaa754491e5..e9c7186b03c9 100644 --- a/src/base.rs +++ b/src/base.rs @@ -565,7 +565,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { | TerminatorKind::CoroutineDrop => { bug!("shouldn't exist at codegen {:?}", bb_data.terminator()); } - TerminatorKind::Drop { place, target, unwind: _, replace: _ } => { + TerminatorKind::Drop { place, target, unwind: _, replace: _, drop, async_fut } => { + assert!( + async_fut.is_none() && drop.is_none(), + "Async Drop must be expanded or reset to sync before codegen" + ); let drop_place = codegen_place(fx, *place); crate::abi::codegen_drop(fx, source_info, drop_place, *target); } From fcf198b5391129ca7ff2b8f39bbf51a4ba2416e7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 28 Apr 2025 15:25:21 +0000 Subject: [PATCH 043/139] Rustup to rustc 1.88.0-nightly (cb31a009e 2025-04-27) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 93dfecedb6d6..acc8cf728d39 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-04-21" +channel = "nightly-2025-04-28" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 17403cd406057139cd12bd7d19b81bbd75a6c41b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 28 Apr 2025 15:15:40 +0000 Subject: [PATCH 044/139] Fix rustc test suite --- scripts/test_rustc_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 575467185c8b..f449f4b323cb 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -83,6 +83,7 @@ rm tests/ui/codegen/issue-28950.rs # depends on stack size optimizations rm tests/ui/codegen/init-large-type.rs # same rm -r tests/run-make/fmt-write-bloat/ # tests an optimization rm tests/ui/statics/const_generics.rs # same +rm tests/ui/linking/executable-no-mangle-strip.rs # requires --gc-sections to work for statics # backend specific tests # ====================== @@ -119,7 +120,6 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same rm tests/ui/consts/issue-33537.rs # same rm tests/ui/consts/const-mut-refs-crate.rs # same rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift -rm tests/ui/abi/simd-abi-checks-avx.rs # attempts to declare function with two different signatures # doesn't work due to the way the rustc test suite is invoked. # should work when using ./x.py test the way it is intended From 7a8d368ac9c858bf81f855e82886f92eb55fa55c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 29 Apr 2025 07:48:13 +0000 Subject: [PATCH 045/139] Fix std_example.rs on s390x --- example/std_example.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/std_example.rs b/example/std_example.rs index 2d9de2a5b8d6..5d83066cffb8 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -166,6 +166,7 @@ fn main() { enum Never {} } + #[cfg(not(target_arch = "s390x"))] // s390x doesn't have vector instructions enabled by default foo(I64X2([0, 0])); transmute_wide_pointer(); @@ -203,9 +204,11 @@ fn rust_call_abi() { rust_call_abi_callee((1, 2)); } +#[cfg_attr(target_arch = "s390x", allow(dead_code))] #[repr(simd)] struct I64X2([i64; 2]); +#[cfg_attr(target_arch = "s390x", allow(dead_code))] #[allow(improper_ctypes_definitions)] extern "C" fn foo(_a: I64X2) {} From bfabf71781ab40ed81a42cb26c6e983ecbe25604 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 30 Apr 2025 12:59:50 +0000 Subject: [PATCH 046/139] Fix naked asm symbol name for cg_clif on macOS --- src/global_asm.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index eef5288027c3..203b443269fa 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -34,7 +34,8 @@ impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> { } fn mangled_name(&self, instance: Instance<'tcx>) -> String { - self.tcx.symbol_name(instance).name.to_owned() + let symbol_name = self.tcx.symbol_name(instance).name.to_owned(); + if self.tcx.sess.target.is_like_darwin { format!("_{symbol_name}") } else { symbol_name } } } From e17184bf9f2d40e12c5a5a134904ab2900342bd4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 30 Apr 2025 13:21:43 +0000 Subject: [PATCH 047/139] Rustup to rustc 1.88.0-nightly (74509131e 2025-04-29) --- patches/0027-stdlib-128bit-atomic-operations.patch | 9 +++++++++ rust-toolchain | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/patches/0027-stdlib-128bit-atomic-operations.patch b/patches/0027-stdlib-128bit-atomic-operations.patch index d7e3b11127c4..38bb43f8204b 100644 --- a/patches/0027-stdlib-128bit-atomic-operations.patch +++ b/patches/0027-stdlib-128bit-atomic-operations.patch @@ -37,6 +37,15 @@ diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index bf2b6d59f88..d5ccce03bbf 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs +@@ -300,8 +300,6 @@ impl_atomic_primitive!(AtomicI32(i32), size("32"), align(4)); + impl_atomic_primitive!(AtomicU32(u32), size("32"), align(4)); + impl_atomic_primitive!(AtomicI64(i64), size("64"), align(8)); + impl_atomic_primitive!(AtomicU64(u64), size("64"), align(8)); +-impl_atomic_primitive!(AtomicI128(i128), size("128"), align(16)); +-impl_atomic_primitive!(AtomicU128(u128), size("128"), align(16)); + + #[cfg(target_pointer_width = "16")] + impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(2)); @@ -3585,44 +3585,6 @@ pub const fn as_ptr(&self) -> *mut $int_type { 8, u64 AtomicU64 diff --git a/rust-toolchain b/rust-toolchain index acc8cf728d39..d0a4304f5721 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-04-28" +channel = "nightly-2025-04-30" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 66d2f6bb0507bbbe70232fe5ccec52b7a1ea51c4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 30 Apr 2025 14:48:45 +0000 Subject: [PATCH 048/139] Fix rustc test suite --- scripts/test_rustc_tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index f449f4b323cb..c59e34094dc8 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -76,6 +76,7 @@ rm tests/ui/asm/aarch64/type-f16.rs rm tests/ui/float/conv-bits-runtime-const.rs rm tests/ui/consts/const-eval/float_methods.rs rm tests/ui/match/match-float.rs +rm tests/ui/float/target-has-reliable-nightly-float.rs # optimization tests # ================== @@ -144,6 +145,7 @@ rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue rm tests/ui/backtrace/synchronized-panic-handler.rs # missing needs-unwind annotation rm tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs # same +rm tests/ui/async-await/async-drop/async-drop-initial.rs # same (rust-lang/rust#140493) rm -r tests/ui/codegen/equal-pointers-unequal # make incorrect assumptions about the location of stack variables rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd From a308984e69e65bcfe76558516686f41bd598e175 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 1 May 2025 09:26:49 +0000 Subject: [PATCH 049/139] Rustup to rustc 1.88.0-nightly (b45dd71d1 2025-04-30) --- rust-toolchain | 2 +- src/driver/jit.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index d0a4304f5721..55b557c0ada9 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-04-30" +channel = "nightly-2025-05-01" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 403e5403ccc6..b1f185b551c3 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -6,6 +6,7 @@ use std::os::raw::{c_char, c_int}; use cranelift_jit::{JITBuilder, JITModule}; use rustc_codegen_ssa::CrateInfo; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::MonoItem; use rustc_session::Session; use rustc_span::sym; From 5930cd904e2a88dac413f69536d95110ee1e26bb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 28 Apr 2025 14:40:16 +0000 Subject: [PATCH 050/139] Rename Instance::new to Instance::new_raw and add a note that it is raw --- src/intrinsics/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index d3f47ad72633..e866b8962551 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1282,7 +1282,7 @@ fn codegen_regular_intrinsic_call<'tcx>( intrinsic.name, ); } - return Err(Instance::new(instance.def_id(), instance.args)); + return Err(Instance::new_raw(instance.def_id(), instance.args)); } } From dfe76361d1cc99b8ce2ee466069b1d1f824dbaa0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 5 May 2025 13:53:58 +0000 Subject: [PATCH 051/139] Rustup to rustc 1.88.0-nightly (13e879094 2025-05-04) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 55b557c0ada9..4ca593e6bea5 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-05-01" +channel = "nightly-2025-05-05" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From fe059c1c548752c9022471e68b6d583a8347d085 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 2 May 2025 20:18:04 +0000 Subject: [PATCH 052/139] Clif ir comment improvements --- src/abi/mod.rs | 5 ++--- src/base.rs | 6 +----- src/value_and_place.rs | 8 ++------ 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 39d04c2f2d78..57ac2d18d494 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -187,11 +187,10 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); if self.clif_comments.enabled() { self.add_comment(func_ref, format!("{:?}", name)); + let inst = self.bcx.func.layout.last_inst(self.bcx.current_block().unwrap()).unwrap(); + self.add_comment(inst, format!("lib_call {}", name)); } let call_inst = self.bcx.ins().call(func_ref, args); - if self.clif_comments.enabled() { - self.add_comment(call_inst, format!("lib_call {}", name)); - } let results = self.bcx.inst_results(call_inst); assert!(results.len() <= 2, "{}", results.len()); results diff --git a/src/base.rs b/src/base.rs index b3a96aa909ac..f46535966f1c 100644 --- a/src/base.rs +++ b/src/base.rs @@ -559,11 +559,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } } -fn codegen_stmt<'tcx>( - fx: &mut FunctionCx<'_, '_, 'tcx>, - #[allow(unused_variables)] cur_block: Block, - stmt: &Statement<'tcx>, -) { +fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: &Statement<'tcx>) { let _print_guard = crate::PrintOnPanic(|| format!("stmt {:?}", stmt)); fx.set_debug_loc(stmt.source_info); diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 4874a4ad9e0d..1168701f1032 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -592,13 +592,9 @@ impl<'tcx> CPlace<'tcx> { assert_eq!(self.layout().size, from.layout().size); if fx.clif_comments.enabled() { - use cranelift_codegen::cursor::{Cursor, CursorPosition}; - let cur_block = match fx.bcx.cursor().position() { - CursorPosition::After(block) => block, - _ => unreachable!(), - }; + let inst = fx.bcx.func.layout.last_inst(fx.bcx.current_block().unwrap()).unwrap(); fx.add_comment( - fx.bcx.func.layout.last_inst(cur_block).unwrap(), + inst, format!( "{}: {:?}: {:?} <- {:?}: {:?}", method, From 9196eb3dd1506048dcbbfd8504e26ac2b130940b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 7 May 2025 13:05:47 +0000 Subject: [PATCH 053/139] Fix mini_core for panic=unwind --- example/mini_core.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 6e345b2a6fdf..832135568f37 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -521,10 +521,27 @@ fn panic_cannot_unwind() -> ! { } #[lang = "eh_personality"] -fn eh_personality() -> ! { +// FIXME personality signature depends on target +fn eh_personality( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { loop {} } +#[lang = "panic_in_cleanup"] +fn panic_in_cleanup() -> ! { + loop {} +} + +#[link(name = "gcc_s")] +extern "C" { + fn _Unwind_Resume(exc: *mut ()) -> !; +} + #[lang = "drop_in_place"] #[allow(unconditional_recursion)] pub unsafe fn drop_in_place(to_drop: *mut T) { From 2f8f4643900301caa2984fd97f6c20347ea9936e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 7 May 2025 14:08:11 +0000 Subject: [PATCH 054/139] Fix mini_core on Windows and macOS --- example/mini_core.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/example/mini_core.rs b/example/mini_core.rs index 832135568f37..1dc799c0aeea 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -537,6 +537,7 @@ fn panic_in_cleanup() -> ! { loop {} } +#[cfg(all(unix, not(target_vendor = "apple")))] #[link(name = "gcc_s")] extern "C" { fn _Unwind_Resume(exc: *mut ()) -> !; From e6d288ba17962c1f7e3ded3cb13e1ad596f9a813 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 8 May 2025 12:43:10 +0200 Subject: [PATCH 055/139] Use intrinsics for `{f16,f32,f64,f128}::{minimum,maximum}` operations --- src/intrinsics/mod.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index e866b8962551..9018d78b00ae 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1109,6 +1109,43 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } + sym::minimumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmin(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); + ret.write_cvalue(fx, val); + } + sym::minimumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmin(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); + ret.write_cvalue(fx, val); + } + sym::maximumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmax(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); + ret.write_cvalue(fx, val); + } + sym::maximumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmax(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); + ret.write_cvalue(fx, val); + } + sym::minnumf32 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); From bebcb9da216ab439a8628219f8021b1770134a35 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 12 May 2025 14:49:12 +0000 Subject: [PATCH 056/139] Add test for Ord impl for Option::NonZero --- tests/codegen/option-niche-eq.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/codegen/option-niche-eq.rs b/tests/codegen/option-niche-eq.rs index 9c5ed9ce57a5..2be9e2bc4892 100644 --- a/tests/codegen/option-niche-eq.rs +++ b/tests/codegen/option-niche-eq.rs @@ -24,6 +24,18 @@ pub fn non_zero_signed_eq(l: Option>, r: Option>) -> b l == r } +// Test for #49892 +// This currently relies on a manual implementation of `PartialOrd`/`Ord` for `Option` +// Once LLVM is better able to optimize this pattern, we can return to using a derive. +// CHECK-LABEL: @non_zero_ord +#[no_mangle] +pub fn non_zero_ord(a: Option>, b: Option>) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp ult i32 + // CHECK-NEXT: ret i1 + a < b +} + // CHECK-LABEL: @non_null_eq #[no_mangle] pub fn non_null_eq(l: Option>, r: Option>) -> bool { From 5eb47eeb851d4428642197cea3a566bcfa5f726a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 12 May 2025 15:09:32 +0000 Subject: [PATCH 057/139] Add failing tests for some Option optimizations --- tests/codegen/option-niche-eq.rs | 13 ++-------- .../option-niche-unfixed/option-bool-eq.rs | 15 ++++++++++++ .../option-niche-unfixed/option-nonzero-eq.rs | 24 +++++++++++++++++++ 3 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 tests/codegen/option-niche-unfixed/option-bool-eq.rs create mode 100644 tests/codegen/option-niche-unfixed/option-nonzero-eq.rs diff --git a/tests/codegen/option-niche-eq.rs b/tests/codegen/option-niche-eq.rs index 2be9e2bc4892..a39e2870a0f4 100644 --- a/tests/codegen/option-niche-eq.rs +++ b/tests/codegen/option-niche-eq.rs @@ -1,3 +1,4 @@ +//@ min-llvm-version: 20 //@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled #![crate_type = "lib"] @@ -24,7 +25,7 @@ pub fn non_zero_signed_eq(l: Option>, r: Option>) -> b l == r } -// Test for #49892 +// FIXME(#49892) // This currently relies on a manual implementation of `PartialOrd`/`Ord` for `Option` // Once LLVM is better able to optimize this pattern, we can return to using a derive. // CHECK-LABEL: @non_zero_ord @@ -73,13 +74,3 @@ pub fn niche_eq(l: Option, r: Option) -> bool { // CHECK-NEXT: ret i1 l == r } - -// FIXME: This should work too -// // FIXME-CHECK-LABEL: @bool_eq -// #[no_mangle] -// pub fn bool_eq(l: Option, r: Option) -> bool { -// // FIXME-CHECK: start: -// // FIXME-CHECK-NEXT: icmp eq i8 -// // FIXME-CHECK-NEXT: ret i1 -// l == r -// } diff --git a/tests/codegen/option-niche-unfixed/option-bool-eq.rs b/tests/codegen/option-niche-unfixed/option-bool-eq.rs new file mode 100644 index 000000000000..fa0e7836afb9 --- /dev/null +++ b/tests/codegen/option-niche-unfixed/option-bool-eq.rs @@ -0,0 +1,15 @@ +//@ should-fail +//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled +//! FIXME(#49892) +//! Tests that LLVM does not fully optimize comparisons of `Option`. +//! If this starts passing, it can be moved to `tests/codegen/option-niche-eq.rs` +#![crate_type = "lib"] + +// CHECK-LABEL: @bool_eq +#[no_mangle] +pub fn bool_eq(l: Option, r: Option) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp eq i8 + // CHECK-NEXT: ret i1 + l == r +} diff --git a/tests/codegen/option-niche-unfixed/option-nonzero-eq.rs b/tests/codegen/option-niche-unfixed/option-nonzero-eq.rs new file mode 100644 index 000000000000..308856cfb7e9 --- /dev/null +++ b/tests/codegen/option-niche-unfixed/option-nonzero-eq.rs @@ -0,0 +1,24 @@ +//@ should-fail +//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled +//! FIXME(#49892) +//! Test that the derived implementation of `PartialEq` for `Option` is not fully +//! optimized by LLVM. If this starts passing, the test and manual impl should +//! be removed. +#![crate_type = "lib"] + +use std::num::NonZero; + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum Option { + None, + Some(T), +} + +// CHECK-LABEL: @non_zero_eq +#[no_mangle] +pub fn non_zero_eq(l: Option>, r: Option>) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp eq i32 + // CHECK-NEXT: ret i1 + l == r +} From 9a0c85655c7b60c5b6f595e98f72275e8052058b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 12 May 2025 18:43:00 +0200 Subject: [PATCH 058/139] Specify that split_ascii_whitespace uses the same definition as is_ascii_whitespace --- library/core/src/str/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index dafabba645c6..0123e52f5470 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -1172,6 +1172,7 @@ impl str { /// The iterator returned will return string slices that are sub-slices of /// the original string slice, separated by any amount of ASCII whitespace. /// + /// This uses the same definition as [`char::is_ascii_whitespace`]. /// To split by Unicode `Whitespace` instead, use [`split_whitespace`]. /// /// [`split_whitespace`]: str::split_whitespace @@ -1190,7 +1191,8 @@ impl str { /// assert_eq!(None, iter.next()); /// ``` /// - /// All kinds of ASCII whitespace are considered: + /// Various kinds of ASCII whitespace are considered + /// (see [`char::is_ascii_whitespace`]): /// /// ``` /// let mut iter = " Mary had\ta little \n\t lamb".split_ascii_whitespace(); From 8f0522dc811b7132c3bd2b2bc5c134a869824cf3 Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 12 May 2025 18:49:36 +1000 Subject: [PATCH 059/139] Fix confusing WTF surrogate safety docs --- library/std/src/ffi/os_str.rs | 6 +++--- library/std/src/sys/os_str/wtf8.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 72bdf03ee61a..7f0033c19621 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -594,9 +594,9 @@ impl OsString { /// The slice must be valid for the platform encoding (as described in /// [`OsStr::from_encoded_bytes_unchecked`]). /// - /// This bypasses the encoding-dependent surrogate joining, so `self` must - /// not end with a leading surrogate half and `other` must not start with - /// with a trailing surrogate half. + /// This bypasses the encoding-dependent surrogate joining, so either + /// `self` must not end with a leading surrogate half, or `other` must not + /// start with a trailing surrogate half. #[inline] pub(crate) unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) { // SAFETY: Guaranteed by caller. diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs index 5174ea65d0cd..892bd2e3de65 100644 --- a/library/std/src/sys/os_str/wtf8.rs +++ b/library/std/src/sys/os_str/wtf8.rs @@ -215,9 +215,9 @@ impl Buf { /// The slice must be valid for the platform encoding (as described in /// [`Slice::from_encoded_bytes_unchecked`]). /// - /// This bypasses the WTF-8 surrogate joining, so `self` must not end with a - /// leading surrogate half and `other` must not start with with a trailing - /// surrogate half. + /// This bypasses the WTF-8 surrogate joining, so either `self` must not + /// end with a leading surrogate half, or `other` must not start with a + /// trailing surrogate half. #[inline] pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) { self.inner.extend_from_slice(other); From 5326fc9bc78ca44e04d4583a8ced3a23768815e6 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 14 Apr 2025 19:01:38 -0500 Subject: [PATCH 060/139] rustdoc: on mobile, make the sidebar full width and linewrap this is because the mobile sidebar cannot be resized, unlike on desktop. --- src/librustdoc/html/static/css/rustdoc.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index a81d5c9c49b4..7be83b65fbfa 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2527,9 +2527,12 @@ in src-script.js and main.js z-index: 11; /* Reduce height slightly to account for mobile topbar. */ height: calc(100vh - 45px); - width: 200px; /* resize indicator: hide this when on touch or mobile */ border-right: none; + width: 100%; + } + .sidebar-elems .block li a { + white-space: wrap; } /* The source view uses a different design for the sidebar toggle, and doesn't have a topbar, From 5240cd3a8210ab56fe5710048f7ab719cbba16a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 16 May 2025 15:46:44 +0200 Subject: [PATCH 061/139] Implement `advance_by` via `try_fold` for `Sized` iterators When `try_fold` is overriden, it is usually easier for compilers to optimize. --- library/core/src/iter/traits/iterator.rs | 36 ++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index d1e71f0e60f2..fab403ce8535 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -294,13 +294,39 @@ pub trait Iterator { #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { - for i in 0..n { - if self.next().is_none() { - // SAFETY: `i` is always less than `n`. - return Err(unsafe { NonZero::new_unchecked(n - i) }); + /// Helper trait to specialize `advance_by` via `try_fold` for `Sized` iterators. + trait SpecAdvanceBy { + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero>; + } + + impl SpecAdvanceBy for I { + default fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero> { + for i in 0..n { + if self.next().is_none() { + // SAFETY: `i` is always less than `n`. + return Err(unsafe { NonZero::new_unchecked(n - i) }); + } + } + Ok(()) } } - Ok(()) + + impl SpecAdvanceBy for I { + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let Some(n) = NonZero::new(n) else { + return Ok(()); + }; + + let res = self.try_fold(n, |n, _| NonZero::new(n.get() - 1)); + + match res { + None => Ok(()), + Some(n) => Err(n), + } + } + } + + self.spec_advance_by(n) } /// Returns the `n`th element of the iterator. From d29d1a332bc44b461859ccc756d53cbd81cbea0e Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:09:06 +0200 Subject: [PATCH 062/139] Docs(lib/alloc/vec): Add the missing `an` to `extract_if`'s first sentence As inspired by the equivalent methods from other collection types. Signed-off-by: Paul Mabileau --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 59879f23d785..4d03ca63ec8a 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3648,7 +3648,7 @@ impl Vec { Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } } - /// Creates an iterator which uses a closure to determine if element in the range should be removed. + /// Creates an iterator which uses a closure to determine if an element in the range should be removed. /// /// If the closure returns true, then the element is removed and yielded. /// If the closure returns false, the element will remain in the vector and will not be yielded From cd5772e396361c72e4662655687a462aee6c6aea Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:14:55 +0200 Subject: [PATCH 063/139] Docs(lib/coll/hm): Reword `extract_if` to use `element` instead of `value` A minor change, but it seemed interesting to unify this one's description, especially considering all the other equivalents use `element` as well. Signed-off-by: Paul Mabileau --- library/std/src/collections/hash/set.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 8514dfd9a984..5043d1bd1df7 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -276,10 +276,10 @@ impl HashSet { Drain { base: self.base.drain() } } - /// Creates an iterator which uses a closure to determine if a value should be removed. + /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// If the closure returns true, then the value is removed and yielded. - /// If the closure returns false, the value will remain in the list and will not be yielded + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, the element will remain in the list and will not be yielded /// by the iterator. /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating From 35f847363729b16332eab1a85900617218495757 Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:22:13 +0200 Subject: [PATCH 064/139] Docs(lib/coll/btm): Split `extract_if`'s first sentence from the following ones This also seems like a small mistake: the first main sentence is put in the same paragraph as the other two following ones while other equivalents all have it split. Therefore, do the same here. Signed-off-by: Paul Mabileau --- library/alloc/src/collections/btree/map.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 5ca32ed741af..ea81645aa649 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1398,10 +1398,12 @@ impl BTreeMap { } /// Creates an iterator that visits all elements (key-value pairs) in - /// ascending key order and uses a closure to determine if an element should - /// be removed. If the closure returns `true`, the element is removed from - /// the map and yielded. If the closure returns `false`, or panics, the - /// element remains in the map and will not be yielded. + /// ascending key order and uses a closure to determine if an element + /// should be removed. + /// + /// If the closure returns `true`, the element is removed from the map and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the map and will not be yielded. /// /// The iterator also lets you mutate the value of each element in the /// closure, regardless of whether you choose to keep or remove it. From 9205ee27a815e5b356cfce6269d9ded1d1c098f7 Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:36:08 +0200 Subject: [PATCH 065/139] Docs(lib/extract_if): Unify paragraph about closure actions Also fixes `HashSet`'s that incorrectly designated itself as a `list`. Signed-off-by: Paul Mabileau --- library/alloc/src/collections/linked_list.rs | 6 +++--- library/alloc/src/vec/mod.rs | 6 +++--- library/std/src/collections/hash/map.rs | 6 +++--- library/std/src/collections/hash/set.rs | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 00e2805d11f6..1890a114d3cb 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1124,9 +1124,9 @@ impl LinkedList { /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the list and will not be yielded - /// by the iterator. + /// If the closure returns `true`, the element is removed from the list and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the list and will not be yielded. /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating /// or the iteration short-circuits, then the remaining elements will be retained. diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 4d03ca63ec8a..e5f2c9468e38 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3650,9 +3650,9 @@ impl Vec { /// Creates an iterator which uses a closure to determine if an element in the range should be removed. /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the vector and will not be yielded - /// by the iterator. + /// If the closure returns `true`, the element is removed from the vector + /// and yielded. If the closure returns `false`, or panics, the element + /// remains in the vector and will not be yielded. /// /// Only elements that fall in the provided range are considered for extraction, but any elements /// after the range will still have to be moved if any element has been extracted. diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 3530f890f529..9732d2c2d5ce 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -650,9 +650,9 @@ impl HashMap { /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// If the closure returns true, the element is removed from the map and yielded. - /// If the closure returns false, or panics, the element remains in the map and will not be - /// yielded. + /// If the closure returns `true`, the element is removed from the map and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the map and will not be yielded. /// /// Note that `extract_if` lets you mutate every value in the filter closure, regardless of /// whether you choose to keep or remove it. diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 5043d1bd1df7..482d57b47f67 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -278,9 +278,9 @@ impl HashSet { /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the list and will not be yielded - /// by the iterator. + /// If the closure returns `true`, the element is removed from the set and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the set and will not be yielded. /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating /// or the iteration short-circuits, then the remaining elements will be retained. From 014434e96f4f42e06b6c2dfc00110209b121040e Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:45:56 +0200 Subject: [PATCH 066/139] Docs(lib/extract_if): Unify paragraph about elements mutation Take the one from `BTreeMap` that seems the best-worded and most precise among the available variations. Signed-off-by: Paul Mabileau --- library/alloc/src/collections/linked_list.rs | 4 ++-- library/alloc/src/vec/mod.rs | 4 ++-- library/std/src/collections/hash/map.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 1890a114d3cb..0e365ebd3080 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1132,8 +1132,8 @@ impl LinkedList { /// or the iteration short-circuits, then the remaining elements will be retained. /// Use `extract_if().for_each(drop)` if you do not need the returned iterator. /// - /// Note that `extract_if` lets you mutate every element in the filter closure, regardless of - /// whether you choose to keep or remove it. + /// The iterator also lets you mutate the value of each element in the + /// closure, regardless of whether you choose to keep or remove it. /// /// # Examples /// diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index e5f2c9468e38..3ea5f160666b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3692,8 +3692,8 @@ impl Vec { /// But `extract_if` is easier to use. `extract_if` is also more efficient, /// because it can backshift the elements of the array in bulk. /// - /// Note that `extract_if` also lets you mutate the elements passed to the filter closure, - /// regardless of whether you choose to keep or remove them. + /// The iterator also lets you mutate the value of each element in the + /// closure, regardless of whether you choose to keep or remove it. /// /// # Panics /// diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 9732d2c2d5ce..5e053d364485 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -654,8 +654,8 @@ impl HashMap { /// yielded. If the closure returns `false`, or panics, the element remains /// in the map and will not be yielded. /// - /// Note that `extract_if` lets you mutate every value in the filter closure, regardless of - /// whether you choose to keep or remove it. + /// The iterator also lets you mutate the value of each element in the + /// closure, regardless of whether you choose to keep or remove it. /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating /// or the iteration short-circuits, then the remaining elements will be retained. From a9330dd0e9fbc1698b69ac82e138d9dcef31bc33 Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:49:57 +0200 Subject: [PATCH 067/139] Docs(lib/coll/hm): Add kv pair to `extract_if`'s first sentence Make it consistent in this regard with `BTreeMap`'s. Signed-off-by: Paul Mabileau --- library/std/src/collections/hash/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 5e053d364485..edbdd0411457 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -648,7 +648,7 @@ impl HashMap { Drain { base: self.base.drain() } } - /// Creates an iterator which uses a closure to determine if an element should be removed. + /// Creates an iterator which uses a closure to determine if an element (key-value pair) should be removed. /// /// If the closure returns `true`, the element is removed from the map and /// yielded. If the closure returns `false`, or panics, the element remains From b1d7480acbc6bcc01f0eef98feaccdf53b387cd3 Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:54:21 +0200 Subject: [PATCH 068/139] Docs(lib/extract_if): Unify example description Signed-off-by: Paul Mabileau --- library/alloc/src/collections/linked_list.rs | 2 +- library/alloc/src/vec/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 0e365ebd3080..d03c1969b5b7 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1137,7 +1137,7 @@ impl LinkedList { /// /// # Examples /// - /// Splitting a list into evens and odds, reusing the original list: + /// Splitting a list into even and odd values, reusing the original list: /// /// ``` /// use std::collections::LinkedList; diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3ea5f160666b..ce7321544b6b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3701,7 +3701,7 @@ impl Vec { /// /// # Examples /// - /// Splitting an array into evens and odds, reusing the original allocation: + /// Splitting a vector into even and odd values, reusing the original vector: /// /// ``` /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; From 3b7ca287a7ecb80185f2c679e663cd9c94cdc9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Fri, 14 Mar 2025 10:48:02 +0100 Subject: [PATCH 069/139] Describe lifetime of call argument temporaries passed indirectly --- compiler/rustc_codegen_ssa/src/mir/block.rs | 48 +++++++++---- .../codegen/align-byval-alignment-mismatch.rs | 7 +- tests/codegen/call-tmps-lifetime.rs | 68 +++++++++++++++++++ .../issue-98156-const-arg-temp-lifetime.rs | 27 -------- 4 files changed, 108 insertions(+), 42 deletions(-) create mode 100644 tests/codegen/call-tmps-lifetime.rs delete mode 100644 tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 950f19a6f0f4..1530ee856475 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1,6 +1,6 @@ use std::cmp; -use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, WrappingRange}; +use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, Size, WrappingRange}; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::packed::Pu128; @@ -158,7 +158,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, mut unwind: mir::UnwindAction, - copied_constant_arguments: &[PlaceRef<'tcx, ::Value>], + lifetime_ends_after_call: &[(Bx::Value, Size)], instance: Option>, mergeable_succ: bool, ) -> MergingSucc { @@ -245,8 +245,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { if let Some((ret_dest, target)) = destination { bx.switch_to_block(fx.llbb(target)); fx.set_debug_loc(bx, self.terminator.source_info); - for tmp in copied_constant_arguments { - bx.lifetime_end(tmp.val.llval, tmp.layout.size); + for &(tmp, size) in lifetime_ends_after_call { + bx.lifetime_end(tmp, size); } fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret); } @@ -259,8 +259,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } if let Some((ret_dest, target)) = destination { - for tmp in copied_constant_arguments { - bx.lifetime_end(tmp.val.llval, tmp.layout.size); + for &(tmp, size) in lifetime_ends_after_call { + bx.lifetime_end(tmp, size); } fx.store_return(bx, ret_dest, &fn_abi.ret, llret); self.funclet_br(fx, bx, target, mergeable_succ) @@ -1048,7 +1048,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (args, None) }; - let mut copied_constant_arguments = vec![]; + // When generating arguments we sometimes introduce temporary allocations with lifetime + // that extend for the duration of a call. Keep track of those allocations and their sizes + // to generate `lifetime_end` when the call returns. + let mut lifetime_ends_after_call: Vec<(Bx::Value, Size)> = Vec::new(); 'make_args: for (i, arg) in first_args.iter().enumerate() { let mut op = self.codegen_operand(bx, &arg.node); @@ -1136,12 +1139,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.lifetime_start(tmp.val.llval, tmp.layout.size); op.val.store(bx, tmp); op.val = Ref(tmp.val); - copied_constant_arguments.push(tmp); + lifetime_ends_after_call.push((tmp.val.llval, tmp.layout.size)); } _ => {} } - self.codegen_argument(bx, op, &mut llargs, &fn_abi.args[i]); + self.codegen_argument( + bx, + op, + &mut llargs, + &fn_abi.args[i], + &mut lifetime_ends_after_call, + ); } let num_untupled = untuple.map(|tup| { self.codegen_arguments_untupled( @@ -1149,6 +1158,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &tup.node, &mut llargs, &fn_abi.args[first_args.len()..], + &mut lifetime_ends_after_call, ) }); @@ -1173,7 +1183,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); let last_arg = fn_abi.args.last().unwrap(); - self.codegen_argument(bx, location, &mut llargs, last_arg); + self.codegen_argument( + bx, + location, + &mut llargs, + last_arg, + &mut lifetime_ends_after_call, + ); } let fn_ptr = match (instance, llfn) { @@ -1189,7 +1205,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &llargs, destination, unwind, - &copied_constant_arguments, + &lifetime_ends_after_call, instance, mergeable_succ, ) @@ -1479,6 +1495,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { op: OperandRef<'tcx, Bx::Value>, llargs: &mut Vec, arg: &ArgAbi<'tcx, Ty<'tcx>>, + lifetime_ends_after_call: &mut Vec<(Bx::Value, Size)>, ) { match arg.mode { PassMode::Ignore => return, @@ -1517,7 +1534,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { None => arg.layout.align.abi, }; let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align); + bx.lifetime_start(scratch.llval, arg.layout.size); op.val.store(bx, scratch.with_type(arg.layout)); + lifetime_ends_after_call.push((scratch.llval, arg.layout.size)); (scratch.llval, scratch.align, true) } PassMode::Cast { .. } => { @@ -1538,7 +1557,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // alignment requirements may be higher than the type's alignment, so copy // to a higher-aligned alloca. let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align); + bx.lifetime_start(scratch.llval, arg.layout.size); bx.typed_place_copy(scratch, op_place_val, op.layout); + lifetime_ends_after_call.push((scratch.llval, arg.layout.size)); (scratch.llval, scratch.align, true) } else { (op_place_val.llval, op_place_val.align, true) @@ -1620,6 +1641,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { operand: &mir::Operand<'tcx>, llargs: &mut Vec, args: &[ArgAbi<'tcx, Ty<'tcx>>], + lifetime_ends_after_call: &mut Vec<(Bx::Value, Size)>, ) -> usize { let tuple = self.codegen_operand(bx, operand); @@ -1632,13 +1654,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { for i in 0..tuple.layout.fields.count() { let field_ptr = tuple_ptr.project_field(bx, i); let field = bx.load_operand(field_ptr); - self.codegen_argument(bx, field, llargs, &args[i]); + self.codegen_argument(bx, field, llargs, &args[i], lifetime_ends_after_call); } } else { // If the tuple is immediate, the elements are as well. for i in 0..tuple.layout.fields.count() { let op = tuple.extract_field(self, bx, i); - self.codegen_argument(bx, op, llargs, &args[i]); + self.codegen_argument(bx, op, llargs, &args[i], lifetime_ends_after_call); } } tuple.layout.fields.count() diff --git a/tests/codegen/align-byval-alignment-mismatch.rs b/tests/codegen/align-byval-alignment-mismatch.rs index 46cfb2972df3..c69fc2de9d25 100644 --- a/tests/codegen/align-byval-alignment-mismatch.rs +++ b/tests/codegen/align-byval-alignment-mismatch.rs @@ -2,9 +2,10 @@ //@ add-core-stubs //@ revisions:i686-linux x86_64-linux -//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu -C panic=abort +//@ compile-flags: -Cno-prepopulate-passes -Copt-level=1 -Cpanic=abort +//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu //@[i686-linux] needs-llvm-components: x86 -//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu -C panic=abort +//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu //@[x86_64-linux] needs-llvm-components: x86 // Tests that we correctly copy arguments into allocas when the alignment of the byval argument @@ -54,8 +55,10 @@ extern "C" { pub unsafe fn rust_to_c_increases_alignment(x: Align1) { // i686-linux: start: // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 4 + // i686-linux-NEXT: call void @llvm.lifetime.start.p0(i64 48, ptr {{.*}}[[ALLOCA]]) // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 4 {{.*}}[[ALLOCA]], ptr {{.*}}align 1 {{.*}}%x // i686-linux-NEXT: call void @extern_c_align1({{.+}} [[ALLOCA]]) + // i686-linux-NEXT: call void @llvm.lifetime.end.p0(i64 48, ptr {{.*}}[[ALLOCA]]) // x86_64-linux: start: // x86_64-linux-NEXT: call void @extern_c_align1 diff --git a/tests/codegen/call-tmps-lifetime.rs b/tests/codegen/call-tmps-lifetime.rs new file mode 100644 index 000000000000..7b7b6e17bddd --- /dev/null +++ b/tests/codegen/call-tmps-lifetime.rs @@ -0,0 +1,68 @@ +// Test that temporary allocas used for call arguments have their lifetimes described by +// intrinsics. +// +//@ add-core-stubs +//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes --crate-type=lib --target i686-unknown-linux-gnu +//@ needs-llvm-components: x86 +#![feature(no_core)] +#![no_std] +#![no_core] +extern crate minicore; +use minicore::*; + +// Const operand. Regression test for #98156. +// +// CHECK-LABEL: define void @const_indirect( +// CHECK-NEXT: start: +// CHECK-NEXT: [[B:%.*]] = alloca +// CHECK-NEXT: [[A:%.*]] = alloca +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4096, ptr [[A]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 4096, i1 false) +// CHECK-NEXT: call void %h(ptr {{.*}} [[A]]) +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4096, ptr [[A]]) +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4096, ptr [[B]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[B]], ptr align 4 {{.*}}, i32 4096, i1 false) +// CHECK-NEXT: call void %h(ptr {{.*}} [[B]]) +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4096, ptr [[B]]) +#[no_mangle] +pub fn const_indirect(h: extern "C" fn([u32; 1024])) { + const C: [u32; 1024] = [0; 1024]; + h(C); + h(C); +} + +#[repr(C)] +pub struct Str { + pub ptr: *const u8, + pub len: usize, +} + +// Pair of immediates. Regression test for #132014. +// +// CHECK-LABEL: define void @immediate_indirect(ptr {{.*}}%s.0, i32 {{.*}}%s.1, ptr {{.*}}%g) +// CHECK-NEXT: start: +// CHECK-NEXT: [[A:%.*]] = alloca +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[A]]) +// CHECK-NEXT: store ptr %s.0, ptr [[A]] +// CHECK-NEXT: [[B:%.]] = getelementptr inbounds i8, ptr [[A]], i32 4 +// CHECK-NEXT: store i32 %s.1, ptr [[B]] +// CHECK-NEXT: call void %g(ptr {{.*}} [[A]]) +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[A]]) +#[no_mangle] +pub fn immediate_indirect(s: Str, g: extern "C" fn(Str)) { + g(s); +} + +// Indirect argument with a higher alignment requirement than the type's. +// +// CHECK-LABEL: define void @align_indirect(ptr{{.*}} align 1{{.*}} %a, ptr{{.*}} %fun) +// CHECK-NEXT: start: +// CHECK-NEXT: [[A:%.*]] = alloca [1024 x i8], align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1024, ptr [[A]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 1 %a, i32 1024, i1 false) +// CHECK-NEXT: call void %fun(ptr {{.*}} [[A]]) +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1024, ptr [[A]]) +#[no_mangle] +pub fn align_indirect(a: [u8; 1024], fun: extern "C" fn([u8; 1024])) { + fun(a); +} diff --git a/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs deleted file mode 100644 index aecb81caf22b..000000000000 --- a/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs +++ /dev/null @@ -1,27 +0,0 @@ -// This test checks that temporaries for indirectly-passed arguments get lifetime markers. - -//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -Zmir-opt-level=0 - -#![crate_type = "lib"] - -extern "Rust" { - fn f(x: [u8; 1024]); -} - -const A: [u8; 1024] = [0; 1024]; - -// CHECK-LABEL: @const_arg_indirect -#[no_mangle] -pub unsafe fn const_arg_indirect() { - // Ensure that the live ranges for the two argument temporaries don't overlap. - - // CHECK: call void @llvm.lifetime.start - // CHECK: call void @f - // CHECK: call void @llvm.lifetime.end - // CHECK: call void @llvm.lifetime.start - // CHECK: call void @f - // CHECK: call void @llvm.lifetime.end - - f(A); - f(A); -} From bc02a99f8f2b3439fb680be39339b3a8c9d23f32 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 18 May 2025 14:30:42 +0000 Subject: [PATCH 070/139] Rustup to rustc 1.89.0-nightly (777d37277 2025-05-17) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 4ca593e6bea5..78cfde6ad01a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-05-05" +channel = "nightly-2025-05-18" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 0e43247bc94d50b4a341e68cfabe8f7fd75f6376 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 18 May 2025 15:02:09 +0000 Subject: [PATCH 071/139] Fix rustc testsuite --- scripts/test_rustc_tests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index c59e34094dc8..d014b6881ff4 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -53,6 +53,8 @@ rm -r tests/run-make/split-debuginfo # same rm -r tests/run-make/target-specs # i686 not supported by Cranelift rm -r tests/run-make/mismatching-target-triples # same rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly +rm tests/ui/asm/global-asm-mono-sym-fn.rs # same +rm tests/ui/asm/naked-asm-mono-sym-fn.rs # same rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo @@ -134,6 +136,8 @@ rm -r tests/run-make/const-trait-stable-toolchain # same rm -r tests/run-make/print-request-help-stable-unstable # same rm -r tests/run-make/incr-add-rust-src-component rm tests/ui/errors/remap-path-prefix-sysroot.rs # different sysroot source path +rm -r tests/run-make/export/extern-opt # something about rustc version mismatches +rm -r tests/run-make/export # same # genuine bugs # ============ From e139d268f0d863fb45111b64dff7c981a377c8af Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 May 2025 16:09:53 +1000 Subject: [PATCH 072/139] Introduce some typedefs to improve readability. --- compiler/rustc_attr_parsing/src/context.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 55c3df003fe1..6edb9133eabd 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -26,12 +26,16 @@ macro_rules! attribute_groups { ( pub(crate) static $name: ident = [$($names: ty),* $(,)?]; ) => { - pub(crate) static $name: LazyLock<( - BTreeMap<&'static [Symbol], Vec, &ArgParser<'_>) + Send + Sync>>>, - Vec) -> Option>> - )> = LazyLock::new(|| { - let mut accepts = BTreeMap::<_, Vec, &ArgParser<'_>) + Send + Sync>>>::new(); - let mut finalizes = Vec::) -> Option>>::new(); + type Accepts = BTreeMap< + &'static [Symbol], + Vec, &ArgParser<'_>)>> + >; + type Finalizes = Vec< + Box) -> Option> + >; + pub(crate) static $name: LazyLock<(Accepts, Finalizes)> = LazyLock::new(|| { + let mut accepts = Accepts::new(); + let mut finalizes = Finalizes::new(); $( { thread_local! { From 5b808b7da8df062f1c4d5d73c98e19e6cc4b283b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 May 2025 16:09:16 +1000 Subject: [PATCH 073/139] Simplify `Accepts`. There only needs to be one `Fn` per symbol, not multiple. --- compiler/rustc_attr_parsing/src/context.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 6edb9133eabd..aef803c7442c 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -28,7 +28,7 @@ macro_rules! attribute_groups { ) => { type Accepts = BTreeMap< &'static [Symbol], - Vec, &ArgParser<'_>)>> + Box, &ArgParser<'_>)> >; type Finalizes = Vec< Box) -> Option> @@ -43,11 +43,12 @@ macro_rules! attribute_groups { }; for (k, v) in <$names>::ATTRIBUTES { - accepts.entry(*k).or_default().push(Box::new(|cx, args| { + let old = accepts.insert(*k, Box::new(|cx, args| { STATE_OBJECT.with_borrow_mut(|s| { v(s, cx, args) }) })); + assert!(old.is_none()); } finalizes.push(Box::new(|cx| { @@ -267,15 +268,11 @@ impl<'sess> AttributeParser<'sess> { let (path, args) = parser.deconstruct(); let parts = path.segments().map(|i| i.name).collect::>(); - if let Some(accepts) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) { - for f in accepts { - let cx = AcceptContext { - group_cx: &group_cx, - attr_span: lower_span(attr.span), - }; + if let Some(accept) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) { + let cx = + AcceptContext { group_cx: &group_cx, attr_span: lower_span(attr.span) }; - f(&cx, &args) - } + accept(&cx, &args) } else { // if we're here, we must be compiling a tool attribute... Or someone forgot to // parse their fancy new attribute. Let's warn them in any case. If you are that From 1525f548bc376b04692b97a84898900e8f27fdd0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 May 2025 16:24:48 +1000 Subject: [PATCH 074/139] Fix up some comments. Some are too long (> 100 chars), some are too short, some are missing full stops, some are missing upper-case letters at the start of sentences. --- compiler/rustc_attr_parsing/src/context.rs | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index aef803c7442c..1360fc687142 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -115,7 +115,8 @@ impl<'a> Deref for AcceptContext<'a> { /// Context given to every attribute parser during finalization. /// -/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create errors, for example. +/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create +/// errors, for example. pub(crate) struct FinalizeContext<'a> { /// The parse context, gives access to the session and the /// diagnostics context. @@ -146,10 +147,9 @@ pub struct AttributeParser<'sess> { sess: &'sess Session, features: Option<&'sess Features>, - /// *only* parse attributes with this symbol. + /// *Only* parse attributes with this symbol. /// - /// Used in cases where we want the lowering infrastructure for - /// parse just a single attribute. + /// Used in cases where we want the lowering infrastructure for parse just a single attribute. parse_only: Option, /// Can be used to instruct parsers to reduce the number of diagnostics it emits. @@ -162,9 +162,9 @@ impl<'sess> AttributeParser<'sess> { /// One example where this is necessary, is to parse `feature` attributes themselves for /// example. /// - /// Try to use this as little as possible. Attributes *should* be lowered during `rustc_ast_lowering`. - /// Some attributes require access to features to parse, which would crash if you tried to do so - /// through [`parse_limited`](Self::parse_limited). + /// Try to use this as little as possible. Attributes *should* be lowered during + /// `rustc_ast_lowering`. Some attributes require access to features to parse, which would + /// crash if you tried to do so through [`parse_limited`](Self::parse_limited). /// /// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with /// that symbol are picked out of the list of instructions and parsed. Those are returned. @@ -222,19 +222,18 @@ impl<'sess> AttributeParser<'sess> { let group_cx = FinalizeContext { cx: self, target_span }; for attr in attrs { - // if we're only looking for a single attribute, - // skip all the ones we don't care about + // If we're only looking for a single attribute, skip all the ones we don't care about. if let Some(expected) = self.parse_only { if !attr.has_name(expected) { continue; } } - // sometimes, for example for `#![doc = include_str!("readme.md")]`, + // Sometimes, for example for `#![doc = include_str!("readme.md")]`, // doc still contains a non-literal. You might say, when we're lowering attributes // that's expanded right? But no, sometimes, when parsing attributes on macros, // we already use the lowering logic and these are still there. So, when `omit_doc` - // is set we *also* want to ignore these + // is set we *also* want to ignore these. if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) { continue; } @@ -274,11 +273,11 @@ impl<'sess> AttributeParser<'sess> { accept(&cx, &args) } else { - // if we're here, we must be compiling a tool attribute... Or someone forgot to - // parse their fancy new attribute. Let's warn them in any case. If you are that - // person, and you really your attribute should remain unparsed, carefully read the - // documentation in this module and if you still think so you can add an exception - // to this assertion. + // If we're here, we must be compiling a tool attribute... Or someone + // forgot to parse their fancy new attribute. Let's warn them in any case. + // If you are that person, and you really think your attribute should + // remain unparsed, carefully read the documentation in this module and if + // you still think so you can add an exception to this assertion. // FIXME(jdonszelmann): convert other attributes, and check with this that // we caught em all From 354b1cbcca13dc85bd0a57f8c2b254831394b6fb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 20 May 2025 09:20:27 +1000 Subject: [PATCH 075/139] Avoid `rustc_span::` qualifiers. In several files they are entirely unnecessary, with the relevant names already imported. And in a few I have added the necessary `use` item. --- .../rustc_attr_parsing/src/attributes/allow_unstable.rs | 4 ++-- compiler/rustc_attr_parsing/src/attributes/deprecation.rs | 4 ++-- compiler/rustc_attr_parsing/src/attributes/mod.rs | 8 ++++---- compiler/rustc_attr_parsing/src/attributes/repr.rs | 6 +++--- compiler/rustc_attr_parsing/src/attributes/stability.rs | 2 +- .../rustc_attr_parsing/src/attributes/transparency.rs | 6 +++--- compiler/rustc_attr_parsing/src/parser.rs | 3 +-- 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index c1d95d07f4c6..b9b6ca261193 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -10,7 +10,7 @@ use crate::session_diagnostics; pub(crate) struct AllowInternalUnstableParser; impl CombineAttributeParser for AllowInternalUnstableParser { - const PATH: &'static [rustc_span::Symbol] = &[sym::allow_internal_unstable]; + const PATH: &'static [Symbol] = &[sym::allow_internal_unstable]; type Item = (Symbol, Span); const CONVERT: ConvertFn = AttributeKind::AllowInternalUnstable; @@ -24,7 +24,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser { pub(crate) struct AllowConstFnUnstableParser; impl CombineAttributeParser for AllowConstFnUnstableParser { - const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_allow_const_fn_unstable]; + const PATH: &'static [Symbol] = &[sym::rustc_allow_const_fn_unstable]; type Item = Symbol; const CONVERT: ConvertFn = AttributeKind::AllowConstFnUnstable; diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index fb3d5f57d4fa..1775770ec680 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -42,9 +42,9 @@ fn get( } impl SingleAttributeParser for DeprecationParser { - const PATH: &'static [rustc_span::Symbol] = &[sym::deprecated]; + const PATH: &'static [Symbol] = &[sym::deprecated]; - fn on_duplicate(cx: &AcceptContext<'_>, first_span: rustc_span::Span) { + fn on_duplicate(cx: &AcceptContext<'_>, first_span: Span) { // FIXME(jdonszelmann): merge with errors from check_attrs.rs cx.emit_err(session_diagnostics::UnusedMultiple { this: cx.attr_span, diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 6ecd6b4d7dbb..f45cf984f719 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -17,7 +17,7 @@ use std::marker::PhantomData; use rustc_attr_data_structures::AttributeKind; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use thin_vec::ThinVec; use crate::context::{AcceptContext, FinalizeContext}; @@ -33,7 +33,7 @@ pub(crate) mod transparency; pub(crate) mod util; type AcceptFn = fn(&mut T, &AcceptContext<'_>, &ArgParser<'_>); -type AcceptMapping = &'static [(&'static [rustc_span::Symbol], AcceptFn)]; +type AcceptMapping = &'static [(&'static [Symbol], AcceptFn)]; /// An [`AttributeParser`] is a type which searches for syntactic attributes. /// @@ -72,7 +72,7 @@ pub(crate) trait AttributeParser: Default + 'static { /// [`SingleAttributeParser`] can only convert attributes one-to-one, and cannot combine multiple /// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example. pub(crate) trait SingleAttributeParser: 'static { - const PATH: &'static [rustc_span::Symbol]; + const PATH: &'static [Symbol]; /// Caled when a duplicate attribute is found. /// @@ -119,7 +119,7 @@ type ConvertFn = fn(ThinVec) -> AttributeKind; /// [`CombineAttributeParser`] can only convert a single kind of attribute, and cannot combine multiple /// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example. pub(crate) trait CombineAttributeParser: 'static { - const PATH: &'static [rustc_span::Symbol]; + const PATH: &'static [Symbol]; type Item; const CONVERT: ConvertFn; diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 43dfb85a7c41..ab523ce0038d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -1,7 +1,7 @@ use rustc_abi::Align; use rustc_ast::{IntTy, LitIntType, LitKind, UintTy}; use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use super::{CombineAttributeParser, ConvertFn}; use crate::context::AcceptContext; @@ -21,7 +21,7 @@ pub(crate) struct ReprParser; impl CombineAttributeParser for ReprParser { type Item = (ReprAttr, Span); - const PATH: &'static [rustc_span::Symbol] = &[sym::repr]; + const PATH: &'static [Symbol] = &[sym::repr]; const CONVERT: ConvertFn = AttributeKind::Repr; fn extend<'a>( @@ -99,7 +99,7 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option, _first_span: Span) {} diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index ce42b0507ed5..d229fc097401 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -1,6 +1,6 @@ use rustc_attr_data_structures::AttributeKind; use rustc_span::hygiene::Transparency; -use rustc_span::sym; +use rustc_span::{Span, Symbol, sym}; use super::{AcceptContext, SingleAttributeParser}; use crate::parser::ArgParser; @@ -11,9 +11,9 @@ pub(crate) struct TransparencyParser; #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] impl SingleAttributeParser for TransparencyParser { - const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_macro_transparency]; + const PATH: &'static [Symbol] = &[sym::rustc_macro_transparency]; - fn on_duplicate(cx: &crate::context::AcceptContext<'_>, first_span: rustc_span::Span) { + fn on_duplicate(cx: &crate::context::AcceptContext<'_>, first_span: Span) { cx.dcx().span_err(vec![first_span, cx.attr_span], "multiple macro transparency attributes"); } diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 077d953cfa31..f433d3574e18 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -12,8 +12,7 @@ use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, Norma use rustc_ast_pretty::pprust; use rustc_errors::DiagCtxtHandle; use rustc_hir::{self as hir, AttrPath}; -use rustc_span::symbol::{Ident, kw, sym}; -use rustc_span::{ErrorGuaranteed, Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; pub struct SegmentIterator<'a> { offset: usize, From 04c7e5a7e320dfc4e5ffda56e370479c3974dbaf Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 20 May 2025 09:43:45 +0000 Subject: [PATCH 076/139] Rustup to rustc 1.89.0-nightly (60dabef95 2025-05-19) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 78cfde6ad01a..4b6ed82762be 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-05-18" +channel = "nightly-2025-05-20" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 81af658cb317a8325b4be9fb89d10cd6d6e4d79e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 20 May 2025 12:16:04 +0000 Subject: [PATCH 077/139] Make clif ir debug output a bit nicer --- src/abi/mod.rs | 18 +++++------ src/base.rs | 4 +-- src/pretty_clif.rs | 73 +++++++++++++++++++++++++++++++----------- src/value_and_place.rs | 2 +- 4 files changed, 66 insertions(+), 31 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 57ac2d18d494..7324856bce4a 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -185,12 +185,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv }; let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap(); let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); + let call_inst = self.bcx.ins().call(func_ref, args); if self.clif_comments.enabled() { self.add_comment(func_ref, format!("{:?}", name)); - let inst = self.bcx.func.layout.last_inst(self.bcx.current_block().unwrap()).unwrap(); - self.add_comment(inst, format!("lib_call {}", name)); + self.add_comment(call_inst, format!("lib_call {}", name)); } - let call_inst = self.bcx.ins().call(func_ref, args); let results = self.bcx.inst_results(call_inst); assert!(results.len() <= 2, "{}", results.len()); results @@ -530,7 +529,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( Some(Instance { def: InstanceKind::Virtual(_, idx), .. }) => { if fx.clif_comments.enabled() { let nop_inst = fx.bcx.ins().nop(); - fx.add_comment( + fx.add_post_comment( nop_inst, with_no_trimmed_paths!(format!( "virtual call; self arg pass mode: {:?}", @@ -556,7 +555,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( None => { if fx.clif_comments.enabled() { let nop_inst = fx.bcx.ins().nop(); - fx.add_comment(nop_inst, "indirect call"); + fx.add_post_comment(nop_inst, "indirect call"); } let func = func.load_scalar(fx); @@ -586,11 +585,6 @@ pub(crate) fn codegen_terminator_call<'tcx>( adjust_call_for_c_variadic(fx, &fn_abi, source_info, func_ref, &mut call_args); } - if fx.clif_comments.enabled() { - let nop_inst = fx.bcx.ins().nop(); - with_no_trimmed_paths!(fx.add_comment(nop_inst, format!("abi: {:?}", fn_abi))); - } - let call_inst = match func_ref { CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), CallTarget::Indirect(sig, func_ptr) => { @@ -598,6 +592,10 @@ pub(crate) fn codegen_terminator_call<'tcx>( } }; + if fx.clif_comments.enabled() { + with_no_trimmed_paths!(fx.add_comment(call_inst, format!("abi: {:?}", fn_abi))); + } + fx.bcx.func.dfg.inst_results(call_inst).iter().copied().collect::>() }); diff --git a/src/base.rs b/src/base.rs index f46535966f1c..c3255327f340 100644 --- a/src/base.rs +++ b/src/base.rs @@ -315,7 +315,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap(); }); let inst = fx.bcx.func.layout.last_inst(block).unwrap(); - fx.add_comment(inst, terminator_head); + fx.add_post_comment(inst, terminator_head); } let source_info = bb_data.terminator().source_info; @@ -570,7 +570,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: if fx.clif_comments.enabled() { let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap(); with_no_trimmed_paths!({ - fx.add_comment(inst, format!("{:?}", stmt)); + fx.add_post_comment(inst, format!("{:?}", stmt)); }); } } diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index cd254b04ed9e..9400ae9fcff0 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -8,40 +8,41 @@ //! target x86_64 //! //! function u0:22(i64) -> i8, i8 system_v { -//! ; symbol _ZN97_$LT$example..IsNotEmpty$u20$as$u20$mini_core..FnOnce$LT$$LP$$RF$$RF$$u5b$u16$u5d$$C$$RP$$GT$$GT$9call_once17hd517c453d67c0915E -//! ; instance Instance { def: Item(WithOptConstParam { did: DefId(0:42 ~ example[4e51]::{impl#0}::call_once), const_param_did: None }), args: [ReErased, ReErased] } -//! ; abi FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: IsNotEmpty, layout: Layout { size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, abi: Aggregate { sized: true }, fields: Arbitrary { offsets: [], memory_index: [] }, largest_niche: None, variants: Single { index: 0 } } }, mode: Ignore }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, abi: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), variants: Single { index: 0 } } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, abi: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], memory_index: [0, 1] }, largest_niche: None, variants: Single { index: 0 } } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false } +//! ; symbol _ZN97_$LT$example..IsNotEmpty$u20$as$u20$mini_core..FnOnce$LT$$LP$$RF$$RF$$u5b$u16$u5d$$C$$RP$$GT$$GT$9call_once17hd361e9f5c3d1c4deE +//! ; instance Instance { def: Item(DefId(0:42 ~ example[3895]::{impl#0}::call_once)), args: ['{erased}, '{erased}] } +//! ; abi FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: IsNotEmpty, layout: Layout { size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: Memory { sized: true }, fields: Arbitrary { offsets: [], memory_index: [] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 12266848898570219025 } }, mode: Ignore }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], memory_index: [0, 1] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 71776127651151873 } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false } //! //! ; kind loc.idx param pass mode ty -//! ; ssa _0 (u8, u8) 2b 1, 8 var=(0, 1) +//! ; ssa _0 (u8, u8) 2b 1 var=(0, 1) //! ; ret _0 - Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) (u8, u8) //! ; arg _1 - Ignore IsNotEmpty -//! ; arg _2.0 = v0 Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) &&[u16] +//! ; arg _2.0 = v0 Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) &'{erased} &'{erased} [u16] //! -//! ; kind local ty size align (abi,pref) -//! ; zst _1 IsNotEmpty 0b 1, 8 align=8,offset= -//! ; stack _2 (&&[u16],) 8b 8, 8 storage=ss0 -//! ; ssa _3 &mut IsNotEmpty 8b 8, 8 var=2 +//! ; kind local ty size align (abi) +//! ; zst _1 IsNotEmpty 0b 1 align=1,offset= +//! ; stack _2 (&'{erased} &'{erased} [u16],) 8b 8 storage=ss0 +//! ; ssa _3 &'{erased} mut IsNotEmpty 8b 8 var=2 //! -//! ss0 = explicit_slot 16 +//! ss0 = explicit_slot 16, align = 16 //! sig0 = (i64, i64) -> i8, i8 system_v -//! fn0 = colocated u0:23 sig0 ; Instance { def: Item(WithOptConstParam { did: DefId(0:46 ~ example[4e51]::{impl#1}::call_mut), const_param_did: None }), args: [ReErased, ReErased] } +//! fn0 = colocated u0:23 sig0 ; Instance { def: Item(DefId(0:46 ~ example[3895]::{impl#1}::call_mut)), args: ['{erased}, '{erased}] } //! //! block0(v0: i64): //! nop -//! ; write_cvalue: Addr(Pointer { base: Stack(ss0), offset: Offset32(0) }, None): &&[u16] <- ByVal(v0): &&[u16] +//! ; write_cvalue: Addr(Pointer { base: Stack(ss0), offset: Offset32(0) }, None): &'{erased} &'{erased} [u16] <- ByVal(v0): &'{erased} &'{erased} [u16] //! stack_store v0, ss0 //! jump block1 //! //! block1: //! nop //! ; _3 = &mut _1 -//! v1 = iconst.i64 8 -//! ; write_cvalue: Var(_3, var2): &mut IsNotEmpty <- ByVal(v1): &mut IsNotEmpty +//! v1 = iconst.i64 1 +//! ; write_cvalue: Var(_3, var2): &'{erased} mut IsNotEmpty <- ByVal(v1): &'{erased} mut IsNotEmpty //! ; -//! ; _0 = >::call_mut(move _3, _2) +//! ; _0 = >::call_mut(move _3, copy _2) //! v2 = stack_load.i64 ss0 -//! v3, v4 = call fn0(v1, v2) ; v1 = 8 +//! ; abi: FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: &mut IsNotEmpty, layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(1 bytes)) }) }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], memory_index: [0, 1] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 71776127651151873 } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false } +//! v3, v4 = call fn0(v1, v2) ; v1 = 1 //! v5 -> v3 //! v6 -> v4 //! ; write_cvalue: VarPair(_0, var0, var1): (u8, u8) <- ByValPair(v3, v4): (u8, u8) @@ -73,6 +74,7 @@ pub(crate) struct CommentWriter { enabled: bool, global_comments: Vec, entity_comments: FxHashMap, + inst_post_comments: FxHashMap, } impl CommentWriter { @@ -95,7 +97,12 @@ impl CommentWriter { vec![] }; - CommentWriter { enabled, global_comments, entity_comments: FxHashMap::default() } + CommentWriter { + enabled, + global_comments, + entity_comments: FxHashMap::default(), + inst_post_comments: FxHashMap::default(), + } } } @@ -127,6 +134,25 @@ impl CommentWriter { } } } + + pub(crate) fn add_post_comment + AsRef>( + &mut self, + entity: Inst, + comment: S, + ) { + debug_assert!(self.enabled); + + use std::collections::hash_map::Entry; + match self.inst_post_comments.entry(entity) { + Entry::Occupied(mut occ) => { + occ.get_mut().push('\n'); + occ.get_mut().push_str(comment.as_ref()); + } + Entry::Vacant(vac) => { + vac.insert(comment.into()); + } + } + } } impl FuncWriter for &'_ CommentWriter { @@ -188,10 +214,13 @@ impl FuncWriter for &'_ CommentWriter { inst: Inst, indent: usize, ) -> fmt::Result { - PlainWriter.write_instruction(w, func, aliases, inst, indent)?; if let Some(comment) = self.entity_comments.get(&inst.into()) { writeln!(w, "; {}", comment.replace('\n', "\n; "))?; } + PlainWriter.write_instruction(w, func, aliases, inst, indent)?; + if let Some(comment) = self.inst_post_comments.get(&inst) { + writeln!(w, "; {}", comment.replace('\n', "\n; "))?; + } Ok(()) } } @@ -208,6 +237,14 @@ impl FunctionCx<'_, '_, '_> { ) { self.clif_comments.add_comment(entity, comment); } + + pub(crate) fn add_post_comment + AsRef>( + &mut self, + entity: Inst, + comment: S, + ) { + self.clif_comments.add_post_comment(entity, comment); + } } pub(crate) fn should_write_ir(tcx: TyCtxt<'_>) -> bool { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 1168701f1032..5ec970b493b5 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -593,7 +593,7 @@ impl<'tcx> CPlace<'tcx> { if fx.clif_comments.enabled() { let inst = fx.bcx.func.layout.last_inst(fx.bcx.current_block().unwrap()).unwrap(); - fx.add_comment( + fx.add_post_comment( inst, format!( "{}: {:?}: {:?} <- {:?}: {:?}", From 4c39287e34fea2a8a3b330a6cf2c3afab21d4951 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 5 May 2025 15:07:38 +0000 Subject: [PATCH 078/139] Update to Cranelift 0.120 --- Cargo.lock | 72 +++++++++++++++++++------------------- Cargo.toml | 24 ++++++------- src/base.rs | 4 +-- src/intrinsics/llvm_x86.rs | 4 +-- src/intrinsics/simd.rs | 8 ++--- 5 files changed, 56 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 066d5a61adde..a906bec8b7e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,42 +43,42 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-assembler-x64" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "263cc79b8a23c29720eb596d251698f604546b48c34d0d84f8fd2761e5bf8888" +checksum = "9ff8e35182c7372df00447cb90a04e584e032c42b9b9b6e8c50ddaaf0d7900d5" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b4a113455f8c0e13e3b3222a9c38d6940b958ff22573108be083495c72820e1" +checksum = "14220f9c2698015c3b94dc6b84ae045c1c45509ddc406e43c6139252757fdb7a" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f96dca41c5acf5d4312c1d04b3391e21a312f8d64ce31a2723a3bb8edd5d4d" +checksum = "d372ef2777ceefd75829e1390211ac240e9196bc60699218f7ea2419038288ee" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d821ed698dd83d9c012447eb63a5406c1e9c23732a2f674fb5b5015afd42202" +checksum = "56323783e423818fa89ce8078e90a3913d2a6e0810399bfce8ebd7ee87baa81f" [[package]] name = "cranelift-codegen" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c52fdec4322cb8d5545a648047819aaeaa04e630f88d3a609c0d3c1a00e9a0" +checksum = "74ffb780aab6186c6e9ba26519654b1ac55a09c0a866f6088a4efbbd84da68ed" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -101,9 +101,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af2c215e0c9afa8069aafb71d22aa0e0dde1048d9a5c3c72a83cacf9b61fcf4a" +checksum = "c23ef13814d3b39c869650d5961128cbbecad83fbdff4e6836a03ecf6862d7ed" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -112,33 +112,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97524b2446fc26a78142132d813679dda19f620048ebc9a9fbb0ac9f2d320dcb" +checksum = "b9f623300657679f847803ce80811454bfff89cea4f6bf684be5c468d4a73631" [[package]] name = "cranelift-control" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e32e900aee81f9e3cc493405ef667a7812cb5c79b5fc6b669e0a2795bda4b22" +checksum = "31f4168af69989aa6b91fab46799ed4df6096f3209f4a6c8fb4358f49c60188f" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16a2e28e0fa6b9108d76879d60fe1cc95ba90e1bcf52bac96496371044484ee" +checksum = "ca6fa9bae1c8de26d71ac2162f069447610fd91e7780cb480ee0d76ac81eabb8" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328181a9083d99762d85954a16065d2560394a862b8dc10239f39668df528b95" +checksum = "b8219205608aa0b0e6769b580284a7e055c7e0c323c1041cde7ca078add3e412" dependencies = [ "cranelift-codegen", "log", @@ -148,15 +148,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e916f36f183e377e9a3ed71769f2721df88b72648831e95bb9fa6b0cd9b1c709" +checksum = "588d0c5964f10860b04043e55aab26d7f7a206b0fd4f10c5260e8aa5773832bd" [[package]] name = "cranelift-jit" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bb584ac927f1076d552504b0075b833b9d61e2e9178ba55df6b2d966b4375d" +checksum = "56bd917ddc524f84f4066f954062875bdfc0dffea068ee94e906d98de5ac7c33" dependencies = [ "anyhow", "cranelift-codegen", @@ -174,9 +174,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c18ccb8e4861cf49cec79998af73b772a2b47212d12d3d63bf57cc4293a1e3" +checksum = "68a03c057d8a992e06596c871341e446af43ff9224f941e5b8adea39137a5391" dependencies = [ "anyhow", "cranelift-codegen", @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc852cf04128877047dc2027aa1b85c64f681dc3a6a37ff45dcbfa26e4d52d2f" +checksum = "19ed3c94cb97b14f92b6a94a1d45ef8c851f6a2ad9114e5d91d233f7da638fed" dependencies = [ "cranelift-codegen", "libc", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f6ad789197bda49f7c98280ee8d7ccd63a5a1cc67283f87798a2d61e089ce4" +checksum = "a64dacef362a69375a604f6636e5e9a174fb96dba3b273646fcd9fa85c1d0997" dependencies = [ "anyhow", "cranelift-codegen", @@ -211,9 +211,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.119.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e1a86340a16e74b4285cc86ac69458fa1c8e7aaff313da4a89d10efd3535ee" +checksum = "85256fac1519a7d25a040c1d850fba67478f3f021ad5fdf738ba4425ee862dbf" [[package]] name = "crc32fast" @@ -341,9 +341,9 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.11.3" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4c3c15aa088eccea44550bffea9e9a5d0b14a264635323d23c6e6351acca98" +checksum = "5216b1837de2149f8bc8e6d5f88a9326b63b8c836ed58ce4a0a29ec736a59734" dependencies = [ "allocator-api2", "bumpalo", @@ -446,9 +446,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "wasmtime-jit-icache-coherence" -version = "32.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb399eaabd7594f695e1159d236bf40ef55babcb3af97f97c027864ed2104db6" +checksum = "175e924dbc944c185808466d1e90b5a7feb610f3b9abdfe26f8ee25fd1086d1c" dependencies = [ "anyhow", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 82fde4b838e1..94fcbd0a5023 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.119.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.119.0" } -cranelift-module = { version = "0.119.0" } -cranelift-native = { version = "0.119.0" } -cranelift-jit = { version = "0.119.0", optional = true } -cranelift-object = { version = "0.119.0" } +cranelift-codegen = { version = "0.120.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.120.0" } +cranelift-module = { version = "0.120.0" } +cranelift-native = { version = "0.120.0" } +cranelift-jit = { version = "0.120.0", optional = true } +cranelift-object = { version = "0.120.0" } target-lexicon = "0.13" gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-32.0.0", version = "0.119.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/src/base.rs b/src/base.rs index c3255327f340..c1f4c065ce03 100644 --- a/src/base.rs +++ b/src/base.rs @@ -806,7 +806,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: let done_block = fx.bcx.create_block(); let index = fx.bcx.append_block_param(loop_block, fx.pointer_type); let zero = fx.bcx.ins().iconst(fx.pointer_type, 0); - fx.bcx.ins().jump(loop_block, &[zero]); + fx.bcx.ins().jump(loop_block, &[zero.into()]); fx.bcx.switch_to_block(loop_block); let done = fx.bcx.ins().icmp_imm(IntCC::Equal, index, times as i64); @@ -816,7 +816,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: let to = lval.place_index(fx, index); to.write_cvalue(fx, operand); let index = fx.bcx.ins().iadd_imm(index, 1); - fx.bcx.ins().jump(loop_block, &[index]); + fx.bcx.ins().jump(loop_block, &[index.into()]); fx.bcx.switch_to_block(done_block); fx.bcx.ins().nop(); diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index e145eda60685..3d67913a8fff 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -147,10 +147,10 @@ pub(super) fn codegen_x86_llvm_intrinsic_call<'tcx>( let offset = fx.bcx.ins().imul(index_lane, scale); let lane_ptr = fx.bcx.ins().iadd(ptr, offset); let res = fx.bcx.ins().load(lane_clif_ty, MemFlags::trusted(), lane_ptr, 0); - fx.bcx.ins().jump(next, &[res]); + fx.bcx.ins().jump(next, &[res.into()]); fx.bcx.switch_to_block(if_disabled); - fx.bcx.ins().jump(next, &[src_lane]); + fx.bcx.ins().jump(next, &[src_lane.into()]); fx.bcx.seal_block(next); fx.bcx.switch_to_block(next); diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 7a041469bccd..46a441488fa6 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -1008,10 +1008,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.switch_to_block(if_enabled); let res = fx.bcx.ins().load(lane_clif_ty, MemFlags::trusted(), ptr_lane, 0); - fx.bcx.ins().jump(next, &[res]); + fx.bcx.ins().jump(next, &[res.into()]); fx.bcx.switch_to_block(if_disabled); - fx.bcx.ins().jump(next, &[val_lane]); + fx.bcx.ins().jump(next, &[val_lane.into()]); fx.bcx.seal_block(next); fx.bcx.switch_to_block(next); @@ -1057,10 +1057,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ptr_val, Offset32::new(offset), ); - fx.bcx.ins().jump(next, &[res]); + fx.bcx.ins().jump(next, &[res.into()]); fx.bcx.switch_to_block(if_disabled); - fx.bcx.ins().jump(next, &[val_lane]); + fx.bcx.ins().jump(next, &[val_lane.into()]); fx.bcx.seal_block(next); fx.bcx.switch_to_block(next); From 8e3d0b2b031ee49596e4ae6da3845928909baca8 Mon Sep 17 00:00:00 2001 From: stefnotch Date: Tue, 20 May 2025 17:17:36 +0200 Subject: [PATCH 079/139] Update availability of Cranelift (#1579) - include source --- Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 28edb5795ce3..4d1e4d843ffe 100644 --- a/Readme.md +++ b/Readme.md @@ -7,7 +7,7 @@ If not please open an issue. ## Download using Rustup -The Cranelift codegen backend is distributed in nightly builds on Linux and x86_64 macOS. If you want to +The Cranelift codegen backend is distributed in nightly builds on Linux, macOS and x86_64 Windows. If you want to install it using Rustup, you can do that by running: ```bash @@ -79,7 +79,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system Not all targets are available as rustup component for nightly. See notes in the platform support matrix. [^xcoff]: XCOFF object file format is not supported. -[^no-rustup]: Not available as rustup component for nightly. You can build it yourself. +[^no-rustup]: Not available as [rustup component for nightly](https://rust-lang.github.io/rustup-components-history/). You can build it yourself. ## Usage From ff1a5ab4c3492ff74f3b964c4201d8c56ce9e35d Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 18 Feb 2025 00:27:30 +0000 Subject: [PATCH 080/139] Rename `cfg_match!` to `cfg_select!` At [1] it was pointed out that `cfg_match!` syntax does not actually align well with match syntax, which is a possible source of confusion. The comment points out that usage is instead more similar to ecosystem `select!` macros. Rename `cfg_match!` to `cfg_select!` to match this. Tracking issue: https://github.com/rust-lang/rust/issues/115585 [1]: https://github.com/rust-lang/rust/issues/115585#issuecomment-2346307605 --- patches/0027-sysroot_tests-128bit-atomic-operations.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/0027-sysroot_tests-128bit-atomic-operations.patch b/patches/0027-sysroot_tests-128bit-atomic-operations.patch index 16c8488acdb5..f6e6bbc2387c 100644 --- a/patches/0027-sysroot_tests-128bit-atomic-operations.patch +++ b/patches/0027-sysroot_tests-128bit-atomic-operations.patch @@ -17,7 +17,7 @@ index 1e336bf..35e6f54 100644 @@ -2,5 +2,4 @@ // tidy-alphabetical-start -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] - #![cfg_attr(test, feature(cfg_match))] + #![cfg_attr(test, feature(cfg_select))] #![feature(alloc_layout_extra)] #![feature(array_chunks)] diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs From 3ab6af049bb84a6e107851ecf333512b0d4562eb Mon Sep 17 00:00:00 2001 From: beetrees Date: Wed, 21 May 2025 15:59:52 +0200 Subject: [PATCH 081/139] Use Cranelift bitcast instead of store & load to bitcast between vectors and non-vectors (#1580) --- src/abi/mod.rs | 5 +---- src/value_and_place.rs | 22 +--------------------- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 7324856bce4a..70d29596e22c 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -154,10 +154,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { let ret = self.lib_call_unadjusted(name, params, returns, &args)[0]; - // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128 - let ret_ptr = self.create_stack_slot(16, 16); - ret_ptr.store(self, ret, MemFlags::trusted()); - Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]) + Cow::Owned(vec![codegen_bitcast(self, types::I128, ret)]) } else if ret_single_i128 && self.tcx.sess.target.arch == "s390x" { // Return i128 using a return area pointer on s390x. let mut params = params; diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 5ec970b493b5..0938c990514c 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -564,27 +564,7 @@ impl<'tcx> CPlace<'tcx> { src_ty, dst_ty, ); - let data = match (src_ty, dst_ty) { - (_, _) if src_ty == dst_ty => data, - - // This is a `write_cvalue_transmute`. - (types::I32, types::F32) - | (types::F32, types::I32) - | (types::I64, types::F64) - | (types::F64, types::I64) => codegen_bitcast(fx, dst_ty, data), - _ if src_ty.is_vector() && dst_ty.is_vector() => codegen_bitcast(fx, dst_ty, data), - _ if src_ty.is_vector() || dst_ty.is_vector() => { - // FIXME(bytecodealliance/wasmtime#6104) do something more efficient for transmutes between vectors and integers. - let ptr = fx.create_stack_slot(src_ty.bytes(), src_ty.bytes()); - ptr.store(fx, data, MemFlags::trusted()); - ptr.load(fx, dst_ty, MemFlags::trusted()) - } - - // `CValue`s should never contain SSA-only types, so if you ended - // up here having seen an error like `B1 -> I8`, then before - // calling `write_cvalue` you need to add a `bint` instruction. - _ => unreachable!("write_cvalue_transmute: {:?} -> {:?}", src_ty, dst_ty), - }; + let data = if src_ty == dst_ty { data } else { codegen_bitcast(fx, dst_ty, data) }; //fx.bcx.set_val_label(data, cranelift_codegen::ir::ValueLabel::new(var.index())); fx.bcx.def_var(var, data); } From 6a9e189f53f8ad77d0cdb4a87ce02a13b89303a2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 May 2025 20:15:22 +0200 Subject: [PATCH 082/139] interpret: do not force_allocate all return places --- .../src/const_eval/dummy_machine.rs | 4 +- .../src/const_eval/eval_queries.rs | 7 ++- .../src/const_eval/machine.rs | 8 +-- .../rustc_const_eval/src/interpret/call.rs | 52 +++++++--------- .../src/interpret/intrinsics.rs | 22 +++---- .../rustc_const_eval/src/interpret/machine.rs | 16 +++-- .../rustc_const_eval/src/interpret/stack.rs | 62 +++++++++---------- .../rustc_const_eval/src/interpret/step.rs | 2 +- src/tools/miri/src/concurrency/thread.rs | 17 ++--- src/tools/miri/src/eval.rs | 19 +++--- src/tools/miri/src/helpers.rs | 2 +- src/tools/miri/src/intrinsics/mod.rs | 7 ++- src/tools/miri/src/machine.rs | 29 +++++---- src/tools/miri/src/shims/foreign_items.rs | 9 ++- .../tests/fail/data_race/stack_pop_race.rs | 5 +- .../fail/data_race/stack_pop_race.stderr | 11 +--- .../fail/tail_calls/dangling-local-var.stderr | 4 +- .../miri/tests/pass/alloc-access-tracking.rs | 4 +- 18 files changed, 138 insertions(+), 142 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index 46dcebc46e9c..8492e01629be 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -90,7 +90,7 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine { _instance: ty::Instance<'tcx>, _abi: &FnAbi<'tcx, Ty<'tcx>>, _args: &[interpret::FnArg<'tcx, Self::Provenance>], - _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>, + _destination: &interpret::PlaceTy<'tcx, Self::Provenance>, _target: Option, _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx, Option<(&'tcx Body<'tcx>, ty::Instance<'tcx>)>> { @@ -108,7 +108,7 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine { _ecx: &mut InterpCx<'tcx, Self>, _instance: ty::Instance<'tcx>, _args: &[interpret::OpTy<'tcx, Self::Provenance>], - _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>, + _destination: &interpret::PlaceTy<'tcx, Self::Provenance>, _target: Option, _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx, Option>> { diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index ce8eceebdf8d..a79ba6a63427 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -71,7 +71,12 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( // This can't use `init_stack_frame` since `body` is not a function, // so computing its ABI would fail. It's also not worth it since there are no arguments to pass. - ecx.push_stack_frame_raw(cid.instance, body, &ret, StackPopCleanup::Root { cleanup: false })?; + ecx.push_stack_frame_raw( + cid.instance, + body, + &ret.clone().into(), + StackPopCleanup::Root { cleanup: false }, + )?; ecx.storage_live_for_always_live_locals()?; // The main interpreter loop. diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 7c7daed525b2..9fe7a2336c32 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -22,7 +22,7 @@ use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, - GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar, + GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, Scalar, compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, }; @@ -226,7 +226,7 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[FnArg<'tcx>], - _dest: &MPlaceTy<'tcx>, + _dest: &PlaceTy<'tcx>, _ret: Option, ) -> InterpResult<'tcx, Option>> { let def_id = instance.def_id(); @@ -343,7 +343,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { orig_instance: ty::Instance<'tcx>, _abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx>], - dest: &MPlaceTy<'tcx>, + dest: &PlaceTy<'tcx>, ret: Option, _unwind: mir::UnwindAction, // unwinding is not supported in consts ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -385,7 +385,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { ecx: &mut InterpCx<'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx, Self::Provenance>, + dest: &PlaceTy<'tcx, Self::Provenance>, target: Option, _unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option>> { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 405208e94f4b..789baea07346 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -339,7 +339,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { caller_fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, - destination: &MPlaceTy<'tcx, M::Provenance>, + destination: &PlaceTy<'tcx, M::Provenance>, mut stack_pop: StackPopCleanup, ) -> InterpResult<'tcx> { // Compute callee information. @@ -487,7 +487,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } // Protect return place for in-place return value passing. - M::protect_in_place_function_argument(self, &destination)?; + // We only need to protect anything if this is actually an in-memory place. + if let Left(mplace) = destination.as_mplace_or_local() { + M::protect_in_place_function_argument(self, &mplace)?; + } // Don't forget to mark "initially live" locals as live. self.storage_live_for_always_live_locals()?; @@ -512,7 +515,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { (caller_abi, caller_fn_abi): (ExternAbi, &FnAbi<'tcx, Ty<'tcx>>), args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, - destination: &MPlaceTy<'tcx, M::Provenance>, + destination: &PlaceTy<'tcx, M::Provenance>, target: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -776,10 +779,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Note that we are using `pop_stack_frame_raw` and not `return_from_current_stack_frame`, // as the latter "executes" the goto to the return block, but we don't want to, // only the tail called function should return to the current return block. - M::before_stack_pop(self, self.frame())?; - - let StackPopInfo { return_action, return_to_block, return_place } = - self.pop_stack_frame_raw(false)?; + let StackPopInfo { return_action, return_to_block, return_place } = self + .pop_stack_frame_raw(false, |_this, _return_place| { + // This function's return value is just discarded, the tail-callee will fill in the return place instead. + interp_ok(()) + })?; assert_eq!(return_action, ReturnAction::Normal); @@ -850,7 +854,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { (ExternAbi::Rust, fn_abi), &[FnArg::Copy(arg.into())], false, - &ret, + &ret.into(), Some(target), unwind, ) @@ -891,28 +895,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_ub_custom!(fluent::const_eval_unwind_past_top); } - M::before_stack_pop(self, self.frame())?; - - // Copy return value. Must of course happen *before* we deallocate the locals. - // Must be *after* `before_stack_pop` as otherwise the return place might still be protected. - let copy_ret_result = if !unwinding { - let op = self - .local_to_op(mir::RETURN_PLACE, None) - .expect("return place should always be live"); - let dest = self.frame().return_place.clone(); - let res = self.copy_op_allow_transmute(&op, &dest); - trace!("return value: {:?}", self.dump_place(&dest.into())); - // We delay actually short-circuiting on this error until *after* the stack frame is - // popped, since we want this error to be attributed to the caller, whose type defines - // this transmute. - res - } else { + // Get out the return value. Must happen *before* the frame is popped as we have to get the + // local's value out. + let return_op = + self.local_to_op(mir::RETURN_PLACE, None).expect("return place should always be live"); + // Do the actual pop + copy. + let stack_pop_info = self.pop_stack_frame_raw(unwinding, |this, return_place| { + this.copy_op_allow_transmute(&return_op, return_place)?; + trace!("return value: {:?}", this.dump_place(return_place)); interp_ok(()) - }; - - // All right, now it is time to actually pop the frame. - // An error here takes precedence over the copy error. - let (stack_pop_info, ()) = self.pop_stack_frame_raw(unwinding).and(copy_ret_result)?; + })?; match stack_pop_info.return_action { ReturnAction::Normal => {} @@ -924,7 +916,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // If we are not doing cleanup, also skip everything else. assert!(self.stack().is_empty(), "only the topmost frame should ever be leaked"); assert!(!unwinding, "tried to skip cleanup during unwinding"); - // Skip machine hook. + // Don't jump anywhere. return interp_ok(()); } } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 090b2a692cfc..ee670b6245f0 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -17,9 +17,9 @@ use tracing::trace; use super::memory::MemoryKind; use super::util::ensure_monomorphic_enough; use super::{ - Allocation, CheckInAllocMsg, ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult, - MPlaceTy, Machine, OpTy, Pointer, PointerArithmetic, Provenance, Scalar, err_inval, - err_ub_custom, err_unsup_format, interp_ok, throw_inval, throw_ub_custom, throw_ub_format, + Allocation, CheckInAllocMsg, ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult, Machine, + OpTy, PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, err_inval, err_ub_custom, + err_unsup_format, interp_ok, throw_inval, throw_ub_custom, throw_ub_format, }; use crate::fluent_generated as fluent; @@ -112,7 +112,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, M::Provenance>], - dest: &MPlaceTy<'tcx, M::Provenance>, + dest: &PlaceTy<'tcx, M::Provenance>, ret: Option, ) -> InterpResult<'tcx, bool> { let instance_args = instance.args; @@ -587,7 +587,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { &mut self, a: &ImmTy<'tcx, M::Provenance>, b: &ImmTy<'tcx, M::Provenance>, - dest: &MPlaceTy<'tcx, M::Provenance>, + dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { assert_eq!(a.layout.ty, b.layout.ty); assert_matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..)); @@ -801,7 +801,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn float_min_intrinsic( &mut self, args: &[OpTy<'tcx, M::Provenance>], - dest: &MPlaceTy<'tcx, M::Provenance>, + dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ()> where F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, @@ -822,7 +822,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn float_max_intrinsic( &mut self, args: &[OpTy<'tcx, M::Provenance>], - dest: &MPlaceTy<'tcx, M::Provenance>, + dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ()> where F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, @@ -843,7 +843,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn float_minimum_intrinsic( &mut self, args: &[OpTy<'tcx, M::Provenance>], - dest: &MPlaceTy<'tcx, M::Provenance>, + dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ()> where F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, @@ -859,7 +859,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn float_maximum_intrinsic( &mut self, args: &[OpTy<'tcx, M::Provenance>], - dest: &MPlaceTy<'tcx, M::Provenance>, + dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ()> where F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, @@ -875,7 +875,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn float_copysign_intrinsic( &mut self, args: &[OpTy<'tcx, M::Provenance>], - dest: &MPlaceTy<'tcx, M::Provenance>, + dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ()> where F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, @@ -890,7 +890,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn float_abs_intrinsic( &mut self, args: &[OpTy<'tcx, M::Provenance>], - dest: &MPlaceTy<'tcx, M::Provenance>, + dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ()> where F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index d13e17a481a4..b65d9444caf0 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -208,7 +208,7 @@ pub trait Machine<'tcx>: Sized { instance: ty::Instance<'tcx>, abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, Self::Provenance>], - destination: &MPlaceTy<'tcx, Self::Provenance>, + destination: &PlaceTy<'tcx, Self::Provenance>, target: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>>; @@ -220,7 +220,7 @@ pub trait Machine<'tcx>: Sized { fn_val: Self::ExtraFnVal, abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, Self::Provenance>], - destination: &MPlaceTy<'tcx, Self::Provenance>, + destination: &PlaceTy<'tcx, Self::Provenance>, target: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; @@ -234,7 +234,7 @@ pub trait Machine<'tcx>: Sized { ecx: &mut InterpCx<'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Self::Provenance>], - destination: &MPlaceTy<'tcx, Self::Provenance>, + destination: &PlaceTy<'tcx, Self::Provenance>, target: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option>>; @@ -536,11 +536,9 @@ pub trait Machine<'tcx>: Sized { interp_ok(()) } - /// Called just before the return value is copied to the caller-provided return place. - fn before_stack_pop( - _ecx: &InterpCx<'tcx, Self>, - _frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>, - ) -> InterpResult<'tcx> { + /// Called just before the frame is removed from the stack (followed by return value copy and + /// local cleanup). + fn before_stack_pop(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> { interp_ok(()) } @@ -675,7 +673,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) { fn_val: !, _abi: &FnAbi<$tcx, Ty<$tcx>>, _args: &[FnArg<$tcx>], - _destination: &MPlaceTy<$tcx, Self::Provenance>, + _destination: &PlaceTy<$tcx, Self::Provenance>, _target: Option, _unwind: mir::UnwindAction, ) -> InterpResult<$tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index d7b03776bc48..2a2d1bb27547 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -15,9 +15,9 @@ use rustc_span::Span; use tracing::{info_span, instrument, trace}; use super::{ - AllocId, CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, - MemPlaceMeta, MemoryKind, Operand, Pointer, Provenance, ReturnAction, Scalar, - from_known_layout, interp_ok, throw_ub, throw_unsup, + AllocId, CtfeProvenance, Immediate, InterpCx, InterpResult, Machine, MemPlace, MemPlaceMeta, + MemoryKind, Operand, PlaceTy, Pointer, Provenance, ReturnAction, Scalar, from_known_layout, + interp_ok, throw_ub, throw_unsup, }; use crate::errors; @@ -76,8 +76,10 @@ pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> { return_to_block: StackPopCleanup, /// The location where the result of the current stack frame should be written to, - /// and its layout in the caller. - pub return_place: MPlaceTy<'tcx, Prov>, + /// and its layout in the caller. This place is to be interpreted relative to the + /// *caller's* stack frame. We use a `PlaceTy` instead of an `MPlaceTy` since this + /// avoids having to move *all* return places into Miri's memory. + pub return_place: PlaceTy<'tcx, Prov>, /// The list of locals for this stack frame, stored in order as /// `[return_ptr, arguments..., variables..., temporaries...]`. @@ -129,7 +131,7 @@ pub struct StackPopInfo<'tcx, Prov: Provenance> { pub return_to_block: StackPopCleanup, /// [`return_place`](Frame::return_place) of the popped stack frame. - pub return_place: MPlaceTy<'tcx, Prov>, + pub return_place: PlaceTy<'tcx, Prov>, } /// State of a local variable including a memoized layout @@ -353,7 +355,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { &mut self, instance: ty::Instance<'tcx>, body: &'tcx mir::Body<'tcx>, - return_place: &MPlaceTy<'tcx, M::Provenance>, + return_place: &PlaceTy<'tcx, M::Provenance>, return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { trace!("body: {:#?}", body); @@ -404,9 +406,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// it. /// /// This also deallocates locals, if necessary. + /// `copy_ret_val` gets called after the frame has been taken from the stack but before the locals have been deallocated. /// - /// [`M::before_stack_pop`] should be called before calling this function. - /// [`M::after_stack_pop`] is called by this function automatically. + /// [`M::before_stack_pop`] and [`M::after_stack_pop`] are called by this function + /// automatically. /// /// The high-level version of this is `return_from_current_stack_frame`. /// @@ -415,47 +418,44 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub(super) fn pop_stack_frame_raw( &mut self, unwinding: bool, + copy_ret_val: impl FnOnce(&mut Self, &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx>, ) -> InterpResult<'tcx, StackPopInfo<'tcx, M::Provenance>> { - let cleanup = self.cleanup_current_frame_locals()?; - + M::before_stack_pop(self)?; let frame = self.stack_mut().pop().expect("tried to pop a stack frame, but there were none"); + // Copy return value (unless we are unwinding). + if !unwinding { + copy_ret_val(self, &frame.return_place)?; + } + let return_to_block = frame.return_to_block; let return_place = frame.return_place.clone(); - let return_action; - if cleanup { - return_action = M::after_stack_pop(self, frame, unwinding)?; - assert_ne!(return_action, ReturnAction::NoCleanup); - } else { - return_action = ReturnAction::NoCleanup; - }; - - interp_ok(StackPopInfo { return_action, return_to_block, return_place }) - } - - /// A private helper for [`pop_stack_frame_raw`](InterpCx::pop_stack_frame_raw). - /// Returns `true` if cleanup has been done, `false` otherwise. - fn cleanup_current_frame_locals(&mut self) -> InterpResult<'tcx, bool> { // Cleanup: deallocate locals. // Usually we want to clean up (deallocate locals), but in a few rare cases we don't. // We do this while the frame is still on the stack, so errors point to the callee. - let return_to_block = self.frame().return_to_block; let cleanup = match return_to_block { StackPopCleanup::Goto { .. } => true, StackPopCleanup::Root { cleanup, .. } => cleanup, }; - if cleanup { + let return_action = if cleanup { // We need to take the locals out, since we need to mutate while iterating. - let locals = mem::take(&mut self.frame_mut().locals); - for local in &locals { + for local in &frame.locals { self.deallocate_local(local.value)?; } - } - interp_ok(cleanup) + // Call the machine hook, which determines the next steps. + let return_action = M::after_stack_pop(self, frame, unwinding)?; + assert_ne!(return_action, ReturnAction::NoCleanup); + return_action + } else { + // We also skip the machine hook when there's no cleanup. This not a real "pop" anyway. + ReturnAction::NoCleanup + }; + + interp_ok(StackPopInfo { return_action, return_to_block, return_place }) } /// In the current stack frame, mark all locals as live that are not arguments and don't have diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 363ceee1970e..975325b0c1e0 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -506,7 +506,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } = self.eval_callee_and_args(terminator, func, args)?; - let destination = self.force_allocation(&self.eval_place(destination)?)?; + let destination = self.eval_place(destination)?; self.init_fn_call( callee, (fn_sig.abi, fn_abi), diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 8aa65e6cb612..6b760034ee80 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -218,34 +218,37 @@ impl<'tcx> Thread<'tcx> { } } - /// Return the top user-relevant frame, if there is one. + /// Return the top user-relevant frame, if there is one. `skip` indicates how many top frames + /// should be skipped. /// Note that the choice to return `None` here when there is no user-relevant frame is part of /// justifying the optimization that only pushes of user-relevant frames require updating the /// `top_user_relevant_frame` field. - fn compute_top_user_relevant_frame(&self) -> Option { + fn compute_top_user_relevant_frame(&self, skip: usize) -> Option { self.stack .iter() .enumerate() .rev() + .skip(skip) .find_map(|(idx, frame)| if frame.extra.is_user_relevant { Some(idx) } else { None }) } - /// Re-compute the top user-relevant frame from scratch. - pub fn recompute_top_user_relevant_frame(&mut self) { - self.top_user_relevant_frame = self.compute_top_user_relevant_frame(); + /// Re-compute the top user-relevant frame from scratch. `skip` indicates how many top frames + /// should be skipped. + pub fn recompute_top_user_relevant_frame(&mut self, skip: usize) { + self.top_user_relevant_frame = self.compute_top_user_relevant_frame(skip); } /// Set the top user-relevant frame to the given value. Must be equal to what /// `get_top_user_relevant_frame` would return! pub fn set_top_user_relevant_frame(&mut self, frame_idx: usize) { - debug_assert_eq!(Some(frame_idx), self.compute_top_user_relevant_frame()); + debug_assert_eq!(Some(frame_idx), self.compute_top_user_relevant_frame(0)); self.top_user_relevant_frame = Some(frame_idx); } /// Returns the topmost frame that is considered user-relevant, or the /// top of the stack if there is no such frame, or `None` if the stack is empty. pub fn top_user_relevant_frame(&self) -> Option { - debug_assert_eq!(self.top_user_relevant_frame, self.compute_top_user_relevant_frame()); + debug_assert_eq!(self.top_user_relevant_frame, self.compute_top_user_relevant_frame(0)); // This can be called upon creation of an allocation. We create allocations while setting up // parts of the Rust runtime when we do not have any stack frames yet, so we need to handle // empty stacks. diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index a90c6ab9d40e..8fe034d25829 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -354,11 +354,10 @@ pub fn create_ecx<'tcx>( argvs.push(arg_place.to_ref(&ecx)); } // Make an array with all these pointers, in the Miri memory. - let argvs_layout = ecx.layout_of(Ty::new_array( - tcx, - Ty::new_imm_ptr(tcx, tcx.types.u8), - u64::try_from(argvs.len()).unwrap(), - ))?; + let u8_ptr_type = Ty::new_imm_ptr(tcx, tcx.types.u8); + let u8_ptr_ptr_type = Ty::new_imm_ptr(tcx, u8_ptr_type); + let argvs_layout = + ecx.layout_of(Ty::new_array(tcx, u8_ptr_type, u64::try_from(argvs.len()).unwrap()))?; let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Machine.into())?; for (idx, arg) in argvs.into_iter().enumerate() { let place = ecx.project_field(&argvs_place, idx)?; @@ -373,10 +372,8 @@ pub fn create_ecx<'tcx>( ecx.mark_immutable(&argc_place); ecx.machine.argc = Some(argc_place.ptr()); - let argv_place = ecx.allocate( - ecx.layout_of(Ty::new_imm_ptr(tcx, tcx.types.unit))?, - MiriMemoryKind::Machine.into(), - )?; + let argv_place = + ecx.allocate(ecx.layout_of(u8_ptr_ptr_type)?, MiriMemoryKind::Machine.into())?; ecx.write_pointer(argvs_place.ptr(), &argv_place)?; ecx.mark_immutable(&argv_place); ecx.machine.argv = Some(argv_place.ptr()); @@ -398,7 +395,9 @@ pub fn create_ecx<'tcx>( } ecx.mark_immutable(&cmd_place); } - ecx.mplace_to_ref(&argvs_place)? + let imm = argvs_place.to_ref(&ecx); + let layout = ecx.layout_of(u8_ptr_ptr_type)?; + ImmTy::from_immediate(imm, layout) }; // Return place (in static memory so that it does not count as leak). diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 8e7c9edfcc07..935afcb6e929 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -470,7 +470,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { caller_fn_abi, &args.iter().map(|a| FnArg::Copy(a.clone().into())).collect::>(), /*with_caller_location*/ false, - &dest, + &dest.into(), stack_pop, ) } diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 982fbc318110..69baa472cd69 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -22,7 +22,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, + dest: &PlaceTy<'tcx>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option>> { @@ -45,7 +45,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let intrinsic_name = this.tcx.item_name(instance.def_id()); let intrinsic_name = intrinsic_name.as_str(); - match this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest, ret)? { + // FIXME: avoid allocating memory + let dest = this.force_allocation(dest)?; + + match this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, &dest, ret)? { EmulateItemResult::NotSupported => { // We haven't handled the intrinsic, let's see if we can use a fallback body. if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 1c6c7894cb45..ac1f9f3822cd 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1120,7 +1120,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { instance: ty::Instance<'tcx>, abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, Provenance>], - dest: &MPlaceTy<'tcx>, + dest: &PlaceTy<'tcx>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -1147,7 +1147,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { fn_val: DynSym, abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, Provenance>], - dest: &MPlaceTy<'tcx>, + dest: &PlaceTy<'tcx>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -1160,7 +1160,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx: &mut MiriInterpCx<'tcx>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, + dest: &PlaceTy<'tcx>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option>> { @@ -1639,15 +1639,21 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { interp_ok(()) } - fn before_stack_pop( - ecx: &InterpCx<'tcx, Self>, - frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>, - ) -> InterpResult<'tcx> { + fn before_stack_pop(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> { + let frame = ecx.frame(); // We want this *before* the return value copy, because the return place itself is protected // until we do `end_call` here. if ecx.machine.borrow_tracker.is_some() { ecx.on_stack_pop(frame)?; } + if frame.extra.is_user_relevant { + // All that we store is whether or not the frame we just removed is local, so now we + // have no idea where the next topmost local frame is. So we recompute it. + // (If this ever becomes a bottleneck, we could have `push` store the previous + // user-relevant frame and restore that here.) + // We have to skip the frame that is just being popped. + ecx.active_thread_mut().recompute_top_user_relevant_frame(/* skip */ 1); + } // tracing-tree can autoamtically annotate scope changes, but it gets very confused by our // concurrency and what it prints is just plain wrong. So we print our own information // instead. (Cc https://github.com/rust-lang/miri/issues/2266) @@ -1661,15 +1667,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { frame: Frame<'tcx, Provenance, FrameExtra<'tcx>>, unwinding: bool, ) -> InterpResult<'tcx, ReturnAction> { - if frame.extra.is_user_relevant { - // All that we store is whether or not the frame we just removed is local, so now we - // have no idea where the next topmost local frame is. So we recompute it. - // (If this ever becomes a bottleneck, we could have `push` store the previous - // user-relevant frame and restore that here.) - ecx.active_thread_mut().recompute_top_user_relevant_frame(); - } let res = { - // Move `frame`` into a sub-scope so we control when it will be dropped. + // Move `frame` into a sub-scope so we control when it will be dropped. let mut frame = frame; let timing = frame.extra.timing.take(); let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding); diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 52c16a0c2e2d..1195b741b19e 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -43,7 +43,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { link_name: Symbol, abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, + dest: &PlaceTy<'tcx>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -69,8 +69,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { _ => {} } + // FIXME: avoid allocating memory + let dest = this.force_allocation(dest)?; + // The rest either implements the logic, or falls back to `lookup_exported_symbol`. - match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { + match this.emulate_foreign_item_inner(link_name, abi, args, &dest)? { EmulateItemResult::NeedsReturn => { trace!("{:?}", this.dump_place(&dest.clone().into())); this.return_to_block(ret)?; @@ -111,7 +114,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { sym: DynSym, abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, + dest: &PlaceTy<'tcx>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs index 5138bcbf8f74..e7632d43126a 100644 --- a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs +++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs @@ -8,7 +8,7 @@ struct MakeSend(*const i32); unsafe impl Send for MakeSend {} fn main() { - race(0); + race(0); //~ERROR: Data race detected between (1) non-atomic read on thread `unnamed-1` and (2) deallocation on thread `main` } // Using an argument for the ptr to point to, since those do not get StorageDead. @@ -22,5 +22,4 @@ fn race(local: i32) { thread::yield_now(); // Deallocating the local (when `main` returns) // races with the read in the other thread. - // Make sure the error points at this function's end, not just the call site. -} //~ERROR: Data race detected between (1) non-atomic read on thread `unnamed-1` and (2) deallocation on thread `main` +} diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr index 643426aba99e..721b75630449 100644 --- a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr +++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) deallocation on thread `main` at ALLOC. (2) just happened here --> tests/fail/data_race/stack_pop_race.rs:LL:CC | -LL | } - | ^ Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) deallocation on thread `main` at ALLOC. (2) just happened here +LL | race(0); + | ^^^^^^^ Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) deallocation on thread `main` at ALLOC. (2) just happened here | help: and (1) occurred earlier here --> tests/fail/data_race/stack_pop_race.rs:LL:CC @@ -12,12 +12,7 @@ LL | let _val = unsafe { *ptr.0 }; = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE (of the first span): - = note: inside `race` at tests/fail/data_race/stack_pop_race.rs:LL:CC -note: inside `main` - --> tests/fail/data_race/stack_pop_race.rs:LL:CC - | -LL | race(0); - | ^^^^^^^ + = note: inside `main` at tests/fail/data_race/stack_pop_race.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr b/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr index 33e1e53ea060..15f73c8a9ae1 100644 --- a/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr +++ b/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr @@ -14,8 +14,8 @@ LL | let local = 0; help: ALLOC was deallocated here: --> tests/fail/tail_calls/dangling-local-var.rs:LL:CC | -LL | become g(ptr) - | ^^^^^^^^^^^^^ +LL | f(std::ptr::null()); + | ^^^^^^^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): = note: inside `g` at tests/fail/tail_calls/dangling-local-var.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.rs b/src/tools/miri/tests/pass/alloc-access-tracking.rs index c47063bef03c..0e88951dc43f 100644 --- a/src/tools/miri/tests/pass/alloc-access-tracking.rs +++ b/src/tools/miri/tests/pass/alloc-access-tracking.rs @@ -1,7 +1,7 @@ #![no_std] #![no_main] -//@compile-flags: -Zmiri-track-alloc-id=21 -Zmiri-track-alloc-accesses -Cpanic=abort -//@normalize-stderr-test: "id 21" -> "id $$ALLOC" +//@compile-flags: -Zmiri-track-alloc-id=20 -Zmiri-track-alloc-accesses -Cpanic=abort +//@normalize-stderr-test: "id 20" -> "id $$ALLOC" //@only-target: linux # alloc IDs differ between OSes (due to extern static allocations) extern "Rust" { From 1eba1b56e33f196e6b48cad2efb41b9b9ab7452f Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 22 May 2025 16:05:52 -0500 Subject: [PATCH 083/139] rustdoc: rip out all the gui tests for <100% width mobile sidebar stuff like "clicking the settings menu closes the mobile sidebar" is now impossible for users to observe, since the mobile sidebar will always cover the settings menu due to being full-width, which is good because that behavior is also now impossible for our testing framework to observe. --- tests/rustdoc-gui/notable-trait.goml | 4 ---- tests/rustdoc-gui/pocket-menu.goml | 13 ------------- tests/rustdoc-gui/sidebar-mobile.goml | 7 +++++-- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index 4624fb80b377..7fc70e0675df 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -244,10 +244,6 @@ click: ".sidebar-menu-toggle" assert: "//*[@class='sidebar shown']" assert-count: ("//*[@class='tooltip popover']", 0) assert-false: "#method\.create_an_iterator_from_read .tooltip:focus" -// Clicking a notable trait tooltip popover should close the sidebar. -click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" -assert-count: ("//*[@class='tooltip popover']", 1) -assert-false: "//*[@class='sidebar shown']" // Also check the focus handling for the settings button. set-window-size: (1100, 600) diff --git a/tests/rustdoc-gui/pocket-menu.goml b/tests/rustdoc-gui/pocket-menu.goml index 4a062fec7516..073172dd8a79 100644 --- a/tests/rustdoc-gui/pocket-menu.goml +++ b/tests/rustdoc-gui/pocket-menu.goml @@ -68,16 +68,3 @@ assert-css: ("#settings-menu .popover", {"display": "block"}) click: ".sidebar-menu-toggle" assert: "//*[@class='sidebar shown']" assert-css: ("#settings-menu .popover", {"display": "none"}) -// Opening the settings popover should close the sidebar. -click: "#settings-menu a" -assert-css: ("#settings-menu .popover", {"display": "block"}) -assert-false: "//*[@class='sidebar shown']" - -// Opening the settings popover at start (which async loads stuff) should also close. -reload: -click: ".sidebar-menu-toggle" -assert: "//*[@class='sidebar shown']" -assert-false: "#settings-menu .popover" -click: "#settings-menu a" -assert-false: "//*[@class='sidebar shown']" -wait-for: "#settings-menu .popover" diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml index 4ada4837a577..0596f8431748 100644 --- a/tests/rustdoc-gui/sidebar-mobile.goml +++ b/tests/rustdoc-gui/sidebar-mobile.goml @@ -32,8 +32,8 @@ assert-css: ( {"display": "block"} ) -// Click elsewhere. -click: "body" +// Click the toggle to close it +click: ".sidebar-menu-toggle" assert-css: (".sidebar", {"display": "block", "left": "-1000px"}) // Open the sidebar menu, and make sure pressing Escape closes it. @@ -57,6 +57,7 @@ scroll-to: ".block.keyword li:nth-child(1)" compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 544}) // Now checking the background color of the sidebar. +reload: show-text: true define-function: ( @@ -72,6 +73,8 @@ define-function: ( "background-color": |background|, "color": |color|, }) + // Close the sidebar menu. + press-key: "Escape" }, ) From 04ddafc53ce0e045bae86ad0b20f5be540ca0e84 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 23 May 2025 10:18:05 +0000 Subject: [PATCH 084/139] Properly analyze captures from unsafe binders --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 16 +++++++++++--- compiler/rustc_hir_typeck/src/upvar.rs | 8 +++++-- compiler/rustc_middle/src/hir/place.rs | 3 +++ .../src/builder/expr/as_place.rs | 3 +++ compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 +++ src/tools/clippy/clippy_utils/src/sugg.rs | 2 ++ tests/ui/unsafe-binders/cat-projection.rs | 21 +++++++++++++++++++ 7 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 tests/ui/unsafe-binders/cat-projection.rs diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 3493d359028d..203413188282 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -13,6 +13,7 @@ use hir::Expr; use hir::def::DefKind; use hir::pat_util::EnumerateAndAdjustIterator as _; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_ast::UnsafeBinderCastKind; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def::{CtorOf, Res}; use rustc_hir::def_id::LocalDefId; @@ -1393,10 +1394,18 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.cat_res(expr.hir_id, expr.span, expr_ty, res) } - // both type ascription and unsafe binder casts don't affect - // the place-ness of the subexpression. + // type ascription doesn't affect the place-ness of the subexpression. hir::ExprKind::Type(e, _) => self.cat_expr(e), - hir::ExprKind::UnsafeBinderCast(_, e, _) => self.cat_expr(e), + + hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Unwrap, e, _) => { + let base = self.cat_expr(e)?; + Ok(self.cat_projection( + expr.hir_id, + base, + expr_ty, + ProjectionKind::UnwrapUnsafeBinder, + )) + } hir::ExprKind::AddrOf(..) | hir::ExprKind::Call(..) @@ -1427,6 +1436,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx | hir::ExprKind::Repeat(..) | hir::ExprKind::InlineAsm(..) | hir::ExprKind::OffsetOf(..) + | hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Wrap, ..) | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr_ty)), } } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 8ab71e5220bb..4b2e87f5674a 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -902,7 +902,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_field<'a>(p: &&Projection<'a>) -> bool { match p.kind { ProjectionKind::Field(_, _) => true, - ProjectionKind::Deref | ProjectionKind::OpaqueCast => false, + ProjectionKind::Deref + | ProjectionKind::OpaqueCast + | ProjectionKind::UnwrapUnsafeBinder => false, p @ (ProjectionKind::Subslice | ProjectionKind::Index) => { bug!("ProjectionKind {:?} was unexpected", p) } @@ -2197,7 +2199,8 @@ fn restrict_capture_precision( } ProjectionKind::Deref => {} ProjectionKind::OpaqueCast => {} - ProjectionKind::Field(..) => {} // ignore + ProjectionKind::Field(..) => {} + ProjectionKind::UnwrapUnsafeBinder => {} } } @@ -2268,6 +2271,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String ProjectionKind::Index => String::from("Index"), ProjectionKind::Subslice => String::from("Subslice"), ProjectionKind::OpaqueCast => String::from("OpaqueCast"), + ProjectionKind::UnwrapUnsafeBinder => String::from("UnwrapUnsafeBinder"), }; if i != 0 { projections_str.push(','); diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index c3d10615cf10..a34a3419d68b 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -43,6 +43,9 @@ pub enum ProjectionKind { /// /// This is unused if `-Znext-solver` is enabled. OpaqueCast, + + /// `unwrap_binder!(expr)` + UnwrapUnsafeBinder, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index fbe530811567..830a129c5854 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -240,6 +240,9 @@ fn strip_prefix<'tcx>( HirProjectionKind::OpaqueCast => { assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..))); } + HirProjectionKind::UnwrapUnsafeBinder => { + assert_matches!(iter.next(), Some(ProjectionElem::UnwrapUnsafeBinder(..))); + } HirProjectionKind::Index | HirProjectionKind::Subslice => { bug!("unexpected projection kind: {:?}", projection); } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index fde23413972b..226dc920a496 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -1220,6 +1220,9 @@ impl<'tcx> ThirBuildCx<'tcx> { HirProjectionKind::OpaqueCast => { ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) } } + HirProjectionKind::UnwrapUnsafeBinder => ExprKind::PlaceUnwrapUnsafeBinder { + source: self.thir.exprs.push(captured_place_expr), + }, HirProjectionKind::Index | HirProjectionKind::Subslice => { // We don't capture these projections, so we can ignore them here continue; diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 93dec113d31a..f4dfc8f4b5a7 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -941,6 +941,8 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { ProjectionKind::Subslice | // Doesn't have surface syntax. Only occurs in patterns. ProjectionKind::OpaqueCast => (), + // Only occurs in closure captures. + ProjectionKind::UnwrapUnsafeBinder => (), ProjectionKind::Deref => { // Explicit derefs are typically handled later on, but // some items do not need explicit deref, such as array accesses, diff --git a/tests/ui/unsafe-binders/cat-projection.rs b/tests/ui/unsafe-binders/cat-projection.rs new file mode 100644 index 000000000000..dd7a78d59b36 --- /dev/null +++ b/tests/ui/unsafe-binders/cat-projection.rs @@ -0,0 +1,21 @@ +//@ check-pass + +#![feature(unsafe_binders)] +#![allow(incomplete_features)] + +use std::unsafe_binder::unwrap_binder; + +#[derive(Copy, Clone)] +pub struct S([usize; 8]); + +// Regression test for . +pub fn by_value(x: unsafe<'a> S) -> usize { + unsafe { (|| unwrap_binder!(x).0[0])() } +} + +// Regression test for . +pub fn by_ref(x: unsafe<'a> &'a S) -> usize { + unsafe { (|| unwrap_binder!(x).0[0])() } +} + +fn main() {} From 11392f4978fe3a81a87e4fd8abcb78a0dcf166e5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 23 May 2025 09:44:22 +0000 Subject: [PATCH 085/139] Emit dummy open drop for unsafe binder --- .../rustc_mir_transform/src/elaborate_drop.rs | 17 +++++++++++++++++ tests/ui/unsafe/move-out-of-non-copy.rs | 15 +++++++++++++++ tests/ui/unsafe/move-out-of-non-copy.stderr | 14 ++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 tests/ui/unsafe/move-out-of-non-copy.rs create mode 100644 tests/ui/unsafe/move-out-of-non-copy.stderr diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 14f7c2a263b6..211e2a92f73d 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -1278,6 +1278,23 @@ where } ty::Slice(ety) => self.drop_loop_trio_for_slice(*ety), + ty::UnsafeBinder(_) => { + // Unsafe binders may elaborate drops if their inner type isn't copy. + // This is enforced in typeck, so this should never happen. + self.tcx().dcx().span_delayed_bug( + self.source_info.span, + "open drop for unsafe binder shouldn't be encountered", + ); + self.elaborator.patch().new_block(BasicBlockData { + statements: vec![], + terminator: Some(Terminator { + source_info: self.source_info, + kind: TerminatorKind::Unreachable, + }), + is_cleanup: self.unwind.is_cleanup(), + }) + } + _ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty), } } diff --git a/tests/ui/unsafe/move-out-of-non-copy.rs b/tests/ui/unsafe/move-out-of-non-copy.rs new file mode 100644 index 000000000000..ca6bf4277a15 --- /dev/null +++ b/tests/ui/unsafe/move-out-of-non-copy.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Zvalidate-mir + +// Regression test for . + +#![feature(unsafe_binders)] +#![allow(incomplete_features)] + +use std::unsafe_binder::unwrap_binder; + +fn id(x: unsafe<> T) -> T { + //~^ ERROR the trait bound `T: Copy` is not satisfied + unsafe { unwrap_binder!(x) } +} + +fn main() {} diff --git a/tests/ui/unsafe/move-out-of-non-copy.stderr b/tests/ui/unsafe/move-out-of-non-copy.stderr new file mode 100644 index 000000000000..4598742c92b4 --- /dev/null +++ b/tests/ui/unsafe/move-out-of-non-copy.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/move-out-of-non-copy.rs:10:13 + | +LL | fn id(x: unsafe<> T) -> T { + | ^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +help: consider restricting type parameter `T` with trait `Copy` + | +LL | fn id(x: unsafe<> T) -> T { + | +++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 89a8abc4bea115c3508ee5ac4eb9ac3a55920316 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 21 May 2025 19:18:31 +0200 Subject: [PATCH 086/139] use `cfg_select!` to select the right `VaListImpl` definition --- library/core/src/ffi/va_list.rs | 311 ++++++++++++++------------------ 1 file changed, 136 insertions(+), 175 deletions(-) diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs index f12bd289f27a..8f7c090bc1ba 100644 --- a/library/core/src/ffi/va_list.rs +++ b/library/core/src/ffi/va_list.rs @@ -5,148 +5,120 @@ use crate::ffi::c_void; #[allow(unused_imports)] use crate::fmt; -use crate::marker::PhantomData; +use crate::marker::{PhantomData, PhantomInvariantLifetime}; use crate::ops::{Deref, DerefMut}; -/// Basic implementation of a `va_list`. // The name is WIP, using `VaListImpl` for now. -#[cfg(any( +// +// Most targets explicitly specify the layout of `va_list`, this layout is matched here. +crate::cfg_select! { all( - not(target_arch = "aarch64"), - not(target_arch = "powerpc"), - not(target_arch = "s390x"), - not(target_arch = "xtensa"), - not(target_arch = "x86_64") - ), - all(target_arch = "aarch64", target_vendor = "apple"), - target_family = "wasm", - target_os = "uefi", - windows, -))] -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - ptr: *mut c_void, + target_arch = "aarch64", + not(target_vendor = "apple"), + not(target_os = "uefi"), + not(windows), + ) => { + /// AArch64 ABI implementation of a `va_list`. See the + /// [AArch64 Procedure Call Standard] for more details. + /// + /// [AArch64 Procedure Call Standard]: + /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf + #[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + stack: *mut c_void, + gr_top: *mut c_void, + vr_top: *mut c_void, + gr_offs: i32, + vr_offs: i32, + _marker: PhantomInvariantLifetime<'f>, + } + } + all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)) => { + /// PowerPC ABI implementation of a `va_list`. + #[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + gpr: u8, + fpr: u8, + reserved: u16, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomInvariantLifetime<'f>, + } + } + target_arch = "s390x" => { + /// s390x ABI implementation of a `va_list`. + #[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + gpr: i64, + fpr: i64, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomInvariantLifetime<'f>, + } + } + all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)) => { + /// x86_64 ABI implementation of a `va_list`. + #[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + gp_offset: i32, + fp_offset: i32, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomInvariantLifetime<'f>, + } + } + target_arch = "xtensa" => { + /// Xtensa ABI implementation of a `va_list`. + #[repr(C)] + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + stk: *mut i32, + reg: *mut i32, + ndx: i32, + _marker: PhantomInvariantLifetime<'f>, + } + } - // Invariant over `'f`, so each `VaListImpl<'f>` object is tied to - // the region of the function it's defined in - _marker: PhantomData<&'f mut &'f c_void>, -} + // The fallback implementation, used for: + // + // - apple aarch64 (see https://github.com/rust-lang/rust/pull/56599) + // - windows + // - uefi + // - any other target for which we don't specify the `VaListImpl` above + // + // In this implementation the `va_list` type is just an alias for an opaque pointer. + // That pointer is probably just the next variadic argument on the caller's stack. + _ => { + /// Basic implementation of a `va_list`. + #[repr(transparent)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + ptr: *mut c_void, -#[cfg(any( - all( - not(target_arch = "aarch64"), - not(target_arch = "powerpc"), - not(target_arch = "s390x"), - not(target_arch = "xtensa"), - not(target_arch = "x86_64") - ), - all(target_arch = "aarch64", target_vendor = "apple"), - target_family = "wasm", - target_os = "uefi", - windows, -))] -impl<'f> fmt::Debug for VaListImpl<'f> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "va_list* {:p}", self.ptr) + // Invariant over `'f`, so each `VaListImpl<'f>` object is tied to + // the region of the function it's defined in + _marker: PhantomInvariantLifetime<'f>, + } + + impl<'f> fmt::Debug for VaListImpl<'f> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "va_list* {:p}", self.ptr) + } + } } } -/// AArch64 ABI implementation of a `va_list`. See the -/// [AArch64 Procedure Call Standard] for more details. -/// -/// [AArch64 Procedure Call Standard]: -/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf -#[cfg(all( - target_arch = "aarch64", - not(target_vendor = "apple"), - not(target_os = "uefi"), - not(windows), -))] -#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - stack: *mut c_void, - gr_top: *mut c_void, - vr_top: *mut c_void, - gr_offs: i32, - vr_offs: i32, - _marker: PhantomData<&'f mut &'f c_void>, -} - -/// PowerPC ABI implementation of a `va_list`. -#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))] -#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - gpr: u8, - fpr: u8, - reserved: u16, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomData<&'f mut &'f c_void>, -} - -/// s390x ABI implementation of a `va_list`. -#[cfg(target_arch = "s390x")] -#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - gpr: i64, - fpr: i64, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomData<&'f mut &'f c_void>, -} - -/// x86_64 ABI implementation of a `va_list`. -#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))] -#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - gp_offset: i32, - fp_offset: i32, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomData<&'f mut &'f c_void>, -} - -/// Xtensa ABI implementation of a `va_list`. -#[cfg(target_arch = "xtensa")] -#[repr(C)] -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - stk: *mut i32, - reg: *mut i32, - ndx: i32, - _marker: PhantomData<&'f mut &'f c_void>, -} - -/// A wrapper for a `va_list` -#[repr(transparent)] -#[derive(Debug)] -pub struct VaList<'a, 'f: 'a> { - #[cfg(any( - all( - not(target_arch = "aarch64"), - not(target_arch = "powerpc"), - not(target_arch = "s390x"), - not(target_arch = "x86_64") - ), - target_arch = "xtensa", - all(target_arch = "aarch64", target_vendor = "apple"), - target_family = "wasm", - target_os = "uefi", - windows, - ))] - inner: VaListImpl<'f>, - - #[cfg(all( +crate::cfg_select! { + all( any( target_arch = "aarch64", target_arch = "powerpc", @@ -158,52 +130,41 @@ pub struct VaList<'a, 'f: 'a> { not(target_family = "wasm"), not(target_os = "uefi"), not(windows), - ))] - inner: &'a mut VaListImpl<'f>, + ) => { + /// A wrapper for a `va_list` + #[repr(transparent)] + #[derive(Debug)] + pub struct VaList<'a, 'f: 'a> { + inner: &'a mut VaListImpl<'f>, + _marker: PhantomData<&'a mut VaListImpl<'f>>, + } - _marker: PhantomData<&'a mut VaListImpl<'f>>, -} -#[cfg(any( - all( - not(target_arch = "aarch64"), - not(target_arch = "powerpc"), - not(target_arch = "s390x"), - not(target_arch = "x86_64") - ), - target_arch = "xtensa", - all(target_arch = "aarch64", target_vendor = "apple"), - target_family = "wasm", - target_os = "uefi", - windows, -))] -impl<'f> VaListImpl<'f> { - /// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. - #[inline] - pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { - VaList { inner: VaListImpl { ..*self }, _marker: PhantomData } + impl<'f> VaListImpl<'f> { + /// Converts a [`VaListImpl`] into a [`VaList`] that is binary-compatible with C's `va_list`. + #[inline] + pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { + VaList { inner: self, _marker: PhantomData } + } + } } -} -#[cfg(all( - any( - target_arch = "aarch64", - target_arch = "powerpc", - target_arch = "s390x", - target_arch = "xtensa", - target_arch = "x86_64" - ), - not(target_arch = "xtensa"), - any(not(target_arch = "aarch64"), not(target_vendor = "apple")), - not(target_family = "wasm"), - not(target_os = "uefi"), - not(windows), -))] -impl<'f> VaListImpl<'f> { - /// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. - #[inline] - pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { - VaList { inner: self, _marker: PhantomData } + _ => { + /// A wrapper for a `va_list` + #[repr(transparent)] + #[derive(Debug)] + pub struct VaList<'a, 'f: 'a> { + inner: VaListImpl<'f>, + _marker: PhantomData<&'a mut VaListImpl<'f>>, + } + + impl<'f> VaListImpl<'f> { + /// Converts a [`VaListImpl`] into a [`VaList`] that is binary-compatible with C's `va_list`. + #[inline] + pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { + VaList { inner: VaListImpl { ..*self }, _marker: PhantomData } + } + } } } From 180ab161b025e62c4fd0f772c820f2621fca4a81 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 23 May 2025 15:02:56 +0200 Subject: [PATCH 087/139] make teach_help message for cast-before-pass-to-variadic more precise --- compiler/rustc_hir_typeck/messages.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 23309102c4da..034cec83299a 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -169,7 +169,7 @@ hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value in hir_typeck_pass_to_variadic_function = can't pass `{$ty}` to variadic function .suggestion = cast the value to `{$cast_ty}` - .teach_help = certain types, like `{$ty}`, must be casted before passing them to a variadic function, because of arcane ABI rules dictated by the C standard + .teach_help = certain types, like `{$ty}`, must be cast before passing them to a variadic function to match the implicit cast that a C compiler would perform as part of C's integer promotion rules hir_typeck_ptr_cast_add_auto_to_object = cannot add {$traits_len -> [1] auto trait {$traits} From 898b6a13f1bdbeb5adbf45875fac01cec09d09a4 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 23 May 2025 16:50:24 +0800 Subject: [PATCH 088/139] further deduplicate ast visitor code --- compiler/rustc_ast/src/mut_visit.rs | 238 +------------- compiler/rustc_ast/src/visit.rs | 475 ++++++++++++++++------------ compiler/rustc_lint/src/early.rs | 2 +- 3 files changed, 285 insertions(+), 430 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index a90349f318c0..6770fd5a4aae 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -20,7 +20,7 @@ use thin_vec::ThinVec; use crate::ast::*; use crate::ptr::P; use crate::tokenstream::*; -use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit}; +use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit, visit_opt, walk_list}; pub trait ExpectOne { fn expect_one(self, err: &'static str) -> A::Item; @@ -33,18 +33,6 @@ impl ExpectOne for SmallVec { } } -pub trait WalkItemKind { - type Ctxt; - fn walk( - &mut self, - span: Span, - id: NodeId, - visibility: &mut Visibility, - ctxt: Self::Ctxt, - visitor: &mut impl MutVisitor, - ); -} - pub trait MutVisitor: Sized { // Methods in this trait have one of three forms: // @@ -451,11 +439,6 @@ fn visit_thin_exprs(vis: &mut T, exprs: &mut ThinVec>) { exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr)) } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -fn visit_bounds(vis: &mut T, bounds: &mut GenericBounds, ctxt: BoundKind) { - visit_vec(bounds, |bound| vis.visit_param_bound(bound, ctxt)); -} - // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_attr_args(vis: &mut T, args: &mut AttrArgs) { match args { @@ -610,12 +593,6 @@ pub fn walk_ty_pat(vis: &mut T, ty: &mut P) { vis.visit_span(span); } -fn walk_foreign_mod(vis: &mut T, foreign_mod: &mut ForeignMod) { - let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod; - visit_safety(vis, safety); - items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); -} - pub fn walk_variant(visitor: &mut T, variant: &mut Variant) { let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = variant; visitor.visit_id(id); @@ -771,22 +748,6 @@ pub fn walk_flat_map_param(vis: &mut T, mut param: Param) -> Smal smallvec![param] } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -fn visit_defaultness(vis: &mut T, defaultness: &mut Defaultness) { - match defaultness { - Defaultness::Default(span) => vis.visit_span(span), - Defaultness::Final => {} - } -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -fn visit_polarity(vis: &mut T, polarity: &mut ImplPolarity) { - match polarity { - ImplPolarity::Positive => {} - ImplPolarity::Negative(span) => vis.visit_span(span), - } -} - fn walk_closure_binder(vis: &mut T, binder: &mut ClosureBinder) { match binder { ClosureBinder::NotPresent => {} @@ -1080,169 +1041,15 @@ pub fn walk_item_kind( kind.walk(span, id, visibility, ctxt, vis) } -impl WalkItemKind for ItemKind { - type Ctxt = (); - fn walk( - &mut self, - span: Span, - id: NodeId, - visibility: &mut Visibility, - _ctxt: Self::Ctxt, - vis: &mut impl MutVisitor, - ) { - match self { - ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident), - ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(box StaticItem { - ident, - ty, - safety: _, - mutability: _, - expr, - define_opaque, - }) => { - vis.visit_ident(ident); - vis.visit_ty(ty); - visit_opt(expr, |expr| vis.visit_expr(expr)); - walk_define_opaques(vis, define_opaque); - } - ItemKind::Const(item) => { - walk_const_item(vis, item); - } - ItemKind::Fn(func) => { - vis.visit_fn(FnKind::Fn(FnCtxt::Free, visibility, &mut *func), span, id); - } - ItemKind::Mod(safety, ident, mod_kind) => { - visit_safety(vis, safety); - vis.visit_ident(ident); - match mod_kind { - ModKind::Loaded( - items, - _inline, - ModSpans { inner_span, inject_use_span }, - _, - ) => { - items.flat_map_in_place(|item| vis.flat_map_item(item)); - vis.visit_span(inner_span); - vis.visit_span(inject_use_span); - } - ModKind::Unloaded => {} - } - } - ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), - ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm), - ItemKind::TyAlias(box TyAlias { - defaultness, - ident, - generics, - where_clauses, - bounds, - ty, - }) => { - visit_defaultness(vis, defaultness); - vis.visit_ident(ident); - vis.visit_generics(generics); - visit_bounds(vis, bounds, BoundKind::Bound); - visit_opt(ty, |ty| vis.visit_ty(ty)); - walk_ty_alias_where_clauses(vis, where_clauses); - } - ItemKind::Enum(ident, EnumDef { variants }, generics) => { - vis.visit_ident(ident); - vis.visit_generics(generics); - variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); - } - ItemKind::Struct(ident, variant_data, generics) - | ItemKind::Union(ident, variant_data, generics) => { - vis.visit_ident(ident); - vis.visit_generics(generics); - vis.visit_variant_data(variant_data); - } - ItemKind::Impl(box Impl { - defaultness, - safety, - generics, - constness, - polarity, - of_trait, - self_ty, - items, - }) => { - visit_defaultness(vis, defaultness); - visit_safety(vis, safety); - vis.visit_generics(generics); - visit_constness(vis, constness); - visit_polarity(vis, polarity); - visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref)); - vis.visit_ty(self_ty); - items.flat_map_in_place(|item| { - vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() }) - }); - } - ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => { - visit_safety(vis, safety); - vis.visit_ident(ident); - vis.visit_generics(generics); - visit_bounds(vis, bounds, BoundKind::Bound); - items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait)); - } - ItemKind::TraitAlias(ident, generics, bounds) => { - vis.visit_ident(ident); - vis.visit_generics(generics); - visit_bounds(vis, bounds, BoundKind::Bound); - } - ItemKind::MacCall(m) => vis.visit_mac_call(m), - ItemKind::MacroDef(ident, def) => { - vis.visit_ident(ident); - vis.visit_macro_def(def) - } - ItemKind::Delegation(box Delegation { - id, - qself, - path, - ident, - rename, - body, - from_glob: _, - }) => { - vis.visit_id(id); - vis.visit_qself(qself); - vis.visit_path(path); - vis.visit_ident(ident); - if let Some(rename) = rename { - vis.visit_ident(rename); - } - if let Some(body) = body { - vis.visit_block(body); - } - } - ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { - vis.visit_qself(qself); - vis.visit_path(prefix); - if let Some(suffixes) = suffixes { - for (ident, rename) in suffixes { - vis.visit_ident(ident); - if let Some(rename) = rename { - vis.visit_ident(rename); - } - } - } - if let Some(body) = body { - vis.visit_block(body); - } - } - } - } -} - impl WalkItemKind for AssocItemKind { type Ctxt = AssocCtxt; - fn walk( + fn walk( &mut self, span: Span, id: NodeId, visibility: &mut Visibility, ctxt: Self::Ctxt, - visitor: &mut impl MutVisitor, + visitor: &mut V, ) { match self { AssocItemKind::Const(item) => { @@ -1306,16 +1113,6 @@ impl WalkItemKind for AssocItemKind { } } -fn walk_const_item(vis: &mut T, item: &mut ConstItem) { - let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item; - visit_defaultness(vis, defaultness); - vis.visit_ident(ident); - vis.visit_generics(generics); - vis.visit_ty(ty); - visit_opt(expr, |expr| vis.visit_expr(expr)); - walk_define_opaques(vis, define_opaque); -} - pub fn walk_crate(vis: &mut T, krate: &mut Crate) { let Crate { attrs, items, spans, id, is_placeholder: _ } = krate; vis.visit_id(id); @@ -1334,19 +1131,6 @@ pub fn walk_assoc_item(visitor: &mut impl MutVisitor, item: &mut P, c walk_item_ctxt(visitor, item, ctxt) } -fn walk_item_ctxt( - visitor: &mut impl MutVisitor, - item: &mut P>, - ctxt: K::Ctxt, -) { - let Item { attrs, id, kind, vis, span, tokens: _ } = item.deref_mut(); - visitor.visit_id(id); - visit_attrs(visitor, attrs); - visitor.visit_vis(vis); - kind.walk(*span, *id, vis, ctxt, visitor); - visitor.visit_span(span); -} - pub fn walk_flat_map_item(vis: &mut impl MutVisitor, mut item: P) -> SmallVec<[P; 1]> { vis.visit_item(&mut item); smallvec![item] @@ -1371,13 +1155,13 @@ pub fn walk_flat_map_assoc_item( impl WalkItemKind for ForeignItemKind { type Ctxt = (); - fn walk( + fn walk( &mut self, span: Span, id: NodeId, visibility: &mut Visibility, _ctxt: Self::Ctxt, - visitor: &mut impl MutVisitor, + visitor: &mut V, ) { match self { ForeignItemKind::Static(box StaticItem { @@ -1786,18 +1570,6 @@ fn walk_capture_by(vis: &mut T, capture_by: &mut CaptureBy) { } } -fn walk_define_opaques( - vis: &mut T, - define_opaque: &mut Option>, -) { - if let Some(define_opaque) = define_opaque { - for (id, path) in define_opaque { - vis.visit_id(id); - vis.visit_path(path) - } - } -} - /// Some value for the AST node that is valid but possibly meaningless. Similar /// to `Default` but not intended for wide use. The value will never be used /// meaningfully, it exists just to support unwinding in `visit_clobber` in the diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e43d7ae065d9..c06942574809 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -112,18 +112,6 @@ pub enum LifetimeCtxt { GenericArg, } -pub trait WalkItemKind { - type Ctxt; - fn walk<'a, V: Visitor<'a>>( - &'a self, - span: Span, - id: NodeId, - visibility: &'a Visibility, - ctxt: Self::Ctxt, - visitor: &mut V, - ) -> V::Result; -} - /// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; @@ -141,6 +129,9 @@ pub trait Visitor<'ast>: Sized { fn visit_ident(&mut self, _ident: &'ast Ident) -> Self::Result { Self::Result::output() } + fn visit_foreign_mod(&mut self, nm: &'ast ForeignMod) -> Self::Result { + walk_foreign_mod(self, nm) + } fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result { walk_item(self, i) } @@ -242,7 +233,7 @@ pub trait Visitor<'ast>: Sized { fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result { walk_mac(self, mac) } - fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) -> Self::Result { + fn visit_macro_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) -> Self::Result { Self::Result::output() } fn visit_path(&mut self, path: &'ast Path, _id: NodeId) -> Self::Result { @@ -318,6 +309,18 @@ pub trait Visitor<'ast>: Sized { #[macro_export] macro_rules! common_visitor_and_walkers { ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => { + pub trait WalkItemKind { + type Ctxt; + fn walk<$($lt,)? V: $Visitor$(<$lt>)?>( + &$($lt)? $($mut)? self, + span: Span, + id: NodeId, + visibility: &$($lt)? $($mut)? Visibility, + ctxt: Self::Ctxt, + visitor: &mut V, + ) $(-> >::Result)?; + } + // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier $(${ignore($lt)} #[expect(unused, rustc::pass_by_value)] @@ -325,7 +328,7 @@ macro_rules! common_visitor_and_walkers { )? fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, span: &$($lt)? $($mut)? Span) $(-> >::Result)? { $( - let _ = stringify!($mut); + ${ignore($mut)} visitor.visit_span(span); )? $(${ignore($lt)}V::Result::output())? @@ -338,7 +341,7 @@ macro_rules! common_visitor_and_walkers { )? fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, id: &$($lt)? $($mut)? NodeId) $(-> >::Result)? { $( - let _ = stringify!($mut); + ${ignore($mut)} visitor.visit_id(id); )? $(${ignore($lt)}V::Result::output())? @@ -362,6 +365,27 @@ macro_rules! common_visitor_and_walkers { } } + fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) $(-> >::Result)? { + match defaultness { + Defaultness::Default(span) => visit_span(vis, span), + Defaultness::Final => { + $(>::Result::output())? + } + } + } + + fn visit_polarity<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, polarity: &$($lt)? $($mut)? ImplPolarity) $(-> >::Result)? { + match polarity { + ImplPolarity::Positive => { $(>::Result::output())? } + ImplPolarity::Negative(span) => visit_span(vis, span), + } + } + + fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) $(-> >::Result)? { + walk_list!(visitor, visit_param_bound, bounds, ctxt); + $(>::Result::output())? + } + pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) $(-> >::Result)? { visitor.visit_ident(ident) } @@ -379,6 +403,246 @@ macro_rules! common_visitor_and_walkers { try_visit!(visit_id(visitor, id)); visitor.visit_ident(ident) } + + fn walk_item_ctxt<$($lt,)? V: $Visitor$(<$lt>)?, K: WalkItemKind>( + visitor: &mut V, + item: &$($mut P>)? $($lt Item)?, + ctxt: K::Ctxt, + ) $(-> >::Result)? { + let Item { attrs, id, kind, vis, span, tokens: _ } = &$($mut *)? *item; + try_visit!(visit_id(visitor, id)); + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_vis(vis)); + try_visit!(kind.walk(*span, *id, vis, ctxt, visitor)); + visit_span(visitor, span) + } + + impl WalkItemKind for ItemKind { + type Ctxt = (); + fn walk<$($lt,)? V: $Visitor$(<$lt>)?>( + &$($lt)? $($mut)? self, + span: Span, + id: NodeId, + visibility: &$($lt)? $($mut)? Visibility, + _ctxt: Self::Ctxt, + vis: &mut V, + ) $(-> >::Result)? { + match self { + ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident), + // FIXME(fee1-dead): look into this weird assymetry + ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree$(${ignore($lt)}, id, false)?), + ItemKind::Static(box StaticItem { + ident, + ty, + safety: _, + mutability: _, + expr, + define_opaque, + }) => { + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_ty(ty)); + visit_opt!(vis, visit_expr, expr); + walk_define_opaques(vis, define_opaque) + } + ItemKind::Const(item) => { + walk_const_item(vis, item) + } + ItemKind::Fn(func) => { + let kind = FnKind::Fn(FnCtxt::Free, visibility, &$($mut)? *func); + vis.visit_fn(kind, span, id) + } + ItemKind::Mod(safety, ident, mod_kind) => { + try_visit!(visit_safety(vis, safety)); + try_visit!(vis.visit_ident(ident)); + match mod_kind { + ModKind::Loaded( + items, + _inline, + ModSpans { inner_span, inject_use_span }, + _, + ) => { + $(${ignore($mut)} + items.flat_map_in_place(|item| vis.flat_map_item(item)); + )? + $(${ignore($lt)} + walk_list!(vis, visit_item, items); + )? + try_visit!(visit_span(vis, inner_span)); + try_visit!(visit_span(vis, inject_use_span)); + } + ModKind::Unloaded => {} + } + $(>::Result::output())? + } + ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), + ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm), + ItemKind::TyAlias(box TyAlias { + defaultness, + ident, + generics, + $(${ignore($lt)} #[expect(unused)])? + where_clauses, + bounds, + ty, + }) => { + try_visit!(visit_defaultness(vis, defaultness)); + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_generics(generics)); + try_visit!(visit_bounds(vis, bounds, BoundKind::Bound)); + visit_opt!(vis, visit_ty, ty); + $(${ignore($mut)} + walk_ty_alias_where_clauses(vis, where_clauses); + )? + $(>::Result::output())? + } + ItemKind::Enum(ident, enum_definition, generics) => { + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_generics(generics)); + $(${ignore($mut)} + enum_definition.variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); + )? + $(${ignore($lt)}vis.visit_enum_def(enum_definition))? + } + ItemKind::Struct(ident, variant_data, generics) + | ItemKind::Union(ident, variant_data, generics) => { + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_generics(generics)); + vis.visit_variant_data(variant_data) + } + ItemKind::Impl(box Impl { + defaultness, + safety, + generics, + constness, + polarity, + of_trait, + self_ty, + items, + }) => { + try_visit!(visit_defaultness(vis, defaultness)); + try_visit!(visit_safety(vis, safety)); + try_visit!(vis.visit_generics(generics)); + try_visit!(visit_constness(vis, constness)); + try_visit!(visit_polarity(vis, polarity)); + visit_opt!(vis, visit_trait_ref, of_trait); + try_visit!(vis.visit_ty(self_ty)); + $(${ignore($mut)} + items.flat_map_in_place(|item| { + vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() }) + }); + )? + $(${ignore($lt)} + walk_list!( + vis, + visit_assoc_item, + items, + AssocCtxt::Impl { of_trait: of_trait.is_some() } + ); + >::Result::output() + )? + } + ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => { + try_visit!(visit_safety(vis, safety)); + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_generics(generics)); + try_visit!(visit_bounds(vis, bounds, BoundKind::Bound)); + $(${ignore($mut)} + items.flat_map_in_place(|item| { + vis.flat_map_assoc_item(item, AssocCtxt::Trait) + }); + )? + $(${ignore($lt)} + walk_list!(vis, visit_assoc_item, items, AssocCtxt::Trait); + >::Result::output() + )? + } + ItemKind::TraitAlias(ident, generics, bounds) => { + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_generics(generics)); + visit_bounds(vis, bounds, BoundKind::Bound) + } + ItemKind::MacCall(m) => vis.visit_mac_call(m), + ItemKind::MacroDef(ident, def) => { + try_visit!(vis.visit_ident(ident)); + // FIXME(fee1-dead) assymetry + vis.visit_macro_def(def$(${ignore($lt)}, id)?) + } + ItemKind::Delegation(box Delegation { + id, + qself, + path, + ident, + rename, + body, + from_glob: _, + }) => { + try_visit!(visit_id(vis, id)); + try_visit!(vis.visit_qself(qself)); + try_visit!(vis.visit_path(path$(${ignore($lt)}, *id)?)); + try_visit!(vis.visit_ident(ident)); + if let Some(rename) = rename { + try_visit!(vis.visit_ident(rename)); + } + if let Some(body) = body { + try_visit!(vis.visit_block(body)); + } + $(>::Result::output())? + } + ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { + try_visit!(vis.visit_qself(qself)); + try_visit!(vis.visit_path(prefix$(${ignore($lt)}, id)?)); + if let Some(suffixes) = suffixes { + for (ident, rename) in suffixes { + try_visit!(vis.visit_ident(ident)); + if let Some(rename) = rename { + try_visit!(vis.visit_ident(rename)); + } + } + } + if let Some(body) = body { + try_visit!(vis.visit_block(body)); + } + $(>::Result::output())? + } + } + } + } + + fn walk_const_item<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, item: &$($lt)? $($mut)? ConstItem) $(-> >::Result)? { + let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item; + try_visit!(visit_defaultness(vis, defaultness)); + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_generics(generics)); + try_visit!(vis.visit_ty(ty)); + visit_opt!(vis, visit_expr, expr); + walk_define_opaques(vis, define_opaque) + } + + fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) $(-> >::Result)? { + let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod; + try_visit!(visit_safety(vis, safety)); + $(${ignore($mut)} + items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); + )? + $( + walk_list!(vis, visit_foreign_item, items); + >::Result::output() + )? + } + + fn walk_define_opaques<$($lt,)? V: $Visitor$(<$lt>)?>( + visitor: &mut V, + define_opaque: &$($lt)? $($mut)? Option>, + ) $(-> >::Result)? { + if let Some(define_opaque) = define_opaque { + for (id, path) in define_opaque { + try_visit!(visit_id(visitor, id)); + // FIXME(fee1-dead): look into this weird assymetry + try_visit!(visitor.visit_path(path$(${ignore($lt)}, *id)?)); + } + } + $(>::Result::output())? + } }; } @@ -417,163 +681,6 @@ pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitR visitor.visit_path(path, *ref_id) } -impl WalkItemKind for ItemKind { - type Ctxt = (); - fn walk<'a, V: Visitor<'a>>( - &'a self, - span: Span, - id: NodeId, - vis: &'a Visibility, - _ctxt: Self::Ctxt, - visitor: &mut V, - ) -> V::Result { - match self { - ItemKind::ExternCrate(_rename, ident) => try_visit!(visitor.visit_ident(ident)), - ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)), - ItemKind::Static(box StaticItem { - ident, - ty, - safety: _, - mutability: _, - expr, - define_opaque, - }) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_ty(ty)); - visit_opt!(visitor, visit_expr, expr); - try_visit!(walk_define_opaques(visitor, define_opaque)); - } - ItemKind::Const(box ConstItem { - defaultness: _, - ident, - generics, - ty, - expr, - define_opaque, - }) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_ty(ty)); - visit_opt!(visitor, visit_expr, expr); - try_visit!(walk_define_opaques(visitor, define_opaque)); - } - ItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Free, vis, &*func); - try_visit!(visitor.visit_fn(kind, span, id)); - } - ItemKind::Mod(_unsafety, ident, mod_kind) => { - try_visit!(visitor.visit_ident(ident)); - match mod_kind { - ModKind::Loaded(items, _inline, _inner_span, _) => { - walk_list!(visitor, visit_item, items); - } - ModKind::Unloaded => {} - } - } - ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => { - walk_list!(visitor, visit_foreign_item, items); - } - ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), - ItemKind::TyAlias(box TyAlias { - generics, - ident, - bounds, - ty, - defaultness: _, - where_clauses: _, - }) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_generics(generics)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - visit_opt!(visitor, visit_ty, ty); - } - ItemKind::Enum(ident, enum_definition, generics) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_enum_def(enum_definition)); - } - ItemKind::Impl(box Impl { - defaultness: _, - safety: _, - generics, - constness: _, - polarity: _, - of_trait, - self_ty, - items, - }) => { - try_visit!(visitor.visit_generics(generics)); - visit_opt!(visitor, visit_trait_ref, of_trait); - try_visit!(visitor.visit_ty(self_ty)); - walk_list!( - visitor, - visit_assoc_item, - items, - AssocCtxt::Impl { of_trait: of_trait.is_some() } - ); - } - ItemKind::Struct(ident, struct_definition, generics) - | ItemKind::Union(ident, struct_definition, generics) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_variant_data(struct_definition)); - } - ItemKind::Trait(box Trait { - safety: _, - is_auto: _, - ident, - generics, - bounds, - items, - }) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_generics(generics)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits); - walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait); - } - ItemKind::TraitAlias(ident, generics, bounds) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_generics(generics)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - } - ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), - ItemKind::MacroDef(ident, ts) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_mac_def(ts, id)) - } - ItemKind::Delegation(box Delegation { - id, - qself, - path, - ident, - rename, - body, - from_glob: _, - }) => { - try_visit!(visitor.visit_qself(qself)); - try_visit!(visitor.visit_path(path, *id)); - try_visit!(visitor.visit_ident(ident)); - visit_opt!(visitor, visit_ident, rename); - visit_opt!(visitor, visit_block, body); - } - ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { - try_visit!(visitor.visit_qself(qself)); - try_visit!(visitor.visit_path(prefix, id)); - if let Some(suffixes) = suffixes { - for (ident, rename) in suffixes { - visitor.visit_ident(ident); - if let Some(rename) = rename { - visitor.visit_ident(rename); - } - } - } - visit_opt!(visitor, visit_block, body); - } - } - V::Result::output() - } -} - pub fn walk_enum_def<'a, V: Visitor<'a>>( visitor: &mut V, EnumDef { variants }: &'a EnumDef, @@ -1121,18 +1228,6 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>( walk_item_ctxt(visitor, item, ctxt) } -fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>( - visitor: &mut V, - item: &'a Item, - ctxt: K::Ctxt, -) -> V::Result { - let Item { id, span, vis, attrs, kind, tokens: _ } = item; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_vis(vis)); - try_visit!(kind.walk(*span, *id, vis, ctxt, visitor)); - V::Result::output() -} - pub fn walk_struct_def<'a, V: Visitor<'a>>( visitor: &mut V, struct_definition: &'a VariantData, @@ -1455,15 +1550,3 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) - } V::Result::output() } - -fn walk_define_opaques<'a, V: Visitor<'a>>( - visitor: &mut V, - define_opaque: &'a Option>, -) -> V::Result { - if let Some(define_opaque) = define_opaque { - for (id, path) in define_opaque { - try_visit!(visitor.visit_path(path, *id)); - } - } - V::Result::output() -} diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index f9601fa5ef1d..2aeff4e66d56 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -277,7 +277,7 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast> ast_visit::walk_attribute(self, attr); } - fn visit_mac_def(&mut self, mac: &'ast ast::MacroDef, id: ast::NodeId) { + fn visit_macro_def(&mut self, mac: &'ast ast::MacroDef, id: ast::NodeId) { lint_callback!(self, check_mac_def, mac); self.check_id(id); } From 7c026ea31daa07d2ab2ae9562f878870ef8705c9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 23 May 2025 16:41:37 +0200 Subject: [PATCH 089/139] Add missing space in usage.md --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index dbe36109f83e..9dcfee4f535a 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -47,7 +47,7 @@ These are a few functions that allow you to easily run rust code from the shell ```bash function jit_naked() { - echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode-Cprefer-dynamic + echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode -Cprefer-dynamic } function jit() { From dcd3168c97c6024b24f80abbb2407c81d9b0a25a Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 23 May 2025 15:51:51 +0100 Subject: [PATCH 090/139] Use correct sign extension on `__powi*f2` arguments --- src/abi/mod.rs | 28 ++++++++++++++++++++++++++++ src/intrinsics/mod.rs | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 70d29596e22c..5f7bf3821d77 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -828,3 +828,31 @@ pub(crate) fn codegen_drop<'tcx>( } } } + +pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam { + let param = AbiParam::new(ty); + if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size.bits() { + match (&*tcx.sess.target.arch, &*tcx.sess.target.vendor) { + ("x86_64", _) | ("aarch64", "apple") => match (ty, is_signed) { + (types::I8 | types::I16, true) => param.sext(), + (types::I8 | types::I16, false) => param.uext(), + _ => param, + }, + ("aarch64", _) => param, + ("riscv64", _) => match (ty, is_signed) { + (types::I32, _) | (_, true) => param.sext(), + _ => param.uext(), + }, + ("s390x", _) => { + if is_signed { + param.sext() + } else { + param.uext() + } + } + _ => unimplemented!("{:?}", tcx.sess.target.arch), + } + } else { + param + } +} diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 25e224ebfe2c..7c18922d93cd 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -416,7 +416,8 @@ fn codegen_float_intrinsic_call<'tcx>( // These intrinsics aren't supported natively by Cranelift. // Lower them to a libcall. sym::powif32 | sym::powif64 => { - let input_tys: Vec<_> = vec![AbiParam::new(clif_ty), AbiParam::new(types::I32)]; + let input_tys: Vec<_> = + vec![AbiParam::new(clif_ty), lib_call_arg_param(fx.tcx, types::I32, true)]; let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0]; CValue::by_val(ret_val, fx.layout_of(ty)) } From 55298ea6ea61f337ac563381582b66d3aa9c0b7f Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 10 May 2025 19:25:46 +0300 Subject: [PATCH 091/139] if stage isn't set explicitly, default to 1 when running miri Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/run.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 0bba441c3fa2..f6eb1f6fd905 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -118,7 +118,15 @@ impl Step for Miri { fn run(self, builder: &Builder<'_>) { let host = builder.build.build; let target = self.target; - let stage = builder.top_stage; + + // `x run` uses stage 0 by default but miri does not work well with stage 0. + // Change the stage to 1 if it's not set explicitly. + let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 { + builder.top_stage + } else { + 1 + }; + if stage == 0 { eprintln!("miri cannot be run at stage 0"); std::process::exit(1); From 17d27c993e67f5a466a0911cf1f54df93514d8db Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 10 May 2025 19:23:36 +0300 Subject: [PATCH 092/139] let `tool::Miri` implementation to handle compilers Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/run.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index f6eb1f6fd905..eeba7780c65b 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -133,8 +133,10 @@ impl Step for Miri { } // This compiler runs on the host, we'll just use it for the target. - let target_compiler = builder.compiler(stage, host); - let host_compiler = tool::get_tool_rustc_compiler(builder, target_compiler); + let target_compiler = builder.compiler(stage, target); + let miri_build = builder.ensure(tool::Miri { compiler: target_compiler, target }); + // Rustc tools are off by one stage, so use the build compiler to run miri. + let host_compiler = miri_build.build_compiler; // Get a target sysroot for Miri. let miri_sysroot = test::Miri::build_miri_sysroot(builder, target_compiler, target); From bcca611b359c74b71e798c2ee30f4695c6218bbf Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 23 May 2025 17:43:19 -0500 Subject: [PATCH 093/139] rustdoc-gui test: apply suggestions from code review --- tests/rustdoc-gui/sidebar-mobile.goml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml index 0596f8431748..6ddc07c6481c 100644 --- a/tests/rustdoc-gui/sidebar-mobile.goml +++ b/tests/rustdoc-gui/sidebar-mobile.goml @@ -57,7 +57,8 @@ scroll-to: ".block.keyword li:nth-child(1)" compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 544}) // Now checking the background color of the sidebar. -reload: +// Close the sidebar menu. +press-key: "Escape" show-text: true define-function: ( @@ -73,6 +74,8 @@ define-function: ( "background-color": |background|, "color": |color|, }) + // Make sure the sidebar is full width + compare-elements-size: (".sidebar", "body", ["width"]) // Close the sidebar menu. press-key: "Escape" }, From 1758f07cb832e9a854f34af437878a10f22dae82 Mon Sep 17 00:00:00 2001 From: quininer Date: Thu, 8 May 2025 17:56:09 +0800 Subject: [PATCH 094/139] Enable xray support for Mac * https://maskray.me/blog/2023-06-18-port-llvm-xray-to-apple-systems * https://github.com/llvm/llvm-project/blob/llvmorg-20.1.4/clang/lib/Driver/XRayArgs.cpp#L31 --- compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs | 1 + compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs | 1 + tests/ui/instrument-xray/target-not-supported.rs | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index d3e0a32c8b8f..6587abb2ba7e 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -22,6 +22,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(128), // FIXME: The leak sanitizer currently fails the tests, see #88132. supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD, + supports_xray: true, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index 2f868e38f1a5..64c170547805 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD, + supports_xray: true, ..opts }, } diff --git a/tests/ui/instrument-xray/target-not-supported.rs b/tests/ui/instrument-xray/target-not-supported.rs index 2045913b186c..697db6bd4b74 100644 --- a/tests/ui/instrument-xray/target-not-supported.rs +++ b/tests/ui/instrument-xray/target-not-supported.rs @@ -1,7 +1,7 @@ // Verifies that `-Z instrument-xray` cannot be used with unsupported targets, // //@ needs-llvm-components: x86 -//@ compile-flags: -Z instrument-xray --target x86_64-apple-darwin +//@ compile-flags: -Z instrument-xray --target x86_64-pc-windows-msvc #![feature(no_core)] #![no_core] From f0fb19ccc87e18402079fbe3106d8090cc8d9f64 Mon Sep 17 00:00:00 2001 From: beetrees Date: Sat, 24 May 2025 13:45:12 +0100 Subject: [PATCH 095/139] Add missing float libcalls to `compiler_builtins.rs` --- src/compiler_builtins.rs | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index 5b6d0ef6ddf7..8886317c12b1 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -46,15 +46,49 @@ builtin_functions! { fn __rust_u128_mulo(a: u128, b: u128, oflow: &mut i32) -> u128; fn __rust_i128_mulo(a: i128, b: i128, oflow: &mut i32) -> i128; - // floats + // integer -> float fn __floattisf(i: i128) -> f32; fn __floattidf(i: i128) -> f64; fn __floatuntisf(i: u128) -> f32; fn __floatuntidf(i: u128) -> f64; + // float -> integer fn __fixsfti(f: f32) -> i128; fn __fixdfti(f: f64) -> i128; fn __fixunssfti(f: f32) -> u128; fn __fixunsdfti(f: f64) -> u128; + // float binops + fn fmodf(a: f32, b: f32) -> f32; + fn fmod(a: f64, b: f64) -> f64; + // Cranelift float libcalls + fn fmaf(a: f32, b: f32, c: f32) -> f32; + fn fma(a: f64, b: f64, c: f64) -> f64; + fn floorf(f: f32) -> f32; + fn floor(f: f64) -> f64; + fn ceilf(f: f32) -> f32; + fn ceil(f: f64) -> f64; + fn truncf(f: f32) -> f32; + fn trunc(f: f64) -> f64; + fn nearbyintf(f: f32) -> f32; + fn nearbyint(f: f64) -> f64; + // float intrinsics + fn __powisf2(a: f32, b: i32) -> f32; + fn __powidf2(a: f64, b: i32) -> f64; + fn powf(a: f32, b: f32) -> f32; + fn pow(a: f64, b: f64) -> f64; + fn expf(f: f32) -> f32; + fn exp(f: f64) -> f64; + fn exp2f(f: f32) -> f32; + fn exp2(f: f64) -> f64; + fn logf(f: f32) -> f32; + fn log(f: f64) -> f64; + fn log2f(f: f32) -> f32; + fn log2(f: f64) -> f64; + fn log10f(f: f32) -> f32; + fn log10(f: f64) -> f64; + fn sinf(f: f32) -> f32; + fn sin(f: f64) -> f64; + fn cosf(f: f32) -> f32; + fn cos(f: f64) -> f64; // allocator // NOTE: These need to be mentioned here despite not being part of compiler_builtins because From 87c425b9e1ce015c4e3dad7729e8d54bc7b6b27b Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 23 May 2025 15:51:51 +0100 Subject: [PATCH 096/139] Add basic support for `f16`/`f128` values --- src/abi/pass_mode.rs | 2 ++ src/common.rs | 8 ++++---- src/value_and_place.rs | 14 +++++++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 06d89bc9ea7d..6d8614aca693 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -22,8 +22,10 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam { (RegKind::Integer, 3..=4) => types::I32, (RegKind::Integer, 5..=8) => types::I64, (RegKind::Integer, 9..=16) => types::I128, + (RegKind::Float, 2) => types::F16, (RegKind::Float, 4) => types::F32, (RegKind::Float, 8) => types::F64, + (RegKind::Float, 16) => types::F128, (RegKind::Vector, size) => types::I8.by(u32::try_from(size).unwrap()).unwrap(), _ => unreachable!("{:?}", reg), }; diff --git a/src/common.rs b/src/common.rs index abe2972ba0cb..2f11b2d2dcc1 100644 --- a/src/common.rs +++ b/src/common.rs @@ -33,10 +33,10 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type { Integer::I128 => types::I128, }, Primitive::Float(float) => match float { - Float::F16 => unimplemented!("f16_f128"), + Float::F16 => types::F16, Float::F32 => types::F32, Float::F64 => types::F64, - Float::F128 => unimplemented!("f16_f128"), + Float::F128 => types::F128, }, // FIXME(erikdesjardins): handle non-default addrspace ptr sizes Primitive::Pointer(_) => pointer_ty(tcx), @@ -64,10 +64,10 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option types::I32, ty::Float(size) => match size { - FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F16 => types::F16, FloatTy::F32 => types::F32, FloatTy::F64 => types::F64, - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => types::F128, }, ty::FnPtr(..) => pointer_ty(tcx), ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 0938c990514c..cbfb215a892a 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -325,7 +325,7 @@ impl<'tcx> CValue<'tcx> { const_val: ty::ScalarInt, ) -> CValue<'tcx> { assert_eq!(const_val.size(), layout.size, "{:#?}: {:?}", const_val, layout); - use cranelift_codegen::ir::immediates::{Ieee32, Ieee64}; + use cranelift_codegen::ir::immediates::{Ieee16, Ieee32, Ieee64, Ieee128}; let clif_ty = fx.clif_type(layout.ty).unwrap(); @@ -346,12 +346,24 @@ impl<'tcx> CValue<'tcx> { let raw_val = const_val.size().truncate(const_val.to_bits(layout.size)); fx.bcx.ins().iconst(clif_ty, raw_val as i64) } + ty::Float(FloatTy::F16) => { + fx.bcx.ins().f16const(Ieee16::with_bits(u16::try_from(const_val).unwrap())) + } ty::Float(FloatTy::F32) => { fx.bcx.ins().f32const(Ieee32::with_bits(u32::try_from(const_val).unwrap())) } ty::Float(FloatTy::F64) => { fx.bcx.ins().f64const(Ieee64::with_bits(u64::try_from(const_val).unwrap())) } + ty::Float(FloatTy::F128) => { + let value = fx + .bcx + .func + .dfg + .constants + .insert(Ieee128::with_bits(u128::try_from(const_val).unwrap()).into()); + fx.bcx.ins().f128const(value) + } _ => panic!( "CValue::const_val for non bool/char/float/integer/pointer type {:?} is not allowed", layout.ty From 27a9590d3db284a12143dafd03bf7343b59b6808 Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 23 May 2025 15:51:51 +0100 Subject: [PATCH 097/139] Add `f16`/`f128` `+`/`-`/`*`/`/`/`%` support --- build_system/build_backend.rs | 2 +- src/base.rs | 11 +++++- src/codegen_f16_f128.rs | 64 +++++++++++++++++++++++++++++++++++ src/compiler_builtins.rs | 8 +++++ src/lib.rs | 4 +++ src/num.rs | 53 ++++++++++++++++++++++++++--- 6 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 src/codegen_f16_f128.rs diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index 72bc422523d5..bf7cf1c0a346 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -18,7 +18,7 @@ pub(crate) fn build_backend( let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs); let mut rustflags = rustflags_from_env("RUSTFLAGS"); - rustflags.push("-Zallow-features=rustc_private".to_owned()); + rustflags.push("-Zallow-features=rustc_private,f16,f128".to_owned()); rustflags_to_cmd_env(&mut cmd, "RUSTFLAGS", &rustflags); if env::var("CG_CLIF_EXPENSIVE_CHECKS").is_ok() { diff --git a/src/base.rs b/src/base.rs index c1f4c065ce03..4617304105a5 100644 --- a/src/base.rs +++ b/src/base.rs @@ -15,9 +15,9 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use crate::constant::ConstantCx; use crate::debuginfo::{FunctionDebugContext, TypeDebugContext}; -use crate::enable_verifier; use crate::prelude::*; use crate::pretty_clif::CommentWriter; +use crate::{codegen_f16_f128, enable_verifier}; pub(crate) struct CodegenedFunction { symbol_name: String, @@ -635,6 +635,15 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: let val = operand.load_scalar(fx); match layout.ty.kind() { ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout), + // FIXME(bytecodealliance/wasmtime#8312): Remove + // once backend lowerings have been added to + // Cranelift. + ty::Float(FloatTy::F16) => { + CValue::by_val(codegen_f16_f128::neg_f16(fx, val), layout) + } + ty::Float(FloatTy::F128) => { + CValue::by_val(codegen_f16_f128::neg_f128(fx, val), layout) + } ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout), _ => unreachable!("un op Neg for {:?}", layout.ty), } diff --git a/src/codegen_f16_f128.rs b/src/codegen_f16_f128.rs new file mode 100644 index 000000000000..c6f0779b82db --- /dev/null +++ b/src/codegen_f16_f128.rs @@ -0,0 +1,64 @@ +use crate::prelude::*; + +pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { + let (value, arg_ty) = + if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" { + ( + fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value), + lib_call_arg_param(fx.tcx, types::I16, false), + ) + } else { + (value, AbiParam::new(types::F16)) + }; + fx.lib_call("__extendhfsf2", vec![arg_ty], vec![AbiParam::new(types::F32)], &[value])[0] +} + +pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { + let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" { + types::I16 + } else { + types::F16 + }; + let ret = fx.lib_call( + "__truncsfhf2", + vec![AbiParam::new(types::F32)], + vec![AbiParam::new(ret_ty)], + &[value], + )[0]; + if ret_ty == types::I16 { fx.bcx.ins().bitcast(types::F16, MemFlags::new(), ret) } else { ret } +} + +pub(crate) fn codegen_f128_binop( + fx: &mut FunctionCx<'_, '_, '_>, + bin_op: BinOp, + lhs: Value, + rhs: Value, +) -> Value { + let name = match bin_op { + BinOp::Add => "__addtf3", + BinOp::Sub => "__subtf3", + BinOp::Mul => "__multf3", + BinOp::Div => "__divtf3", + _ => unreachable!("handled in `codegen_float_binop`"), + }; + fx.lib_call( + name, + vec![AbiParam::new(types::F128), AbiParam::new(types::F128)], + vec![AbiParam::new(types::F128)], + &[lhs, rhs], + )[0] +} + +pub(crate) fn neg_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { + let bits = fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value); + let bits = fx.bcx.ins().bxor_imm(bits, 0x8000); + fx.bcx.ins().bitcast(types::F16, MemFlags::new(), bits) +} + +pub(crate) fn neg_f128(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { + let bits = fx.bcx.ins().bitcast(types::I128, MemFlags::new(), value); + let (low, high) = fx.bcx.ins().isplit(bits); + let high = fx.bcx.ins().bxor_imm(high, 0x8000_0000_0000_0000_u64 as i64); + let bits = fx.bcx.ins().iconcat(low, high); + fx.bcx.ins().bitcast(types::F128, MemFlags::new(), bits) +} diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index 8886317c12b1..0c75df845db0 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -56,9 +56,17 @@ builtin_functions! { fn __fixdfti(f: f64) -> i128; fn __fixunssfti(f: f32) -> u128; fn __fixunsdfti(f: f64) -> u128; + // float -> float + fn __extendhfsf2(f: f16) -> f32; + fn __truncsfhf2(f: f32) -> f16; // float binops + fn __addtf3(a: f128, b: f128) -> f128; + fn __subtf3(a: f128, b: f128) -> f128; + fn __multf3(a: f128, b: f128) -> f128; + fn __divtf3(a: f128, b: f128) -> f128; fn fmodf(a: f32, b: f32) -> f32; fn fmod(a: f64, b: f64) -> f64; + fn fmodf128(a: f128, b: f128) -> f128; // Cranelift float libcalls fn fmaf(a: f32, b: f32, c: f32) -> f32; fn fma(a: f64, b: f64, c: f64) -> f64; diff --git a/src/lib.rs b/src/lib.rs index d41a808198cd..03dfd495682c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,9 @@ #![cfg_attr(doc, feature(rustdoc_internals))] // Note: please avoid adding other feature gates where possible #![feature(rustc_private)] +// Only used to define intrinsics in `compiler_builtins.rs`. +#![feature(f16)] +#![feature(f128)] // Note: please avoid adding other feature gates where possible #![warn(rust_2018_idioms)] #![warn(unreachable_pub)] @@ -57,6 +60,7 @@ mod allocator; mod analyze; mod base; mod cast; +mod codegen_f16_f128; mod codegen_i128; mod common; mod compiler_builtins; diff --git a/src/num.rs b/src/num.rs index 90627f8060b8..3ed276267de6 100644 --- a/src/num.rs +++ b/src/num.rs @@ -1,5 +1,6 @@ //! Various operations on integer and floating-point numbers +use crate::codegen_f16_f128; use crate::prelude::*; fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> IntCC { @@ -350,25 +351,60 @@ pub(crate) fn codegen_float_binop<'tcx>( let lhs = in_lhs.load_scalar(fx); let rhs = in_rhs.load_scalar(fx); + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have + // been added to Cranelift. + let (lhs, rhs) = if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F16) { + (codegen_f16_f128::f16_to_f32(fx, lhs), codegen_f16_f128::f16_to_f32(fx, rhs)) + } else { + (lhs, rhs) + }; let b = fx.bcx.ins(); let res = match bin_op { + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings + // have been added to Cranelift. + BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div + if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F128) => + { + codegen_f16_f128::codegen_f128_binop(fx, bin_op, lhs, rhs) + } BinOp::Add => b.fadd(lhs, rhs), BinOp::Sub => b.fsub(lhs, rhs), BinOp::Mul => b.fmul(lhs, rhs), BinOp::Div => b.fdiv(lhs, rhs), BinOp::Rem => { - let (name, ty) = match in_lhs.layout().ty.kind() { - ty::Float(FloatTy::F32) => ("fmodf", types::F32), - ty::Float(FloatTy::F64) => ("fmod", types::F64), + let (name, ty, lhs, rhs) = match in_lhs.layout().ty.kind() { + ty::Float(FloatTy::F16) => ( + "fmodf", + types::F32, + // FIXME(bytecodealliance/wasmtime#8312): Already converted + // by the FIXME above. + // fx.bcx.ins().fpromote(types::F32, lhs), + // fx.bcx.ins().fpromote(types::F32, rhs), + lhs, + rhs, + ), + ty::Float(FloatTy::F32) => ("fmodf", types::F32, lhs, rhs), + ty::Float(FloatTy::F64) => ("fmod", types::F64, lhs, rhs), + ty::Float(FloatTy::F128) => ("fmodf128", types::F128, lhs, rhs), _ => bug!(), }; - fx.lib_call( + let ret_val = fx.lib_call( name, vec![AbiParam::new(ty), AbiParam::new(ty)], vec![AbiParam::new(ty)], &[lhs, rhs], - )[0] + )[0]; + + let ret_val = if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F16) { + // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift + // operation once Cranelift backend lowerings have been + // implemented. + codegen_f16_f128::f32_to_f16(fx, ret_val) + } else { + ret_val + }; + return CValue::by_val(ret_val, in_lhs.layout()); } BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { let fltcc = match bin_op { @@ -386,6 +422,13 @@ pub(crate) fn codegen_float_binop<'tcx>( _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs), }; + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have + // been added to Cranelift. + let res = if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F16) { + codegen_f16_f128::f32_to_f16(fx, res) + } else { + res + }; CValue::by_val(res, in_lhs.layout()) } From 38d48dbe083b680b54e39c2ead2a92d76001786c Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 23 May 2025 15:51:51 +0100 Subject: [PATCH 098/139] Add `f16`/`f128` comparison support --- src/codegen_f16_f128.rs | 54 +++++++++++++++++++++++++ src/compiler_builtins.rs | 9 +++++ src/intrinsics/mod.rs | 87 ++++++++++++++++++++++++++++++++++++++++ src/num.rs | 17 +++++--- 4 files changed, 162 insertions(+), 5 deletions(-) diff --git a/src/codegen_f16_f128.rs b/src/codegen_f16_f128.rs index c6f0779b82db..c570fbbd993d 100644 --- a/src/codegen_f16_f128.rs +++ b/src/codegen_f16_f128.rs @@ -28,6 +28,42 @@ pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value if ret_ty == types::I16 { fx.bcx.ins().bitcast(types::F16, MemFlags::new(), ret) } else { ret } } +pub(crate) fn fcmp(fx: &mut FunctionCx<'_, '_, '_>, cc: FloatCC, lhs: Value, rhs: Value) -> Value { + let ty = fx.bcx.func.dfg.value_type(lhs); + match ty { + types::F32 | types::F64 => fx.bcx.ins().fcmp(cc, lhs, rhs), + types::F16 => { + let lhs = f16_to_f32(fx, lhs); + let rhs = f16_to_f32(fx, rhs); + fx.bcx.ins().fcmp(cc, lhs, rhs) + } + types::F128 => { + let (name, int_cc) = match cc { + FloatCC::Equal => ("__eqtf2", IntCC::Equal), + FloatCC::NotEqual => ("__netf2", IntCC::NotEqual), + FloatCC::LessThan => ("__lttf2", IntCC::SignedLessThan), + FloatCC::LessThanOrEqual => ("__letf2", IntCC::SignedLessThanOrEqual), + FloatCC::GreaterThan => ("__gttf2", IntCC::SignedGreaterThan), + FloatCC::GreaterThanOrEqual => ("__getf2", IntCC::SignedGreaterThanOrEqual), + _ => unreachable!("not currently used in rustc_codegen_cranelift: {cc:?}"), + }; + let res = fx.lib_call( + name, + vec![AbiParam::new(types::F128), AbiParam::new(types::F128)], + // FIXME(rust-lang/compiler-builtins#919): This should be `I64` on non-AArch64 + // architectures, but switching it before compiler-builtins is fixed causes test + // failures. + vec![AbiParam::new(types::I32)], + &[lhs, rhs], + )[0]; + let zero = fx.bcx.ins().iconst(types::I32, 0); + let res = fx.bcx.ins().icmp(int_cc, res, zero); + res + } + _ => unreachable!("{ty:?}"), + } +} + pub(crate) fn codegen_f128_binop( fx: &mut FunctionCx<'_, '_, '_>, bin_op: BinOp, @@ -62,3 +98,21 @@ pub(crate) fn neg_f128(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { let bits = fx.bcx.ins().iconcat(low, high); fx.bcx.ins().bitcast(types::F128, MemFlags::new(), bits) } + +pub(crate) fn fmin_f128(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { + fx.lib_call( + "fminimumf128", + vec![AbiParam::new(types::F128), AbiParam::new(types::F128)], + vec![AbiParam::new(types::F128)], + &[a, b], + )[0] +} + +pub(crate) fn fmax_f128(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { + fx.lib_call( + "fmaximumf128", + vec![AbiParam::new(types::F128), AbiParam::new(types::F128)], + vec![AbiParam::new(types::F128)], + &[a, b], + )[0] +} diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index 0c75df845db0..017a1370abd7 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -67,6 +67,15 @@ builtin_functions! { fn fmodf(a: f32, b: f32) -> f32; fn fmod(a: f64, b: f64) -> f64; fn fmodf128(a: f128, b: f128) -> f128; + // float comparison + fn __eqtf2(a: f128, b: f128) -> i32; + fn __netf2(a: f128, b: f128) -> i32; + fn __lttf2(a: f128, b: f128) -> i32; + fn __letf2(a: f128, b: f128) -> i32; + fn __gttf2(a: f128, b: f128) -> i32; + fn __getf2(a: f128, b: f128) -> i32; + fn fminimumf128(a: f128, b: f128) -> f128; + fn fmaximumf128(a: f128, b: f128) -> f128; // Cranelift float libcalls fn fmaf(a: f32, b: f32, c: f32) -> f32; fn fma(a: f64, b: f64, c: f64) -> f64; diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 7c18922d93cd..6481d211234e 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -27,6 +27,7 @@ use rustc_span::{Symbol, sym}; pub(crate) use self::llvm::codegen_llvm_intrinsic_call; use crate::cast::clif_intcast; +use crate::codegen_f16_f128; use crate::prelude::*; fn bug_on_incorrect_arg_count(intrinsic: impl std::fmt::Display) -> ! { @@ -1118,6 +1119,20 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } + sym::minimumf16 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + // FIXME(bytecodealliance/wasmtime#8312): Use `fmin` directly once + // Cranelift backend lowerings are implemented. + let a = codegen_f16_f128::f16_to_f32(fx, a); + let b = codegen_f16_f128::f16_to_f32(fx, b); + let val = fx.bcx.ins().fmin(a, b); + let val = codegen_f16_f128::f32_to_f16(fx, val); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f16)); + ret.write_cvalue(fx, val); + } sym::minimumf32 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); @@ -1136,6 +1151,31 @@ fn codegen_regular_intrinsic_call<'tcx>( let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); } + sym::minimumf128 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + // FIXME(bytecodealliance/wasmtime#8312): Use `fmin` once Cranelift + // backend lowerings are implemented. + let val = codegen_f16_f128::fmin_f128(fx, a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f128)); + ret.write_cvalue(fx, val); + } + sym::maximumf16 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + // FIXME(bytecodealliance/wasmtime#8312): Use `fmax` directly once + // Cranelift backend lowerings are implemented. + let a = codegen_f16_f128::f16_to_f32(fx, a); + let b = codegen_f16_f128::f16_to_f32(fx, b); + let val = fx.bcx.ins().fmax(a, b); + let val = codegen_f16_f128::f32_to_f16(fx, val); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f16)); + ret.write_cvalue(fx, val); + } sym::maximumf32 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); @@ -1154,7 +1194,27 @@ fn codegen_regular_intrinsic_call<'tcx>( let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); } + sym::maximumf128 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + // FIXME(bytecodealliance/wasmtime#8312): Use `fmax` once Cranelift + // backend lowerings are implemented. + let val = codegen_f16_f128::fmax_f128(fx, a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f128)); + ret.write_cvalue(fx, val); + } + + sym::minnumf16 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = crate::num::codegen_float_min(fx, a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f16)); + ret.write_cvalue(fx, val); + } sym::minnumf32 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); @@ -1173,6 +1233,24 @@ fn codegen_regular_intrinsic_call<'tcx>( let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); } + sym::minnumf128 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = crate::num::codegen_float_min(fx, a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f128)); + ret.write_cvalue(fx, val); + } + sym::maxnumf16 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = crate::num::codegen_float_max(fx, a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f16)); + ret.write_cvalue(fx, val); + } sym::maxnumf32 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); @@ -1191,6 +1269,15 @@ fn codegen_regular_intrinsic_call<'tcx>( let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); } + sym::maxnumf128 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = crate::num::codegen_float_max(fx, a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f128)); + ret.write_cvalue(fx, val); + } sym::catch_unwind => { intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic); diff --git a/src/num.rs b/src/num.rs index 3ed276267de6..f53045df6e79 100644 --- a/src/num.rs +++ b/src/num.rs @@ -416,7 +416,10 @@ pub(crate) fn codegen_float_binop<'tcx>( BinOp::Gt => FloatCC::GreaterThan, _ => unreachable!(), }; - let val = fx.bcx.ins().fcmp(fltcc, lhs, rhs); + // FIXME(bytecodealliance/wasmtime#8312): Replace with Cranelift + // `fcmp` once `f16`/`f128` backend lowerings have been added to + // Cranelift. + let val = codegen_f16_f128::fcmp(fx, fltcc, lhs, rhs); return CValue::by_val(val, fx.layout_of(fx.tcx.types.bool)); } _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs), @@ -500,15 +503,19 @@ fn codegen_ptr_binop<'tcx>( // and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing // a float against itself. Only in case of NaN is it not equal to itself. pub(crate) fn codegen_float_min(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { - let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); - let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b); + // FIXME(bytecodealliance/wasmtime#8312): Replace with Cranelift `fcmp` once + // `f16`/`f128` backend lowerings have been added to Cranelift. + let a_is_nan = codegen_f16_f128::fcmp(fx, FloatCC::NotEqual, a, a); + let a_ge_b = codegen_f16_f128::fcmp(fx, FloatCC::GreaterThanOrEqual, a, b); let temp = fx.bcx.ins().select(a_ge_b, b, a); fx.bcx.ins().select(a_is_nan, b, temp) } pub(crate) fn codegen_float_max(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { - let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); - let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b); + // FIXME(bytecodealliance/wasmtime#8312): Replace with Cranelift `fcmp` once + // `f16`/`f128` backend lowerings have been added to Cranelift. + let a_is_nan = codegen_f16_f128::fcmp(fx, FloatCC::NotEqual, a, a); + let a_le_b = codegen_f16_f128::fcmp(fx, FloatCC::LessThanOrEqual, a, b); let temp = fx.bcx.ins().select(a_le_b, b, a); fx.bcx.ins().select(a_is_nan, b, temp) } From e46186f9944cf10c35b228e38ba6312903587896 Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 23 May 2025 15:51:51 +0100 Subject: [PATCH 099/139] Add support for casting to and from `f16`/`f128` --- src/cast.rs | 21 ++++++- src/codegen_f16_f128.rs | 123 +++++++++++++++++++++++++++++++++++++++ src/compiler_builtins.rs | 19 ++++++ 3 files changed, 161 insertions(+), 2 deletions(-) diff --git a/src/cast.rs b/src/cast.rs index e2346324232f..8a725680e705 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -1,5 +1,6 @@ //! Various number casting functions +use crate::codegen_f16_f128; use crate::prelude::*; pub(crate) fn clif_intcast( @@ -36,6 +37,14 @@ pub(crate) fn clif_int_or_float_cast( ) -> Value { let from_ty = fx.bcx.func.dfg.value_type(from); + // FIXME(bytecodealliance/wasmtime#8312): Remove in favour of native + // Cranelift operations once Cranelift backends have lowerings for them. + if matches!(from_ty, types::F16 | types::F128) + || matches!(to_ty, types::F16 | types::F128) && from_ty != to_ty + { + return codegen_f16_f128::codegen_cast(fx, from, from_signed, to_ty, to_signed); + } + if from_ty.is_int() && to_ty.is_int() { // int-like -> int-like clif_intcast( @@ -58,8 +67,10 @@ pub(crate) fn clif_int_or_float_cast( "__float{sign}ti{flt}f", sign = if from_signed { "" } else { "un" }, flt = match to_ty { + types::F16 => "h", types::F32 => "s", types::F64 => "d", + types::F128 => "t", _ => unreachable!("{:?}", to_ty), }, ); @@ -90,8 +101,10 @@ pub(crate) fn clif_int_or_float_cast( "__fix{sign}{flt}fti", sign = if to_signed { "" } else { "uns" }, flt = match from_ty { + types::F16 => "h", types::F32 => "s", types::F64 => "d", + types::F128 => "t", _ => unreachable!("{:?}", to_ty), }, ); @@ -145,8 +158,12 @@ pub(crate) fn clif_int_or_float_cast( } else if from_ty.is_float() && to_ty.is_float() { // float -> float match (from_ty, to_ty) { - (types::F32, types::F64) => fx.bcx.ins().fpromote(types::F64, from), - (types::F64, types::F32) => fx.bcx.ins().fdemote(types::F32, from), + (types::F16, types::F32 | types::F64 | types::F128) + | (types::F32, types::F64 | types::F128) + | (types::F64, types::F128) => fx.bcx.ins().fpromote(to_ty, from), + (types::F128, types::F64 | types::F32 | types::F16) + | (types::F64, types::F32 | types::F16) + | (types::F32, types::F16) => fx.bcx.ins().fdemote(to_ty, from), _ => from, } } else { diff --git a/src/codegen_f16_f128.rs b/src/codegen_f16_f128.rs index c570fbbd993d..a887341cec43 100644 --- a/src/codegen_f16_f128.rs +++ b/src/codegen_f16_f128.rs @@ -13,6 +13,11 @@ pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value fx.lib_call("__extendhfsf2", vec![arg_ty], vec![AbiParam::new(types::F32)], &[value])[0] } +fn f16_to_f64(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { + let ret = f16_to_f32(fx, value); + fx.bcx.ins().fpromote(types::F64, ret) +} + pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" { types::I16 @@ -28,6 +33,21 @@ pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value if ret_ty == types::I16 { fx.bcx.ins().bitcast(types::F16, MemFlags::new(), ret) } else { ret } } +fn f64_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { + let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" { + types::I16 + } else { + types::F16 + }; + let ret = fx.lib_call( + "__truncdfhf2", + vec![AbiParam::new(types::F64)], + vec![AbiParam::new(ret_ty)], + &[value], + )[0]; + if ret_ty == types::I16 { fx.bcx.ins().bitcast(types::F16, MemFlags::new(), ret) } else { ret } +} + pub(crate) fn fcmp(fx: &mut FunctionCx<'_, '_, '_>, cc: FloatCC, lhs: Value, rhs: Value) -> Value { let ty = fx.bcx.func.dfg.value_type(lhs); match ty { @@ -99,6 +119,109 @@ pub(crate) fn neg_f128(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { fx.bcx.ins().bitcast(types::F128, MemFlags::new(), bits) } +pub(crate) fn codegen_cast( + fx: &mut FunctionCx<'_, '_, '_>, + from: Value, + from_signed: bool, + to_ty: Type, + to_signed: bool, +) -> Value { + let from_ty = fx.bcx.func.dfg.value_type(from); + if from_ty.is_float() && to_ty.is_float() { + let name = match (from_ty, to_ty) { + (types::F16, types::F32) => return f16_to_f32(fx, from), + (types::F16, types::F64) => return f16_to_f64(fx, from), + (types::F16, types::F128) => "__extendhftf2", + (types::F32, types::F128) => "__extendsftf2", + (types::F64, types::F128) => "__extenddftf2", + (types::F128, types::F64) => "__trunctfdf2", + (types::F128, types::F32) => "__trunctfsf2", + (types::F128, types::F16) => "__trunctfhf2", + (types::F64, types::F16) => return f64_to_f16(fx, from), + (types::F32, types::F16) => return f32_to_f16(fx, from), + _ => unreachable!("{from_ty:?} -> {to_ty:?}"), + }; + fx.lib_call(name, vec![AbiParam::new(from_ty)], vec![AbiParam::new(to_ty)], &[from])[0] + } else if from_ty.is_int() && to_ty == types::F16 { + let res = clif_int_or_float_cast(fx, from, from_signed, types::F32, false); + f32_to_f16(fx, res) + } else if from_ty == types::F16 && to_ty.is_int() { + let from = f16_to_f32(fx, from); + clif_int_or_float_cast(fx, from, false, to_ty, to_signed) + } else if from_ty.is_int() && to_ty == types::F128 { + let (from, from_ty) = if from_ty.bits() < 32 { + (clif_int_or_float_cast(fx, from, from_signed, types::I32, from_signed), types::I32) + } else { + (from, from_ty) + }; + let name = format!( + "__float{sign}{size}itf", + sign = if from_signed { "" } else { "un" }, + size = match from_ty { + types::I32 => 's', + types::I64 => 'd', + types::I128 => 't', + _ => unreachable!("{from_ty:?}"), + }, + ); + fx.lib_call( + &name, + vec![lib_call_arg_param(fx.tcx, from_ty, from_signed)], + vec![AbiParam::new(to_ty)], + &[from], + )[0] + } else if from_ty == types::F128 && to_ty.is_int() { + let ret_ty = if to_ty.bits() < 32 { types::I32 } else { to_ty }; + let name = format!( + "__fix{sign}tf{size}i", + sign = if from_signed { "" } else { "un" }, + size = match ret_ty { + types::I32 => 's', + types::I64 => 'd', + types::I128 => 't', + _ => unreachable!("{from_ty:?}"), + }, + ); + let ret = + fx.lib_call(&name, vec![AbiParam::new(from_ty)], vec![AbiParam::new(to_ty)], &[from]) + [0]; + let val = if ret_ty == to_ty { + ret + } else { + let (min, max) = match (to_ty, to_signed) { + (types::I8, false) => (0, i64::from(u8::MAX)), + (types::I16, false) => (0, i64::from(u16::MAX)), + (types::I8, true) => (i64::from(i8::MIN as u32), i64::from(i8::MAX as u32)), + (types::I16, true) => (i64::from(i16::MIN as u32), i64::from(i16::MAX as u32)), + _ => unreachable!("{to_ty:?}"), + }; + let min_val = fx.bcx.ins().iconst(types::I32, min); + let max_val = fx.bcx.ins().iconst(types::I32, max); + + let val = if to_signed { + let has_underflow = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, ret, min); + let has_overflow = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThan, ret, max); + let bottom_capped = fx.bcx.ins().select(has_underflow, min_val, ret); + fx.bcx.ins().select(has_overflow, max_val, bottom_capped) + } else { + let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, ret, max); + fx.bcx.ins().select(has_overflow, max_val, ret) + }; + fx.bcx.ins().ireduce(to_ty, val) + }; + + if let Some(false) = fx.tcx.sess.opts.unstable_opts.saturating_float_casts { + return val; + } + + let is_not_nan = fcmp(fx, FloatCC::Equal, from, from); + let zero = type_zero_value(&mut fx.bcx, to_ty); + fx.bcx.ins().select(is_not_nan, val, zero) + } else { + unreachable!("{from_ty:?} -> {to_ty:?}"); + } +} + pub(crate) fn fmin_f128(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { fx.lib_call( "fminimumf128", diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index 017a1370abd7..d9cbffd7ae01 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -49,15 +49,34 @@ builtin_functions! { // integer -> float fn __floattisf(i: i128) -> f32; fn __floattidf(i: i128) -> f64; + fn __floatsitf(i: i32) -> f128; + fn __floatditf(i: i64) -> f128; + fn __floattitf(i: i128) -> f128; fn __floatuntisf(i: u128) -> f32; fn __floatuntidf(i: u128) -> f64; + fn __floatunsitf(i: u32) -> f128; + fn __floatunditf(i: u64) -> f128; + fn __floatuntitf(i: u128) -> f128; // float -> integer fn __fixsfti(f: f32) -> i128; fn __fixdfti(f: f64) -> i128; + fn __fixtfsi(f: f128) -> i32; + fn __fixtfdi(f: f128) -> i64; + fn __fixtfti(f: f128) -> i128; fn __fixunssfti(f: f32) -> u128; fn __fixunsdfti(f: f64) -> u128; + fn __fixunstfsi(f: f128) -> u32; + fn __fixunstfdi(f: f128) -> u64; + fn __fixunstfti(f: f128) -> u128; // float -> float fn __extendhfsf2(f: f16) -> f32; + fn __extendhftf2(f: f16) -> f128; + fn __extendsftf2(f: f32) -> f128; + fn __extenddftf2(f: f64) -> f128; + fn __trunctfdf2(f: f128) -> f64; + fn __trunctfsf2(f: f128) -> f32; + fn __trunctfhf2(f: f128) -> f16; + fn __truncdfhf2(f: f64) -> f16; fn __truncsfhf2(f: f32) -> f16; // float binops fn __addtf3(a: f128, b: f128) -> f128; From 2055f01323fbeada8857f9a0725c12567891c377 Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 23 May 2025 15:51:51 +0100 Subject: [PATCH 100/139] Add `f16`/`f128` intrinsic support --- src/codegen_f16_f128.rs | 43 ++++++++++++++++++++++ src/compiler_builtins.rs | 15 ++++++++ src/intrinsics/mod.rs | 79 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 136 insertions(+), 1 deletion(-) diff --git a/src/codegen_f16_f128.rs b/src/codegen_f16_f128.rs index a887341cec43..1e202be1f185 100644 --- a/src/codegen_f16_f128.rs +++ b/src/codegen_f16_f128.rs @@ -119,6 +119,41 @@ pub(crate) fn neg_f128(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { fx.bcx.ins().bitcast(types::F128, MemFlags::new(), bits) } +pub(crate) fn abs_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { + let bits = fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value); + let bits = fx.bcx.ins().band_imm(bits, 0x7fff); + fx.bcx.ins().bitcast(types::F16, MemFlags::new(), bits) +} + +pub(crate) fn abs_f128(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { + let bits = fx.bcx.ins().bitcast(types::I128, MemFlags::new(), value); + let (low, high) = fx.bcx.ins().isplit(bits); + let high = fx.bcx.ins().band_imm(high, 0x7fff_ffff_ffff_ffff_u64 as i64); + let bits = fx.bcx.ins().iconcat(low, high); + fx.bcx.ins().bitcast(types::F128, MemFlags::new(), bits) +} + +pub(crate) fn copysign_f16(fx: &mut FunctionCx<'_, '_, '_>, lhs: Value, rhs: Value) -> Value { + let lhs = fx.bcx.ins().bitcast(types::I16, MemFlags::new(), lhs); + let rhs = fx.bcx.ins().bitcast(types::I16, MemFlags::new(), rhs); + let res = fx.bcx.ins().band_imm(lhs, 0x7fff); + let sign = fx.bcx.ins().band_imm(rhs, 0x8000); + let res = fx.bcx.ins().bor(res, sign); + fx.bcx.ins().bitcast(types::F16, MemFlags::new(), res) +} + +pub(crate) fn copysign_f128(fx: &mut FunctionCx<'_, '_, '_>, lhs: Value, rhs: Value) -> Value { + let lhs = fx.bcx.ins().bitcast(types::I128, MemFlags::new(), lhs); + let rhs = fx.bcx.ins().bitcast(types::I128, MemFlags::new(), rhs); + let (low, lhs_high) = fx.bcx.ins().isplit(lhs); + let (_, rhs_high) = fx.bcx.ins().isplit(rhs); + let high = fx.bcx.ins().band_imm(lhs_high, 0x7fff_ffff_ffff_ffff_u64 as i64); + let sign = fx.bcx.ins().band_imm(rhs_high, 0x8000_0000_0000_0000_u64 as i64); + let high = fx.bcx.ins().bor(high, sign); + let res = fx.bcx.ins().iconcat(low, high); + fx.bcx.ins().bitcast(types::F128, MemFlags::new(), res) +} + pub(crate) fn codegen_cast( fx: &mut FunctionCx<'_, '_, '_>, from: Value, @@ -222,6 +257,14 @@ pub(crate) fn codegen_cast( } } +pub(crate) fn fma_f16(fx: &mut FunctionCx<'_, '_, '_>, x: Value, y: Value, z: Value) -> Value { + let x = f16_to_f64(fx, x); + let y = f16_to_f64(fx, y); + let z = f16_to_f64(fx, z); + let res = fx.bcx.ins().fma(x, y, z); + f64_to_f16(fx, res) +} + pub(crate) fn fmin_f128(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { fx.lib_call( "fminimumf128", diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index d9cbffd7ae01..6eea19211fa1 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -109,6 +109,8 @@ builtin_functions! { // float intrinsics fn __powisf2(a: f32, b: i32) -> f32; fn __powidf2(a: f64, b: i32) -> f64; + // FIXME(f16_f128): `compiler-builtins` doesn't currently support `__powitf2` on MSVC. + // fn __powitf2(a: f128, b: i32) -> f128; fn powf(a: f32, b: f32) -> f32; fn pow(a: f64, b: f64) -> f64; fn expf(f: f32) -> f32; @@ -125,6 +127,19 @@ builtin_functions! { fn sin(f: f64) -> f64; fn cosf(f: f32) -> f32; fn cos(f: f64) -> f64; + fn fmaf128(a: f128, b: f128, c: f128) -> f128; + fn floorf16(f: f16) -> f16; + fn floorf128(f: f128) -> f128; + fn ceilf16(f: f16) -> f16; + fn ceilf128(f: f128) -> f128; + fn truncf16(f: f16) -> f16; + fn truncf128(f: f128) -> f128; + fn rintf16(f: f16) -> f16; + fn rintf128(f: f128) -> f128; + fn sqrtf16(f: f16) -> f16; + fn sqrtf128(f: f128) -> f128; + // FIXME(f16_f128): Add other float intrinsics as compiler-builtins gains support (meaning they + // are available on all targets). // allocator // NOTE: These need to be mentioned here despite not being part of compiler_builtins because diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 6481d211234e..b21ca32c9a2e 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -249,8 +249,10 @@ fn bool_to_zero_or_max_uint<'tcx>( let ty = fx.clif_type(ty).unwrap(); let int_ty = match ty { + types::F16 => types::I16, types::F32 => types::I32, types::F64 => types::I64, + types::F128 => types::I128, ty => ty, }; @@ -309,45 +311,83 @@ fn codegen_float_intrinsic_call<'tcx>( ret: CPlace<'tcx>, ) -> bool { let (name, arg_count, ty, clif_ty) = match intrinsic { + sym::expf16 => ("expf16", 1, fx.tcx.types.f16, types::F16), sym::expf32 => ("expf", 1, fx.tcx.types.f32, types::F32), sym::expf64 => ("exp", 1, fx.tcx.types.f64, types::F64), + sym::expf128 => ("expf128", 1, fx.tcx.types.f128, types::F128), + sym::exp2f16 => ("exp2f16", 1, fx.tcx.types.f16, types::F16), sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32, types::F32), sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64, types::F64), + sym::exp2f128 => ("exp2f128", 1, fx.tcx.types.f128, types::F128), + sym::sqrtf16 => ("sqrtf16", 1, fx.tcx.types.f16, types::F16), sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32, types::F32), sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64, types::F64), + sym::sqrtf128 => ("sqrtf128", 1, fx.tcx.types.f128, types::F128), + sym::powif16 => ("__powisf2", 2, fx.tcx.types.f16, types::F16), // compiler-builtins sym::powif32 => ("__powisf2", 2, fx.tcx.types.f32, types::F32), // compiler-builtins sym::powif64 => ("__powidf2", 2, fx.tcx.types.f64, types::F64), // compiler-builtins + sym::powif128 => ("__powitf2", 2, fx.tcx.types.f128, types::F128), // compiler-builtins + sym::powf16 => ("powf16", 2, fx.tcx.types.f16, types::F16), sym::powf32 => ("powf", 2, fx.tcx.types.f32, types::F32), sym::powf64 => ("pow", 2, fx.tcx.types.f64, types::F64), + sym::powf128 => ("powf128", 2, fx.tcx.types.f128, types::F128), + sym::logf16 => ("logf16", 1, fx.tcx.types.f16, types::F16), sym::logf32 => ("logf", 1, fx.tcx.types.f32, types::F32), sym::logf64 => ("log", 1, fx.tcx.types.f64, types::F64), + sym::logf128 => ("logf128", 1, fx.tcx.types.f128, types::F128), + sym::log2f16 => ("log2f16", 1, fx.tcx.types.f16, types::F16), sym::log2f32 => ("log2f", 1, fx.tcx.types.f32, types::F32), sym::log2f64 => ("log2", 1, fx.tcx.types.f64, types::F64), + sym::log2f128 => ("log2f128", 1, fx.tcx.types.f128, types::F128), + sym::log10f16 => ("log10f16", 1, fx.tcx.types.f16, types::F16), sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32), sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64), + sym::log10f128 => ("log10f128", 1, fx.tcx.types.f128, types::F128), + sym::fabsf16 => ("fabsf16", 1, fx.tcx.types.f16, types::F16), sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32, types::F32), sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), + sym::fabsf128 => ("fabsf128", 1, fx.tcx.types.f128, types::F128), + sym::fmaf16 => ("fmaf16", 3, fx.tcx.types.f16, types::F16), sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), + sym::fmaf128 => ("fmaf128", 3, fx.tcx.types.f128, types::F128), // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf16 => ("fmaf16", 3, fx.tcx.types.f16, types::F16), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f16 sym::fmuladdf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f32 sym::fmuladdf64 => ("fma", 3, fx.tcx.types.f64, types::F64), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f64 + sym::fmuladdf128 => ("fmaf128", 3, fx.tcx.types.f128, types::F128), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f128 + sym::copysignf16 => ("copysignf16", 2, fx.tcx.types.f16, types::F16), sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32), sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64), + sym::copysignf128 => ("copysignf128", 2, fx.tcx.types.f128, types::F128), + sym::floorf16 => ("floorf16", 1, fx.tcx.types.f16, types::F16), sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32), sym::floorf64 => ("floor", 1, fx.tcx.types.f64, types::F64), + sym::floorf128 => ("floorf128", 1, fx.tcx.types.f128, types::F128), + sym::ceilf16 => ("ceilf16", 1, fx.tcx.types.f16, types::F16), sym::ceilf32 => ("ceilf", 1, fx.tcx.types.f32, types::F32), sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64), + sym::ceilf128 => ("ceilf128", 1, fx.tcx.types.f128, types::F128), + sym::truncf16 => ("truncf16", 1, fx.tcx.types.f16, types::F16), sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32), sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64), + sym::truncf128 => ("truncf128", 1, fx.tcx.types.f128, types::F128), + sym::round_ties_even_f16 => ("rintf16", 1, fx.tcx.types.f16, types::F16), sym::round_ties_even_f32 => ("rintf", 1, fx.tcx.types.f32, types::F32), sym::round_ties_even_f64 => ("rint", 1, fx.tcx.types.f64, types::F64), + sym::round_ties_even_f128 => ("rintf128", 1, fx.tcx.types.f128, types::F128), + sym::roundf16 => ("roundf16", 1, fx.tcx.types.f16, types::F16), sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32), sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), + sym::roundf128 => ("roundf128", 1, fx.tcx.types.f128, types::F128), + sym::sinf16 => ("sinf16", 1, fx.tcx.types.f16, types::F16), sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), + sym::sinf128 => ("sinf128", 1, fx.tcx.types.f128, types::F128), + sym::cosf16 => ("cosf16", 1, fx.tcx.types.f16, types::F16), sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), sym::cosf64 => ("cos", 1, fx.tcx.types.f64, types::F64), + sym::cosf128 => ("cosf128", 1, fx.tcx.types.f128, types::F128), _ => return false, }; @@ -380,13 +420,26 @@ fn codegen_float_intrinsic_call<'tcx>( }; let layout = fx.layout_of(ty); + // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift operations + // for `f16` and `f128` once the lowerings have been implemented in Cranelift. let res = match intrinsic { + sym::fmaf16 | sym::fmuladdf16 => { + CValue::by_val(codegen_f16_f128::fma_f16(fx, args[0], args[1], args[2]), layout) + } sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => { CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) } + sym::copysignf16 => { + CValue::by_val(codegen_f16_f128::copysign_f16(fx, args[0], args[1]), layout) + } + sym::copysignf128 => { + CValue::by_val(codegen_f16_f128::copysign_f128(fx, args[0], args[1]), layout) + } sym::copysignf32 | sym::copysignf64 => { CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout) } + sym::fabsf16 => CValue::by_val(codegen_f16_f128::abs_f16(fx, args[0]), layout), + sym::fabsf128 => CValue::by_val(codegen_f16_f128::abs_f128(fx, args[0]), layout), sym::fabsf32 | sym::fabsf64 | sym::floorf32 @@ -416,12 +469,36 @@ fn codegen_float_intrinsic_call<'tcx>( // These intrinsics aren't supported natively by Cranelift. // Lower them to a libcall. - sym::powif32 | sym::powif64 => { + sym::powif16 | sym::powif32 | sym::powif64 | sym::powif128 => { + let temp; + let (clif_ty, args) = if intrinsic == sym::powif16 { + temp = [codegen_f16_f128::f16_to_f32(fx, args[0]), args[1]]; + (types::F32, temp.as_slice()) + } else { + (clif_ty, args) + }; let input_tys: Vec<_> = vec![AbiParam::new(clif_ty), lib_call_arg_param(fx.tcx, types::I32, true)]; let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0]; + let ret_val = if intrinsic == sym::powif16 { + codegen_f16_f128::f32_to_f16(fx, ret_val) + } else { + ret_val + }; CValue::by_val(ret_val, fx.layout_of(ty)) } + sym::powf16 => { + // FIXME(f16_f128): Rust `compiler-builtins` doesn't export `powf16` yet. + let x = codegen_f16_f128::f16_to_f32(fx, args[0]); + let y = codegen_f16_f128::f16_to_f32(fx, args[1]); + let ret_val = fx.lib_call( + "powf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + &[x, y], + )[0]; + CValue::by_val(codegen_f16_f128::f32_to_f16(fx, ret_val), fx.layout_of(ty)) + } _ => { let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect(); let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0]; From 02195f56c718defd1df04a452530b14cc96155c9 Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 23 May 2025 15:51:51 +0100 Subject: [PATCH 101/139] Enable tests and `compiler-builtins` for `f16`/`f128` --- build_system/build_sysroot.rs | 2 +- scripts/setup_rust_fork.sh | 2 +- scripts/test_rustc_tests.sh | 8 -------- src/lib.rs | 32 +++++++++++++++++++++++++++----- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index a6e956c51f13..00955998e703 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -235,7 +235,7 @@ fn build_clif_sysroot_for_triple( compiler.rustflags.extend(rustflags); let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs); build_cmd.arg("--release"); - build_cmd.arg("--features").arg("backtrace panic-unwind compiler-builtins-no-f16-f128"); + build_cmd.arg("--features").arg("backtrace panic-unwind"); build_cmd.arg(format!("-Zroot-dir={}", STDLIB_SRC.to_path(dirs).display())); build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true"); build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index ca6426f2ba9d..532702bb1a46 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -43,7 +43,7 @@ verbose-tests = false # disabled bootstrap will crash trying to copy llvm tools for the bootstrap # compiler. llvm-tools = false -std-features = ["panic-unwind", "compiler-builtins-no-f16-f128"] +std-features = ["panic-unwind"] EOF diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index d014b6881ff4..32c71f433b0f 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -72,14 +72,6 @@ rm tests/ui/consts/precise-drop-with-coverage.rs rm tests/ui/issues/issue-85461.rs rm -r tests/ui/instrument-coverage/ -# missing f16/f128 support -rm tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs -rm tests/ui/asm/aarch64/type-f16.rs -rm tests/ui/float/conv-bits-runtime-const.rs -rm tests/ui/consts/const-eval/float_methods.rs -rm tests/ui/match/match-float.rs -rm tests/ui/float/target-has-reliable-nightly-float.rs - # optimization tests # ================== rm tests/ui/codegen/issue-28950.rs # depends on stack size optimizations diff --git a/src/lib.rs b/src/lib.rs index 03dfd495682c..8ef623cde005 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,14 +201,36 @@ impl CodegenBackend for CraneliftCodegenBackend { // FIXME do `unstable_target_features` properly let unstable_target_features = target_features.clone(); + // FIXME(f16_f128): LLVM 20 (currently used by `rustc`) passes `f128` in XMM registers on + // Windows, whereas LLVM 21+ and Cranelift pass it indirectly. This means that `f128` won't + // work when linking against a LLVM-built sysroot. + let has_reliable_f128 = !sess.target.is_like_windows; + let has_reliable_f16 = match &*sess.target.arch { + // FIXME(f16_f128): LLVM 20 does not support `f16` on s390x, meaning the required + // builtins are not available in `compiler-builtins`. + "s390x" => false, + // FIXME(f16_f128): `rustc_codegen_llvm` currently disables support on Windows GNU + // targets due to GCC using a different ABI than LLVM. Therefore `f16` won't be + // available when using a LLVM-built sysroot. + "x86_64" + if sess.target.os == "windows" + && sess.target.env == "gnu" + && sess.target.abi != "llvm" => + { + false + } + _ => true, + }; + TargetConfig { target_features, unstable_target_features, - // Cranelift does not yet support f16 or f128 - has_reliable_f16: false, - has_reliable_f16_math: false, - has_reliable_f128: false, - has_reliable_f128_math: false, + // `rustc_codegen_cranelift` polyfills functionality not yet + // available in Cranelift. + has_reliable_f16, + has_reliable_f16_math: has_reliable_f16, + has_reliable_f128, + has_reliable_f128_math: has_reliable_f128, } } From ec5e841957c2f0200496aa551823157d92a19cc5 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 24 May 2025 15:12:14 +0200 Subject: [PATCH 102/139] ci: move PR job x86_64-gnu-tools to codebuild --- src/ci/github-actions/jobs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 2daa86246053..1d175bd97e6a 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -123,7 +123,7 @@ pr: DOCKER_SCRIPT: x86_64-gnu-llvm.sh <<: *job-linux-16c - name: x86_64-gnu-tools - <<: *job-linux-16c + <<: *job-linux-36c-codebuild # Jobs that run when you perform a try build (@bors try) # These jobs automatically inherit envs.try, to avoid repeating From 01503d0c1e43a23de92ad1577cbdceb7afe47dab Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 24 May 2025 20:22:58 +0200 Subject: [PATCH 103/139] Avoid extra path trimming in method not found error Method errors have an extra check that force trim paths whenever the normal string is longer than 10 characters, which can be quite unhelpful when multiple items have the same name (for example an `Error`). A user reported this force trimming as being quite unhelpful when they had a method error where the precise path of the `Error` mattered. The code uses `tcx.short_string` already to get the normal path, which tries to be clever around trimming paths if necessary, so there is no reason for this extra force trimming. --- compiler/rustc_hir_typeck/src/method/suggest.rs | 6 +----- .../crate-loading/multiple-dep-versions.stderr | 4 ++-- tests/ui/associated-types/issue-43924.stderr | 2 +- tests/ui/attributes/rustc_confusables.stderr | 6 +++--- tests/ui/empty/empty-struct-braces-expr.stderr | 4 ++-- .../multiline-removal-suggestion.svg | 10 +++++----- .../functions-closures/fn-help-with-err.stderr | 2 +- .../hrtb-doesnt-borrow-self-1.stderr | 2 +- .../hrtb-doesnt-borrow-self-2.stderr | 2 +- .../impl-trait/no-method-suggested-traits.stderr | 16 ++++++++-------- tests/ui/issues/issue-30123.stderr | 2 +- tests/ui/issues/issue-41880.stderr | 2 +- tests/ui/macros/missing-writer.stderr | 4 ++-- tests/ui/methods/issue-19521.stderr | 2 +- .../method-not-found-generic-arg-elision.stderr | 2 +- tests/ui/methods/receiver-equality.stderr | 2 +- tests/ui/methods/untrimmed-path-type.rs | 11 +++++++++++ tests/ui/methods/untrimmed-path-type.stderr | 9 +++++++++ tests/ui/mismatched_types/issue-36053-2.stderr | 2 +- tests/ui/nll/issue-57362-2.stderr | 2 +- .../nll/issue-57642-higher-ranked-subtype.stderr | 4 ++-- tests/ui/object-pointer-types.stderr | 2 +- .../mut-borrow-needed-by-trait.stderr | 4 ++-- tests/ui/suggestions/suggest-using-chars.stderr | 4 ++-- tests/ui/typeck/issue-31173.stderr | 2 +- ...boxed-closures-static-call-wrong-trait.stderr | 2 +- 26 files changed, 63 insertions(+), 47 deletions(-) create mode 100644 tests/ui/methods/untrimmed-path-type.rs create mode 100644 tests/ui/methods/untrimmed-path-type.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 342eed751a58..7b71f5de7569 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -599,7 +599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); let mut ty_file = None; - let (mut ty_str, short_ty_str) = + let (ty_str, short_ty_str) = if trait_missing_method && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() { (predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string())) } else { @@ -738,10 +738,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(within_macro_span, "due to this macro variable"); } - if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 { - ty_str = short_ty_str; - } - if rcvr_ty.references_error() { err.downgrade_to_delayed_bug(); } diff --git a/tests/run-make/crate-loading/multiple-dep-versions.stderr b/tests/run-make/crate-loading/multiple-dep-versions.stderr index 6e1d6111b581..dea08bb96c97 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.stderr +++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr @@ -39,7 +39,7 @@ error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in t --> replaced | LL | Type.foo(); - | ^^^ method not found in `Type` + | ^^^ method not found in `dep_2_reexport::Type` | note: there are multiple different versions of crate `dependency` in the dependency graph --> replaced @@ -63,7 +63,7 @@ error[E0599]: no function or associated item named `bar` found for struct `dep_2 --> replaced | LL | Type::bar(); - | ^^^ function or associated item not found in `Type` + | ^^^ function or associated item not found in `dep_2_reexport::Type` | note: there are multiple different versions of crate `dependency` in the dependency graph --> replaced diff --git a/tests/ui/associated-types/issue-43924.stderr b/tests/ui/associated-types/issue-43924.stderr index ab1a9511ec6c..526f425b21e7 100644 --- a/tests/ui/associated-types/issue-43924.stderr +++ b/tests/ui/associated-types/issue-43924.stderr @@ -14,7 +14,7 @@ error[E0599]: no function or associated item named `default` found for trait obj --> $DIR/issue-43924.rs:14:39 | LL | assert_eq!(<() as Foo>::Out::default().to_string(), "false"); - | ^^^^^^^ function or associated item not found in `dyn ToString` + | ^^^^^^^ function or associated item not found in `(dyn ToString + 'static)` error: aborting due to 2 previous errors diff --git a/tests/ui/attributes/rustc_confusables.stderr b/tests/ui/attributes/rustc_confusables.stderr index 55c9219a08a8..aba384ff8ac8 100644 --- a/tests/ui/attributes/rustc_confusables.stderr +++ b/tests/ui/attributes/rustc_confusables.stderr @@ -42,13 +42,13 @@ error[E0599]: no method named `foo` found for struct `rustc_confusables_across_c --> $DIR/rustc_confusables.rs:15:7 | LL | x.foo(); - | ^^^ method not found in `BTreeSet` + | ^^^ method not found in `rustc_confusables_across_crate::BTreeSet` error[E0599]: no method named `push` found for struct `rustc_confusables_across_crate::BTreeSet` in the current scope --> $DIR/rustc_confusables.rs:17:7 | LL | x.push(); - | ^^^^ method not found in `BTreeSet` + | ^^^^ method not found in `rustc_confusables_across_crate::BTreeSet` | help: you might have meant to use `insert` | @@ -60,7 +60,7 @@ error[E0599]: no method named `test` found for struct `rustc_confusables_across_ --> $DIR/rustc_confusables.rs:20:7 | LL | x.test(); - | ^^^^ method not found in `BTreeSet` + | ^^^^ method not found in `rustc_confusables_across_crate::BTreeSet` error[E0599]: no method named `pulled` found for struct `rustc_confusables_across_crate::BTreeSet` in the current scope --> $DIR/rustc_confusables.rs:22:7 diff --git a/tests/ui/empty/empty-struct-braces-expr.stderr b/tests/ui/empty/empty-struct-braces-expr.stderr index 8ec8ecf46bf0..a176107a06e2 100644 --- a/tests/ui/empty/empty-struct-braces-expr.stderr +++ b/tests/ui/empty/empty-struct-braces-expr.stderr @@ -121,7 +121,7 @@ error[E0599]: no variant or associated item named `Empty3` found for enum `empty --> $DIR/empty-struct-braces-expr.rs:25:19 | LL | let xe3 = XE::Empty3; - | ^^^^^^ variant or associated item not found in `XE` + | ^^^^^^ variant or associated item not found in `empty_struct::XE` | help: there is a variant with a similar name | @@ -132,7 +132,7 @@ error[E0599]: no variant or associated item named `Empty3` found for enum `empty --> $DIR/empty-struct-braces-expr.rs:26:19 | LL | let xe3 = XE::Empty3(); - | ^^^^^^ variant or associated item not found in `XE` + | ^^^^^^ variant or associated item not found in `empty_struct::XE` | help: there is a variant with a similar name | diff --git a/tests/ui/error-emitter/multiline-removal-suggestion.svg b/tests/ui/error-emitter/multiline-removal-suggestion.svg index 95c7740f6995..9c9bd163ecd4 100644 --- a/tests/ui/error-emitter/multiline-removal-suggestion.svg +++ b/tests/ui/error-emitter/multiline-removal-suggestion.svg @@ -1,4 +1,4 @@ - +
+ /// + /// This function always resolves `..` to the "lexical" parent. + /// That is "a/b/../c" will always resolve to `a/c` which can change the meaning of the path. + /// In particular, `a/c` and `a/b/../c` are distinct on many systems because `b` may be a symbolic link, so its parent isn’t `a`. + /// + ///
+ /// + /// [`path::absolute`](absolute) is an alternative that preserves `..`. + /// Or [`Path::canonicalize`] can be used to resolve any `..` by querying the filesystem. + #[unstable(feature = "normalize_lexically", issue = "134694")] + pub fn normalize_lexically(&self) -> Result { + let mut lexical = PathBuf::new(); + let mut iter = self.components().peekable(); + + // Find the root, if any, and add it to the lexical path. + // Here we treat the Windows path "C:\" as a single "root" even though + // `components` splits it into two: (Prefix, RootDir). + let root = match iter.peek() { + Some(Component::ParentDir) => return Err(NormalizeError), + Some(p @ Component::RootDir) | Some(p @ Component::CurDir) => { + lexical.push(p); + iter.next(); + lexical.as_os_str().len() + } + Some(Component::Prefix(prefix)) => { + lexical.push(prefix.as_os_str()); + iter.next(); + if let Some(p @ Component::RootDir) = iter.peek() { + lexical.push(p); + iter.next(); + } + lexical.as_os_str().len() + } + None => return Ok(PathBuf::new()), + Some(Component::Normal(_)) => 0, + }; + + for component in iter { + match component { + Component::RootDir => unreachable!(), + Component::Prefix(_) => return Err(NormalizeError), + Component::CurDir => continue, + Component::ParentDir => { + // It's an error if ParentDir causes us to go above the "root". + if lexical.as_os_str().len() == root { + return Err(NormalizeError); + } else { + lexical.pop(); + } + } + Component::Normal(path) => lexical.push(path), + } + } + Ok(lexical) + } + /// Reads a symbolic link, returning the file that the link points to. /// /// This is an alias to [`fs::read_link`]. @@ -3502,6 +3570,15 @@ impl Error for StripPrefixError { } } +#[unstable(feature = "normalize_lexically", issue = "134694")] +impl fmt::Display for NormalizeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("parent reference `..` points outside of base directory") + } +} +#[unstable(feature = "normalize_lexically", issue = "134694")] +impl Error for NormalizeError {} + /// Makes the path absolute without accessing the filesystem. /// /// If the path is relative, the current directory is used as the base directory. diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs index 87e0d226cbd3..781855a2d14a 100644 --- a/library/std/tests/path.rs +++ b/library/std/tests/path.rs @@ -3,7 +3,8 @@ path_add_extension, path_file_prefix, maybe_uninit_slice, - os_string_pathbuf_leak + os_string_pathbuf_leak, + normalize_lexically )] use std::clone::CloneToUninit; @@ -2007,3 +2008,56 @@ fn test_embedded_newline() { assert_eq!(path.file_name(), Some(OsStr::new("foo\nbar"))); assert_eq!(path.to_str(), Some("foo\nbar")); } + +#[test] +fn normalize_lexically() { + #[track_caller] + fn check_ok(a: &str, b: &str) { + assert_eq!(Path::new(a).normalize_lexically().unwrap(), PathBuf::from(b)); + } + + #[track_caller] + fn check_err(a: &str) { + assert!(Path::new(a).normalize_lexically().is_err()); + } + + // Relative paths + check_ok("a", "a"); + check_ok("./a", "./a"); + check_ok("a/b/c", "a/b/c"); + check_ok("a/././b/./c/.", "a/b/c"); + check_ok("a/../c", "c"); + check_ok("./a/b", "./a/b"); + check_ok("a/../b/c/..", "b"); + + check_err(".."); + check_err("../.."); + check_err("a/../.."); + check_err("a/../../b"); + check_err("a/../../b/c"); + check_err("a/../b/../.."); + + // Check we don't escape the root or prefix + #[cfg(unix)] + { + check_err("/.."); + check_err("/a/../.."); + } + #[cfg(windows)] + { + check_err(r"C:\.."); + check_err(r"C:\a\..\.."); + + check_err(r"C:.."); + check_err(r"C:a\..\.."); + + check_err(r"\\server\share\.."); + check_err(r"\\server\share\a\..\.."); + + check_err(r"\.."); + check_err(r"\a\..\.."); + + check_err(r"\\?\UNC\server\share\.."); + check_err(r"\\?\UNC\server\share\a\..\.."); + } +} From 7820d2caba4452e129c47389c302da7edb537404 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 May 2025 10:37:43 +0000 Subject: [PATCH 110/139] Don't use relation just to equate regions in response --- .../rustc_infer/src/infer/canonical/query_response.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index ec72e05494be..e9cfc96ba508 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -23,7 +23,7 @@ use crate::infer::canonical::{ QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse, }; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; -use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult}; +use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin}; use crate::traits::query::NoSolution; use crate::traits::{ Obligation, ObligationCause, PredicateObligation, PredicateObligations, ScrubbedTraitError, @@ -593,10 +593,10 @@ impl<'tcx> InferCtxt<'tcx> { // no action needed } (GenericArgKind::Lifetime(v1), GenericArgKind::Lifetime(v2)) => { - obligations.extend( - self.at(cause, param_env) - .eq(DefineOpaqueTypes::Yes, v1, v2)? - .into_obligations(), + self.inner.borrow_mut().unwrap_region_constraints().make_eqregion( + SubregionOrigin::RelateRegionParamBound(cause.span, None), + v1, + v2, ); } (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => { From 9a8cf3dd0c92afeaac7a83e8d178f1b002ac42b0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 May 2025 10:37:58 +0000 Subject: [PATCH 111/139] Comment for not using select_in_new_trait_solver --- compiler/rustc_trait_selection/src/solve/select.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 1f3168fafb1d..21812c8017da 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -15,6 +15,7 @@ use crate::solve::inspect::{self, ProofTreeInferCtxtExt}; #[extension(pub trait InferCtxtSelectExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { + /// Do not use this directly. This is called from [`crate::traits::SelectionContext::select`]. fn select_in_new_trait_solver( &self, obligation: &TraitObligation<'tcx>, From 3850b1faa2c55f250cfb91df0d8de70d3ed893bd Mon Sep 17 00:00:00 2001 From: Ross Sullivan Date: Sun, 25 May 2025 13:50:45 +0900 Subject: [PATCH 112/139] feat(unstable-book): Added unstable feature doc comments as feature descriptions --- src/tools/tidy/src/features.rs | 17 ++++++++++++++ src/tools/unstable-book-gen/src/main.rs | 23 ++++++++++++++----- src/tools/unstable-book-gen/src/stub-issue.md | 2 ++ .../unstable-book-gen/src/stub-no-issue.md | 2 ++ 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index fcd7943e6e0a..6093e7fd2632 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -54,6 +54,7 @@ pub struct Feature { pub tracking_issue: Option, pub file: PathBuf, pub line: usize, + pub description: Option, } impl Feature { fn tracking_issue_display(&self) -> impl fmt::Display { @@ -296,6 +297,7 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba let mut prev_names = vec![]; let lines = contents.lines().zip(1..); + let mut doc_comments: Vec = Vec::new(); for (line, line_number) in lines { let line = line.trim(); @@ -332,6 +334,13 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba continue; } + if in_feature_group { + if let Some(doc_comment) = line.strip_prefix("///") { + doc_comments.push(doc_comment.trim().to_string()); + continue; + } + } + let mut parts = line.split(','); let level = match parts.next().map(|l| l.trim().trim_start_matches('(')) { Some("unstable") => Status::Unstable, @@ -438,9 +447,15 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba tracking_issue, file: path.to_path_buf(), line: line_number, + description: if doc_comments.is_empty() { + None + } else { + Some(doc_comments.join(" ")) + }, }); } } + doc_comments.clear(); } } @@ -564,6 +579,7 @@ fn map_lib_features( tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none), file: file.to_path_buf(), line: i + 1, + description: None, }; mf(Ok((feature_name, feature)), file, i + 1); continue; @@ -600,6 +616,7 @@ fn map_lib_features( tracking_issue, file: file.to_path_buf(), line: i + 1, + description: None, }; if line.contains(']') { mf(Ok((feature_name, feature)), file, i + 1); diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index 6cbdc83d5b5f..334357729600 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -12,13 +12,18 @@ use tidy::unstable_book::{ collect_unstable_feature_names, }; -fn generate_stub_issue(path: &Path, name: &str, issue: u32) { - let content = format!(include_str!("stub-issue.md"), name = name, issue = issue); +fn generate_stub_issue(path: &Path, name: &str, issue: u32, description: &str) { + let content = format!( + include_str!("stub-issue.md"), + name = name, + issue = issue, + description = description + ); t!(write(path, content), path); } -fn generate_stub_no_issue(path: &Path, name: &str) { - let content = format!(include_str!("stub-no-issue.md"), name = name); +fn generate_stub_no_issue(path: &Path, name: &str, description: &str) { + let content = format!(include_str!("stub-no-issue.md"), name = name, description = description); t!(write(path, content), path); } @@ -58,11 +63,17 @@ fn generate_unstable_book_files(src: &Path, out: &Path, features: &Features) { let file_name = format!("{feature_name}.md"); let out_file_path = out.join(&file_name); let feature = &features[&feature_name_underscore]; + let description = feature.description.as_deref().unwrap_or_default(); if let Some(issue) = feature.tracking_issue { - generate_stub_issue(&out_file_path, &feature_name_underscore, issue.get()); + generate_stub_issue( + &out_file_path, + &feature_name_underscore, + issue.get(), + &description, + ); } else { - generate_stub_no_issue(&out_file_path, &feature_name_underscore); + generate_stub_no_issue(&out_file_path, &feature_name_underscore, &description); } } } diff --git a/src/tools/unstable-book-gen/src/stub-issue.md b/src/tools/unstable-book-gen/src/stub-issue.md index 8698fb7278f6..f1e91b4ac172 100644 --- a/src/tools/unstable-book-gen/src/stub-issue.md +++ b/src/tools/unstable-book-gen/src/stub-issue.md @@ -1,5 +1,7 @@ # `{name}` +{description} + The tracking issue for this feature is: [#{issue}] [#{issue}]: https://github.com/rust-lang/rust/issues/{issue} diff --git a/src/tools/unstable-book-gen/src/stub-no-issue.md b/src/tools/unstable-book-gen/src/stub-no-issue.md index 3da140633d0f..3674d0048aeb 100644 --- a/src/tools/unstable-book-gen/src/stub-no-issue.md +++ b/src/tools/unstable-book-gen/src/stub-no-issue.md @@ -1,5 +1,7 @@ # `{name}` +{description} + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ From 231e8cb34e6a2c549ffd1f0c69ff2521b0ccc3e9 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 24 May 2025 19:59:20 -0400 Subject: [PATCH 113/139] add "Compiler environment variables" section to the unstable book --- src/doc/unstable-book/src/compiler-environment-variables.md | 1 + .../RUSTC_BOOTSTRAP.md} | 2 +- .../RUSTC_OVERRIDE_VERSION_STRING.md} | 0 src/doc/unstable-book/src/compiler-flags/allow-features.md | 2 +- src/tools/unstable-book-gen/src/SUMMARY.md | 2 ++ src/tools/unstable-book-gen/src/main.rs | 5 +++++ 6 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-environment-variables.md rename src/doc/unstable-book/src/{compiler-flags/rustc-bootstrap.md => compiler-environment-variables/RUSTC_BOOTSTRAP.md} (98%) rename src/doc/unstable-book/src/{compiler-flags/rustc-override-version-string.md => compiler-environment-variables/RUSTC_OVERRIDE_VERSION_STRING.md} (100%) diff --git a/src/doc/unstable-book/src/compiler-environment-variables.md b/src/doc/unstable-book/src/compiler-environment-variables.md new file mode 100644 index 000000000000..db912fdf3bac --- /dev/null +++ b/src/doc/unstable-book/src/compiler-environment-variables.md @@ -0,0 +1 @@ +# Compiler environment variables diff --git a/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md b/src/doc/unstable-book/src/compiler-environment-variables/RUSTC_BOOTSTRAP.md similarity index 98% rename from src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md rename to src/doc/unstable-book/src/compiler-environment-variables/RUSTC_BOOTSTRAP.md index 1520b86341b2..fed28a332669 100644 --- a/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md +++ b/src/doc/unstable-book/src/compiler-environment-variables/RUSTC_BOOTSTRAP.md @@ -14,7 +14,7 @@ Cargo disallows setting `cargo::rustc-env=RUSTC_BOOTSTRAP` in build scripts. Build systems can limit the features they enable with [`-Z allow-features=feature1,feature2`][Z-allow-features]. Crates can fully opt out of unstable features by using [`#![forbid(unstable_features)]`][unstable-features] at the crate root (or any other way of enabling lints, such as `-F unstable-features`). -[Z-allow-features]: ./allow-features.html +[Z-allow-features]: ../compiler-flags/allow-features.html [unstable-features]: ../../rustc/lints/listing/allowed-by-default.html#unstable-features ## Why does this environment variable exist? diff --git a/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md b/src/doc/unstable-book/src/compiler-environment-variables/RUSTC_OVERRIDE_VERSION_STRING.md similarity index 100% rename from src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md rename to src/doc/unstable-book/src/compiler-environment-variables/RUSTC_OVERRIDE_VERSION_STRING.md diff --git a/src/doc/unstable-book/src/compiler-flags/allow-features.md b/src/doc/unstable-book/src/compiler-flags/allow-features.md index 84fa465c89b4..49a41a8c5a31 100644 --- a/src/doc/unstable-book/src/compiler-flags/allow-features.md +++ b/src/doc/unstable-book/src/compiler-flags/allow-features.md @@ -11,4 +11,4 @@ Features are comma-separated, for example `-Z allow-features=ffi_pure,f16`. If the flag is present, any feature listed will be allowed and any feature not listed will be disallowed. Any unrecognized feature is ignored. -[`RUSTC_BOOTSTRAP`]: ./rustc-bootstrap.html +[`RUSTC_BOOTSTRAP`]: ../compiler-environment-variables/RUSTC_BOOTSTRAP.html diff --git a/src/tools/unstable-book-gen/src/SUMMARY.md b/src/tools/unstable-book-gen/src/SUMMARY.md index 933c928e2f09..fd4ea1dada62 100644 --- a/src/tools/unstable-book-gen/src/SUMMARY.md +++ b/src/tools/unstable-book-gen/src/SUMMARY.md @@ -1,5 +1,7 @@ [The Unstable Book](the-unstable-book.md) +- [Compiler environment variables](compiler-environment-variables.md) +{compiler_env_vars} - [Compiler flags](compiler-flags.md) {compiler_flags} - [Language features](language-features.md) diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index 6cbdc83d5b5f..b9a2d313182f 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -30,8 +30,12 @@ fn set_to_summary_str(set: &BTreeSet, dir: &str) -> String { fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) { let compiler_flags = collect_unstable_book_section_file_names(&path.join("src/compiler-flags")); + let compiler_env_vars = + collect_unstable_book_section_file_names(&path.join("src/compiler-environment-variables")); let compiler_flags_str = set_to_summary_str(&compiler_flags, "compiler-flags"); + let compiler_env_vars_str = + set_to_summary_str(&compiler_env_vars, "compiler-environment-variables"); let unstable_lang_features = collect_unstable_feature_names(&lang_features); let unstable_lib_features = collect_unstable_feature_names(&lib_features); @@ -42,6 +46,7 @@ fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Featur let summary_path = path.join("src/SUMMARY.md"); let content = format!( include_str!("SUMMARY.md"), + compiler_env_vars = compiler_env_vars_str, compiler_flags = compiler_flags_str, language_features = lang_features_str, library_features = lib_features_str From 5f857a9871240efe6e15ca94dd03e06b90c6413d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 May 2025 15:40:56 +0200 Subject: [PATCH 114/139] Rename `clean::Enum::variants` method into `non_stripped_variants` --- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/render/sidebar.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 07ecd98f7759..f353ad5cf917 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2107,7 +2107,7 @@ impl Enum { self.variants.iter().any(|f| f.is_stripped()) } - pub(crate) fn variants(&self) -> impl Iterator { + pub(crate) fn non_stripped_variants(&self) -> impl Iterator { self.variants.iter().filter(|v| !v.is_stripped()) } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 39a631b637bd..552e67c9f53d 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1535,7 +1535,7 @@ fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Displa fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::Display { fmt::from_fn(|w| { - let count_variants = e.variants().count(); + let count_variants = e.non_stripped_variants().count(); wrap_item(w, |w| { render_attributes_in_code(w, it, cx); write!( diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 361966325fb3..91540e06e339 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -599,7 +599,7 @@ fn sidebar_enum<'a>( deref_id_map: &'a DefIdMap, ) { let mut variants = e - .variants() + .non_stripped_variants() .filter_map(|v| v.name) .map(|name| Link::new(format!("variant.{name}"), name.to_string())) .collect::>(); From 560aec13ba62c1a8fd7b2f9fbeada61096809613 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 May 2025 17:10:38 +0200 Subject: [PATCH 115/139] Unify rendering of type aliases without ADT items --- src/librustdoc/clean/types.rs | 13 + src/librustdoc/html/render/print_item.rs | 274 +++++++++--------- src/librustdoc/html/templates/item_union.html | 7 +- 3 files changed, 154 insertions(+), 140 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index f353ad5cf917..98d57494dbe6 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -610,6 +610,9 @@ impl Item { UnionItem(ref union_) => Some(union_.has_stripped_entries()), EnumItem(ref enum_) => Some(enum_.has_stripped_entries()), VariantItem(ref v) => v.has_stripped_entries(), + TypeAliasItem(ref type_alias) => { + type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries()) + } _ => None, } } @@ -2345,6 +2348,16 @@ pub(crate) enum TypeAliasInnerType { Struct { ctor_kind: Option, fields: Vec }, } +impl TypeAliasInnerType { + fn has_stripped_entries(&self) -> Option { + Some(match self { + Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()), + Self::Union { fields } => fields.iter().any(|f| f.is_stripped()), + Self::Struct { fields, .. } => fields.iter().any(|f| f.is_stripped()), + }) + } +} + #[derive(Clone, Debug)] pub(crate) struct TypeAlias { pub(crate) type_: Type, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 552e67c9f53d..616d89bca6a7 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1278,94 +1278,40 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> match inner_type { clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => { - let variants_iter = || variants.iter().filter(|i| !i.is_stripped()); let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity(); let enum_def_id = ty.ty_adt_def().unwrap().did(); - wrap_item(w, |w| { - let variants_len = variants.len(); - let variants_count = variants_iter().count(); - let has_stripped_entries = variants_len != variants_count; - - write!( - w, - "enum {}{}{}", - it.name.unwrap(), - t.generics.print(cx), - render_enum_fields( - cx, - Some(&t.generics), - variants, - variants_count, - has_stripped_entries, - *is_non_exhaustive, - enum_def_id, - ) - ) - })?; - write!(w, "{}", item_variants(cx, it, variants, enum_def_id))?; + DisplayEnum { + variants, + generics: &t.generics, + is_non_exhaustive: *is_non_exhaustive, + def_id: enum_def_id, + } + .render_into(cx, it, false, w)?; } clean::TypeAliasInnerType::Union { fields } => { - wrap_item(w, |w| { - let fields_count = fields.iter().filter(|i| !i.is_stripped()).count(); - let has_stripped_fields = fields.len() != fields_count; - - write!( - w, - "union {}{}{}", - it.name.unwrap(), - t.generics.print(cx), - render_struct_fields( - Some(&t.generics), - None, - fields, - "", - true, - has_stripped_fields, - cx, - ), - ) - })?; - write!(w, "{}", item_fields(cx, it, fields, None))?; + ItemUnion { cx, it, fields, generics: &t.generics, document_union: false } + .render_into(w)?; } clean::TypeAliasInnerType::Struct { ctor_kind, fields } => { - wrap_item(w, |w| { - let fields_count = fields.iter().filter(|i| !i.is_stripped()).count(); - let has_stripped_fields = fields.len() != fields_count; - - write!( - w, - "struct {}{}{}", - it.name.unwrap(), - t.generics.print(cx), - render_struct_fields( - Some(&t.generics), - *ctor_kind, - fields, - "", - true, - has_stripped_fields, - cx, - ), - ) - })?; - write!(w, "{}", item_fields(cx, it, fields, None))?; + DisplayStruct { ctor_kind: *ctor_kind, generics: &t.generics, fields } + .render_into(cx, it, false, w)?; } } + } else { + let def_id = it.item_id.expect_def_id(); + // Render any items associated directly to this alias, as otherwise they + // won't be visible anywhere in the docs. It would be nice to also show + // associated items from the aliased type (see discussion in #32077), but + // we need #14072 to make sense of the generics. + write!( + w, + "{}{}", + render_assoc_items(cx, it, def_id, AssocItemRender::All), + document_type_layout(cx, def_id) + )?; } - let def_id = it.item_id.expect_def_id(); - // Render any items associated directly to this alias, as otherwise they - // won't be visible anywhere in the docs. It would be nice to also show - // associated items from the aliased type (see discussion in #32077), but - // we need #14072 to make sense of the generics. - write!( - w, - "{}{}", - render_assoc_items(cx, it, def_id, AssocItemRender::All), - document_type_layout(cx, def_id) - )?; - // [RUSTDOCIMPL] type.impl // // Include type definitions from the alias target type. @@ -1463,50 +1409,53 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> }) } -fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display { - item_template!( - #[template(path = "item_union.html")] - struct ItemUnion<'a, 'cx> { - cx: &'a Context<'cx>, - it: &'a clean::Item, - s: &'a clean::Union, - }, - methods = [document, document_type_layout, render_attributes_in_pre, render_assoc_items] - ); +item_template!( + #[template(path = "item_union.html")] + struct ItemUnion<'a, 'cx> { + cx: &'a Context<'cx>, + it: &'a clean::Item, + fields: &'a [clean::Item], + generics: &'a clean::Generics, + document_union: bool, + }, + methods = [document, document_type_layout, render_attributes_in_pre, render_assoc_items] +); - impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { - fn render_union(&self) -> impl Display { - render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx) - } - - fn document_field(&self, field: &'a clean::Item) -> impl Display { - document(self.cx, field, Some(self.it), HeadingOffset::H3) - } - - fn stability_field(&self, field: &clean::Item) -> Option { - field.stability_class(self.cx.tcx()) - } - - fn print_ty(&self, ty: &'a clean::Type) -> impl Display { - ty.print(self.cx) - } - - fn fields_iter( - &self, - ) -> iter::Peekable> { - self.s - .fields - .iter() - .filter_map(|f| match f.kind { - clean::StructFieldItem(ref ty) => Some((f, ty)), - _ => None, - }) - .peekable() - } +impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { + fn render_union(&self) -> impl Display { + render_union(self.it, Some(&self.generics), &self.fields, self.cx) } + fn document_field(&self, field: &'a clean::Item) -> impl Display { + document(self.cx, field, Some(self.it), HeadingOffset::H3) + } + + fn stability_field(&self, field: &clean::Item) -> Option { + field.stability_class(self.cx.tcx()) + } + + fn print_ty(&self, ty: &'a clean::Type) -> impl Display { + ty.print(self.cx) + } + + fn fields_iter( + &self, + ) -> iter::Peekable> { + self.fields + .iter() + .filter_map(|f| match f.kind { + clean::StructFieldItem(ref ty) => Some((f, ty)), + _ => None, + }) + .peekable() + } +} + +fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display { fmt::from_fn(|w| { - ItemUnion { cx, it, s }.render_into(w).unwrap(); + ItemUnion { cx, it, fields: &s.fields, generics: &s.generics, document_union: true } + .render_into(w) + .unwrap(); Ok(()) }) } @@ -1533,9 +1482,25 @@ fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Displa }) } -fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::Display { - fmt::from_fn(|w| { - let count_variants = e.non_stripped_variants().count(); +struct DisplayEnum<'a> { + variants: &'a IndexVec, + generics: &'a clean::Generics, + is_non_exhaustive: bool, + def_id: DefId, +} + +impl<'a> DisplayEnum<'a> { + fn render_into( + self, + cx: &Context<'_>, + it: &clean::Item, + document_enum: bool, + w: &mut W, + ) -> fmt::Result { + let variants_count = self.variants.iter().filter(|i| !i.is_stripped()).count(); + let variants_len = self.variants.len(); + let has_stripped_entries = variants_len != variants_count; + wrap_item(w, |w| { render_attributes_in_code(w, it, cx); write!( @@ -1543,23 +1508,25 @@ fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::D "{}enum {}{}{}", visibility_print_with_space(it, cx), it.name.unwrap(), - e.generics.print(cx), + self.generics.print(cx), render_enum_fields( cx, - Some(&e.generics), - &e.variants, - count_variants, - e.has_stripped_entries(), - it.is_non_exhaustive(), - it.def_id().unwrap(), + Some(self.generics), + self.variants, + variants_count, + has_stripped_entries, + self.is_non_exhaustive, + self.def_id, ), ) })?; - write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; + if document_enum { + write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; + } - if count_variants != 0 { - write!(w, "{}", item_variants(cx, it, &e.variants, it.def_id().unwrap()))?; + if variants_count != 0 { + write!(w, "{}", item_variants(cx, it, self.variants, self.def_id))?; } let def_id = it.item_id.expect_def_id(); write!( @@ -1568,6 +1535,18 @@ fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::D render_assoc_items(cx, it, def_id, AssocItemRender::All), document_type_layout(cx, def_id) ) + } +} + +fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::Display { + fmt::from_fn(|w| { + DisplayEnum { + variants: &e.variants, + generics: &e.generics, + is_non_exhaustive: it.is_non_exhaustive(), + def_id: it.def_id().unwrap(), + } + .render_into(cx, it, true, w) }) } @@ -1955,27 +1934,48 @@ fn item_constant( }) } -fn item_struct(cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) -> impl fmt::Display { - fmt::from_fn(|w| { +struct DisplayStruct<'a> { + ctor_kind: Option, + generics: &'a clean::Generics, + fields: &'a [clean::Item], +} + +impl<'a> DisplayStruct<'a> { + fn render_into( + self, + cx: &Context<'_>, + it: &clean::Item, + document_struct: bool, + w: &mut W, + ) -> fmt::Result { wrap_item(w, |w| { render_attributes_in_code(w, it, cx); write!( w, "{}", - render_struct(it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx) + render_struct(it, Some(self.generics), self.ctor_kind, self.fields, "", true, cx) ) })?; - let def_id = it.item_id.expect_def_id(); + if document_struct { + write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; + } + let def_id = it.item_id.expect_def_id(); write!( w, - "{}{}{}{}", - document(cx, it, None, HeadingOffset::H2), - item_fields(cx, it, &s.fields, s.ctor_kind), + "{}{}{}", + item_fields(cx, it, self.fields, self.ctor_kind), render_assoc_items(cx, it, def_id, AssocItemRender::All), document_type_layout(cx, def_id), ) + } +} + +fn item_struct(cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) -> impl fmt::Display { + fmt::from_fn(|w| { + DisplayStruct { ctor_kind: s.ctor_kind, generics: &s.generics, fields: s.fields.as_slice() } + .render_into(cx, it, true, w) }) } diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html index b1c1d5a63a03..f3780fb4c5ba 100644 --- a/src/librustdoc/html/templates/item_union.html +++ b/src/librustdoc/html/templates/item_union.html @@ -2,15 +2,16 @@ {{ self.render_attributes_in_pre()|safe }} {{ self.render_union()|safe }} -{{ self.document()|safe }} +{% if self.document_union %} + {{ self.document()|safe }} +{% endif %} {% if self.fields_iter().peek().is_some() %}

{# #} Fields§ {# #}

{% for (field, ty) in self.fields_iter() %} {% let name = field.name.expect("union field name") %} - {# #} + {# #} § {# #} {{ name }}: {{+ self.print_ty(ty)|safe }} {# #} From 4194745687ead479898587b85f1388635b3422e2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 May 2025 17:36:32 +0200 Subject: [PATCH 116/139] Split `Item::attributes` method into three --- src/librustdoc/clean/types.rs | 145 ++++++++++++++++------------- src/librustdoc/html/render/mod.rs | 4 +- src/librustdoc/json/conversions.rs | 2 +- 3 files changed, 81 insertions(+), 70 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 98d57494dbe6..1766627ce392 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -764,14 +764,11 @@ impl Item { Some(tcx.visibility(def_id)) } - pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Vec { + pub(crate) fn attributes_witout_repr(&self, tcx: TyCtxt<'_>, is_json: bool) -> Vec { const ALLOWED_ATTRIBUTES: &[Symbol] = &[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive]; - use rustc_abi::IntegerType; - - let mut attrs: Vec = self - .attrs + self.attrs .other_attrs .iter() .filter_map(|attr| { @@ -799,74 +796,88 @@ impl Item { None } }) - .collect(); + .collect() + } - // Add #[repr(...)] - if let Some(def_id) = self.def_id() - && let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_() - { - let adt = tcx.adt_def(def_id); - let repr = adt.repr(); - let mut out = Vec::new(); - if repr.c() { - out.push("C"); - } - if repr.transparent() { - // Render `repr(transparent)` iff the non-1-ZST field is public or at least one - // field is public in case all fields are 1-ZST fields. - let render_transparent = is_json - || cache.document_private - || adt - .all_fields() - .find(|field| { - let ty = - field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did)); - tcx.layout_of( - ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty), - ) - .is_ok_and(|layout| !layout.is_1zst()) - }) - .map_or_else( - || adt.all_fields().any(|field| field.vis.is_public()), - |field| field.vis.is_public(), - ); + pub(crate) fn attributes_and_repr( + &self, + tcx: TyCtxt<'_>, + cache: &Cache, + is_json: bool, + ) -> Vec { + let mut attrs = self.attributes_witout_repr(tcx, is_json); - if render_transparent { - out.push("transparent"); - } - } - if repr.simd() { - out.push("simd"); - } - let pack_s; - if let Some(pack) = repr.pack { - pack_s = format!("packed({})", pack.bytes()); - out.push(&pack_s); - } - let align_s; - if let Some(align) = repr.align { - align_s = format!("align({})", align.bytes()); - out.push(&align_s); - } - let int_s; - if let Some(int) = repr.int { - int_s = match int { - IntegerType::Pointer(is_signed) => { - format!("{}size", if is_signed { 'i' } else { 'u' }) - } - IntegerType::Fixed(size, is_signed) => { - format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8) - } - }; - out.push(&int_s); - } - if !out.is_empty() { - attrs.push(format!("#[repr({})]", out.join(", "))); - } + if let Some(repr_attr) = self.repr(tcx, cache) { + attrs.push(repr_attr); } attrs } + /// Returns a `#[repr(...)]` representation. + pub(crate) fn repr(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Option { + use rustc_abi::IntegerType; + + let def_id = self.def_id()?; + if !matches!(self.type_(), ItemType::Struct | ItemType::Enum | ItemType::Union) { + return None; + } + let adt = tcx.adt_def(def_id); + let repr = adt.repr(); + let mut out = Vec::new(); + if repr.c() { + out.push("C"); + } + if repr.transparent() { + // Render `repr(transparent)` iff the non-1-ZST field is public or at least one + // field is public in case all fields are 1-ZST fields. + let render_transparent = is_json + || cache.document_private + || adt + .all_fields() + .find(|field| { + let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did)); + tcx.layout_of( + ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty), + ) + .is_ok_and(|layout| !layout.is_1zst()) + }) + .map_or_else( + || adt.all_fields().any(|field| field.vis.is_public()), + |field| field.vis.is_public(), + ); + + if render_transparent { + out.push("transparent"); + } + } + if repr.simd() { + out.push("simd"); + } + let pack_s; + if let Some(pack) = repr.pack { + pack_s = format!("packed({})", pack.bytes()); + out.push(&pack_s); + } + let align_s; + if let Some(align) = repr.align { + align_s = format!("align({})", align.bytes()); + out.push(&align_s); + } + let int_s; + if let Some(int) = repr.int { + int_s = match int { + IntegerType::Pointer(is_signed) => { + format!("{}size", if is_signed { 'i' } else { 'u' }) + } + IntegerType::Fixed(size, is_signed) => { + format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8) + } + }; + out.push(&int_s); + } + if !out.is_empty() { Some(format!("#[repr({})]", out.join(", "))) } else { None } + } + pub fn is_doc_hidden(&self) -> bool { self.attrs.is_doc_hidden() } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 06cb9269cc87..6b4fd3cd834a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1194,7 +1194,7 @@ fn render_assoc_item( // a whitespace prefix and newline. fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display { fmt::from_fn(move |f| { - for a in it.attributes(cx.tcx(), cx.cache(), false) { + for a in it.attributes_and_repr(cx.tcx(), cx.cache(), false) { writeln!(f, "{prefix}{a}")?; } Ok(()) @@ -1204,7 +1204,7 @@ fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> // When an attribute is rendered inside a tag, it is formatted using // a div to produce a newline after it. fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) { - for attr in it.attributes(cx.tcx(), cx.cache(), false) { + for attr in it.attributes_and_repr(cx.tcx(), cx.cache(), false) { write!(w, "
{attr}
").unwrap(); } } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 705f9b2202c6..bfcb794b89a2 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -40,7 +40,7 @@ impl JsonRenderer<'_> { }) .collect(); let docs = item.opt_doc_value(); - let attrs = item.attributes(self.tcx, self.cache(), true); + let attrs = item.attributes_and_repr(self.tcx, self.cache(), true); let span = item.span(self.tcx); let visibility = item.visibility(self.tcx); let clean::ItemInner { name, item_id, .. } = *item.inner; From eb9f05481be266598527ba9b5eb890cc56555733 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 May 2025 17:44:24 +0200 Subject: [PATCH 117/139] Rename the `document_*` argument/field into `is_type_alias` --- src/librustdoc/html/render/print_item.rs | 22 +++++++++---------- src/librustdoc/html/templates/item_union.html | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 616d89bca6a7..692e11b2689e 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1287,15 +1287,15 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> is_non_exhaustive: *is_non_exhaustive, def_id: enum_def_id, } - .render_into(cx, it, false, w)?; + .render_into(cx, it, true, w)?; } clean::TypeAliasInnerType::Union { fields } => { - ItemUnion { cx, it, fields, generics: &t.generics, document_union: false } + ItemUnion { cx, it, fields, generics: &t.generics, is_type_alias: true } .render_into(w)?; } clean::TypeAliasInnerType::Struct { ctor_kind, fields } => { DisplayStruct { ctor_kind: *ctor_kind, generics: &t.generics, fields } - .render_into(cx, it, false, w)?; + .render_into(cx, it, true, w)?; } } } else { @@ -1416,7 +1416,7 @@ item_template!( it: &'a clean::Item, fields: &'a [clean::Item], generics: &'a clean::Generics, - document_union: bool, + is_type_alias: bool, }, methods = [document, document_type_layout, render_attributes_in_pre, render_assoc_items] ); @@ -1453,7 +1453,7 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display { fmt::from_fn(|w| { - ItemUnion { cx, it, fields: &s.fields, generics: &s.generics, document_union: true } + ItemUnion { cx, it, fields: &s.fields, generics: &s.generics, is_type_alias: false } .render_into(w) .unwrap(); Ok(()) @@ -1494,7 +1494,7 @@ impl<'a> DisplayEnum<'a> { self, cx: &Context<'_>, it: &clean::Item, - document_enum: bool, + is_type_alias: bool, w: &mut W, ) -> fmt::Result { let variants_count = self.variants.iter().filter(|i| !i.is_stripped()).count(); @@ -1521,7 +1521,7 @@ impl<'a> DisplayEnum<'a> { ) })?; - if document_enum { + if !is_type_alias { write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; } @@ -1546,7 +1546,7 @@ fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::D is_non_exhaustive: it.is_non_exhaustive(), def_id: it.def_id().unwrap(), } - .render_into(cx, it, true, w) + .render_into(cx, it, false, w) }) } @@ -1945,7 +1945,7 @@ impl<'a> DisplayStruct<'a> { self, cx: &Context<'_>, it: &clean::Item, - document_struct: bool, + is_type_alias: bool, w: &mut W, ) -> fmt::Result { wrap_item(w, |w| { @@ -1957,7 +1957,7 @@ impl<'a> DisplayStruct<'a> { ) })?; - if document_struct { + if !is_type_alias { write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; } @@ -1975,7 +1975,7 @@ impl<'a> DisplayStruct<'a> { fn item_struct(cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) -> impl fmt::Display { fmt::from_fn(|w| { DisplayStruct { ctor_kind: s.ctor_kind, generics: &s.generics, fields: s.fields.as_slice() } - .render_into(cx, it, true, w) + .render_into(cx, it, false, w) }) } diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html index f3780fb4c5ba..99a9bc874dd5 100644 --- a/src/librustdoc/html/templates/item_union.html +++ b/src/librustdoc/html/templates/item_union.html @@ -2,7 +2,7 @@ {{ self.render_attributes_in_pre()|safe }} {{ self.render_union()|safe }}
-{% if self.document_union %} +{% if !self.is_type_alias %} {{ self.document()|safe }} {% endif %} {% if self.fields_iter().peek().is_some() %} From 4f3dd7b0180b1212aab607202ec6aa0d4fabb323 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 May 2025 18:47:25 +0200 Subject: [PATCH 118/139] Tweak attribute rendering depending on wether or not it is a type alias --- src/librustdoc/clean/types.rs | 129 ++++++++++++----------- src/librustdoc/html/render/mod.rs | 22 +++- src/librustdoc/html/render/print_item.rs | 100 +++++++++++++++--- tests/rustdoc/type-layout.rs | 2 +- 4 files changed, 173 insertions(+), 80 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1766627ce392..c0bae5971a42 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -815,67 +815,7 @@ impl Item { /// Returns a `#[repr(...)]` representation. pub(crate) fn repr(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Option { - use rustc_abi::IntegerType; - - let def_id = self.def_id()?; - if !matches!(self.type_(), ItemType::Struct | ItemType::Enum | ItemType::Union) { - return None; - } - let adt = tcx.adt_def(def_id); - let repr = adt.repr(); - let mut out = Vec::new(); - if repr.c() { - out.push("C"); - } - if repr.transparent() { - // Render `repr(transparent)` iff the non-1-ZST field is public or at least one - // field is public in case all fields are 1-ZST fields. - let render_transparent = is_json - || cache.document_private - || adt - .all_fields() - .find(|field| { - let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did)); - tcx.layout_of( - ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty), - ) - .is_ok_and(|layout| !layout.is_1zst()) - }) - .map_or_else( - || adt.all_fields().any(|field| field.vis.is_public()), - |field| field.vis.is_public(), - ); - - if render_transparent { - out.push("transparent"); - } - } - if repr.simd() { - out.push("simd"); - } - let pack_s; - if let Some(pack) = repr.pack { - pack_s = format!("packed({})", pack.bytes()); - out.push(&pack_s); - } - let align_s; - if let Some(align) = repr.align { - align_s = format!("align({})", align.bytes()); - out.push(&align_s); - } - let int_s; - if let Some(int) = repr.int { - int_s = match int { - IntegerType::Pointer(is_signed) => { - format!("{}size", if is_signed { 'i' } else { 'u' }) - } - IntegerType::Fixed(size, is_signed) => { - format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8) - } - }; - out.push(&int_s); - } - if !out.is_empty() { Some(format!("#[repr({})]", out.join(", "))) } else { None } + repr_attributes(tcx, cache, self.def_id()?, self.type_(), is_json) } pub fn is_doc_hidden(&self) -> bool { @@ -887,6 +827,73 @@ impl Item { } } +pub(crate) fn repr_attributes( + tcx: TyCtxt<'_>, + cache: &Cache, + def_id: DefId, + item_type: ItemType, + is_json: bool, +) -> Option { + use rustc_abi::IntegerType; + + if !matches!(item_type, ItemType::Struct | ItemType::Enum | ItemType::Union) { + return None; + } + let adt = tcx.adt_def(def_id); + let repr = adt.repr(); + let mut out = Vec::new(); + if repr.c() { + out.push("C"); + } + if repr.transparent() { + // Render `repr(transparent)` iff the non-1-ZST field is public or at least one + // field is public in case all fields are 1-ZST fields. + let render_transparent = cache.document_private + || is_json + || adt + .all_fields() + .find(|field| { + let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did)); + tcx.layout_of(ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty)) + .is_ok_and(|layout| !layout.is_1zst()) + }) + .map_or_else( + || adt.all_fields().any(|field| field.vis.is_public()), + |field| field.vis.is_public(), + ); + + if render_transparent { + out.push("transparent"); + } + } + if repr.simd() { + out.push("simd"); + } + let pack_s; + if let Some(pack) = repr.pack { + pack_s = format!("packed({})", pack.bytes()); + out.push(&pack_s); + } + let align_s; + if let Some(align) = repr.align { + align_s = format!("align({})", align.bytes()); + out.push(&align_s); + } + let int_s; + if let Some(int) = repr.int { + int_s = match int { + IntegerType::Pointer(is_signed) => { + format!("{}size", if is_signed { 'i' } else { 'u' }) + } + IntegerType::Fixed(size, is_signed) => { + format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8) + } + }; + out.push(&int_s); + } + if !out.is_empty() { Some(format!("#[repr({})]", out.join(", "))) } else { None } +} + #[derive(Clone, Debug)] pub(crate) enum ItemKind { ExternCrateItem { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6b4fd3cd834a..f155ea52040a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1201,11 +1201,31 @@ fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> }) } +struct CodeAttribute(String); + +impl CodeAttribute { + fn render_into(self, w: &mut impl fmt::Write) { + write!(w, "
{}
", self.0).unwrap(); + } +} + // When an attribute is rendered inside a tag, it is formatted using // a div to produce a newline after it. fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) { for attr in it.attributes_and_repr(cx.tcx(), cx.cache(), false) { - write!(w, "
{attr}
").unwrap(); + CodeAttribute(attr).render_into(w); + } +} + +/// used for type aliases to only render their `repr` attribute. +fn render_repr_attributes_in_code( + w: &mut impl fmt::Write, + cx: &Context<'_>, + def_id: DefId, + item_type: ItemType, +) { + if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) { + CodeAttribute(repr).render_into(w); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 692e11b2689e..5f81ec68548f 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -20,7 +20,7 @@ use super::{ collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference, item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls, render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre, - render_impl, render_rightside, render_stability_since_raw, + render_impl, render_repr_attributes_in_code, render_rightside, render_stability_since_raw, render_stability_since_raw_with_extra, write_section_heading, }; use crate::clean; @@ -1290,12 +1290,30 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> .render_into(cx, it, true, w)?; } clean::TypeAliasInnerType::Union { fields } => { - ItemUnion { cx, it, fields, generics: &t.generics, is_type_alias: true } - .render_into(w)?; + let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity(); + let union_def_id = ty.ty_adt_def().unwrap().did(); + + ItemUnion { + cx, + it, + fields, + generics: &t.generics, + is_type_alias: true, + def_id: union_def_id, + } + .render_into(w)?; } clean::TypeAliasInnerType::Struct { ctor_kind, fields } => { - DisplayStruct { ctor_kind: *ctor_kind, generics: &t.generics, fields } - .render_into(cx, it, true, w)?; + let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity(); + let struct_def_id = ty.ty_adt_def().unwrap().did(); + + DisplayStruct { + ctor_kind: *ctor_kind, + generics: &t.generics, + fields, + def_id: struct_def_id, + } + .render_into(cx, it, true, w)?; } } } else { @@ -1417,8 +1435,9 @@ item_template!( fields: &'a [clean::Item], generics: &'a clean::Generics, is_type_alias: bool, + def_id: DefId, }, - methods = [document, document_type_layout, render_attributes_in_pre, render_assoc_items] + methods = [document, document_type_layout, render_assoc_items] ); impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { @@ -1449,13 +1468,41 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { }) .peekable() } + + fn render_attributes_in_pre(&self) -> impl fmt::Display { + fmt::from_fn(move |f| { + if !self.is_type_alias { + for a in self.it.attributes_and_repr(self.cx.tcx(), self.cx.cache(), false) { + writeln!(f, "{a}")?; + } + } else { + // For now we only render `repr` attributes for type aliases. + if let Some(repr) = clean::repr_attributes( + self.cx.tcx(), + self.cx.cache(), + self.def_id, + ItemType::Union, + ) { + writeln!(f, "{repr}")?; + }; + } + Ok(()) + }) + } } fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display { fmt::from_fn(|w| { - ItemUnion { cx, it, fields: &s.fields, generics: &s.generics, is_type_alias: false } - .render_into(w) - .unwrap(); + ItemUnion { + cx, + it, + fields: &s.fields, + generics: &s.generics, + is_type_alias: false, + def_id: it.def_id().unwrap(), + } + .render_into(w) + .unwrap(); Ok(()) }) } @@ -1502,7 +1549,12 @@ impl<'a> DisplayEnum<'a> { let has_stripped_entries = variants_len != variants_count; wrap_item(w, |w| { - render_attributes_in_code(w, it, cx); + if !is_type_alias { + render_attributes_in_code(w, it, cx); + } else { + // For now we only render `repr` attributes for type aliases. + render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Enum); + } write!( w, "{}enum {}{}{}", @@ -1521,19 +1573,22 @@ impl<'a> DisplayEnum<'a> { ) })?; - if !is_type_alias { + let def_id = it.item_id.expect_def_id(); + let layout_def_id = if !is_type_alias { write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; - } + def_id + } else { + self.def_id + }; if variants_count != 0 { write!(w, "{}", item_variants(cx, it, self.variants, self.def_id))?; } - let def_id = it.item_id.expect_def_id(); write!( w, "{}{}", render_assoc_items(cx, it, def_id, AssocItemRender::All), - document_type_layout(cx, def_id) + document_type_layout(cx, layout_def_id) ) } } @@ -1938,6 +1993,7 @@ struct DisplayStruct<'a> { ctor_kind: Option, generics: &'a clean::Generics, fields: &'a [clean::Item], + def_id: DefId, } impl<'a> DisplayStruct<'a> { @@ -1949,7 +2005,12 @@ impl<'a> DisplayStruct<'a> { w: &mut W, ) -> fmt::Result { wrap_item(w, |w| { - render_attributes_in_code(w, it, cx); + if !is_type_alias { + render_attributes_in_code(w, it, cx); + } else { + // For now we only render `repr` attributes for type aliases. + render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Struct); + } write!( w, "{}", @@ -1974,8 +2035,13 @@ impl<'a> DisplayStruct<'a> { fn item_struct(cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) -> impl fmt::Display { fmt::from_fn(|w| { - DisplayStruct { ctor_kind: s.ctor_kind, generics: &s.generics, fields: s.fields.as_slice() } - .render_into(cx, it, false, w) + DisplayStruct { + ctor_kind: s.ctor_kind, + generics: &s.generics, + fields: s.fields.as_slice(), + def_id: it.def_id().unwrap(), + } + .render_into(cx, it, false, w) }) } diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs index 6de435dbcc14..482b8b597dd3 100644 --- a/tests/rustdoc/type-layout.rs +++ b/tests/rustdoc/type-layout.rs @@ -61,7 +61,7 @@ pub type TypeAlias = X; pub type GenericTypeAlias = (Generic<(u32, ())>, Generic); // Regression test for the rustdoc equivalent of #85103. -//@ hasraw type_layout/type.Edges.html 'Encountered an error during type layout; the type failed to be normalized.' +//@ hasraw type_layout/type.Edges.html 'Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.' pub type Edges<'a, E> = std::borrow::Cow<'a, [E]>; //@ !hasraw type_layout/trait.MyTrait.html 'Size: ' From 2b292d1b78194e0fb702b1271f4322d0b1d5d1bf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 May 2025 18:47:50 +0200 Subject: [PATCH 119/139] Add regression test for #140739 --- tests/rustdoc/type-alias/repr.rs | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tests/rustdoc/type-alias/repr.rs diff --git a/tests/rustdoc/type-alias/repr.rs b/tests/rustdoc/type-alias/repr.rs new file mode 100644 index 000000000000..cf9079803609 --- /dev/null +++ b/tests/rustdoc/type-alias/repr.rs @@ -0,0 +1,42 @@ +// This test ensures that the `repr` attribute is displayed in type aliases. +// +// Regression test for . + +#![crate_name = "foo"] + +/// bla +#[repr(C)] +pub struct Foo1; + +//@ has 'foo/type.Bar1.html' +//@ has - '//*[@class="rust item-decl"]/code' '#[repr(C)]pub struct Bar1;' +// Ensures that we see the doc comment of the type alias and not of the aliased type. +//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar' +/// bar +pub type Bar1 = Foo1; + +/// bla +#[repr(C)] +pub union Foo2 { + pub a: u8, +} + +//@ has 'foo/type.Bar2.html' +//@ matches - '//*[@class="rust item-decl"]' '#\[repr\(C\)\]\npub union Bar2 \{*' +// Ensures that we see the doc comment of the type alias and not of the aliased type. +//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar' +/// bar +pub type Bar2 = Foo2; + +/// bla +#[repr(C)] +pub enum Foo3 { + A, +} + +//@ has 'foo/type.Bar3.html' +//@ matches - '//*[@class="rust item-decl"]' '#\[repr\(C\)\]pub enum Bar3 \{*' +// Ensures that we see the doc comment of the type alias and not of the aliased type. +//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar' +/// bar +pub type Bar3 = Foo3; From 3646a09811bfca55e976117b4c2b8bf0b4cb5aee Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 May 2025 22:55:50 +0200 Subject: [PATCH 120/139] Improve code --- src/librustdoc/clean/types.rs | 11 +-- src/librustdoc/html/render/mod.rs | 10 +-- src/librustdoc/html/render/print_item.rs | 78 ++++++++++--------- src/librustdoc/html/templates/item_union.html | 2 +- 4 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c0bae5971a42..63533f9fb83a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -764,7 +764,7 @@ impl Item { Some(tcx.visibility(def_id)) } - pub(crate) fn attributes_witout_repr(&self, tcx: TyCtxt<'_>, is_json: bool) -> Vec { + pub(crate) fn attributes_without_repr(&self, tcx: TyCtxt<'_>, is_json: bool) -> Vec { const ALLOWED_ATTRIBUTES: &[Symbol] = &[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive]; @@ -805,7 +805,7 @@ impl Item { cache: &Cache, is_json: bool, ) -> Vec { - let mut attrs = self.attributes_witout_repr(tcx, is_json); + let mut attrs = self.attributes_without_repr(tcx, is_json); if let Some(repr_attr) = self.repr(tcx, cache) { attrs.push(repr_attr); @@ -813,7 +813,7 @@ impl Item { attrs } - /// Returns a `#[repr(...)]` representation. + /// Returns a stringified `#[repr(...)]` attribute. pub(crate) fn repr(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Option { repr_attributes(tcx, cache, self.def_id()?, self.type_(), is_json) } @@ -2370,8 +2370,9 @@ impl TypeAliasInnerType { fn has_stripped_entries(&self) -> Option { Some(match self { Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()), - Self::Union { fields } => fields.iter().any(|f| f.is_stripped()), - Self::Struct { fields, .. } => fields.iter().any(|f| f.is_stripped()), + Self::Union { fields } | Self::Struct { fields, .. } => { + fields.iter().any(|f| f.is_stripped()) + } }) } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f155ea52040a..14b35d3c3920 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1203,17 +1203,15 @@ fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> struct CodeAttribute(String); -impl CodeAttribute { - fn render_into(self, w: &mut impl fmt::Write) { - write!(w, "
{}
", self.0).unwrap(); - } +fn render_code_attribute(code_attr: CodeAttribute, w: &mut impl fmt::Write) { + write!(w, "
{}
", code_attr.0).unwrap(); } // When an attribute is rendered inside a tag, it is formatted using // a div to produce a newline after it. fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) { for attr in it.attributes_and_repr(cx.tcx(), cx.cache(), false) { - CodeAttribute(attr).render_into(w); + render_code_attribute(CodeAttribute(attr), w); } } @@ -1225,7 +1223,7 @@ fn render_repr_attributes_in_code( item_type: ItemType, ) { if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) { - CodeAttribute(repr).render_into(w); + render_code_attribute(CodeAttribute(repr), w); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 5f81ec68548f..3ef578cb03d0 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1457,26 +1457,23 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { ty.print(self.cx) } - fn fields_iter( - &self, - ) -> iter::Peekable> { - self.fields - .iter() - .filter_map(|f| match f.kind { - clean::StructFieldItem(ref ty) => Some((f, ty)), - _ => None, - }) - .peekable() + // FIXME (GuillaumeGomez): When is implemented, + // we can replace the returned value with: + // + // `iter::Peekable>` + // + // And update `item_union.html`. + fn fields_iter(&self) -> impl Iterator { + self.fields.iter().filter_map(|f| match f.kind { + clean::StructFieldItem(ref ty) => Some((f, ty)), + _ => None, + }) } fn render_attributes_in_pre(&self) -> impl fmt::Display { fmt::from_fn(move |f| { - if !self.is_type_alias { - for a in self.it.attributes_and_repr(self.cx.tcx(), self.cx.cache(), false) { - writeln!(f, "{a}")?; - } - } else { - // For now we only render `repr` attributes for type aliases. + if self.is_type_alias { + // For now the only attributes we render for type aliases are `repr` attributes. if let Some(repr) = clean::repr_attributes( self.cx.tcx(), self.cx.cache(), @@ -1485,6 +1482,10 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { ) { writeln!(f, "{repr}")?; }; + } else { + for a in self.it.attributes_and_repr(self.cx.tcx(), self.cx.cache(), false) { + writeln!(f, "{a}")?; + } } Ok(()) }) @@ -1501,8 +1502,7 @@ fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt: is_type_alias: false, def_id: it.def_id().unwrap(), } - .render_into(w) - .unwrap(); + .render_into(w)?; Ok(()) }) } @@ -1529,14 +1529,14 @@ fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Displa }) } -struct DisplayEnum<'a> { - variants: &'a IndexVec, - generics: &'a clean::Generics, +struct DisplayEnum<'clean> { + variants: &'clean IndexVec, + generics: &'clean clean::Generics, is_non_exhaustive: bool, def_id: DefId, } -impl<'a> DisplayEnum<'a> { +impl<'clean> DisplayEnum<'clean> { fn render_into( self, cx: &Context<'_>, @@ -1544,16 +1544,16 @@ impl<'a> DisplayEnum<'a> { is_type_alias: bool, w: &mut W, ) -> fmt::Result { - let variants_count = self.variants.iter().filter(|i| !i.is_stripped()).count(); + let non_stripped_variant_count = self.variants.iter().filter(|i| !i.is_stripped()).count(); let variants_len = self.variants.len(); - let has_stripped_entries = variants_len != variants_count; + let has_stripped_entries = variants_len != non_stripped_variant_count; wrap_item(w, |w| { - if !is_type_alias { - render_attributes_in_code(w, it, cx); - } else { - // For now we only render `repr` attributes for type aliases. + if is_type_alias { + // For now the only attributes we render for type aliases are `repr` attributes. render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Enum); + } else { + render_attributes_in_code(w, it, cx); } write!( w, @@ -1565,7 +1565,7 @@ impl<'a> DisplayEnum<'a> { cx, Some(self.generics), self.variants, - variants_count, + non_stripped_variant_count, has_stripped_entries, self.is_non_exhaustive, self.def_id, @@ -1574,14 +1574,16 @@ impl<'a> DisplayEnum<'a> { })?; let def_id = it.item_id.expect_def_id(); - let layout_def_id = if !is_type_alias { - write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; - def_id - } else { + let layout_def_id = if is_type_alias { self.def_id + } else { + write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; + // We don't return the same `DefId` since the layout size of the type alias might be + // different since we might have more information on the generics. + def_id }; - if variants_count != 0 { + if non_stripped_variant_count != 0 { write!(w, "{}", item_variants(cx, it, self.variants, self.def_id))?; } write!( @@ -2005,11 +2007,11 @@ impl<'a> DisplayStruct<'a> { w: &mut W, ) -> fmt::Result { wrap_item(w, |w| { - if !is_type_alias { - render_attributes_in_code(w, it, cx); - } else { - // For now we only render `repr` attributes for type aliases. + if is_type_alias { + // For now the only attributes we render for type aliases are `repr` attributes. render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Struct); + } else { + render_attributes_in_code(w, it, cx); } write!( w, diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html index 99a9bc874dd5..b5d3367a6a10 100644 --- a/src/librustdoc/html/templates/item_union.html +++ b/src/librustdoc/html/templates/item_union.html @@ -5,7 +5,7 @@ {% if !self.is_type_alias %} {{ self.document()|safe }} {% endif %} -{% if self.fields_iter().peek().is_some() %} +{% if self.fields_iter().next().is_some() %}

{# #} Fields§ {# #}

From ec97b0f0b57376550efa4d144b62955970f22f02 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 May 2025 15:27:32 +0200 Subject: [PATCH 121/139] Update to new API --- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/print_item.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 63533f9fb83a..bb3469867d51 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -807,7 +807,7 @@ impl Item { ) -> Vec { let mut attrs = self.attributes_without_repr(tcx, is_json); - if let Some(repr_attr) = self.repr(tcx, cache) { + if let Some(repr_attr) = self.repr(tcx, cache, is_json) { attrs.push(repr_attr); } attrs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 14b35d3c3920..5677b13033db 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1222,7 +1222,7 @@ fn render_repr_attributes_in_code( def_id: DefId, item_type: ItemType, ) { - if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) { + if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type, false) { render_code_attribute(CodeAttribute(repr), w); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3ef578cb03d0..b4663961c1b7 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1479,6 +1479,7 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { self.cx.cache(), self.def_id, ItemType::Union, + false, ) { writeln!(f, "{repr}")?; }; From 84a3255cc309c9c25e8ed2c16435bb882f364e96 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 24 May 2025 17:24:55 +0000 Subject: [PATCH 122/139] Fast path fold_predicate in old canonicalizer --- compiler/rustc_infer/src/infer/canonical/canonicalizer.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 26ecaebe97f2..0b543f091f73 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -493,6 +493,10 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { ct } } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if p.flags().intersects(self.needs_canonical_flags) { p.super_fold_with(self) } else { p } + } } impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { From 4765fd6b76835058044bed2a25acd1c6335332e4 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 25 May 2025 17:58:44 +0200 Subject: [PATCH 123/139] Fix `unused_braces` lint suggestion when encountering attributes --- compiler/rustc_lint/src/unused.rs | 35 ++++++++++--------- .../unused-braces-attrs-issue-141549.fixed | 15 ++++++++ .../unused-braces-attrs-issue-141549.rs | 15 ++++++++ .../unused-braces-attrs-issue-141549.stderr | 19 ++++++++++ 4 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 tests/ui/lint/unused/unused-braces-attrs-issue-141549.fixed create mode 100644 tests/ui/lint/unused/unused-braces-attrs-issue-141549.rs create mode 100644 tests/ui/lint/unused/unused-braces-attrs-issue-141549.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 50a27d7e84f5..1620f425794f 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1,8 +1,7 @@ use std::iter; -use rustc_ast as ast; use rustc_ast::util::{classify, parser}; -use rustc_ast::{ExprKind, StmtKind}; +use rustc_ast::{self as ast, ExprKind, HasAttrs as _, StmtKind}; use rustc_errors::{MultiSpan, pluralize}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -780,26 +779,30 @@ trait UnusedDelimLint { right_pos: Option, is_kw: bool, ) { - let spans = match value.kind { - ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => stmt - .span - .find_ancestor_inside(value.span) - .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))), + let span_with_attrs = match value.kind { + ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => { + // For the statements with attributes, like `{ #[allow()] println!("Hello!") }`, + // the span should contains the attributes, or the suggestion will remove them. + if let Some(attr_lo) = stmt.attrs().iter().map(|attr| attr.span.lo()).min() { + stmt.span.with_lo(attr_lo) + } else { + stmt.span + } + } ast::ExprKind::Paren(ref expr) => { // For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`, // the span should contains the attributes, or the suggestion will remove them. - let expr_span_with_attrs = - if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() { - expr.span.with_lo(attr_lo) - } else { - expr.span - }; - expr_span_with_attrs.find_ancestor_inside(value.span).map(|expr_span| { - (value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())) - }) + if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() { + expr.span.with_lo(attr_lo) + } else { + expr.span + } } _ => return, }; + let spans = span_with_attrs + .find_ancestor_inside(value.span) + .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))); let keep_space = ( left_pos.is_some_and(|s| s >= value.span.lo()), right_pos.is_some_and(|s| s <= value.span.hi()), diff --git a/tests/ui/lint/unused/unused-braces-attrs-issue-141549.fixed b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.fixed new file mode 100644 index 000000000000..6129da306766 --- /dev/null +++ b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.fixed @@ -0,0 +1,15 @@ +//@ check-pass +//@ run-rustfix + +#![allow(dead_code)] +#![warn(unused_braces)] + +use std::cmp::Ordering; + +#[rustfmt::skip] +fn ptr_cmp(p1: *const T, p2: *const T) -> Ordering { + #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2) + //~^ WARN unnecessary braces around block return value +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-braces-attrs-issue-141549.rs b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.rs new file mode 100644 index 000000000000..a550ebc49737 --- /dev/null +++ b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ run-rustfix + +#![allow(dead_code)] +#![warn(unused_braces)] + +use std::cmp::Ordering; + +#[rustfmt::skip] +fn ptr_cmp(p1: *const T, p2: *const T) -> Ordering { + { #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2) } + //~^ WARN unnecessary braces around block return value +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-braces-attrs-issue-141549.stderr b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.stderr new file mode 100644 index 000000000000..0b2b6211ab94 --- /dev/null +++ b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.stderr @@ -0,0 +1,19 @@ +warning: unnecessary braces around block return value + --> $DIR/unused-braces-attrs-issue-141549.rs:11:5 + | +LL | { #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2) } + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/unused-braces-attrs-issue-141549.rs:5:9 + | +LL | #![warn(unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - { #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2) } +LL + #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2) + | + +warning: 1 warning emitted + From 45ed022d636ec72dfbb22269196007b0e71a9c7d Mon Sep 17 00:00:00 2001 From: quininer Date: Mon, 19 May 2025 10:44:00 +0800 Subject: [PATCH 124/139] Add compiler tests for xray --- tests/assembly/aarch64-xray.rs | 25 +++++++++++++++++ tests/assembly/x86_64-xray.rs | 25 +++++++++++++++++ tests/ui/instrument-xray/platform-support.rs | 27 +++++++++++++++++++ ...rr => platform-support.unsupported.stderr} | 0 .../instrument-xray/target-not-supported.rs | 10 ------- 5 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 tests/assembly/aarch64-xray.rs create mode 100644 tests/assembly/x86_64-xray.rs create mode 100644 tests/ui/instrument-xray/platform-support.rs rename tests/ui/instrument-xray/{target-not-supported.stderr => platform-support.unsupported.stderr} (100%) delete mode 100644 tests/ui/instrument-xray/target-not-supported.rs diff --git a/tests/assembly/aarch64-xray.rs b/tests/assembly/aarch64-xray.rs new file mode 100644 index 000000000000..d5ee01118439 --- /dev/null +++ b/tests/assembly/aarch64-xray.rs @@ -0,0 +1,25 @@ +//@ assembly-output: emit-asm +//@ compile-flags: -Zinstrument-xray=always + +//@ revisions: aarch64-linux +//@[aarch64-linux] compile-flags: --target=aarch64-unknown-linux-gnu +//@[aarch64-linux] needs-llvm-components: aarch64 +//@[aarch64-linux] only-aarch64-unknown-linux-gnu + +//@ revisions: aarch64-darwin +//@[aarch64-darwin] compile-flags: --target=aarch64-apple-darwin +//@[aarch64-darwin] needs-llvm-components: aarch64 +//@[aarch64-darwin] only-aarch64-apple-darwin + +#![crate_type = "lib"] + +// CHECK-LABEL: xray_func: +#[no_mangle] +pub fn xray_func() { + // CHECK: nop + + std::hint::black_box(()); + + // CHECK: b #32 + // CHECK-NEXT: nop +} diff --git a/tests/assembly/x86_64-xray.rs b/tests/assembly/x86_64-xray.rs new file mode 100644 index 000000000000..4cf3e8cda13c --- /dev/null +++ b/tests/assembly/x86_64-xray.rs @@ -0,0 +1,25 @@ +//@ assembly-output: emit-asm +//@ compile-flags: -Zinstrument-xray=always -Cllvm-args=-x86-asm-syntax=intel + +//@ revisions: x86_64-linux +//@[x86_64-linux] compile-flags: --target=x86_64-unknown-linux-gnu +//@[x86_64-linux] needs-llvm-components: x86 +//@[x86_64-linux] only-x86_64-unknown-linux-gnu + +//@ revisions: x86_64-darwin +//@[x86_64-darwin] compile-flags: --target=x86_64-apple-darwin +//@[x86_64-darwin] needs-llvm-components: x86 +//@[x86_64-darwin] only-x86_64-apple-darwin + +#![crate_type = "lib"] + +// CHECK-LABEL: xray_func: +#[no_mangle] +pub fn xray_func() { + // CHECK: nop word ptr [rax + rax + 512] + + std::hint::black_box(()); + + // CHECK: ret + // CHECK-NEXT: nop word ptr cs:[rax + rax + 512] +} diff --git a/tests/ui/instrument-xray/platform-support.rs b/tests/ui/instrument-xray/platform-support.rs new file mode 100644 index 000000000000..238018b348de --- /dev/null +++ b/tests/ui/instrument-xray/platform-support.rs @@ -0,0 +1,27 @@ +//@ only-nightly (flag is still unstable) +//@ needs-xray + +//@ revisions: unsupported +//@[unsupported] needs-llvm-components: x86 +//@[unsupported] compile-flags: -Z instrument-xray --target=x86_64-pc-windows-msvc + +//@ revisions: x86_64-linux +//@[x86_64-linux] needs-llvm-components: x86 +//@[x86_64-linux] compile-flags: -Z instrument-xray --target=x86_64-unknown-linux-gnu +//@[x86_64-linux] check-pass + +//@ revisions: x86_64-darwin +//@[x86_64-darwin] needs-llvm-components: x86 +//@[x86_64-darwin] compile-flags: -Z instrument-xray --target=x86_64-apple-darwin +//@[x86_64-darwin] check-pass + +//@ revisions: aarch64-darwin +//@[aarch64-darwin] needs-llvm-components: aarch64 +//@[aarch64-darwin] compile-flags: -Z instrument-xray --target=aarch64-apple-darwin +//@[aarch64-darwin] check-pass + +#![feature(no_core)] +#![no_core] +#![no_main] + +//[unsupported]~? ERROR XRay instrumentation is not supported for this target diff --git a/tests/ui/instrument-xray/target-not-supported.stderr b/tests/ui/instrument-xray/platform-support.unsupported.stderr similarity index 100% rename from tests/ui/instrument-xray/target-not-supported.stderr rename to tests/ui/instrument-xray/platform-support.unsupported.stderr diff --git a/tests/ui/instrument-xray/target-not-supported.rs b/tests/ui/instrument-xray/target-not-supported.rs deleted file mode 100644 index 697db6bd4b74..000000000000 --- a/tests/ui/instrument-xray/target-not-supported.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Verifies that `-Z instrument-xray` cannot be used with unsupported targets, -// -//@ needs-llvm-components: x86 -//@ compile-flags: -Z instrument-xray --target x86_64-pc-windows-msvc - -#![feature(no_core)] -#![no_core] -#![no_main] - -//~? ERROR XRay instrumentation is not supported for this target From 979dcf8e2f213e4f4b645cb62e7fe9f4f2c0c785 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 25 May 2025 18:39:17 +0000 Subject: [PATCH 125/139] Rustup to rustc 1.89.0-nightly (5e16c6620 2025-05-24) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 4b6ed82762be..af4bd6dc6b85 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-05-20" +channel = "nightly-2025-05-25" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 245bf503e2a948ac98170516d11df632e85a948b Mon Sep 17 00:00:00 2001 From: bendn Date: Sun, 25 May 2025 02:01:04 +0700 Subject: [PATCH 126/139] increase perf of charsearcher for single ascii characters --- library/core/src/str/iter.rs | 2 +- library/core/src/str/pattern.rs | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 425c4eaee28e..49c581f352eb 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -656,7 +656,7 @@ impl<'a, P: Pattern> SplitInternal<'a, P> { None } - #[inline] + #[inline(always)] fn next(&mut self) -> Option<&'a str> { if self.finished { return None; diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index bcbbb11c83b2..e8189a2187b6 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -429,8 +429,23 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { SearchStep::Done } } - #[inline] + #[inline(always)] fn next_match(&mut self) -> Option<(usize, usize)> { + if self.utf8_size == 1 { + return match self + .haystack + .as_bytes() + .get(self.finger..self.finger_back)? + .iter() + .position(|x| *x == self.utf8_encoded[0]) + { + Some(x) => { + self.finger += x + 1; + Some((self.finger - 1, self.finger)) + } + None => None, + }; + } loop { // get the haystack after the last character found let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?; @@ -498,6 +513,21 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { } #[inline] fn next_match_back(&mut self) -> Option<(usize, usize)> { + if self.utf8_size == 1 { + return match self + .haystack + .get(self.finger..self.finger_back)? + .as_bytes() + .iter() + .rposition(|&x| x == self.utf8_encoded[0]) + { + Some(x) => { + self.finger_back = self.finger + x; + Some((self.finger_back, self.finger_back + 1)) + } + None => None, + }; + } let haystack = self.haystack.as_bytes(); loop { // get the haystack up to but not including the last character searched From 4aed799d34480f2f9f959ec285e4a0481037f9d3 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 25 May 2025 18:58:21 +0000 Subject: [PATCH 127/139] Update tidy exceptions --- src/tools/tidy/src/deps.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 9bb06c31c5c0..9f333cc43cf8 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -200,6 +200,7 @@ const EXCEPTIONS_CRANELIFT: ExceptionList = &[ ("cranelift-module", "Apache-2.0 WITH LLVM-exception"), ("cranelift-native", "Apache-2.0 WITH LLVM-exception"), ("cranelift-object", "Apache-2.0 WITH LLVM-exception"), + ("cranelift-srcgen", "Apache-2.0 WITH LLVM-exception"), ("foldhash", "Zlib"), ("mach2", "BSD-2-Clause OR MIT OR Apache-2.0"), ("regalloc2", "Apache-2.0 WITH LLVM-exception"), @@ -525,6 +526,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "cranelift-module", "cranelift-native", "cranelift-object", + "cranelift-srcgen", "crc32fast", "equivalent", "fallible-iterator", From ade24354f4bc344db9b1647d949d97dec19bdd77 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 24 May 2025 17:24:59 +0000 Subject: [PATCH 128/139] Do not canonicalize in new solver if it has nothing to canonicalize --- .../src/canonicalizer.rs | 59 ++++++++++++++++--- .../rustc_next_trait_solver/src/resolve.rs | 4 ++ 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 93b8940ee37d..addeb3e2b78e 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -4,12 +4,22 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack}; use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, QueryInput}; use rustc_type_ir::{ - self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, InferCtxtLike, Interner, - TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, Flags, InferCtxtLike, Interner, + TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use crate::delegate::SolverDelegate; +/// Does this have infer/placeholder/param, free regions or ReErased? +const NEEDS_CANONICAL: TypeFlags = TypeFlags::from_bits( + TypeFlags::HAS_INFER.bits() + | TypeFlags::HAS_PLACEHOLDER.bits() + | TypeFlags::HAS_PARAM.bits() + | TypeFlags::HAS_FREE_REGIONS.bits() + | TypeFlags::HAS_RE_ERASED.bits(), +) +.unwrap(); + /// Whether we're canonicalizing a query input or the query response. /// /// When canonicalizing an input we're in the context of the caller @@ -79,7 +89,11 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { cache: Default::default(), }; - let value = value.fold_with(&mut canonicalizer); + let value = if value.has_type_flags(NEEDS_CANONICAL) { + value.fold_with(&mut canonicalizer) + } else { + value + }; assert!(!value.has_infer(), "unexpected infer in {value:?}"); assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); let (max_universe, variables) = canonicalizer.finalize(); @@ -111,7 +125,14 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { cache: Default::default(), }; - let param_env = input.goal.param_env.fold_with(&mut env_canonicalizer); + + let param_env = input.goal.param_env; + let param_env = if param_env.has_type_flags(NEEDS_CANONICAL) { + param_env.fold_with(&mut env_canonicalizer) + } else { + param_env + }; + debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST); // Then canonicalize the rest of the input without keeping `'static` // while *mostly* reusing the canonicalizer from above. @@ -134,10 +155,22 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { cache: Default::default(), }; - let predicate = input.goal.predicate.fold_with(&mut rest_canonicalizer); + let predicate = input.goal.predicate; + let predicate = if predicate.has_type_flags(NEEDS_CANONICAL) { + predicate.fold_with(&mut rest_canonicalizer) + } else { + predicate + }; let goal = Goal { param_env, predicate }; + + let predefined_opaques_in_body = input.predefined_opaques_in_body; let predefined_opaques_in_body = - input.predefined_opaques_in_body.fold_with(&mut rest_canonicalizer); + if input.predefined_opaques_in_body.has_type_flags(NEEDS_CANONICAL) { + predefined_opaques_in_body.fold_with(&mut rest_canonicalizer) + } else { + predefined_opaques_in_body + }; + let value = QueryInput { goal, predefined_opaques_in_body }; assert!(!value.has_infer(), "unexpected infer in {value:?}"); @@ -387,7 +420,11 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { | ty::Alias(_, _) | ty::Bound(_, _) | ty::Error(_) => { - return ensure_sufficient_stack(|| t.super_fold_with(self)); + return if t.has_type_flags(NEEDS_CANONICAL) { + ensure_sufficient_stack(|| t.super_fold_with(self)) + } else { + t + }; } }; @@ -522,11 +559,17 @@ impl, I: Interner> TypeFolder for Canonicaliz | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) - | ty::ConstKind::Expr(_) => return c.super_fold_with(self), + | ty::ConstKind::Expr(_) => { + return if c.has_type_flags(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c }; + } }; let var = self.get_or_insert_bound_var(c, kind); Const::new_anon_bound(self.cx(), self.binder_index, var) } + + fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { + if p.flags().intersects(NEEDS_CANONICAL) { p.super_fold_with(self) } else { p } + } } diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index 992c5ddf504e..39abec2d7d8d 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -86,4 +86,8 @@ impl, I: Interner> TypeFolder for EagerResolv } } } + + fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { + if p.has_infer() { p.super_fold_with(self) } else { p } + } } From cf9ac0eec16bb863add283b58de5a25a131b142d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 May 2025 22:16:10 +0200 Subject: [PATCH 129/139] const-check: stop recommending the use of rustc_allow_const_fn_unstable --- compiler/rustc_const_eval/messages.ftl | 3 +- compiler/rustc_const_eval/src/errors.rs | 5 - .../dont_promote_unstable_const_fn.stderr | 7 +- .../ui/consts/const-unstable-intrinsic.stderr | 21 +-- .../min_const_fn_libstd_stability.stderr | 49 +------ ...in_const_unsafe_fn_libstd_stability.stderr | 21 +-- ...n_const_unsafe_fn_libstd_stability2.stderr | 21 +-- ...e_const_stab_unmarked_crate_imports.stderr | 7 +- ...ive_const_stab_unstable_if_unmarked.stderr | 14 +- .../const-eval-select-stability.stderr | 7 +- .../ui/traits/const-traits/staged-api.stderr | 133 +++--------------- 11 files changed, 41 insertions(+), 247 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index f4defd2aa134..7d4afc9d3d95 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -424,8 +424,7 @@ const_eval_unstable_in_stable_exposed = .unstable_sugg = if the {$is_function_call2 -> [true] caller *[false] function - } is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) - .bypass_sugg = otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + } is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` const_eval_unstable_intrinsic = `{$name}` is not yet stable as a const intrinsic const_eval_unstable_intrinsic_suggestion = add `#![feature({$feature})]` to the crate attributes to enable diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 826ea0e58ecc..7c35e47bbf80 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -58,11 +58,6 @@ pub(crate) struct UnstableInStableExposed { code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n", applicability = "has-placeholders" )] - #[suggestion( - const_eval_bypass_sugg, - code = "#[rustc_allow_const_fn_unstable({gate})]\n", - applicability = "has-placeholders" - )] pub attr_span: Span, } diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr index a506f2a282bb..b505b76a6abf 100644 --- a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr +++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr @@ -5,14 +5,9 @@ LL | const fn bar() -> u32 { foo() } | ^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn bar() -> u32 { foo() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo)] LL | const fn bar() -> u32 { foo() } | diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr index 308b02386f5c..7e7ba966cee1 100644 --- a/tests/ui/consts/const-unstable-intrinsic.stderr +++ b/tests/ui/consts/const-unstable-intrinsic.stderr @@ -46,14 +46,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | size_of_val(&x); | ^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_main() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local)] LL | const fn const_main() { | @@ -63,14 +58,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | min_align_of_val(&x); | ^^^^^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_main() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local)] LL | const fn const_main() { | @@ -88,14 +78,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | super::size_of_val(src); | ^^^^^^^^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const unsafe fn copy(src: *const T, _dst: *mut T, _count: usize) { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local)] LL | const unsafe fn copy(src: *const T, _dst: *mut T, _count: usize) { | diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index 26dedc49a392..9efc252ce6b0 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -5,14 +5,9 @@ LL | const fn bar() -> u32 { foo() } | ^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn bar() -> u32 { foo() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo)] LL | const fn bar() -> u32 { foo() } | @@ -23,14 +18,9 @@ LL | const fn bar2() -> u32 { foo2() } | ^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn bar2() -> u32 { foo2() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo2)] LL | const fn bar2() -> u32 { foo2() } | @@ -40,14 +30,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | let x = async { 13 }; | ^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn bar3() -> u32 { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_async_blocks)] LL | const fn bar3() -> u32 { | @@ -58,14 +43,9 @@ LL | foo() | ^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn bar3() -> u32 { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo)] LL | const fn bar3() -> u32 { | @@ -76,14 +56,9 @@ LL | const fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn bar2_gated() -> u32 { foo2_gated() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo2)] LL | const fn bar2_gated() -> u32 { foo2_gated() } | @@ -94,14 +69,9 @@ LL | pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_g | ^^^^^^^^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo2)] LL | pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() } | @@ -112,14 +82,9 @@ LL | const fn stable_indirect() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_indirect() -> u32 { foo2_gated() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo2)] LL | const fn stable_indirect() -> u32 { foo2_gated() } | diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr index b61f7db6f43b..0712a790955a 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -5,14 +5,9 @@ LL | const unsafe fn bar() -> u32 { unsafe { foo() } } | ^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const unsafe fn bar() -> u32 { unsafe { foo() } } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo)] LL | const unsafe fn bar() -> u32 { unsafe { foo() } } | @@ -23,14 +18,9 @@ LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } | ^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo2)] LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } | @@ -41,14 +31,9 @@ LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } | ^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo2)] LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } | diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr index fad8e396e9ab..618b9a16dd46 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr @@ -5,14 +5,9 @@ LL | const unsafe fn bar() -> u32 { foo() } | ^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const unsafe fn bar() -> u32 { foo() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo)] LL | const unsafe fn bar() -> u32 { foo() } | @@ -23,14 +18,9 @@ LL | const unsafe fn bar2() -> u32 { foo2() } | ^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const unsafe fn bar2() -> u32 { foo2() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo2)] LL | const unsafe fn bar2() -> u32 { foo2() } | @@ -41,14 +31,9 @@ LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(foo2)] LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } | diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr index bbe749f59589..04804cb6d339 100644 --- a/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr +++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr @@ -5,14 +5,9 @@ LL | unstable_if_unmarked_const_fn_crate::not_stably_const(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_fn() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(rustc_private)] LL | const fn stable_fn() { | diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr index 9d7b81c822bd..14940ae93f89 100644 --- a/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr +++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr @@ -5,14 +5,9 @@ LL | not_stably_const(); | ^^^^^^^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | pub const fn expose_on_stable() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(rustc_private)] LL | pub const fn expose_on_stable() { | @@ -22,14 +17,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | let _x = async { 15 }; | ^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | pub const fn expose_on_stable() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_async_blocks)] LL | pub const fn expose_on_stable() { | diff --git a/tests/ui/intrinsics/const-eval-select-stability.stderr b/tests/ui/intrinsics/const-eval-select-stability.stderr index 5f443b1d4ff7..513c19cbb5b7 100644 --- a/tests/ui/intrinsics/const-eval-select-stability.stderr +++ b/tests/ui/intrinsics/const-eval-select-stability.stderr @@ -4,14 +4,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const_eval_select((), nothing, log); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | pub const fn hey() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_eval_select)] LL | pub const fn hey() { | diff --git a/tests/ui/traits/const-traits/staged-api.stderr b/tests/ui/traits/const-traits/staged-api.stderr index cdf577287eec..4756c490cb10 100644 --- a/tests/ui/traits/const-traits/staged-api.stderr +++ b/tests/ui/traits/const-traits/staged-api.stderr @@ -71,14 +71,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn const_context() { | @@ -88,14 +83,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] LL | const fn const_context() { | @@ -105,14 +95,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Foo::func(); | ^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn const_context() { | @@ -122,14 +107,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Foo::func(); | ^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] LL | const fn const_context() { | @@ -139,14 +119,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Unstable2::func(); | ^^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn const_context() { | @@ -156,14 +131,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Unstable2::func(); | ^^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] LL | const fn const_context() { | @@ -173,14 +143,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | conditionally_const::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn const_context() { | @@ -190,14 +155,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn stable_const_context() { | @@ -207,14 +167,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] LL | const fn stable_const_context() { | @@ -224,14 +179,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Foo::func(); | ^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn stable_const_context() { | @@ -241,14 +191,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Foo::func(); | ^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] LL | const fn stable_const_context() { | @@ -259,14 +204,9 @@ LL | const_context_not_const_stable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local_feature)] LL | const fn stable_const_context() { | @@ -276,14 +216,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | conditionally_const::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn stable_const_context() { | @@ -293,14 +228,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn implicitly_stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn implicitly_stable_const_context() { | @@ -310,14 +240,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn implicitly_stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] LL | const fn implicitly_stable_const_context() { | @@ -327,14 +252,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Foo::func(); | ^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn implicitly_stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn implicitly_stable_const_context() { | @@ -344,14 +264,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | Foo::func(); | ^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn implicitly_stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] LL | const fn implicitly_stable_const_context() { | @@ -362,14 +277,9 @@ LL | const_context_not_const_stable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn implicitly_stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local_feature)] LL | const fn implicitly_stable_const_context() { | @@ -379,14 +289,9 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | conditionally_const::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn implicitly_stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] LL | const fn implicitly_stable_const_context() { | From e388a3e40538519c89908190baaefbc69a9c985f Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Sat, 24 May 2025 23:18:32 +0200 Subject: [PATCH 130/139] extend allocbytes with associated type --- .../src/const_eval/dummy_machine.rs | 5 ++ .../src/const_eval/machine.rs | 3 + .../src/interpret/intrinsics.rs | 2 +- .../rustc_const_eval/src/interpret/machine.rs | 4 ++ .../rustc_const_eval/src/interpret/memory.rs | 8 ++- .../rustc_const_eval/src/interpret/util.rs | 2 +- .../src/mir/interpret/allocation.rs | 58 +++++++++++++------ compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/vtable.rs | 2 +- .../src/builder/expr/as_constant.rs | 6 +- .../rustc_mir_transform/src/large_enums.rs | 1 + compiler/rustc_smir/src/rustc_smir/alloc.rs | 2 + src/tools/miri/src/alloc_addresses/mod.rs | 6 +- src/tools/miri/src/alloc_bytes.rs | 9 ++- src/tools/miri/src/concurrency/thread.rs | 2 +- src/tools/miri/src/machine.rs | 3 + 16 files changed, 81 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index 46dcebc46e9c..ba1d074133df 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -197,4 +197,9 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine { ) -> &'a mut Vec> { unimplemented!() } + + fn get_default_alloc_params( + &self, + ) -> ::AllocParams { + } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 7c7daed525b2..14c00553076a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -735,6 +735,9 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { Cow::Owned(compute_range()) } } + + fn get_default_alloc_params(&self) -> ::AllocParams { + } } // Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 090b2a692cfc..3343f48cdd99 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -26,7 +26,7 @@ use crate::fluent_generated as fluent; /// Directly returns an `Allocation` containing an absolute path representation of the given type. pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { let path = crate::util::type_name(tcx, ty); - let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes()); + let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes(), ()); tcx.mk_const_alloc(alloc) } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index d13e17a481a4..9f215eca2fd4 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -628,6 +628,10 @@ pub trait Machine<'tcx>: Sized { // Default to no caching. Cow::Owned(compute_range()) } + + /// Compute the value passed to the constructors of the `AllocBytes` type for + /// abstract machine allocations. + fn get_default_alloc_params(&self) -> ::AllocParams; } /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 43bf48a9b961..99a4bc1b7d6e 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -233,10 +233,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { kind: MemoryKind, init: AllocInit, ) -> InterpResult<'tcx, Pointer> { + let params = self.machine.get_default_alloc_params(); let alloc = if M::PANIC_ON_ALLOC_FAIL { - Allocation::new(size, align, init) + Allocation::new(size, align, init, params) } else { - Allocation::try_new(size, align, init)? + Allocation::try_new(size, align, init, params)? }; self.insert_allocation(alloc, kind) } @@ -248,7 +249,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { kind: MemoryKind, mutability: Mutability, ) -> InterpResult<'tcx, Pointer> { - let alloc = Allocation::from_bytes(bytes, align, mutability); + let params = self.machine.get_default_alloc_params(); + let alloc = Allocation::from_bytes(bytes, align, mutability, params); self.insert_allocation(alloc, kind) } diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 847905e83431..83a170926191 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -38,7 +38,7 @@ pub(crate) fn create_static_alloc<'tcx>( static_def_id: LocalDefId, layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit)?; + let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit, ())?; let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into()); assert_eq!(ecx.machine.static_root_ids, None); ecx.machine.static_root_ids = Some((alloc_id, static_def_id)); diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 57aafbb26bc8..f17747558fc5 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -27,12 +27,21 @@ use crate::ty; /// Functionality required for the bytes of an `Allocation`. pub trait AllocBytes: Clone + fmt::Debug + Deref + DerefMut { + /// The type of extra parameters passed in when creating an allocation. + /// Can be used by `interpret::Machine` instances to make runtime-configuration-dependent + /// decisions about the allocation strategy. + type AllocParams; + /// Create an `AllocBytes` from a slice of `u8`. - fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self; + fn from_bytes<'a>( + slice: impl Into>, + _align: Align, + _params: Self::AllocParams, + ) -> Self; /// Create a zeroed `AllocBytes` of the specified size and alignment. /// Returns `None` if we ran out of memory on the host. - fn zeroed(size: Size, _align: Align) -> Option; + fn zeroed(size: Size, _align: Align, _params: Self::AllocParams) -> Option; /// Gives direct access to the raw underlying storage. /// @@ -51,11 +60,13 @@ pub trait AllocBytes: Clone + fmt::Debug + Deref + DerefMut`. impl AllocBytes for Box<[u8]> { - fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self { + type AllocParams = (); + + fn from_bytes<'a>(slice: impl Into>, _align: Align, _params: ()) -> Self { Box::<[u8]>::from(slice.into()) } - fn zeroed(size: Size, _align: Align) -> Option { + fn zeroed(size: Size, _align: Align, _params: ()) -> Option { let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes().try_into().ok()?).ok()?; // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]> let bytes = unsafe { bytes.assume_init() }; @@ -172,9 +183,8 @@ fn all_zero(buf: &[u8]) -> bool { } /// Custom encoder for [`Allocation`] to more efficiently represent the case where all bytes are 0. -impl Encodable for Allocation +impl Encodable for Allocation> where - Bytes: AllocBytes, ProvenanceMap: Encodable, Extra: Encodable, { @@ -192,9 +202,8 @@ where } } -impl Decodable for Allocation +impl Decodable for Allocation> where - Bytes: AllocBytes, ProvenanceMap: Decodable, Extra: Decodable, { @@ -203,7 +212,7 @@ where let len = decoder.read_usize(); let bytes = if all_zero { vec![0u8; len] } else { decoder.read_raw_bytes(len).to_vec() }; - let bytes = Bytes::from_bytes(bytes, align); + let bytes = as AllocBytes>::from_bytes(bytes, align, ()); let provenance = Decodable::decode(decoder); let init_mask = Decodable::decode(decoder); @@ -395,8 +404,9 @@ impl Allocation { slice: impl Into>, align: Align, mutability: Mutability, + params: ::AllocParams, ) -> Self { - let bytes = Bytes::from_bytes(slice, align); + let bytes = Bytes::from_bytes(slice, align, params); let size = Size::from_bytes(bytes.len()); Self { bytes, @@ -408,14 +418,18 @@ impl Allocation { } } - pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into>) -> Self { - Allocation::from_bytes(slice, Align::ONE, Mutability::Not) + pub fn from_bytes_byte_aligned_immutable<'a>( + slice: impl Into>, + params: ::AllocParams, + ) -> Self { + Allocation::from_bytes(slice, Align::ONE, Mutability::Not, params) } fn new_inner( size: Size, align: Align, init: AllocInit, + params: ::AllocParams, fail: impl FnOnce() -> R, ) -> Result { // We raise an error if we cannot create the allocation on the host. @@ -424,7 +438,7 @@ impl Allocation { // deterministic. However, we can be non-deterministic here because all uses of const // evaluation (including ConstProp!) will make compilation fail (via hard error // or ICE) upon encountering a `MemoryExhausted` error. - let bytes = Bytes::zeroed(size, align).ok_or_else(fail)?; + let bytes = Bytes::zeroed(size, align, params).ok_or_else(fail)?; Ok(Allocation { bytes, @@ -444,8 +458,13 @@ impl Allocation { /// Try to create an Allocation of `size` bytes, failing if there is not enough memory /// available to the compiler to do so. - pub fn try_new<'tcx>(size: Size, align: Align, init: AllocInit) -> InterpResult<'tcx, Self> { - Self::new_inner(size, align, init, || { + pub fn try_new<'tcx>( + size: Size, + align: Align, + init: AllocInit, + params: ::AllocParams, + ) -> InterpResult<'tcx, Self> { + Self::new_inner(size, align, init, params, || { ty::tls::with(|tcx| tcx.dcx().delayed_bug("exhausted memory during interpretation")); InterpErrorKind::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) }) @@ -457,8 +476,13 @@ impl Allocation { /// /// Example use case: To obtain an Allocation filled with specific data, /// first call this function and then call write_scalar to fill in the right data. - pub fn new(size: Size, align: Align, init: AllocInit) -> Self { - match Self::new_inner(size, align, init, || { + pub fn new( + size: Size, + align: Align, + init: AllocInit, + params: ::AllocParams, + ) -> Self { + match Self::new_inner(size, align, init, params, || { panic!( "interpreter ran out of memory: cannot create allocation of {} bytes", size.bytes() diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8c915fea950a..70172e55e541 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1582,7 +1582,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns the same `AllocId` if called again with the same bytes. pub fn allocate_bytes_dedup(self, bytes: &[u8], salt: usize) -> interpret::AllocId { // Create an allocation that just contains these bytes. - let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes); + let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes, ()); let alloc = self.mk_const_alloc(alloc); self.reserve_and_set_memory_dedup(alloc, salt) } diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 6c9e0e7c0eb8..74b6a840a2e7 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -110,7 +110,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let ptr_align = tcx.data_layout.pointer_align.abi; let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap(); - let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit); + let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit, ()); // No need to do any alignment checks on the memory accesses below, because we know the // allocation is correctly aligned as we created it above. Also we're only offsetting by diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index 64d092e03545..eb8e98ec3644 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -121,14 +121,14 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> let value = match (lit, lit_ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); - let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes()); + let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes(), ()); let allocation = tcx.mk_const_alloc(allocation); ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() } } (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => { - let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]); + let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8], ()); let allocation = tcx.mk_const_alloc(allocation); ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() } } @@ -138,7 +138,7 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> } (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) => { - let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]); + let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8], ()); let allocation = tcx.mk_const_alloc(allocation); ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() } } diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 47cb478fe33e..1a91d6bd7da9 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -241,6 +241,7 @@ impl EnumSizeOpt { data, tcx.data_layout.ptr_sized_integer().align(&tcx.data_layout).abi, Mutability::Not, + (), ); let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc)); Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc))) diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 9cb89634c52e..a6d31ac4e13d 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -48,6 +48,7 @@ pub(crate) fn try_new_allocation<'tcx>( size, layout.align.abi, AllocInit::Uninit, + (), ); allocation .write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar) @@ -65,6 +66,7 @@ pub(crate) fn try_new_allocation<'tcx>( layout.size, layout.align.abi, AllocInit::Uninit, + (), ); allocation .write_scalar( diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 21bd7fb54c6c..d2977a55e465 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -139,7 +139,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { AllocKind::LiveData => { if memory_kind == MiriMemoryKind::Global.into() { // For new global allocations, we always pre-allocate the memory to be able use the machine address directly. - let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align) + let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align, ()) .unwrap_or_else(|| { panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes", size = info.size) }); @@ -159,7 +159,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { AllocKind::Function | AllocKind::VTable => { // Allocate some dummy memory to get a unique address for this function/vtable. let alloc_bytes = - MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap()); + MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap(), ()); let ptr = alloc_bytes.as_ptr(); // Leak the underlying memory to ensure it remains unique. std::mem::forget(alloc_bytes); @@ -429,7 +429,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { prepared_alloc_bytes.copy_from_slice(bytes); interp_ok(prepared_alloc_bytes) } else { - interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)) + interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align, ())) } } diff --git a/src/tools/miri/src/alloc_bytes.rs b/src/tools/miri/src/alloc_bytes.rs index 6788494c01cc..2bac2659ec09 100644 --- a/src/tools/miri/src/alloc_bytes.rs +++ b/src/tools/miri/src/alloc_bytes.rs @@ -24,7 +24,7 @@ impl Clone for MiriAllocBytes { fn clone(&self) -> Self { let bytes: Cow<'_, [u8]> = Cow::Borrowed(self); let align = Align::from_bytes(self.layout.align().to_u64()).unwrap(); - MiriAllocBytes::from_bytes(bytes, align) + MiriAllocBytes::from_bytes(bytes, align, ()) } } @@ -86,7 +86,10 @@ impl MiriAllocBytes { } impl AllocBytes for MiriAllocBytes { - fn from_bytes<'a>(slice: impl Into>, align: Align) -> Self { + /// Placeholder! + type AllocParams = (); + + fn from_bytes<'a>(slice: impl Into>, align: Align, _params: ()) -> Self { let slice = slice.into(); let size = slice.len(); let align = align.bytes(); @@ -102,7 +105,7 @@ impl AllocBytes for MiriAllocBytes { alloc_bytes } - fn zeroed(size: Size, align: Align) -> Option { + fn zeroed(size: Size, align: Align, _params: ()) -> Option { let size = size.bytes(); let align = align.bytes(); // SAFETY: `alloc_fn` will only be used with `size != 0`. diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 8aa65e6cb612..36fd20ee0a6f 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -899,7 +899,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let mut alloc = alloc.inner().adjust_from_tcx( &this.tcx, |bytes, align| { - interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)) + interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align, ())) }, |ptr| this.global_root_pointer(ptr), )?; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index f75adffd9508..131ecf2d0b91 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1804,6 +1804,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ) -> Cow<'e, RangeSet> { Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range)) } + + /// Placeholder! + fn get_default_alloc_params(&self) -> ::AllocParams { () } } /// Trait for callbacks handling asynchronous machine operations. From 3efd885927958ec8af33fbd1fa2da3d62bbae108 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 22 May 2025 18:55:49 +0000 Subject: [PATCH 131/139] Avoid obligation construction dance with query region constraints --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../src/infer/canonical/query_response.rs | 62 +++---------------- compiler/rustc_infer/src/infer/context.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 13 ---- .../src/infer/outlives/obligations.rs | 34 +++++++++- .../src/solve/delegate.rs | 2 +- .../src/traits/auto_trait.rs | 8 ++- .../src/traits/fulfill.rs | 4 +- .../src/traits/outlives_bounds.rs | 21 +------ 9 files changed, 52 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 2ec14b2f018c..248af02f86de 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -742,7 +742,7 @@ fn ty_known_to_outlive<'tcx>( region: ty::Region<'tcx>, ) -> bool { test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { - infcx.register_region_obligation(infer::RegionObligation { + infcx.type_outlives_predicate(infer::RegionObligation { sub_region: region, sup_type: ty, origin: infer::RelateParamBound(DUMMY_SP, ty, None), diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index e9cfc96ba508..c7cb1c39a9c5 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -12,23 +12,20 @@ use std::iter; use rustc_index::{Idx, IndexVec}; use rustc_middle::arena::ArenaAllocatable; +use rustc_middle::bug; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable}; -use rustc_middle::{bug, span_bug}; use tracing::{debug, instrument}; use crate::infer::canonical::instantiate::{CanonicalExt, instantiate_value}; use crate::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues, - QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse, + QueryRegionConstraints, QueryResponse, }; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin}; use crate::traits::query::NoSolution; -use crate::traits::{ - Obligation, ObligationCause, PredicateObligation, PredicateObligations, ScrubbedTraitError, - TraitEngine, -}; +use crate::traits::{ObligationCause, PredicateObligations, ScrubbedTraitError, TraitEngine}; impl<'tcx> InferCtxt<'tcx> { /// This method is meant to be invoked as the final step of a canonical query @@ -169,15 +166,13 @@ impl<'tcx> InferCtxt<'tcx> { where R: Debug + TypeFoldable>, { - let InferOk { value: result_args, mut obligations } = + let InferOk { value: result_args, obligations } = self.query_response_instantiation(cause, param_env, original_values, query_response)?; - obligations.extend(self.query_outlives_constraints_into_obligations( - cause, - param_env, - &query_response.value.region_constraints.outlives, - &result_args, - )); + for (predicate, _category) in &query_response.value.region_constraints.outlives { + let predicate = instantiate_value(self.tcx, &result_args, *predicate); + self.outlives_predicate_with_cause(predicate, cause); + } let user_result: R = query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone()); @@ -525,47 +520,6 @@ impl<'tcx> InferCtxt<'tcx> { self.unify_canonical_vars(cause, param_env, original_values, instantiated_query_response) } - /// Converts the region constraints resulting from a query into an - /// iterator of obligations. - fn query_outlives_constraints_into_obligations( - &self, - cause: &ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - uninstantiated_region_constraints: &[QueryOutlivesConstraint<'tcx>], - result_args: &CanonicalVarValues<'tcx>, - ) -> impl Iterator> { - uninstantiated_region_constraints.iter().map(move |&constraint| { - let predicate = instantiate_value(self.tcx, result_args, constraint); - self.query_outlives_constraint_to_obligation(predicate, cause.clone(), param_env) - }) - } - - pub fn query_outlives_constraint_to_obligation( - &self, - (predicate, _): QueryOutlivesConstraint<'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Obligation<'tcx, ty::Predicate<'tcx>> { - let ty::OutlivesPredicate(k1, r2) = predicate; - - let atom = match k1.unpack() { - GenericArgKind::Lifetime(r1) => ty::PredicateKind::Clause( - ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)), - ), - GenericArgKind::Type(t1) => ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( - ty::OutlivesPredicate(t1, r2), - )), - GenericArgKind::Const(..) => { - // Consts cannot outlive one another, so we don't expect to - // encounter this branch. - span_bug!(cause.span, "unexpected const outlives {:?}", predicate); - } - }; - let predicate = ty::Binder::dummy(atom); - - Obligation::new(self.tcx, cause, param_env, predicate) - } - /// Given two sets of values for the same set of canonical variables, unify them. /// The second set is produced lazily by supplying indices from the first set. fn unify_canonical_vars( diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 359b9da11ced..c151fee2cd52 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -214,7 +214,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) { - self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span)); + self.type_outlives_predicate_with_cause(ty, r, &ObligationCause::dummy_with_span(span)); } type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b408d76010d7..30ac03332875 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -738,19 +738,6 @@ impl<'tcx> InferCtxt<'tcx> { }) } - pub fn region_outlives_predicate( - &self, - cause: &traits::ObligationCause<'tcx>, - predicate: ty::PolyRegionOutlivesPredicate<'tcx>, - ) { - self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| { - let origin = SubregionOrigin::from_obligation_cause(cause, || { - RelateRegionParamBound(cause.span, None) - }); - self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` - }) - } - /// Number of type variables created so far. pub fn num_ty_vars(&self) -> usize { self.inner.borrow_mut().type_variables().num_vars() diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 5fd98e35e5ce..3786a36c9fdb 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -80,19 +80,47 @@ use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrig use crate::traits::{ObligationCause, ObligationCauseCode}; impl<'tcx> InferCtxt<'tcx> { + pub fn outlives_predicate_with_cause( + &self, + ty::OutlivesPredicate(arg, r2): ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>, + cause: &ObligationCause<'tcx>, + ) { + match arg.unpack() { + ty::GenericArgKind::Lifetime(r1) => { + self.region_outlives_predicate(ty::OutlivesPredicate(r1, r2), cause); + } + ty::GenericArgKind::Type(ty1) => { + self.type_outlives_predicate_with_cause(ty1, r2, cause); + } + ty::GenericArgKind::Const(_) => unreachable!(), + } + } + + pub fn region_outlives_predicate( + &self, + ty::OutlivesPredicate(r_a, r_b): ty::RegionOutlivesPredicate<'tcx>, + cause: &ObligationCause<'tcx>, + ) { + let origin = SubregionOrigin::from_obligation_cause(cause, || { + SubregionOrigin::RelateRegionParamBound(cause.span, None) + }); + // `b : a` ==> `a <= b` + self.sub_regions(origin, r_b, r_a); + } + /// Registers that the given region obligation must be resolved /// from within the scope of `body_id`. These regions are enqueued /// and later processed by regionck, when full type information is /// available (see `region_obligations` field for more /// information). #[instrument(level = "debug", skip(self))] - pub fn register_region_obligation(&self, obligation: RegionObligation<'tcx>) { + pub fn type_outlives_predicate(&self, obligation: RegionObligation<'tcx>) { let mut inner = self.inner.borrow_mut(); inner.undo_log.push(UndoLog::PushRegionObligation); inner.region_obligations.push(obligation); } - pub fn register_region_obligation_with_cause( + pub fn type_outlives_predicate_with_cause( &self, sup_type: Ty<'tcx>, sub_region: Region<'tcx>, @@ -124,7 +152,7 @@ impl<'tcx> InferCtxt<'tcx> { ) }); - self.register_region_obligation(RegionObligation { sup_type, sub_region, origin }); + self.type_outlives_predicate(RegionObligation { sup_type, sub_region, origin }); } /// Trait queries just want to pass back type obligations "as is" diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index b68a78453660..e66d1c041272 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -76,7 +76,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< Some(HasChanged::No) } ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => { - self.0.register_region_obligation_with_cause( + self.0.type_outlives_predicate_with_cause( outlives.0, outlives.1, &ObligationCause::dummy_with_span(span), diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 02521c9453d9..620c15917377 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -726,7 +726,9 @@ impl<'tcx> AutoTraitFinder<'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => { let binder = bound_predicate.rebind(binder); - selcx.infcx.region_outlives_predicate(&dummy_cause, binder) + selcx.infcx.enter_forall(binder, |pred| { + selcx.infcx.region_outlives_predicate(pred, &dummy_cause); + }); } ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(binder)) => { let binder = bound_predicate.rebind(binder); @@ -735,14 +737,14 @@ impl<'tcx> AutoTraitFinder<'tcx> { binder.map_bound_ref(|pred| pred.0).no_bound_vars(), ) { (None, Some(t_a)) => { - selcx.infcx.register_region_obligation_with_cause( + selcx.infcx.type_outlives_predicate_with_cause( t_a, selcx.infcx.tcx.lifetimes.re_static, &dummy_cause, ); } (Some(ty::OutlivesPredicate(t_a, r_b)), _) => { - selcx.infcx.register_region_obligation_with_cause( + selcx.infcx.type_outlives_predicate_with_cause( t_a, r_b, &dummy_cause, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 34c3c905bd97..e210bfbefba2 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -428,7 +428,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => { if infcx.considering_regions { - infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data)); + infcx.region_outlives_predicate(data, &obligation.cause); } ProcessResult::Changed(Default::default()) @@ -439,7 +439,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { r_b, ))) => { if infcx.considering_regions { - infcx.register_region_obligation_with_cause(t_a, r_b, &obligation.cause); + infcx.type_outlives_predicate_with_cause(t_a, r_b, &obligation.cause); } ProcessResult::Changed(Default::default()) } diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 68983ef80fa4..8641206abb9c 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -9,7 +9,7 @@ use rustc_span::def_id::LocalDefId; use tracing::instrument; use crate::infer::InferCtxt; -use crate::traits::{ObligationCause, ObligationCtxt}; +use crate::traits::ObligationCause; /// Implied bounds are region relationships that we deduce /// automatically. The idea is that (e.g.) a caller must check that a @@ -79,24 +79,9 @@ fn implied_outlives_bounds<'a, 'tcx>( if !constraints.is_empty() { let QueryRegionConstraints { outlives } = constraints; - // Instantiation may have produced new inference variables and constraints on those - // variables. Process these constraints. - let ocx = ObligationCtxt::new(infcx); let cause = ObligationCause::misc(span, body_id); - for &constraint in &outlives { - ocx.register_obligation(infcx.query_outlives_constraint_to_obligation( - constraint, - cause.clone(), - param_env, - )); - } - - let errors = ocx.select_all_or_error(); - if !errors.is_empty() { - infcx.dcx().span_bug( - span, - "implied_outlives_bounds failed to solve obligations from instantiation", - ); + for &(predicate, _) in &outlives { + infcx.outlives_predicate_with_cause(predicate, &cause); } }; From 4d783c3c193129350425a08fcdb0921b1e0d74a8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 May 2025 11:06:14 +0000 Subject: [PATCH 132/139] Don't retry in pred_known_to_hold_modulo_regions in new solver, since new solver is more complete Just a totally unrelated nitpick I'm folding into the PR, since it's code I'd like for us to prune when the new solver lands. --- compiler/rustc_trait_selection/src/traits/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index a9bdb909bdcf..999ef97683ca 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -221,7 +221,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>( if result.must_apply_modulo_regions() { true - } else if result.may_apply() { + } else if result.may_apply() && !infcx.next_trait_solver() { // Sometimes obligations are ambiguous because the recursive evaluator // is not smart enough, so we fall back to fulfillment when we're not certain // that an obligation holds or not. Even still, we must make sure that From 9d742eea252f25a7b6719618cc154074dba16063 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 May 2025 08:36:17 +0000 Subject: [PATCH 133/139] Rename --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../src/infer/canonical/query_response.rs | 2 +- compiler/rustc_infer/src/infer/context.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 6 ++-- .../src/infer/outlives/obligations.rs | 33 ++++++++++++------- .../src/infer/snapshot/undo_log.rs | 4 +-- .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/solve/delegate.rs | 2 +- .../src/traits/auto_trait.rs | 6 ++-- .../src/traits/fulfill.rs | 4 +-- .../src/traits/outlives_bounds.rs | 2 +- .../query/type_op/implied_outlives_bounds.rs | 4 +-- 12 files changed, 39 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 248af02f86de..06c5e518fc64 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -742,7 +742,7 @@ fn ty_known_to_outlive<'tcx>( region: ty::Region<'tcx>, ) -> bool { test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { - infcx.type_outlives_predicate(infer::RegionObligation { + infcx.register_type_outlives_constraint_inner(infer::TypeOutlivesConstraint { sub_region: region, sup_type: ty, origin: infer::RelateParamBound(DUMMY_SP, ty, None), diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index c7cb1c39a9c5..bda33f3f455b 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -171,7 +171,7 @@ impl<'tcx> InferCtxt<'tcx> { for (predicate, _category) in &query_response.value.region_constraints.outlives { let predicate = instantiate_value(self.tcx, &result_args, *predicate); - self.outlives_predicate_with_cause(predicate, cause); + self.register_outlives_constraint(predicate, cause); } let user_result: R = diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index c151fee2cd52..f7fe32a06e63 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -214,7 +214,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) { - self.type_outlives_predicate_with_cause(ty, r, &ObligationCause::dummy_with_span(span)); + self.register_type_outlives_constraint(ty, r, &ObligationCause::dummy_with_span(span)); } type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 30ac03332875..8fb25cb9b32f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -150,7 +150,7 @@ pub struct InferCtxtInner<'tcx> { /// for each body-id in this map, which will process the /// obligations within. This is expected to be done 'late enough' /// that all type inference variables have been bound and so forth. - region_obligations: Vec>, + region_obligations: Vec>, /// Caches for opaque type inference. opaque_type_storage: OpaqueTypeStorage<'tcx>, @@ -173,7 +173,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } #[inline] - pub fn region_obligations(&self) -> &[RegionObligation<'tcx>] { + pub fn region_obligations(&self) -> &[TypeOutlivesConstraint<'tcx>] { &self.region_obligations } @@ -488,7 +488,7 @@ impl fmt::Display for FixupError { /// See the `region_obligations` field for more information. #[derive(Clone, Debug)] -pub struct RegionObligation<'tcx> { +pub struct TypeOutlivesConstraint<'tcx> { pub sub_region: ty::Region<'tcx>, pub sup_type: Ty<'tcx>, pub origin: SubregionOrigin<'tcx>, diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 3786a36c9fdb..890902af02bc 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -76,27 +76,29 @@ use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::resolve::OpportunisticRegionResolver; use crate::infer::snapshot::undo_log::UndoLog; -use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound}; +use crate::infer::{ + self, GenericKind, InferCtxt, SubregionOrigin, TypeOutlivesConstraint, VerifyBound, +}; use crate::traits::{ObligationCause, ObligationCauseCode}; impl<'tcx> InferCtxt<'tcx> { - pub fn outlives_predicate_with_cause( + pub fn register_outlives_constraint( &self, ty::OutlivesPredicate(arg, r2): ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>, cause: &ObligationCause<'tcx>, ) { match arg.unpack() { ty::GenericArgKind::Lifetime(r1) => { - self.region_outlives_predicate(ty::OutlivesPredicate(r1, r2), cause); + self.register_region_outlives_constraint(ty::OutlivesPredicate(r1, r2), cause); } ty::GenericArgKind::Type(ty1) => { - self.type_outlives_predicate_with_cause(ty1, r2, cause); + self.register_type_outlives_constraint(ty1, r2, cause); } ty::GenericArgKind::Const(_) => unreachable!(), } } - pub fn region_outlives_predicate( + pub fn register_region_outlives_constraint( &self, ty::OutlivesPredicate(r_a, r_b): ty::RegionOutlivesPredicate<'tcx>, cause: &ObligationCause<'tcx>, @@ -104,7 +106,7 @@ impl<'tcx> InferCtxt<'tcx> { let origin = SubregionOrigin::from_obligation_cause(cause, || { SubregionOrigin::RelateRegionParamBound(cause.span, None) }); - // `b : a` ==> `a <= b` + // `'a: 'b` ==> `'b <= 'a` self.sub_regions(origin, r_b, r_a); } @@ -114,13 +116,16 @@ impl<'tcx> InferCtxt<'tcx> { /// available (see `region_obligations` field for more /// information). #[instrument(level = "debug", skip(self))] - pub fn type_outlives_predicate(&self, obligation: RegionObligation<'tcx>) { + pub fn register_type_outlives_constraint_inner( + &self, + obligation: TypeOutlivesConstraint<'tcx>, + ) { let mut inner = self.inner.borrow_mut(); - inner.undo_log.push(UndoLog::PushRegionObligation); + inner.undo_log.push(UndoLog::PushTypeOutlivesConstraint); inner.region_obligations.push(obligation); } - pub fn type_outlives_predicate_with_cause( + pub fn register_type_outlives_constraint( &self, sup_type: Ty<'tcx>, sub_region: Region<'tcx>, @@ -152,11 +157,15 @@ impl<'tcx> InferCtxt<'tcx> { ) }); - self.type_outlives_predicate(RegionObligation { sup_type, sub_region, origin }); + self.register_type_outlives_constraint_inner(TypeOutlivesConstraint { + sup_type, + sub_region, + origin, + }); } /// Trait queries just want to pass back type obligations "as is" - pub fn take_registered_region_obligations(&self) -> Vec> { + pub fn take_registered_region_obligations(&self) -> Vec> { std::mem::take(&mut self.inner.borrow_mut().region_obligations) } @@ -194,7 +203,7 @@ impl<'tcx> InferCtxt<'tcx> { ); } - for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { + for TypeOutlivesConstraint { sup_type, sub_region, origin } in my_region_obligations { let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region)); let ty::OutlivesPredicate(sup_type, sub_region) = deeply_normalize_ty(outlives, origin.clone()) diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index b7412d3d6a6d..6193f35f3eb6 100644 --- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs @@ -26,7 +26,7 @@ pub(crate) enum UndoLog<'tcx> { RegionConstraintCollector(region_constraints::UndoLog<'tcx>), RegionUnificationTable(sv::UndoLog>>), ProjectionCache(traits::UndoLog<'tcx>), - PushRegionObligation, + PushTypeOutlivesConstraint, } macro_rules! impl_from { @@ -72,7 +72,7 @@ impl<'tcx> Rollback> for InferCtxtInner<'tcx> { self.region_constraint_storage.as_mut().unwrap().unification_table.reverse(undo) } UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo), - UndoLog::PushRegionObligation => { + UndoLog::PushTypeOutlivesConstraint => { self.region_obligations.pop(); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index dfabb94ebfc6..ef955410247f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1024,7 +1024,7 @@ where } pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) { - // `b : a` ==> `a <= b` + // `'a: 'b` ==> `'b <= 'a` self.delegate.sub_regions(b, a, self.origin_span); } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index e66d1c041272..eea311fe66eb 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -76,7 +76,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< Some(HasChanged::No) } ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => { - self.0.type_outlives_predicate_with_cause( + self.0.register_type_outlives_constraint( outlives.0, outlives.1, &ObligationCause::dummy_with_span(span), diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 620c15917377..3ae908ec16b8 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -727,7 +727,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => { let binder = bound_predicate.rebind(binder); selcx.infcx.enter_forall(binder, |pred| { - selcx.infcx.region_outlives_predicate(pred, &dummy_cause); + selcx.infcx.register_region_outlives_constraint(pred, &dummy_cause); }); } ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(binder)) => { @@ -737,14 +737,14 @@ impl<'tcx> AutoTraitFinder<'tcx> { binder.map_bound_ref(|pred| pred.0).no_bound_vars(), ) { (None, Some(t_a)) => { - selcx.infcx.type_outlives_predicate_with_cause( + selcx.infcx.register_type_outlives_constraint( t_a, selcx.infcx.tcx.lifetimes.re_static, &dummy_cause, ); } (Some(ty::OutlivesPredicate(t_a, r_b)), _) => { - selcx.infcx.type_outlives_predicate_with_cause( + selcx.infcx.register_type_outlives_constraint( t_a, r_b, &dummy_cause, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e210bfbefba2..951dfb879aed 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -428,7 +428,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => { if infcx.considering_regions { - infcx.region_outlives_predicate(data, &obligation.cause); + infcx.register_region_outlives_constraint(data, &obligation.cause); } ProcessResult::Changed(Default::default()) @@ -439,7 +439,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { r_b, ))) => { if infcx.considering_regions { - infcx.type_outlives_predicate_with_cause(t_a, r_b, &obligation.cause); + infcx.register_type_outlives_constraint(t_a, r_b, &obligation.cause); } ProcessResult::Changed(Default::default()) } diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 8641206abb9c..59d3ac21387f 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -81,7 +81,7 @@ fn implied_outlives_bounds<'a, 'tcx>( let QueryRegionConstraints { outlives } = constraints; let cause = ObligationCause::misc(span, body_id); for &(predicate, _) in &outlives { - infcx.outlives_predicate_with_cause(predicate, &cause); + infcx.register_outlives_constraint(predicate, &cause); } }; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index d9b57f0c67d1..e294f7839aac 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -1,6 +1,6 @@ use std::ops::ControlFlow; -use rustc_infer::infer::RegionObligation; +use rustc_infer::infer::TypeOutlivesConstraint; use rustc_infer::infer::canonical::CanonicalQueryInput; use rustc_infer::traits::query::OutlivesBound; use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds; @@ -141,7 +141,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( && !ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat && ty.visit_with(&mut ContainsBevyParamSet { tcx: ocx.infcx.tcx }).is_break() { - for RegionObligation { sup_type, sub_region, .. } in + for TypeOutlivesConstraint { sup_type, sub_region, .. } in ocx.infcx.take_registered_region_obligations() { let mut components = smallvec![]; From e2215a8ad9099c35df2de789efd9262c3fd59c65 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 May 2025 10:17:33 +0000 Subject: [PATCH 134/139] Don't rerun goals if none of its vars have changed --- compiler/rustc_infer/src/infer/context.rs | 51 +++++++ .../src/infer/opaque_types/table.rs | 6 + .../src/solve/eval_ctxt/canonical.rs | 15 +- .../src/solve/eval_ctxt/mod.rs | 129 ++++++++++++++---- .../rustc_next_trait_solver/src/solve/mod.rs | 19 +++ .../src/solve/fulfill.rs | 112 +++++++++------ .../src/solve/fulfill/derive_errors.rs | 24 ++-- .../src/solve/inspect/analyse.rs | 7 +- compiler/rustc_type_ir/src/infer_ctxt.rs | 7 +- compiler/rustc_type_ir/src/inherent.rs | 8 ++ 10 files changed, 290 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 359b9da11ced..173d47493c56 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -89,6 +89,57 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) } + fn is_changed_arg(&self, arg: ty::GenericArg<'tcx>) -> bool { + match arg.unpack() { + ty::GenericArgKind::Lifetime(_) => { + // Lifetimes should not change affect trait selection. + false + } + ty::GenericArgKind::Type(ty) => { + if let ty::Infer(infer_ty) = *ty.kind() { + match infer_ty { + ty::InferTy::TyVar(vid) => { + !self.probe_ty_var(vid).is_err_and(|_| self.root_var(vid) == vid) + } + ty::InferTy::IntVar(vid) => { + let mut inner = self.inner.borrow_mut(); + !matches!( + inner.int_unification_table().probe_value(vid), + ty::IntVarValue::Unknown + if inner.int_unification_table().find(vid) == vid + ) + } + ty::InferTy::FloatVar(vid) => { + let mut inner = self.inner.borrow_mut(); + !matches!( + inner.float_unification_table().probe_value(vid), + ty::FloatVarValue::Unknown + if inner.float_unification_table().find(vid) == vid + ) + } + ty::InferTy::FreshTy(_) + | ty::InferTy::FreshIntTy(_) + | ty::InferTy::FreshFloatTy(_) => true, + } + } else { + true + } + } + ty::GenericArgKind::Const(ct) => { + if let ty::ConstKind::Infer(infer_ct) = ct.kind() { + match infer_ct { + ty::InferConst::Var(vid) => !self + .probe_const_var(vid) + .is_err_and(|_| self.root_const_var(vid) == vid), + ty::InferConst::Fresh(_) => true, + } + } else { + true + } + } + } + } + fn next_region_infer(&self) -> ty::Region<'tcx> { self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) } diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 46752840e1ba..ab65da3913da 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -24,6 +24,12 @@ pub struct OpaqueTypeStorageEntries { duplicate_entries: usize, } +impl rustc_type_ir::inherent::OpaqueTypeStorageEntries for OpaqueTypeStorageEntries { + fn needs_reevaluation(self, canonicalized: usize) -> bool { + self.opaque_types != canonicalized + } +} + impl<'tcx> OpaqueTypeStorage<'tcx> { #[instrument(level = "debug")] pub(crate) fn remove( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 455a178595b2..66d4cd23112d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -53,10 +53,10 @@ where { /// Canonicalizes the goal remembering the original values /// for each bound variable. - pub(super) fn canonicalize_goal>( + pub(super) fn canonicalize_goal( &self, - goal: Goal, - ) -> (Vec, CanonicalInput) { + goal: Goal, + ) -> (Vec, CanonicalInput) { // We only care about one entry per `OpaqueTypeKey` here, // so we only canonicalize the lookup table and ignore // duplicate entries. @@ -130,7 +130,12 @@ where if goals.is_empty() { assert!(matches!(goals_certainty, Certainty::Yes)); } - (Certainty::Yes, NestedNormalizationGoals(goals)) + ( + Certainty::Yes, + NestedNormalizationGoals( + goals.into_iter().map(|(s, g, _)| (s, g)).collect(), + ), + ) } _ => { let certainty = shallow_certainty.and(goals_certainty); @@ -272,7 +277,7 @@ where pub(super) fn instantiate_and_apply_query_response( &mut self, param_env: I::ParamEnv, - original_values: Vec, + original_values: &[I::GenericArg], response: CanonicalResponse, ) -> (NestedNormalizationGoals, Certainty) { let instantiation = Self::compute_query_response_instantiation_values( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index dfabb94ebfc6..d8a97724e816 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -22,8 +22,9 @@ use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ - CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, - HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, + CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalEvaluationKind, + GoalSource, GoalStalledOn, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, + QueryResult, }; pub(super) mod canonical; @@ -115,7 +116,7 @@ where pub(super) search_graph: &'a mut SearchGraph, - nested_goals: Vec<(GoalSource, Goal)>, + nested_goals: Vec<(GoalSource, Goal, Option>)>, pub(super) origin_span: I::Span, @@ -147,8 +148,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate { goal: Goal::Predicate>, generate_proof_tree: GenerateProofTree, span: ::Span, + stalled_on: Option>, ) -> ( - Result<(HasChanged, Certainty), NoSolution>, + Result, NoSolution>, Option>, ); @@ -171,8 +173,12 @@ pub trait SolverDelegateEvalExt: SolverDelegate { &self, goal: Goal::Predicate>, generate_proof_tree: GenerateProofTree, + stalled_on: Option>, ) -> ( - Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution>, + Result< + (NestedNormalizationGoals, GoalEvaluation), + NoSolution, + >, Option>, ); } @@ -188,9 +194,10 @@ where goal: Goal, generate_proof_tree: GenerateProofTree, span: I::Span, - ) -> (Result<(HasChanged, Certainty), NoSolution>, Option>) { + stalled_on: Option>, + ) -> (Result, NoSolution>, Option>) { EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| { - ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) + ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on) }) } @@ -201,7 +208,7 @@ where ) -> bool { self.probe(|| { EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| { - ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) + ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, None) }) .0 }) @@ -213,8 +220,9 @@ where &self, goal: Goal, generate_proof_tree: GenerateProofTree, + stalled_on: Option>, ) -> ( - Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution>, + Result<(NestedNormalizationGoals, GoalEvaluation), NoSolution>, Option>, ) { EvalCtxt::enter_root( @@ -222,7 +230,9 @@ where self.cx().recursion_limit(), generate_proof_tree, I::Span::dummy(), - |ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal), + |ecx| { + ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on) + }, ) } } @@ -447,11 +457,12 @@ where goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal, - ) -> Result<(HasChanged, Certainty), NoSolution> { - let (normalization_nested_goals, has_changed, certainty) = - self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?; + stalled_on: Option>, + ) -> Result, NoSolution> { + let (normalization_nested_goals, goal_evaluation) = + self.evaluate_goal_raw(goal_evaluation_kind, source, goal, stalled_on)?; assert!(normalization_nested_goals.is_empty()); - Ok((has_changed, certainty)) + Ok(goal_evaluation) } /// Recursively evaluates `goal`, returning the nested goals in case @@ -466,7 +477,29 @@ where goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal, - ) -> Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution> { + stalled_on: Option>, + ) -> Result<(NestedNormalizationGoals, GoalEvaluation), NoSolution> { + // If we have run this goal before, and it was stalled, check that any of the goal's + // args have changed. Otherwise, we don't need to re-run the goal because it'll remain + // stalled, since it'll canonicalize the same way and evaluation is pure. + if let Some(stalled_on) = stalled_on { + if !stalled_on.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value)) + && !self + .delegate + .opaque_types_storage_num_entries() + .needs_reevaluation(stalled_on.num_opaques) + { + return Ok(( + NestedNormalizationGoals::empty(), + GoalEvaluation { + certainty: Certainty::Maybe(stalled_on.stalled_cause), + has_changed: HasChanged::No, + stalled_on: Some(stalled_on), + }, + )); + } + } + let (orig_values, canonical_goal) = self.canonicalize_goal(goal); let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); @@ -489,7 +522,7 @@ where if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No }; let (normalization_nested_goals, certainty) = - self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); + self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response); self.inspect.goal_evaluation(goal_evaluation); // FIXME: We previously had an assert here that checked that recomputing @@ -502,7 +535,42 @@ where // Once we have decided on how to handle trait-system-refactor-initiative#75, // we should re-add an assert here. - Ok((normalization_nested_goals, has_changed, certainty)) + let stalled_on = match certainty { + Certainty::Yes => None, + Certainty::Maybe(stalled_cause) => match has_changed { + // FIXME: We could recompute a *new* set of stalled variables by walking + // through the orig values, resolving, and computing the root vars of anything + // that is not resolved. Only when *these* have changed is it meaningful + // to recompute this goal. + HasChanged::Yes => None, + HasChanged::No => { + // Remove the unconstrained RHS arg, which is expected to have changed. + let mut stalled_vars = orig_values; + if let Some(normalizes_to) = goal.predicate.as_normalizes_to() { + let normalizes_to = normalizes_to.skip_binder(); + let rhs_arg: I::GenericArg = normalizes_to.term.into(); + let idx = stalled_vars + .iter() + .rposition(|arg| *arg == rhs_arg) + .expect("expected unconstrained arg"); + stalled_vars.swap_remove(idx); + } + + Some(GoalStalledOn { + num_opaques: canonical_goal + .canonical + .value + .predefined_opaques_in_body + .opaque_types + .len(), + stalled_vars, + stalled_cause, + }) + } + }, + }; + + Ok((normalization_nested_goals, GoalEvaluation { certainty, has_changed, stalled_on })) } fn compute_goal(&mut self, goal: Goal) -> QueryResult { @@ -602,7 +670,7 @@ where let cx = self.cx(); // If this loop did not result in any progress, what's our final certainty. let mut unchanged_certainty = Some(Certainty::Yes); - for (source, goal) in mem::take(&mut self.nested_goals) { + for (source, goal, stalled_on) in mem::take(&mut self.nested_goals) { if let Some(has_changed) = self.delegate.compute_goal_fast_path(goal, self.origin_span) { if matches!(has_changed, HasChanged::Yes) { @@ -630,11 +698,18 @@ where let unconstrained_goal = goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs }); - let (NestedNormalizationGoals(nested_goals), _, certainty) = - self.evaluate_goal_raw(GoalEvaluationKind::Nested, source, unconstrained_goal)?; + let ( + NestedNormalizationGoals(nested_goals), + GoalEvaluation { certainty, stalled_on, has_changed: _ }, + ) = self.evaluate_goal_raw( + GoalEvaluationKind::Nested, + source, + unconstrained_goal, + stalled_on, + )?; // Add the nested goals from normalization to our own nested goals. trace!(?nested_goals); - self.nested_goals.extend(nested_goals); + self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None))); // Finally, equate the goal's RHS with the unconstrained var. // @@ -660,6 +735,8 @@ where // looking at the "has changed" return from evaluate_goal, // because we expect the `unconstrained_rhs` part of the predicate // to have changed -- that means we actually normalized successfully! + // FIXME: Do we need to eagerly resolve here? Or should we check + // if the cache key has any changed vars? let with_resolved_vars = self.resolve_vars_if_possible(goal); if pred.alias != goal.predicate.as_normalizes_to().unwrap().skip_binder().alias { unchanged_certainty = None; @@ -668,13 +745,13 @@ where match certainty { Certainty::Yes => {} Certainty::Maybe(_) => { - self.nested_goals.push((source, with_resolved_vars)); + self.nested_goals.push((source, with_resolved_vars, stalled_on)); unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } else { - let (has_changed, certainty) = - self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?; + let GoalEvaluation { certainty, has_changed, stalled_on } = + self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, stalled_on)?; if has_changed == HasChanged::Yes { unchanged_certainty = None; } @@ -682,7 +759,7 @@ where match certainty { Certainty::Yes => {} Certainty::Maybe(_) => { - self.nested_goals.push((source, goal)); + self.nested_goals.push((source, goal, stalled_on)); unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } @@ -706,7 +783,7 @@ where goal.predicate = goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env)); self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); - self.nested_goals.push((source, goal)); + self.nested_goals.push((source, goal, None)); } #[instrument(level = "trace", skip(self, goals))] diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 2a6418071541..a7a984181d7f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -21,6 +21,7 @@ mod project_goals; mod search_graph; mod trait_goals; +use derive_where::derive_where; use rustc_type_ir::inherent::*; pub use rustc_type_ir::solve::*; use rustc_type_ir::{self as ty, Interner, TypingMode}; @@ -369,3 +370,21 @@ fn response_no_constraints_raw( }, } } + +/// The result of evaluating a goal. +pub struct GoalEvaluation { + pub certainty: Certainty, + pub has_changed: HasChanged, + /// If the [`Certainty`] was `Maybe`, then keep track of whether the goal has changed + /// before rerunning it. + pub stalled_on: Option>, +} + +/// The conditions that must change for a goal to warrant +#[derive_where(Clone, Debug; I: Interner)] +pub struct GoalStalledOn { + pub num_opaques: usize, + pub stalled_vars: Vec, + /// The cause that will be returned on subsequent evaluations if this goal remains stalled. + pub stalled_cause: MaybeCause, +} diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index aa3be43fcd16..d273703a9b12 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -13,8 +13,11 @@ use rustc_middle::ty::{ self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode, }; use rustc_next_trait_solver::delegate::SolverDelegate as _; -use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _}; +use rustc_next_trait_solver::solve::{ + GenerateProofTree, GoalEvaluation, GoalStalledOn, HasChanged, SolverDelegateEvalExt as _, +}; use rustc_span::Span; +use thin_vec::ThinVec; use tracing::instrument; use self::derive_errors::*; @@ -25,6 +28,10 @@ use crate::traits::{FulfillmentError, ScrubbedTraitError}; mod derive_errors; +// FIXME: Do we need to use a `ThinVec` here? +type PendingObligations<'tcx> = + ThinVec<(PredicateObligation<'tcx>, Option>>)>; + /// A trait engine using the new trait solver. /// /// This is mostly identical to how `evaluate_all` works inside of the @@ -54,13 +61,17 @@ struct ObligationStorage<'tcx> { /// We cannot eagerly return these as error so we instead store them here /// to avoid recomputing them each time `select_where_possible` is called. /// This also allows us to return the correct `FulfillmentError` for them. - overflowed: PredicateObligations<'tcx>, - pending: PredicateObligations<'tcx>, + overflowed: Vec>, + pending: PendingObligations<'tcx>, } impl<'tcx> ObligationStorage<'tcx> { - fn register(&mut self, obligation: PredicateObligation<'tcx>) { - self.pending.push(obligation); + fn register( + &mut self, + obligation: PredicateObligation<'tcx>, + stalled_on: Option>>, + ) { + self.pending.push((obligation, stalled_on)); } fn has_pending_obligations(&self) -> bool { @@ -68,7 +79,8 @@ impl<'tcx> ObligationStorage<'tcx> { } fn clone_pending(&self) -> PredicateObligations<'tcx> { - let mut obligations = self.pending.clone(); + let mut obligations: PredicateObligations<'tcx> = + self.pending.iter().map(|(o, _)| o.clone()).collect(); obligations.extend(self.overflowed.iter().cloned()); obligations } @@ -76,8 +88,9 @@ impl<'tcx> ObligationStorage<'tcx> { fn drain_pending( &mut self, cond: impl Fn(&PredicateObligation<'tcx>) -> bool, - ) -> PredicateObligations<'tcx> { - let (unstalled, pending) = mem::take(&mut self.pending).into_iter().partition(cond); + ) -> PendingObligations<'tcx> { + let (unstalled, pending) = + mem::take(&mut self.pending).into_iter().partition(|(o, _)| cond(o)); self.pending = pending; unstalled } @@ -90,13 +103,21 @@ impl<'tcx> ObligationStorage<'tcx> { // we were to do another step of `select_where_possible`, which goals would // change. // FIXME: is merged, this can be removed. - self.overflowed.extend(ExtractIf::new(&mut self.pending, |o| { - let goal = o.as_goal(); - let result = <&SolverDelegate<'tcx>>::from(infcx) - .evaluate_root_goal(goal, GenerateProofTree::No, o.cause.span) - .0; - matches!(result, Ok((HasChanged::Yes, _))) - })); + self.overflowed.extend( + ExtractIf::new(&mut self.pending, |(o, stalled_on)| { + let goal = o.as_goal(); + let result = <&SolverDelegate<'tcx>>::from(infcx) + .evaluate_root_goal( + goal, + GenerateProofTree::No, + o.cause.span, + stalled_on.take(), + ) + .0; + matches!(result, Ok(GoalEvaluation { has_changed: HasChanged::Yes, .. })) + }) + .map(|(o, _)| o), + ); }) } } @@ -119,11 +140,11 @@ impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> { &self, infcx: &InferCtxt<'tcx>, obligation: &PredicateObligation<'tcx>, - result: &Result<(HasChanged, Certainty), NoSolution>, + result: &Result>, NoSolution>, ) { if let Some(inspector) = infcx.obligation_inspector.get() { let result = match result { - Ok((_, c)) => Ok(*c), + Ok(GoalEvaluation { certainty, .. }) => Ok(*certainty), Err(NoSolution) => Err(NoSolution), }; (inspector)(infcx, &obligation, result); @@ -142,14 +163,14 @@ where obligation: PredicateObligation<'tcx>, ) { assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); - self.obligations.register(obligation); + self.obligations.register(obligation, None); } fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { self.obligations .pending .drain(..) - .map(|obligation| NextSolverError::Ambiguity(obligation)) + .map(|(obligation, _)| NextSolverError::Ambiguity(obligation)) .chain( self.obligations .overflowed @@ -164,8 +185,8 @@ where assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); let mut errors = Vec::new(); loop { - let mut has_changed = false; - for mut obligation in self.obligations.drain_pending(|_| true) { + let mut any_changed = false; + for (mut obligation, stalled_on) in self.obligations.drain_pending(|_| true) { if !infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) { self.obligations.on_fulfillment_overflow(infcx); // Only return true errors that we have accumulated while processing. @@ -177,15 +198,20 @@ where if let Some(fast_path_has_changed) = delegate.compute_goal_fast_path(goal, obligation.cause.span) { - has_changed |= matches!(fast_path_has_changed, HasChanged::Yes); + any_changed |= matches!(fast_path_has_changed, HasChanged::Yes); continue; } let result = delegate - .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span) + .evaluate_root_goal( + goal, + GenerateProofTree::No, + obligation.cause.span, + stalled_on, + ) .0; self.inspect_evaluated_obligation(infcx, &obligation, &result); - let (changed, certainty) = match result { + let GoalEvaluation { certainty, has_changed, stalled_on } = match result { Ok(result) => result, Err(NoSolution) => { errors.push(E::from_solver_error( @@ -196,7 +222,7 @@ where } }; - if changed == HasChanged::Yes { + if has_changed == HasChanged::Yes { // We increment the recursion depth here to track the number of times // this goal has resulted in inference progress. This doesn't precisely // model the way that we track recursion depth in the old solver due @@ -204,16 +230,16 @@ where // approximation and should only result in fulfillment overflow in // pathological cases. obligation.recursion_depth += 1; - has_changed = true; + any_changed = true; } match certainty { Certainty::Yes => {} - Certainty::Maybe(_) => self.obligations.register(obligation), + Certainty::Maybe(_) => self.obligations.register(obligation, stalled_on), } } - if !has_changed { + if !any_changed { break; } } @@ -247,20 +273,24 @@ where return Default::default(); } - self.obligations.drain_pending(|obl| { - infcx.probe(|_| { - infcx - .visit_proof_tree( - obl.as_goal(), - &mut StalledOnCoroutines { - stalled_generators, - span: obl.cause.span, - cache: Default::default(), - }, - ) - .is_break() + self.obligations + .drain_pending(|obl| { + infcx.probe(|_| { + infcx + .visit_proof_tree( + obl.as_goal(), + &mut StalledOnCoroutines { + stalled_generators, + span: obl.cause.span, + cache: Default::default(), + }, + ) + .is_break() + }) }) - }) + .into_iter() + .map(|(o, _)| o) + .collect() } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index f64cd5ffebe3..1c9d69da3228 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -11,7 +11,9 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; +use rustc_next_trait_solver::solve::{ + GenerateProofTree, GoalEvaluation, SolverDelegateEvalExt as _, +}; use tracing::{instrument, trace}; use crate::solve::delegate::SolverDelegate; @@ -93,19 +95,21 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( root_obligation.as_goal(), GenerateProofTree::No, root_obligation.cause.span, + None, ) .0 { - Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { + Ok(GoalEvaluation { certainty: Certainty::Maybe(MaybeCause::Ambiguity), .. }) => { (FulfillmentErrorCode::Ambiguity { overflow: None }, true) } - Ok(( - _, - Certainty::Maybe(MaybeCause::Overflow { - suggest_increasing_limit, - keep_constraints: _, - }), - )) => ( + Ok(GoalEvaluation { + certainty: + Certainty::Maybe(MaybeCause::Overflow { + suggest_increasing_limit, + keep_constraints: _, + }), + .. + }) => ( FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, // Don't look into overflows because we treat overflows weirdly anyways. // We discard the inference constraints from overflowing goals, so @@ -115,7 +119,7 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( // FIXME: We should probably just look into overflows here. false, ), - Ok((_, Certainty::Yes)) => { + Ok(GoalEvaluation { certainty: Certainty::Yes, .. }) => { bug!( "did not expect successful goal when collecting ambiguity errors for `{:?}`", infcx.resolve_vars_if_possible(root_obligation.predicate), diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 9795655e8422..49a8b363b0ab 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -219,8 +219,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { // building their proof tree, the expected term was unconstrained, but when // instantiating the candidate it is already constrained to the result of another // candidate. - let proof_tree = - infcx.probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1); + let proof_tree = infcx + .probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes, None).1); InspectGoal::new( infcx, self.goal.depth + 1, @@ -236,7 +236,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { // constraints, we get an ICE if we already applied the constraints // from the chosen candidate. let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span).1) + .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span, None).1) .unwrap(); InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) } @@ -442,6 +442,7 @@ impl<'tcx> InferCtxt<'tcx> { goal, GenerateProofTree::Yes, visitor.span(), + None, ); let proof_tree = proof_tree.unwrap(); visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc)) diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index c14907621173..2bc12d0a23bf 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,11 +1,10 @@ -use std::fmt::Debug; - use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::fold::TypeFoldable; +use crate::inherent::*; use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; use crate::{self as ty, Interner}; @@ -168,6 +167,8 @@ pub trait InferCtxtLike: Sized { vid: ty::RegionVid, ) -> ::Region; + fn is_changed_arg(&self, arg: ::GenericArg) -> bool; + fn next_region_infer(&self) -> ::Region; fn next_ty_infer(&self) -> ::Ty; fn next_const_infer(&self) -> ::Const; @@ -248,7 +249,7 @@ pub trait InferCtxtLike: Sized { span: ::Span, ); - type OpaqueTypeStorageEntries: Debug + Copy + Default; + type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries; fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries; fn clone_opaque_types_lookup_table( &self, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index ee4a8096462a..dde55effc3d0 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -297,6 +297,7 @@ pub trait GenericArg>: + From + From + From + + From { fn as_term(&self) -> Option { match self.kind() { @@ -596,6 +597,13 @@ pub trait Span: Copy + Debug + Hash + Eq + TypeFoldable { fn dummy() -> Self; } +pub trait OpaqueTypeStorageEntries: Debug + Copy + Default { + /// Whether the number of opaques has changed in a way that necessitates + /// reevaluating a goal. For now, this is only when the number of non-duplicated + /// entries changed. + fn needs_reevaluation(self, canonicalized: usize) -> bool; +} + pub trait SliceLike: Sized + Copy { type Item: Copy; type IntoIter: Iterator + DoubleEndedIterator; From a59c86ab449ddb83f824b12f87c1e2c6a38399be Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 23 May 2025 11:47:02 +0000 Subject: [PATCH 135/139] Deduplicate dyn compatibility violations due to coercion --- compiler/rustc_hir_typeck/src/coercion.rs | 18 +++++- .../dyn/mut-is-pointer-like.stderr | 20 +------ tests/ui/async-await/dyn/works.stderr | 20 +------ tests/ui/async-await/dyn/wrong-size.stderr | 20 +------ .../almost-supertrait-associated-type.rs | 1 - .../almost-supertrait-associated-type.stderr | 26 ++------ .../ui/dyn-compatibility/associated-consts.rs | 1 - .../associated-consts.stderr | 19 +----- tests/ui/dyn-compatibility/generics.rs | 2 - tests/ui/dyn-compatibility/generics.stderr | 40 +------------ .../mention-correct-dyn-incompatible-trait.rs | 1 - ...tion-correct-dyn-incompatible-trait.stderr | 21 +------ tests/ui/dyn-compatibility/mentions-Self.rs | 2 - .../ui/dyn-compatibility/mentions-Self.stderr | 38 +----------- tests/ui/dyn-compatibility/no-static.rs | 1 - tests/ui/dyn-compatibility/no-static.stderr | 27 +-------- tests/ui/dyn-compatibility/sized-2.rs | 1 - tests/ui/dyn-compatibility/sized-2.stderr | 18 +----- tests/ui/dyn-compatibility/sized.rs | 1 - tests/ui/dyn-compatibility/sized.stderr | 18 +----- .../ui/dyn-compatibility/taint-const-eval.rs | 1 - .../dyn-compatibility/taint-const-eval.stderr | 26 +------- ...ure-gate-dispatch-from-dyn-missing-impl.rs | 1 - ...gate-dispatch-from-dyn-missing-impl.stderr | 22 +------ .../gat-in-trait-path.rs | 1 - .../gat-in-trait-path.stderr | 19 +----- .../generic-associated-types/issue-71176.rs | 1 - .../issue-71176.stderr | 20 +------ .../generic-associated-types/issue-76535.rs | 1 - .../issue-76535.stderr | 21 +------ .../generic-associated-types/issue-79422.rs | 14 +++-- .../issue-79422.stderr | 27 ++------- .../trait-bounds/span-bug-issue-121597.rs | 1 - .../trait-bounds/span-bug-issue-121597.stderr | 20 +------ ...ible-trait-in-return-position-dyn-trait.rs | 4 +- ...-trait-in-return-position-dyn-trait.stderr | 60 +------------------ .../impl-trait/in-trait/dyn-compatibility.rs | 1 - .../in-trait/dyn-compatibility.stderr | 20 +------ tests/ui/issues/issue-18959.rs | 1 - tests/ui/issues/issue-18959.stderr | 19 +----- tests/ui/issues/issue-19380.rs | 1 - tests/ui/issues/issue-19380.stderr | 27 +-------- tests/ui/issues/issue-50781.rs | 1 - tests/ui/issues/issue-50781.stderr | 20 +------ .../ui/kindck/kindck-inherited-copy-bound.rs | 1 - .../kindck/kindck-inherited-copy-bound.stderr | 18 +----- .../arbitrary-self-types-dyn-incompatible.rs | 1 - ...bitrary-self-types-dyn-incompatible.stderr | 22 +------ .../statics/unsizing-wfcheck-issue-127299.rs | 1 - .../unsizing-wfcheck-issue-127299.stderr | 26 +------- tests/ui/traits/issue-20692.rs | 1 - tests/ui/traits/issue-20692.stderr | 21 +------ tests/ui/traits/issue-38604.rs | 2 +- tests/ui/traits/issue-38604.stderr | 19 +----- .../supertrait-dyn-compatibility.rs | 1 - .../supertrait-dyn-compatibility.stderr | 21 +------ ...onicalize-fresh-infer-vars-issue-103626.rs | 1 - ...alize-fresh-infer-vars-issue-103626.stderr | 26 +------- tests/ui/traits/object/safety.rs | 1 - tests/ui/traits/object/safety.stderr | 27 +-------- tests/ui/traits/test-2.rs | 1 - tests/ui/traits/test-2.stderr | 26 +------- 62 files changed, 73 insertions(+), 767 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 4f77594deca6..ddc80fab2ce1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -47,7 +47,7 @@ use rustc_infer::infer::relate::RelateResult; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::{ IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation, - PredicateObligations, + PredicateObligations, SelectionError, }; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::{ @@ -677,7 +677,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { return Err(TypeError::Mismatch); } - // Dyn-compatibility violations or miscellaneous. + Err(SelectionError::TraitDynIncompatible(_)) => { + // Dyn compatibility errors in coercion will *always* be due to the + // fact that the RHS of the coercion is a non-dyn compatible `dyn Trait` + // writen in source somewhere (otherwise we will never have lowered + // the dyn trait from HIR to middle). + // + // There's no reason to emit yet another dyn compatibility error, + // especially since the span will differ slightly and thus not be + // deduplicated at all! + self.fcx.set_tainted_by_errors( + self.fcx + .dcx() + .span_delayed_bug(self.cause.span, "dyn compatibility during coercion"), + ); + } Err(err) => { let guar = self.err_ctxt().report_selection_error( obligation.clone(), diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr index 07c3fd3527f2..9b818a15c29c 100644 --- a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr +++ b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr @@ -24,24 +24,6 @@ LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output; | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` = help: consider moving `async_dispatch` to another trait -error[E0038]: the trait `AsyncTrait` is not dyn compatible - --> $DIR/mut-is-pointer-like.rs:35:56 - | -LL | let x: Pin<&mut dyn AsyncTrait> = f; - | ^ `AsyncTrait` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/mut-is-pointer-like.rs:16:14 - | -LL | trait AsyncTrait { - | ---------- this trait is not dyn compatible... -... -LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output; - | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` - = help: consider moving `async_dispatch` to another trait - = note: required for the cast from `Pin<&mut {async block@$DIR/mut-is-pointer-like.rs:32:32: 32:37}>` to `Pin<&mut dyn AsyncTrait>` - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/dyn/works.stderr b/tests/ui/async-await/dyn/works.stderr index 1fe2b28eca82..5d2cc385cbd6 100644 --- a/tests/ui/async-await/dyn/works.stderr +++ b/tests/ui/async-await/dyn/works.stderr @@ -7,24 +7,6 @@ LL | #![feature(async_fn_in_dyn_trait)] = note: see issue #133119 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0038]: the trait `AsyncTrait` is not dyn compatible - --> $DIR/works.rs:27:34 - | -LL | let x: &dyn AsyncTrait = &"hello, world!"; - | ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/works.rs:14:14 - | -LL | trait AsyncTrait { - | ---------- this trait is not dyn compatible... -LL | async fn async_dispatch(&self); - | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` - = help: consider moving `async_dispatch` to another trait - = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. - = note: required for the cast from `&&'static str` to `&dyn AsyncTrait` - error[E0038]: the trait `AsyncTrait` is not dyn compatible --> $DIR/works.rs:27:16 | @@ -42,6 +24,6 @@ LL | async fn async_dispatch(&self); = help: consider moving `async_dispatch` to another trait = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/dyn/wrong-size.stderr b/tests/ui/async-await/dyn/wrong-size.stderr index b4684f4fc174..930ca571417d 100644 --- a/tests/ui/async-await/dyn/wrong-size.stderr +++ b/tests/ui/async-await/dyn/wrong-size.stderr @@ -7,24 +7,6 @@ LL | #![feature(async_fn_in_dyn_trait)] = note: see issue #133119 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0038]: the trait `AsyncTrait` is not dyn compatible - --> $DIR/wrong-size.rs:21:30 - | -LL | let x: &dyn AsyncTrait = &"hello, world!"; - | ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/wrong-size.rs:9:14 - | -LL | trait AsyncTrait { - | ---------- this trait is not dyn compatible... -LL | async fn async_dispatch(&self); - | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` - = help: consider moving `async_dispatch` to another trait - = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. - = note: required for the cast from `&&'static str` to `&dyn AsyncTrait` - error[E0038]: the trait `AsyncTrait` is not dyn compatible --> $DIR/wrong-size.rs:21:12 | @@ -42,6 +24,6 @@ LL | async fn async_dispatch(&self); = help: consider moving `async_dispatch` to another trait = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs index 1b1b8bcf03dc..d73b67dc0809 100644 --- a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs +++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs @@ -6,7 +6,6 @@ use std::marker::PhantomData; fn transmute(t: T) -> U { (&PhantomData:: as &dyn Foo).transmute(t) //~^ ERROR the trait `Foo` is not dyn compatible - //~| ERROR the trait `Foo` is not dyn compatible } struct ActuallySuper; diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr index a384697ee083..d3022b5d8cd4 100644 --- a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr +++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr @@ -1,12 +1,12 @@ error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/almost-supertrait-associated-type.rs:21:20 + --> $DIR/almost-supertrait-associated-type.rs:20:20 | LL | impl Dyn for dyn Foo + '_ { | ^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/almost-supertrait-associated-type.rs:33:34 + --> $DIR/almost-supertrait-associated-type.rs:32:34 | LL | trait Foo: Super | --- this trait is not dyn compatible... @@ -23,7 +23,7 @@ LL | (&PhantomData:: as &dyn Foo).transmute(t) | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/almost-supertrait-associated-type.rs:33:34 + --> $DIR/almost-supertrait-associated-type.rs:32:34 | LL | trait Foo: Super | --- this trait is not dyn compatible... @@ -32,24 +32,6 @@ LL | fn transmute(&self, t: T) -> >::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type = help: consider moving `transmute` to another trait -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/almost-supertrait-associated-type.rs:7:6 - | -LL | (&PhantomData:: as &dyn Foo).transmute(t) - | ^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/almost-supertrait-associated-type.rs:33:34 - | -LL | trait Foo: Super - | --- this trait is not dyn compatible... -... -LL | fn transmute(&self, t: T) -> >::Assoc; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type - = help: consider moving `transmute` to another trait - = note: required for the cast from `&PhantomData` to `&dyn Foo` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/associated-consts.rs b/tests/ui/dyn-compatibility/associated-consts.rs index 10d151d9a8b5..69fff81b2814 100644 --- a/tests/ui/dyn-compatibility/associated-consts.rs +++ b/tests/ui/dyn-compatibility/associated-consts.rs @@ -8,7 +8,6 @@ trait Bar { fn make_bar(t: &T) -> &dyn Bar { //~^ ERROR E0038 t - //~^ ERROR E0038 } fn main() { diff --git a/tests/ui/dyn-compatibility/associated-consts.stderr b/tests/ui/dyn-compatibility/associated-consts.stderr index beaf263af07e..dc64c93a577e 100644 --- a/tests/ui/dyn-compatibility/associated-consts.stderr +++ b/tests/ui/dyn-compatibility/associated-consts.stderr @@ -14,23 +14,6 @@ LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/associated-consts.rs:10:5 - | -LL | t - | ^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/associated-consts.rs:5:11 - | -LL | trait Bar { - | --- this trait is not dyn compatible... -LL | const X: usize; - | ^ ...because it contains this associated `const` - = help: consider moving `X` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/generics.rs b/tests/ui/dyn-compatibility/generics.rs index dcce17f925bc..c25bdab361ba 100644 --- a/tests/ui/dyn-compatibility/generics.rs +++ b/tests/ui/dyn-compatibility/generics.rs @@ -15,14 +15,12 @@ trait Quux { fn make_bar(t: &T) -> &dyn Bar { //~^ ERROR E0038 t - //~^ ERROR E0038 } fn make_bar_explicit(t: &T) -> &dyn Bar { //~^ ERROR E0038 t as &dyn Bar //~^ ERROR E0038 - //~| ERROR E0038 } fn make_quux(t: &T) -> &dyn Quux { diff --git a/tests/ui/dyn-compatibility/generics.stderr b/tests/ui/dyn-compatibility/generics.stderr index c01930105419..aec51970ebb1 100644 --- a/tests/ui/dyn-compatibility/generics.stderr +++ b/tests/ui/dyn-compatibility/generics.stderr @@ -15,7 +15,7 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/generics.rs:21:40 + --> $DIR/generics.rs:20:40 | LL | fn make_bar_explicit(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` is not dyn compatible @@ -31,24 +31,7 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/generics.rs:17:5 - | -LL | t - | ^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/generics.rs:7:8 - | -LL | trait Bar { - | --- this trait is not dyn compatible... -LL | fn bar(&self, t: T); - | ^^^ ...because method `bar` has generic type parameters - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/generics.rs:23:10 + --> $DIR/generics.rs:22:10 | LL | t as &dyn Bar | ^^^^^^^^ `Bar` is not dyn compatible @@ -63,23 +46,6 @@ LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/generics.rs:23:5 - | -LL | t as &dyn Bar - | ^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/generics.rs:7:8 - | -LL | trait Bar { - | --- this trait is not dyn compatible... -LL | fn bar(&self, t: T); - | ^^^ ...because method `bar` has generic type parameters - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs index 1289d2d7874a..d8b1bc5b7177 100644 --- a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs @@ -18,5 +18,4 @@ fn main() { let mut thing = Thing; let test: &mut dyn Bar = &mut thing; //~^ ERROR E0038 - //~| ERROR E0038 } diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr index c1e93ccb83ca..5bc1847ebde5 100644 --- a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr @@ -1,22 +1,3 @@ -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30 - | -LL | let test: &mut dyn Bar = &mut thing; - | ^^^^^^^^^^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 - | -LL | fn foo(&self, val: T); - | ^^^ ...because method `foo` has generic type parameters -... -LL | trait Bar: Foo { } - | --- this trait is not dyn compatible... - = help: consider moving `foo` to another trait - = help: only type `Thing` implements `Bar`; consider using it directly instead. - = note: required for the cast from `&mut Thing` to `&mut dyn Bar` - error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15 | @@ -35,6 +16,6 @@ LL | trait Bar: Foo { } = help: consider moving `foo` to another trait = help: only type `Thing` implements `Bar`; consider using it directly instead. -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/mentions-Self.rs b/tests/ui/dyn-compatibility/mentions-Self.rs index ce210f4776f7..8b0d5ec6604a 100644 --- a/tests/ui/dyn-compatibility/mentions-Self.rs +++ b/tests/ui/dyn-compatibility/mentions-Self.rs @@ -18,13 +18,11 @@ trait Quux { fn make_bar(t: &T) -> &dyn Bar { //~^ ERROR E0038 t - //~^ ERROR E0038 } fn make_baz(t: &T) -> &dyn Baz { //~^ ERROR E0038 t - //~^ ERROR E0038 } fn make_quux(t: &T) -> &dyn Quux { diff --git a/tests/ui/dyn-compatibility/mentions-Self.stderr b/tests/ui/dyn-compatibility/mentions-Self.stderr index 6d1ae90152e6..9d41e1d92ddf 100644 --- a/tests/ui/dyn-compatibility/mentions-Self.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self.stderr @@ -15,7 +15,7 @@ LL | fn bar(&self, x: &Self); = help: consider moving `bar` to another trait error[E0038]: the trait `Baz` is not dyn compatible - --> $DIR/mentions-Self.rs:24:31 + --> $DIR/mentions-Self.rs:23:31 | LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^ `Baz` is not dyn compatible @@ -30,40 +30,6 @@ LL | fn baz(&self) -> Self; | ^^^^ ...because method `baz` references the `Self` type in its return type = help: consider moving `baz` to another trait -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/mentions-Self.rs:20:5 - | -LL | t - | ^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/mentions-Self.rs:7:22 - | -LL | trait Bar { - | --- this trait is not dyn compatible... -LL | fn bar(&self, x: &Self); - | ^^^^^ ...because method `bar` references the `Self` type in this parameter - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error[E0038]: the trait `Baz` is not dyn compatible - --> $DIR/mentions-Self.rs:26:5 - | -LL | t - | ^ `Baz` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/mentions-Self.rs:11:22 - | -LL | trait Baz { - | --- this trait is not dyn compatible... -LL | fn baz(&self) -> Self; - | ^^^^ ...because method `baz` references the `Self` type in its return type - = help: consider moving `baz` to another trait - = note: required for the cast from `&T` to `&dyn Baz` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/no-static.rs b/tests/ui/dyn-compatibility/no-static.rs index 9bd871619728..2d5954afffda 100644 --- a/tests/ui/dyn-compatibility/no-static.rs +++ b/tests/ui/dyn-compatibility/no-static.rs @@ -17,5 +17,4 @@ impl Foo for Bar {} fn main() { let b: Box = Box::new(Bar); //~^ ERROR E0038 - //~| ERROR E0038 } diff --git a/tests/ui/dyn-compatibility/no-static.stderr b/tests/ui/dyn-compatibility/no-static.stderr index 814ab0d53c3f..8e4f109c97db 100644 --- a/tests/ui/dyn-compatibility/no-static.stderr +++ b/tests/ui/dyn-compatibility/no-static.stderr @@ -46,31 +46,6 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() where Self: Sized {} | +++++++++++++++++ -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/no-static.rs:18:27 - | -LL | let b: Box = Box::new(Bar); - | ^^^^^^^^^^^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/no-static.rs:5:8 - | -LL | trait Foo { - | --- this trait is not dyn compatible... -LL | fn foo() {} - | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `Bar` implements `Foo`; consider using it directly instead. - = note: required for the cast from `Box` to `Box` -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self) {} - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() where Self: Sized {} - | +++++++++++++++++ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/sized-2.rs b/tests/ui/dyn-compatibility/sized-2.rs index f61d49ee8dff..c99dcce46b2c 100644 --- a/tests/ui/dyn-compatibility/sized-2.rs +++ b/tests/ui/dyn-compatibility/sized-2.rs @@ -10,7 +10,6 @@ trait Bar fn make_bar(t: &T) -> &dyn Bar { //~^ ERROR E0038 t - //~^ ERROR E0038 } fn main() { diff --git a/tests/ui/dyn-compatibility/sized-2.stderr b/tests/ui/dyn-compatibility/sized-2.stderr index 1834d906bb89..70bd5f6dd36c 100644 --- a/tests/ui/dyn-compatibility/sized-2.stderr +++ b/tests/ui/dyn-compatibility/sized-2.stderr @@ -13,22 +13,6 @@ LL | trait Bar LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/sized-2.rs:12:5 - | -LL | t - | ^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/sized-2.rs:5:18 - | -LL | trait Bar - | --- this trait is not dyn compatible... -LL | where Self : Sized - | ^^^^^ ...because it requires `Self: Sized` - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/sized.rs b/tests/ui/dyn-compatibility/sized.rs index eb5279c17e62..b5a8a4be766a 100644 --- a/tests/ui/dyn-compatibility/sized.rs +++ b/tests/ui/dyn-compatibility/sized.rs @@ -8,7 +8,6 @@ trait Bar: Sized { fn make_bar(t: &T) -> &dyn Bar { //~^ ERROR E0038 t - //~^ ERROR E0038 } fn main() {} diff --git a/tests/ui/dyn-compatibility/sized.stderr b/tests/ui/dyn-compatibility/sized.stderr index c66e299cf6f5..0cc41179d9a8 100644 --- a/tests/ui/dyn-compatibility/sized.stderr +++ b/tests/ui/dyn-compatibility/sized.stderr @@ -13,22 +13,6 @@ LL | trait Bar: Sized { | | | this trait is not dyn compatible... -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/sized.rs:10:5 - | -LL | t - | ^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/sized.rs:4:12 - | -LL | trait Bar: Sized { - | --- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait is not dyn compatible... - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/taint-const-eval.rs b/tests/ui/dyn-compatibility/taint-const-eval.rs index 64c4df611e65..a5c01e1791e7 100644 --- a/tests/ui/dyn-compatibility/taint-const-eval.rs +++ b/tests/ui/dyn-compatibility/taint-const-eval.rs @@ -7,6 +7,5 @@ trait Qux { static FOO: &(dyn Qux + Sync) = "desc"; //~^ ERROR the trait `Qux` is not dyn compatible //~| ERROR the trait `Qux` is not dyn compatible -//~| ERROR the trait `Qux` is not dyn compatible fn main() {} diff --git a/tests/ui/dyn-compatibility/taint-const-eval.stderr b/tests/ui/dyn-compatibility/taint-const-eval.stderr index 942c20db6ce0..585c1f012c78 100644 --- a/tests/ui/dyn-compatibility/taint-const-eval.stderr +++ b/tests/ui/dyn-compatibility/taint-const-eval.stderr @@ -21,30 +21,6 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o LL | fn bar() where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Qux` is not dyn compatible - --> $DIR/taint-const-eval.rs:7:33 - | -LL | static FOO: &(dyn Qux + Sync) = "desc"; - | ^^^^^^ `Qux` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/taint-const-eval.rs:4:8 - | -LL | trait Qux { - | --- this trait is not dyn compatible... -LL | fn bar(); - | ^^^ ...because associated function `bar` has no `self` parameter - = note: required for the cast from `&'static str` to `&'static (dyn Qux + Sync + 'static)` -help: consider turning `bar` into a method by giving it a `&self` argument - | -LL | fn bar(&self); - | +++++ -help: alternatively, consider constraining `bar` so it does not apply to trait objects - | -LL | fn bar() where Self: Sized; - | +++++++++++++++++ - error[E0038]: the trait `Qux` is not dyn compatible --> $DIR/taint-const-eval.rs:7:15 | @@ -69,6 +45,6 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o LL | fn bar() where Self: Sized; | +++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs index 37eabbf16022..8d7ccea9e647 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs @@ -31,5 +31,4 @@ impl Trait for i32 { fn main() { Ptr(Box::new(4)) as Ptr; //~^ ERROR the trait `Trait` is not dyn compatible - //~^^ ERROR the trait `Trait` is not dyn compatible } diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr index 6634ce121186..18b99d24083b 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr @@ -17,26 +17,6 @@ LL | fn ptr(self: Ptr); | ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on = help: only type `i32` implements `Trait`; consider using it directly instead. -error[E0038]: the trait `Trait` is not dyn compatible - --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:5 - | -LL | fn ptr(self: Ptr); - | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` -... -LL | Ptr(Box::new(4)) as Ptr; - | ^^^^^^^^^^^^^^^^ `Trait` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 - | -LL | trait Trait { - | ----- this trait is not dyn compatible... -LL | fn ptr(self: Ptr); - | ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on - = help: only type `i32` implements `Trait`; consider using it directly instead. - = note: required for the cast from `Ptr<{integer}>` to `Ptr` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs index 7523803eacff..774e16d84c50 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.rs +++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs @@ -26,5 +26,4 @@ fn main() { let foo = Fooer(5); f(Box::new(foo)); //~^ ERROR the trait `Foo` is not dyn compatible - //~| ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.stderr index e57f6b48401f..d4ccd80f1465 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.stderr +++ b/tests/ui/generic-associated-types/gat-in-trait-path.stderr @@ -30,23 +30,6 @@ LL | type A<'a> where Self: 'a; | ^ ...because it contains the generic associated type `A` = help: consider moving `A` to another trait -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/gat-in-trait-path.rs:27:5 - | -LL | f(Box::new(foo)); - | ^^^^^^^^^^^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/gat-in-trait-path.rs:6:10 - | -LL | trait Foo { - | --- this trait is not dyn compatible... -LL | type A<'a> where Self: 'a; - | ^ ...because it contains the generic associated type `A` - = help: consider moving `A` to another trait - = note: required for the cast from `Box>` to `Box<(dyn Foo = &'a ()> + 'static)>` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs index d3a0caffec1e..8ecfa93750d4 100644 --- a/tests/ui/generic-associated-types/issue-71176.rs +++ b/tests/ui/generic-associated-types/issue-71176.rs @@ -18,6 +18,5 @@ fn main() { Holder { inner: Box::new(()), //~^ ERROR: the trait `Provider` is not dyn compatible - //~| ERROR: the trait `Provider` is not dyn compatible }; } diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr index 56439f6dfea8..f231056a2eed 100644 --- a/tests/ui/generic-associated-types/issue-71176.stderr +++ b/tests/ui/generic-associated-types/issue-71176.stderr @@ -82,25 +82,7 @@ LL | type A<'a>; = help: consider moving `A` to another trait = help: only type `()` implements `Provider`; consider using it directly instead. -error[E0038]: the trait `Provider` is not dyn compatible - --> $DIR/issue-71176.rs:19:16 - | -LL | inner: Box::new(()), - | ^^^^^^^^^^^^ `Provider` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/issue-71176.rs:2:10 - | -LL | trait Provider { - | -------- this trait is not dyn compatible... -LL | type A<'a>; - | ^ ...because it contains the generic associated type `A` - = help: consider moving `A` to another trait - = help: only type `()` implements `Provider`; consider using it directly instead. - = note: required for the cast from `Box<()>` to `Box<(dyn Provider = _> + 'static), {type error}>` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-76535.rs b/tests/ui/generic-associated-types/issue-76535.rs index 9e18c82c7f1c..dc697401a58c 100644 --- a/tests/ui/generic-associated-types/issue-76535.rs +++ b/tests/ui/generic-associated-types/issue-76535.rs @@ -33,6 +33,5 @@ impl SuperTrait for SuperStruct { fn main() { let sub: Box> = Box::new(SuperStruct::new(0)); //~^ ERROR missing generics for associated type - //~^^ ERROR the trait //~| ERROR the trait } diff --git a/tests/ui/generic-associated-types/issue-76535.stderr b/tests/ui/generic-associated-types/issue-76535.stderr index b828234afa12..9bac3318948c 100644 --- a/tests/ui/generic-associated-types/issue-76535.stderr +++ b/tests/ui/generic-associated-types/issue-76535.stderr @@ -32,26 +32,7 @@ LL | type SubType<'a>: SubTrait where Self: 'a; = help: only type `SuperStruct` implements `SuperTrait` within this crate; consider using it directly instead. = note: `SuperTrait` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type -error[E0038]: the trait `SuperTrait` is not dyn compatible - --> $DIR/issue-76535.rs:34:57 - | -LL | let sub: Box> = Box::new(SuperStruct::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/issue-76535.rs:4:10 - | -LL | pub trait SuperTrait { - | ---------- this trait is not dyn compatible... -LL | type SubType<'a>: SubTrait where Self: 'a; - | ^^^^^^^ ...because it contains the generic associated type `SubType` - = help: consider moving `SubType` to another trait - = help: only type `SuperStruct` implements `SuperTrait` within this crate; consider using it directly instead. - = note: `SuperTrait` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type - = note: required for the cast from `Box` to `Box = SubStruct<'_>>>` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-79422.rs b/tests/ui/generic-associated-types/issue-79422.rs index fba7a86990ec..462614b36127 100644 --- a/tests/ui/generic-associated-types/issue-79422.rs +++ b/tests/ui/generic-associated-types/issue-79422.rs @@ -15,12 +15,17 @@ impl<'a, T> RefCont<'a, T> for Box { } trait MapLike { - type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + type VRefCont<'a>: RefCont<'a, V> + where + Self: 'a; fn get<'a>(&'a self, key: &K) -> Option>; } impl MapLike for std::collections::BTreeMap { - type VRefCont<'a> = &'a V where Self: 'a; + type VRefCont<'a> + = &'a V + where + Self: 'a; fn get<'a>(&'a self, key: &K) -> Option<&'a V> { std::collections::BTreeMap::get(self, key) } @@ -37,8 +42,7 @@ impl MapLike for Source { fn main() { let m = Box::new(std::collections::BTreeMap::::new()) - //~^ ERROR the trait as Box>>; - //~^ ERROR missing generics for associated type - //~| ERROR the trait + //~^ ERROR the trait + //~| ERROR missing generics for associated type } diff --git a/tests/ui/generic-associated-types/issue-79422.stderr b/tests/ui/generic-associated-types/issue-79422.stderr index 6311e4de272d..403cb67adb41 100644 --- a/tests/ui/generic-associated-types/issue-79422.stderr +++ b/tests/ui/generic-associated-types/issue-79422.stderr @@ -1,5 +1,5 @@ error[E0107]: missing generics for associated type `MapLike::VRefCont` - --> $DIR/issue-79422.rs:41:36 + --> $DIR/issue-79422.rs:45:36 | LL | as Box>>; | ^^^^^^^^ expected 1 lifetime argument @@ -7,7 +7,7 @@ LL | as Box>>; note: associated type defined here, with 1 lifetime parameter: `'a` --> $DIR/issue-79422.rs:18:10 | -LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; +LL | type VRefCont<'a>: RefCont<'a, V> | ^^^^^^^^ -- help: add missing lifetime argument | @@ -15,7 +15,7 @@ LL | as Box = dyn RefCont<'_, u8>>>; | ++++ error[E0038]: the trait `MapLike` is not dyn compatible - --> $DIR/issue-79422.rs:41:12 + --> $DIR/issue-79422.rs:45:12 | LL | as Box>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible @@ -26,28 +26,11 @@ note: for a trait to be dyn compatible it needs to allow building a vtable | LL | trait MapLike { | ------- this trait is not dyn compatible... -LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; +LL | type VRefCont<'a>: RefCont<'a, V> | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` = help: consider moving `VRefCont` to another trait -error[E0038]: the trait `MapLike` is not dyn compatible - --> $DIR/issue-79422.rs:39:13 - | -LL | let m = Box::new(std::collections::BTreeMap::::new()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/issue-79422.rs:18:10 - | -LL | trait MapLike { - | ------- this trait is not dyn compatible... -LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; - | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` - = help: consider moving `VRefCont` to another trait - = note: required for the cast from `Box>` to `Box = (dyn RefCont<'_, u8> + 'static)>>` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs index 5d039cd5dc65..949c49a820b7 100644 --- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs +++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs @@ -13,7 +13,6 @@ fn needs_bar(_: *mut Type2) {} fn main() { let x: &dyn Foo = &(); //~^ ERROR the trait `Foo` is not dyn compatible - //~| ERROR the trait `Foo` is not dyn compatible needs_bar(x); //~^ ERROR mismatched types diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr index 183ee678d7a4..10a9e2c8d24b 100644 --- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr +++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr @@ -1,19 +1,3 @@ -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/span-bug-issue-121597.rs:14:23 - | -LL | let x: &dyn Foo = &(); - | ^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/span-bug-issue-121597.rs:4:12 - | -LL | trait Foo: for Bar {} - | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables - | | - | this trait is not dyn compatible... - = note: required for the cast from `&()` to `&dyn Foo` - error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/span-bug-issue-121597.rs:14:12 | @@ -30,7 +14,7 @@ LL | trait Foo: for Bar {} | this trait is not dyn compatible... error[E0308]: mismatched types - --> $DIR/span-bug-issue-121597.rs:18:15 + --> $DIR/span-bug-issue-121597.rs:17:15 | LL | needs_bar(x); | --------- ^ types differ in mutability @@ -45,7 +29,7 @@ note: function defined here LL | fn needs_bar(_: *mut Type2) {} | ^^^^^^^^^ ------------- -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0308. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs index 901d4b39cf36..c3dc417b1873 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs @@ -29,9 +29,9 @@ fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` is not d fn cat() -> Box { //~ ERROR the trait `DynIncompatible` is not dyn compatible if true { - return Box::new(A); //~ ERROR is not dyn compatible + return Box::new(A); } - Box::new(B) //~ ERROR is not dyn compatible + Box::new(B) } fn main() {} diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr index 2c314b07bcee..a230090eb00e 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr @@ -75,65 +75,7 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `DynIncompatible` is not dyn compatible - --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:32:16 - | -LL | return Box::new(A); - | ^^^^^^^^^^^ `DynIncompatible` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 - | -LL | trait DynIncompatible { - | --------------- this trait is not dyn compatible... -LL | fn foo() -> Self; - | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement `DynIncompatible`: - A - B - consider defining an enum where each variant holds one of these types, - implementing `DynIncompatible` for this new enum and using it instead - = note: required for the cast from `Box` to `Box<(dyn DynIncompatible + 'static)>` -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self) -> Self; - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() -> Self where Self: Sized; - | +++++++++++++++++ - -error[E0038]: the trait `DynIncompatible` is not dyn compatible - --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:34:5 - | -LL | Box::new(B) - | ^^^^^^^^^^^ `DynIncompatible` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 - | -LL | trait DynIncompatible { - | --------------- this trait is not dyn compatible... -LL | fn foo() -> Self; - | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement `DynIncompatible`: - A - B - consider defining an enum where each variant holds one of these types, - implementing `DynIncompatible` for this new enum and using it instead - = note: required for the cast from `Box` to `Box<(dyn DynIncompatible + 'static)>` -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self) -> Self; - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() -> Self where Self: Sized; - | +++++++++++++++++ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0038, E0746. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.rs b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs index 92203c470bba..45b431f6d306 100644 --- a/tests/ui/impl-trait/in-trait/dyn-compatibility.rs +++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs @@ -13,6 +13,5 @@ impl Foo for u32 { fn main() { let i = Box::new(42_u32) as Box; //~^ ERROR the trait `Foo` is not dyn compatible - //~| ERROR the trait `Foo` is not dyn compatible let s = i.baz(); } diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr index 5c498548affd..d65ed6bbcdac 100644 --- a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr +++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr @@ -15,24 +15,6 @@ LL | fn baz(&self) -> impl Debug; = help: consider moving `baz` to another trait = help: only type `u32` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/dyn-compatibility.rs:14:13 - | -LL | let i = Box::new(42_u32) as Box; - | ^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/dyn-compatibility.rs:4:22 - | -LL | trait Foo { - | --- this trait is not dyn compatible... -LL | fn baz(&self) -> impl Debug; - | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type - = help: consider moving `baz` to another trait - = help: only type `u32` implements `Foo`; consider using it directly instead. - = note: required for the cast from `Box` to `Box` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-18959.rs b/tests/ui/issues/issue-18959.rs index dbc73bafce9e..4fe669adcdaf 100644 --- a/tests/ui/issues/issue-18959.rs +++ b/tests/ui/issues/issue-18959.rs @@ -17,6 +17,5 @@ fn main() { let mut thing = Thing; let test: &dyn Bar = &mut thing; //~^ ERROR E0038 - //~| ERROR E0038 foo(test); } diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr index 7ddfdb49d959..5345046ba6d3 100644 --- a/tests/ui/issues/issue-18959.stderr +++ b/tests/ui/issues/issue-18959.stderr @@ -14,23 +14,6 @@ LL | pub trait Bar: Foo { } | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait -error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/issue-18959.rs:18:26 - | -LL | let test: &dyn Bar = &mut thing; - | ^^^^^^^^^^ `Bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/issue-18959.rs:1:20 - | -LL | pub trait Foo { fn foo(&self, ext_thing: &T); } - | ^^^ ...because method `foo` has generic type parameters -LL | pub trait Bar: Foo { } - | --- this trait is not dyn compatible... - = help: consider moving `foo` to another trait - = note: required for the cast from `&mut Thing` to `&dyn Bar` - error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/issue-18959.rs:18:15 | @@ -47,6 +30,6 @@ LL | pub trait Bar: Foo { } | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-19380.rs b/tests/ui/issues/issue-19380.rs index 8b3fe4d2b099..fce737cba18d 100644 --- a/tests/ui/issues/issue-19380.rs +++ b/tests/ui/issues/issue-19380.rs @@ -15,6 +15,5 @@ struct Bar { const FOO : Foo = Foo; const BAR : Bar = Bar { foos: &[&FOO]}; //~^ ERROR E0038 -//~| ERROR E0038 fn main() { } diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/issues/issue-19380.stderr index f8509891d3ab..4c41d41ae379 100644 --- a/tests/ui/issues/issue-19380.stderr +++ b/tests/ui/issues/issue-19380.stderr @@ -22,31 +22,6 @@ help: alternatively, consider constraining `qiz` so it does not apply to trait o LL | fn qiz() where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Qiz` is not dyn compatible - --> $DIR/issue-19380.rs:16:33 - | -LL | const BAR : Bar = Bar { foos: &[&FOO]}; - | ^^^^ `Qiz` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/issue-19380.rs:2:6 - | -LL | trait Qiz { - | --- this trait is not dyn compatible... -LL | fn qiz(); - | ^^^ ...because associated function `qiz` has no `self` parameter - = help: only type `Foo` implements `Qiz`; consider using it directly instead. - = note: required for the cast from `&Foo` to `&'static (dyn Qiz + 'static)` -help: consider turning `qiz` into a method by giving it a `&self` argument - | -LL | fn qiz(&self); - | +++++ -help: alternatively, consider constraining `qiz` so it does not apply to trait objects - | -LL | fn qiz() where Self: Sized; - | +++++++++++++++++ - error[E0038]: the trait `Qiz` is not dyn compatible --> $DIR/issue-19380.rs:16:31 | @@ -71,6 +46,6 @@ help: alternatively, consider constraining `qiz` so it does not apply to trait o LL | fn qiz() where Self: Sized; | +++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-50781.rs b/tests/ui/issues/issue-50781.rs index ab90db1cadcf..d837b848591f 100644 --- a/tests/ui/issues/issue-50781.rs +++ b/tests/ui/issues/issue-50781.rs @@ -15,5 +15,4 @@ pub fn main() { // Check that this does not segfault. ::foo(&()); //~^ ERROR the trait `X` is not dyn compatible - //~| ERROR the trait `X` is not dyn compatible } diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr index 88b83a83e0cf..be6519429a51 100644 --- a/tests/ui/issues/issue-50781.stderr +++ b/tests/ui/issues/issue-50781.stderr @@ -15,24 +15,6 @@ LL | fn foo(&self) where Self: Trait; = help: consider moving `foo` to another trait = help: only type `()` implements `X`; consider using it directly instead. -error[E0038]: the trait `X` is not dyn compatible - --> $DIR/issue-50781.rs:16:23 - | -LL | ::foo(&()); - | ^^^ `X` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/issue-50781.rs:4:8 - | -LL | trait X { - | - this trait is not dyn compatible... -LL | fn foo(&self) where Self: Trait; - | ^^^ ...because method `foo` references the `Self` type in its `where` clause - = help: consider moving `foo` to another trait - = help: only type `()` implements `X`; consider using it directly instead. - = note: required for the cast from `&()` to `&dyn X` - error[E0038]: the trait `X` is not dyn compatible --> $DIR/issue-50781.rs:16:6 | @@ -50,6 +32,6 @@ LL | fn foo(&self) where Self: Trait; = help: consider moving `foo` to another trait = help: only type `()` implements `X`; consider using it directly instead. -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.rs b/tests/ui/kindck/kindck-inherited-copy-bound.rs index 20d54a3fb106..92c2b273c2c1 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.rs +++ b/tests/ui/kindck/kindck-inherited-copy-bound.rs @@ -22,7 +22,6 @@ fn b() { let y = &x; let z = &x as &dyn Foo; //~^ ERROR E0038 - //~| ERROR E0038 } fn main() { } diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.stderr index edfa7ae7769d..05d31f48f47a 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.stderr @@ -34,23 +34,7 @@ LL | trait Foo : Copy { | | | this trait is not dyn compatible... -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/kindck-inherited-copy-bound.rs:23:13 - | -LL | let z = &x as &dyn Foo; - | ^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/kindck-inherited-copy-bound.rs:6:13 - | -LL | trait Foo : Copy { - | --- ^^^^ ...because it requires `Self: Sized` - | | - | this trait is not dyn compatible... - = note: required for the cast from `&Box<{integer}>` to `&dyn Foo` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0277. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs b/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs index 0477d9d79c77..b223f18327b1 100644 --- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs @@ -28,7 +28,6 @@ impl Bar for usize { fn make_foo() { let x = Rc::new(5usize) as Rc; //~^ ERROR E0038 - //~| ERROR E0038 } fn make_bar() { diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr index 9fb4c80329d5..977ccecea064 100644 --- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr @@ -17,26 +17,6 @@ LL | fn foo(self: &Rc) -> usize; | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on = help: only type `usize` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/arbitrary-self-types-dyn-incompatible.rs:29:13 - | -LL | fn foo(self: &Rc) -> usize; - | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` -... -LL | let x = Rc::new(5usize) as Rc; - | ^^^^^^^^^^^^^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/arbitrary-self-types-dyn-incompatible.rs:4:18 - | -LL | trait Foo { - | --- this trait is not dyn compatible... -LL | fn foo(self: &Rc) -> usize; - | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on - = help: only type `usize` implements `Foo`; consider using it directly instead. - = note: required for the cast from `Rc` to `Rc` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.rs b/tests/ui/statics/unsizing-wfcheck-issue-127299.rs index fd07937d90f2..14ba38d75356 100644 --- a/tests/ui/statics/unsizing-wfcheck-issue-127299.rs +++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.rs @@ -12,6 +12,5 @@ pub struct Lint { static FOO: &Lint = &Lint { desc: "desc" }; //~^ ERROR cannot be shared between threads safely //~| ERROR is not dyn compatible -//~| ERROR is not dyn compatible fn main() {} diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr index 28427161e870..e401277a0209 100644 --- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr +++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr @@ -51,7 +51,6 @@ LL | trait Qux { | --- this trait is not dyn compatible... LL | fn bar() -> i32; | ^^^ ...because associated function `bar` has no `self` parameter - = note: required for the cast from `&'static str` to `&'static (dyn Qux + 'static)` help: consider turning `bar` into a method by giving it a `&self` argument | LL | fn bar(&self) -> i32; @@ -61,30 +60,7 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o LL | fn bar() -> i32 where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Qux` is not dyn compatible - --> $DIR/unsizing-wfcheck-issue-127299.rs:12:35 - | -LL | static FOO: &Lint = &Lint { desc: "desc" }; - | ^^^^^^ `Qux` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8 - | -LL | trait Qux { - | --- this trait is not dyn compatible... -LL | fn bar() -> i32; - | ^^^ ...because associated function `bar` has no `self` parameter -help: consider turning `bar` into a method by giving it a `&self` argument - | -LL | fn bar(&self) -> i32; - | +++++ -help: alternatively, consider constraining `bar` so it does not apply to trait objects - | -LL | fn bar() -> i32 where Self: Sized; - | +++++++++++++++++ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0038, E0277. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-20692.rs b/tests/ui/traits/issue-20692.rs index 10611a232f71..79edc389ec4a 100644 --- a/tests/ui/traits/issue-20692.rs +++ b/tests/ui/traits/issue-20692.rs @@ -2,7 +2,6 @@ trait Array: Sized + Copy {} fn f(x: &T) { let _ = x - //~^ ERROR `Array` is not dyn compatible as &dyn Array; //~^ ERROR `Array` is not dyn compatible diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr index 32e29de49a11..e902a582cc70 100644 --- a/tests/ui/traits/issue-20692.stderr +++ b/tests/ui/traits/issue-20692.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Array` is not dyn compatible - --> $DIR/issue-20692.rs:7:5 + --> $DIR/issue-20692.rs:6:5 | LL | &dyn Array; | ^^^^^^^^^^ `Array` is not dyn compatible @@ -14,23 +14,6 @@ LL | trait Array: Sized + Copy {} | | ...because it requires `Self: Sized` | this trait is not dyn compatible... -error[E0038]: the trait `Array` is not dyn compatible - --> $DIR/issue-20692.rs:4:13 - | -LL | let _ = x - | ^ `Array` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/issue-20692.rs:1:14 - | -LL | trait Array: Sized + Copy {} - | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized` - | | | - | | ...because it requires `Self: Sized` - | this trait is not dyn compatible... - = note: required for the cast from `&T` to `&dyn Array` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-38604.rs b/tests/ui/traits/issue-38604.rs index d90aa61ef9f3..70f0ef0cb9cb 100644 --- a/tests/ui/traits/issue-38604.rs +++ b/tests/ui/traits/issue-38604.rs @@ -12,5 +12,5 @@ impl Foo for () { fn main() { let _f: Box = //~ ERROR `Foo` is not dyn compatible - Box::new(()); //~ ERROR `Foo` is not dyn compatible + Box::new(()); } diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr index e6a6b44e7304..0455230b1aa3 100644 --- a/tests/ui/traits/issue-38604.stderr +++ b/tests/ui/traits/issue-38604.stderr @@ -14,23 +14,6 @@ LL | trait Foo where u32: Q { | this trait is not dyn compatible... = help: only type `()` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/issue-38604.rs:15:9 - | -LL | Box::new(()); - | ^^^^^^^^^^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/issue-38604.rs:2:22 - | -LL | trait Foo where u32: Q { - | --- ^^^^^^^ ...because it uses `Self` as a type parameter - | | - | this trait is not dyn compatible... - = help: only type `()` implements `Foo`; consider using it directly instead. - = note: required for the cast from `Box<()>` to `Box` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs index 28785ae3dea1..2945b28eec36 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs +++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs @@ -18,7 +18,6 @@ impl Bar for () {} fn main() { let x: &dyn Foo = &(); //~^ ERROR the trait `Foo` is not dyn compatible - //~| ERROR the trait `Foo` is not dyn compatible needs_bar(x); //~^ ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr index 43b69d0b50e4..2cf6329d0a10 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr +++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr @@ -7,23 +7,6 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/supertrait-dyn-compatibility.rs:19:23 - | -LL | let x: &dyn Foo = &(); - | ^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/supertrait-dyn-compatibility.rs:4:12 - | -LL | trait Foo: for Bar {} - | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables - | | - | this trait is not dyn compatible... - = help: only type `()` implements `Foo`; consider using it directly instead. - = note: required for the cast from `&()` to `&dyn Foo` - error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/supertrait-dyn-compatibility.rs:19:12 | @@ -41,7 +24,7 @@ LL | trait Foo: for Bar {} = help: only type `()` implements `Foo`; consider using it directly instead. error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/supertrait-dyn-compatibility.rs:22:5 + --> $DIR/supertrait-dyn-compatibility.rs:21:5 | LL | needs_bar(x); | ^^^^^^^^^ `Foo` is not dyn compatible @@ -56,6 +39,6 @@ LL | trait Foo: for Bar {} | this trait is not dyn compatible... = help: only type `()` implements `Foo`; consider using it directly instead. -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs index 6fcd67b4950f..415b050b9d69 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs @@ -9,7 +9,6 @@ trait Try { fn w<'a, T: 'a, F: Fn(&'a T)>() { let b: &dyn FromResidual = &(); //~^ ERROR: the trait `FromResidual` is not dyn compatible - //~| ERROR: the trait `FromResidual` is not dyn compatible //~| ERROR the type parameter `R` must be explicitly specified } diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index b4bbd65b2f47..0f872dfba5d5 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -13,30 +13,6 @@ help: set the type parameter to the desired type LL | let b: &dyn FromResidual = &(); | +++ -error[E0038]: the trait `FromResidual` is not dyn compatible - --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32 - | -LL | let b: &dyn FromResidual = &(); - | ^^^ `FromResidual` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8 - | -LL | trait FromResidual::Residual> { - | ------------ this trait is not dyn compatible... -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter - = note: required for the cast from `&()` to `&dyn FromResidual<{type error}>` -help: consider turning `from_residual` into a method by giving it a `&self` argument - | -LL | fn from_residual(&self, residual: R) -> Self; - | ++++++ -help: alternatively, consider constraining `from_residual` so it does not apply to trait objects - | -LL | fn from_residual(residual: R) -> Self where Self: Sized; - | +++++++++++++++++ - error[E0038]: the trait `FromResidual` is not dyn compatible --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12 | @@ -60,7 +36,7 @@ help: alternatively, consider constraining `from_residual` so it does not apply LL | fn from_residual(residual: R) -> Self where Self: Sized; | +++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0393. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/safety.rs b/tests/ui/traits/object/safety.rs index f4abcf8542e5..ec039557b635 100644 --- a/tests/ui/traits/object/safety.rs +++ b/tests/ui/traits/object/safety.rs @@ -13,5 +13,4 @@ impl Tr for St { fn main() { let _: &dyn Tr = &St; //~ ERROR E0038 - //~^ ERROR E0038 } diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr index 593e42619f41..a3671d90d283 100644 --- a/tests/ui/traits/object/safety.stderr +++ b/tests/ui/traits/object/safety.stderr @@ -1,28 +1,3 @@ -error[E0038]: the trait `Tr` is not dyn compatible - --> $DIR/safety.rs:15:22 - | -LL | let _: &dyn Tr = &St; - | ^^^ `Tr` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/safety.rs:4:8 - | -LL | trait Tr { - | -- this trait is not dyn compatible... -LL | fn foo(); - | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `St` implements `Tr`; consider using it directly instead. - = note: required for the cast from `&St` to `&dyn Tr` -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self); - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() where Self: Sized; - | +++++++++++++++++ - error[E0038]: the trait `Tr` is not dyn compatible --> $DIR/safety.rs:15:12 | @@ -47,6 +22,6 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() where Self: Sized; | +++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/test-2.rs b/tests/ui/traits/test-2.rs index 4ee880da87ad..1b7fc55b99a8 100644 --- a/tests/ui/traits/test-2.rs +++ b/tests/ui/traits/test-2.rs @@ -12,5 +12,4 @@ fn main() { //~^ ERROR method takes 1 generic argument but 2 (Box::new(10) as Box).dup(); //~^ ERROR E0038 - //~| ERROR E0038 } diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr index b52839c300ef..e4e39e9194ca 100644 --- a/tests/ui/traits/test-2.stderr +++ b/tests/ui/traits/test-2.stderr @@ -49,31 +49,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead -error[E0038]: the trait `bar` is not dyn compatible - --> $DIR/test-2.rs:13:6 - | -LL | (Box::new(10) as Box).dup(); - | ^^^^^^^^^^^^ `bar` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/test-2.rs:4:30 - | -LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } - | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters - | | | - | | ...because method `dup` references the `Self` type in its return type - | this trait is not dyn compatible... - = help: consider moving `dup` to another trait - = help: consider moving `blah` to another trait - = help: the following types implement `bar`: - i32 - u32 - consider defining an enum where each variant holds one of these types, - implementing `bar` for this new enum and using it instead - = note: required for the cast from `Box<{integer}>` to `Box` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`. From aa94ac1252a6479e3c4c1570f23e546157eea7c3 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 27 May 2025 04:54:50 +0000 Subject: [PATCH 136/139] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 306fd0d27e8f..9c82eb416d18 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3d86494a0d0131c32eb15e3a4b685707b9ff000d +d76fe154029e03aeb64af721beafdcef856d576a From d43c2e7448920a8803625c7922b8c28c2c365c04 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 27 May 2025 20:08:14 +0800 Subject: [PATCH 137/139] distcheck: document what distcheck is intended to exercise --- src/bootstrap/src/core/build_steps/test.rs | 9 ++++++++- .../host-x86_64/x86_64-gnu-distcheck/Dockerfile | 12 ++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index acd6fc477055..bb682751a2ec 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2964,7 +2964,14 @@ impl Step for Distcheck { run.builder.ensure(Distcheck); } - /// Runs "distcheck", a 'make check' from a tarball + /// Runs `distcheck`, which is a collection of smoke tests: + /// + /// - Run `make check` from an unpacked dist tarball to make sure we can at the minimum run + /// check steps from those sources. + /// - Check that selected dist components (`rust-src` only at the moment) at least have expected + /// directory shape and crate manifests that cargo can generate a lockfile from. + /// + /// FIXME(#136822): dist components are under-tested. fn run(self, builder: &Builder<'_>) { builder.info("Distcheck"); let dir = builder.tempdir().join("distcheck"); diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile index 2217e6ee7043..98fd31a22e93 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile @@ -1,3 +1,15 @@ +# Runs `distcheck`, which is a collection of smoke tests: +# +# - Run `make check` from an unpacked dist tarball to make sure we can at the +# minimum run check steps from those sources. +# - Check that selected dist components at least have expected directory shape +# and crate manifests that cargo can generate a lockfile from. +# +# Refer to `src/bootstrap/src/core/build_steps/test.rs` `Distcheck::run` for +# specifics. +# +# FIXME(#136822): dist components are generally under-tested. + FROM ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive From bf0aab9b2e5d8ebd33517668e121c8caf554acb0 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 27 May 2025 05:03:22 +0000 Subject: [PATCH 138/139] fmt --- src/tools/miri/src/concurrency/thread.rs | 6 +++++- src/tools/miri/src/machine.rs | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 15f15572c93d..5014bbeedb0b 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -902,7 +902,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let mut alloc = alloc.inner().adjust_from_tcx( &this.tcx, |bytes, align| { - interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align, ())) + interp_ok(MiriAllocBytes::from_bytes( + std::borrow::Cow::Borrowed(bytes), + align, + (), + )) }, |ptr| this.global_root_pointer(ptr), )?; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 5d5c19a24fa3..f1d3e949eaed 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1805,7 +1805,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } /// Placeholder! - fn get_default_alloc_params(&self) -> ::AllocParams { () } + fn get_default_alloc_params(&self) -> ::AllocParams { + () + } } /// Trait for callbacks handling asynchronous machine operations. From 86d03991678f391eba7b6ac489a44da178c8f8d4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 May 2025 08:18:25 +0200 Subject: [PATCH 139/139] pacify clippy --- src/tools/miri/src/machine.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index f1d3e949eaed..0c5127d802f8 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1805,9 +1805,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } /// Placeholder! - fn get_default_alloc_params(&self) -> ::AllocParams { - () - } + fn get_default_alloc_params(&self) -> ::AllocParams {} } /// Trait for callbacks handling asynchronous machine operations.