diff options
787 files changed, 13742 insertions, 7362 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff62e1ded61..3929b064c26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,12 +31,13 @@ defaults: run: shell: bash concurrency: - group: "${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }}" + group: "${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }}" cancel-in-progress: true jobs: pr: name: "PR - ${{ matrix.name }}" env: + PR_CI_JOB: 1 CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" @@ -211,18 +212,6 @@ jobs: - name: dist-loongarch64-linux os: ubuntu-20.04-8core-32gb env: {} - - name: dist-mips-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-mips64-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-mips64el-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-mipsel-linux - os: ubuntu-20.04-8core-32gb - env: {} - name: dist-powerpc-linux os: ubuntu-20.04-8core-32gb env: {} @@ -308,10 +297,6 @@ jobs: env: RUST_BACKTRACE: 1 os: ubuntu-20.04-8core-32gb - - name: x86_64-gnu-llvm-14-stage1 - env: - RUST_BACKTRACE: 1 - os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-nopt os: ubuntu-20.04-4core-16gb env: {} @@ -400,15 +385,10 @@ jobs: RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc" SCRIPT: make ci-msvc os: windows-2019-8core-32gb - - name: x86_64-msvc-cargo - env: - SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-lld" - os: windows-2019-8core-32gb - - name: x86_64-msvc-tools + - name: x86_64-msvc-ext env: - SCRIPT: src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json" + SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json" DEPLOY_TOOLSTATES_JSON: toolstates-windows.json os: windows-2019-8core-32gb - name: i686-mingw @@ -428,7 +408,7 @@ jobs: - name: dist-x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: PGO_HOST=x86_64-pc-windows-msvc python src/ci/stage-build.py python x.py dist bootstrap --include-default-paths + SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 os: windows-2019-8core-32gb - name: dist-i686-msvc diff --git a/Cargo.lock b/Cargo.lock index cdf6a4cc2de..96eda77abb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -172,6 +172,9 @@ name = "anyhow" version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +dependencies = [ + "backtrace", +] [[package]] name = "ar_archive_writer" @@ -259,6 +262,12 @@ dependencies = [ ] [[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] name = "basic-toml" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -328,6 +337,10 @@ dependencies = [ [[package]] name = "build_helper" version = "0.1.0" +dependencies = [ + "serde", + "serde_derive", +] [[package]] name = "bump-stage0" @@ -637,9 +650,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.93" +version = "0.1.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76630810d973ecea3dbf611e1b7aecfb1012751ef1ff8de3998f89014a166781" +checksum = "6866e0f3638013234db3c89ead7a14d278354338e7237257407500009012b23f" dependencies = [ "cc", "rustc-std-workspace-core", @@ -686,6 +699,16 @@ dependencies = [ ] [[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] name = "core-foundation-sys" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -767,6 +790,16 @@ dependencies = [ ] [[package]] +name = "cstr" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11a39d776a3b35896711da8a04dc1835169dcd36f710878187637314e47941b" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] name = "ctrlc" version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -976,6 +1009,15 @@ dependencies = [ ] [[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] name = "env_logger" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1165,6 +1207,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] name = "form_urlencoded" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1190,6 +1247,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" [[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] name = "futf" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1387,6 +1450,25 @@ dependencies = [ ] [[package]] +name = "h2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] name = "handlebars" version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1485,6 +1567,49 @@ dependencies = [ ] [[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm 0.2.7", +] + +[[package]] name = "humantime" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1500,6 +1625,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] +name = "hyper" +version = "0.14.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abfba89e19b959ca163c7752ba59d737c1ceea53a5d31a149c805446fc958064" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] name = "iana-time-zone" version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1708,13 +1870,19 @@ dependencies = [ ] [[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + +[[package]] name = "is-terminal" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" dependencies = [ "hermit-abi 0.3.1", - "rustix 0.38.1", + "rustix 0.38.2", "windows-sys 0.48.0", ] @@ -1857,6 +2025,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] name = "libz-sys" version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2095,6 +2269,17 @@ dependencies = [ ] [[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] name = "miow" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2132,6 +2317,24 @@ dependencies = [ ] [[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] name = "new_debug_unreachable" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2160,6 +2363,15 @@ dependencies = [ ] [[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] name = "nu-ansi-term" version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2231,6 +2443,32 @@ dependencies = [ ] [[package]] +name = "openssl" +version = "0.10.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.8", +] + +[[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2249,6 +2487,28 @@ dependencies = [ ] [[package]] +name = "opt-dist" +version = "0.1.0" +dependencies = [ + "anyhow", + "build_helper", + "camino", + "env_logger 0.10.0", + "fs_extra", + "glob", + "humansize", + "humantime 2.1.0", + "log", + "reqwest", + "serde", + "serde_json", + "sysinfo", + "tar", + "xz", + "zip", +] + +[[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2267,7 +2527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" dependencies = [ "cfg-if", - "libm", + "libm 0.1.4", ] [[package]] @@ -2721,6 +2981,43 @@ dependencies = [ ] [[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] name = "rls" version = "2.0.0" dependencies = [ @@ -3016,6 +3313,7 @@ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ "bitflags 1.3.2", + "cstr", "libc", "measureme", "object", @@ -3148,7 +3446,6 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ "rustc_driver_impl", - "rustix 0.37.11", ] [[package]] @@ -3937,6 +4234,7 @@ dependencies = [ "rustc_hir", "rustc_middle", "rustc_span", + "scoped-tls", "tracing", ] @@ -4206,9 +4504,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.11" +version = "0.37.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" +checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c" dependencies = [ "bitflags 1.3.2", "errno", @@ -4220,9 +4518,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.1" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc6396159432b5c8490d4e301d8c705f61860b8b6c863bf79942ce5401968f3" +checksum = "aabcb0461ebd01d6b79945797c27f8529082226cb630a9865a71870ff63532a4" dependencies = [ "bitflags 2.3.3", "errno", @@ -4285,6 +4583,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] +name = "security-framework" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] name = "self_cell" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4341,6 +4662,18 @@ dependencies = [ ] [[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] name = "sha1" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4619,6 +4952,20 @@ dependencies = [ ] [[package]] +name = "sysinfo" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9557d0845b86eea8182f7b10dff120214fb6cd9fd937b6f4917714e546a38695" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "winapi", +] + +[[package]] name = "sysroot" version = "0.0.0" dependencies = [ @@ -4648,7 +4995,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.11", + "rustix 0.37.22", "windows-sys 0.48.0", ] @@ -4689,7 +5036,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" dependencies = [ - "rustix 0.37.11", + "rustix 0.37.22", "windows-sys 0.48.0", ] @@ -4837,7 +5184,36 @@ dependencies = [ "autocfg", "backtrace", "bytes", + "libc", + "mio", + "num_cpus", "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", ] [[package]] @@ -4890,6 +5266,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" [[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] name = "tracing" version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4975,6 +5357,12 @@ dependencies = [ ] [[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] name = "twox-hash" version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5018,9 +5406,9 @@ checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "ui_test" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a2e70adc9d18b9b4dd80ea57aeec447103c6fbb354a07c080adad451c645e1" +checksum = "c21899b59f53717dfad29e4f46e5b21a200a1b6888ab86532a07cfc8b48dd78c" dependencies = [ "bstr", "cargo-platform", @@ -5293,6 +5681,15 @@ dependencies = [ ] [[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5329,6 +5726,18 @@ dependencies = [ ] [[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] name = "wasm-bindgen-macro" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5358,6 +5767,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5552,6 +5971,15 @@ dependencies = [ ] [[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] name = "writeable" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5567,6 +5995,15 @@ dependencies = [ ] [[package]] +name = "xz" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c887690ff2a2e233e8e49633461521f98ec57fbff9d59a884c9a4f04ec1da34" +dependencies = [ + "xz2", +] + +[[package]] name = "xz2" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5671,3 +6108,15 @@ dependencies = [ "syn 1.0.109", "synstructure 0.12.6", ] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", +] diff --git a/Cargo.toml b/Cargo.toml index 20b1c656d35..53bf9a8af2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ members = [ "src/tools/suggest-tests", "src/tools/generate-windows-sys", "src/tools/rustdoc-gui-test", + "src/tools/opt-dist", ] exclude = [ diff --git a/README.md b/README.md index 901213d2ca9..8a6c559b0b3 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,9 @@ Read ["Installation"] from [The Book]. The Rust build system uses a Python script called `x.py` to build the compiler, which manages the bootstrapping process. It lives at the root of the project. -It also uses a file named `config.toml` to determine various configuration settings for the build. -You can see a full list of options in `config.example.toml`. +It also uses a file named `config.toml` to determine various configuration +settings for the build. You can see a full list of options in +`config.example.toml`. The `x.py` command can be run directly on most Unix systems in the following format: @@ -33,7 +34,8 @@ format: ``` This is how the documentation and examples assume you are running `x.py`. -See the [rustc dev guide][rustcguidebuild] if this does not work on your platform. +See the [rustc dev guide][rustcguidebuild] if this does not work on your +platform. More information about `x.py` can be found by running it with the `--help` flag or reading the [rustc dev guide][rustcguidebuild]. @@ -105,24 +107,26 @@ See [the rustc-dev-guide for more info][sysllvm]. When complete, `./x.py install` will place several programs into `$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the - API-documentation tool. By default, it will also include [Cargo], Rust's package manager. - You can disable this behavior by passing `--set build.extended=false` to `./configure`. + API-documentation tool. By default, it will also include [Cargo], Rust's + package manager. You can disable this behavior by passing + `--set build.extended=false` to `./configure`. [Cargo]: https://github.com/rust-lang/cargo #### Configure and Make -This project provides a configure script and makefile (the latter of which just invokes `x.py`). -`./configure` is the recommended way to programatically generate a `config.toml`. `make` is not -recommended (we suggest using `x.py` directly), but it is supported and we try not to break it -unnecessarily. +This project provides a configure script and makefile (the latter of which just +invokes `x.py`). `./configure` is the recommended way to programatically +generate a `config.toml`. `make` is not recommended (we suggest using `x.py` +directly), but it is supported and we try not to break it unnecessarily. ```sh ./configure make && sudo make install ``` -`configure` generates a `config.toml` which can also be used with normal `x.py` invocations. +`configure` generates a `config.toml` which can also be used with normal `x.py` +invocations. ### Building on Windows @@ -193,7 +197,7 @@ toolchain. #### MSVC MSVC builds of Rust additionally require an installation of Visual Studio 2017 -(or later) so `rustc` can use its linker. The simplest way is to get +(or later) so `rustc` can use its linker. The simplest way is to get [Visual Studio], check the "C++ build tools" and "Windows 10 SDK" workload. [Visual Studio]: https://visualstudio.microsoft.com/downloads/ @@ -234,7 +238,8 @@ Windows build triples are: The build triple can be specified by either specifying `--build=<triple>` when invoking `x.py` commands, or by creating a `config.toml` file (as described in -[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing `--set build.build=<triple>` to `./configure`. +[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing +`--set build.build=<triple>` to `./configure`. ## Building Documentation diff --git a/RELEASES.md b/RELEASES.md index fa95df685aa..419c20b9071 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,146 @@ +Version 1.71.0 (2023-07-13) +========================== + +<a id="1.71.0-Language"></a> + +Language +-------- + +- [Stabilize `raw-dylib`, `link_ordinal`, `import_name_type` and `-Cdlltool`.](https://github.com/rust-lang/rust/pull/109677/) +- [Uplift `clippy::{drop,forget}_{ref,copy}` lints.](https://github.com/rust-lang/rust/pull/109732/) +- [Type inference is more conservative around constrained vars.](https://github.com/rust-lang/rust/pull/110100/) +- [Use fulfillment to check `Drop` impl compatibility](https://github.com/rust-lang/rust/pull/110577/) + +<a id="1.71.0-Compiler"></a> + +Compiler +-------- + +- [Evaluate place expression in `PlaceMention`](https://github.com/rust-lang/rust/pull/104844/), + making `let _ =` patterns more consistent with respect to the borrow checker. +- [Add `--print deployment-target` flag for Apple targets.](https://github.com/rust-lang/rust/pull/105354/) +- [Stabilize `extern "C-unwind"` and friends.](https://github.com/rust-lang/rust/pull/106075/) + The existing `extern "C"` etc. may change behavior for cross-language unwinding in a future release. +- [Update the version of musl used on `*-linux-musl` targets to 1.2.3](https://github.com/rust-lang/rust/pull/107129/), + enabling [time64](https://musl.libc.org/time64.html) on 32-bit systems. +- [Stabilize `debugger_visualizer`](https://github.com/rust-lang/rust/pull/108668/) + for embedding metadata like Microsoft's Natvis. +- [Enable flatten-format-args by default.](https://github.com/rust-lang/rust/pull/109999/) +- [Make `Self` respect tuple constructor privacy.](https://github.com/rust-lang/rust/pull/111245/) +- [Improve niche placement by trying two strategies and picking the better result.](https://github.com/rust-lang/rust/pull/108106/) +- [Use `apple-m1` as the target CPU for `aarch64-apple-darwin`.](https://github.com/rust-lang/rust/pull/109899/) +- [Add Tier 3 support for the `x86_64h-apple-darwin` target.](https://github.com/rust-lang/rust/pull/108795/) +- [Promote `loongarch64-unknown-linux-gnu` to Tier 2 with host tools.](https://github.com/rust-lang/rust/pull/110936/) + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + +<a id="1.71.0-Libraries"></a> + +Libraries +--------- +- [Rework handling of recursive panics.](https://github.com/rust-lang/rust/pull/110975/) + Additional panics are allowed while unwinding, as long as they are caught before escaping + a `Drop` implementation, but panicking within a panic hook is now an immediate abort. +- [Loosen `From<&[T]> for Box<[T]>` bound to `T: Clone`.](https://github.com/rust-lang/rust/pull/103406/) +- [Remove unnecessary `T: Send` bound](https://github.com/rust-lang/rust/pull/111134/) + in `Error for mpsc::SendError<T>` and `TrySendError<T>`. +- [Fix docs for `alloc::realloc`](https://github.com/rust-lang/rust/pull/108630/) + to match `Layout` requirements that the size must not exceed `isize::MAX`. +- [Document `const {}` syntax for `std::thread_local`.](https://github.com/rust-lang/rust/pull/110620/) + This syntax was stabilized in Rust 1.59, but not previously mentioned in release notes. + +<a id="1.71.0-Stabilized-APIs"></a> + +Stabilized APIs +--------------- + +- [`CStr::is_empty`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.is_empty) +- [`BuildHasher::hash_one`](https://doc.rust-lang.org/stable/std/hash/trait.BuildHasher.html#method.hash_one) +- [`NonZeroI*::is_positive`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html#method.is_positive) +- [`NonZeroI*::is_negative`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html#method.is_negative) +- [`NonZeroI*::checked_neg`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html#method.checked_neg) +- [`NonZeroI*::overflowing_neg`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html#method.overflowing_neg) +- [`NonZeroI*::saturating_neg`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html#method.saturating_neg) +- [`NonZeroI*::wrapping_neg`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html#method.wrapping_neg) +- [`Neg for NonZeroI*`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html#impl-Neg-for-NonZeroI32) +- [`Neg for &NonZeroI*`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI32.html#impl-Neg-for-%26NonZeroI32) +- [`From<[T; N]> for (T...)`](https://doc.rust-lang.org/stable/std/primitive.array.html#impl-From%3C%5BT;+1%5D%3E-for-(T,)) + (array to N-tuple for N in 1..=12) +- [`From<(T...)> for [T; N]`](https://doc.rust-lang.org/stable/std/primitive.array.html#impl-From%3C(T,)%3E-for-%5BT;+1%5D) + (N-tuple to array for N in 1..=12) +- [`windows::io::AsHandle for Box<T>`](https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsHandle.html#impl-AsHandle-for-Box%3CT%3E) +- [`windows::io::AsHandle for Rc<T>`](https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsHandle.html#impl-AsHandle-for-Rc%3CT%3E) +- [`windows::io::AsHandle for Arc<T>`](https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsHandle.html#impl-AsHandle-for-Arc%3CT%3E) +- [`windows::io::AsSocket for Box<T>`](https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsSocket.html#impl-AsSocket-for-Box%3CT%3E) +- [`windows::io::AsSocket for Rc<T>`](https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsSocket.html#impl-AsSocket-for-Rc%3CT%3E) +- [`windows::io::AsSocket for Arc<T>`](https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsSocket.html#impl-AsSocket-for-Arc%3CT%3E) + +These APIs are now stable in const contexts: + +- [`<*const T>::read`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.read) +- [`<*const T>::read_unaligned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.read_unaligned) +- [`<*mut T>::read`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.read-1) +- [`<*mut T>::read_unaligned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.read_unaligned-1) +- [`ptr::read`](https://doc.rust-lang.org/stable/std/ptr/fn.read.html) +- [`ptr::read_unaligned`](https://doc.rust-lang.org/stable/std/ptr/fn.read_unaligned.html) +- [`<[T]>::split_at`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_at) + +<a id="1.71.0-Cargo"></a> + +Cargo +----- +- [Allow named debuginfo options in `Cargo.toml`.](https://github.com/rust-lang/cargo/pull/11958/) +- [Add `workspace_default_members` to the output of `cargo metadata`.](https://github.com/rust-lang/cargo/pull/11978/) +- [`cargo add` now considers `rust-version` when selecting packages.](https://github.com/rust-lang/cargo/pull/12078/) +- [Automatically inherit workspace fields when running `cargo new`/`cargo init`.](https://github.com/rust-lang/cargo/pull/12069/) + +<a id="1.71.0-Rustdoc"></a> + +Rustdoc +------- + +- [Add a new `rustdoc::unescaped_backticks` lint for broken inline code.](https://github.com/rust-lang/rust/pull/105848/) +- [Support strikethrough with single tildes.](https://github.com/rust-lang/rust/pull/111152/) (`~~old~~` vs. `~new~`) + +<a id="1.71.0-Misc"></a> + +Misc +---- + +<a id="1.71.0-Compatibility-Notes"></a> + +Compatibility Notes +------------------- + +- [Remove structural match from `TypeId`.](https://github.com/rust-lang/rust/pull/103291/) + Code that uses a constant `TypeId` in a pattern will potentially be broken. + Known cases have already been fixed -- in particular, users of the `log` + crate's `kv_unstable` feature should update to `log v0.4.18` or later. +- [Add a `sysroot` crate to represent the standard library crates.](https://github.com/rust-lang/rust/pull/108865/) + This does not affect stable users, but may require adjustment in tools that build their own standard library. +- [Cargo optimizes its usage under `rustup`.](https://github.com/rust-lang/cargo/pull/11917/) When + Cargo detects it will run `rustc` pointing to a rustup proxy, it'll try bypassing the proxy and + use the underlying binary directly. There are assumptions around the interaction with rustup and + `RUSTUP_TOOLCHAIN`. However, it's not expected to affect normal users. +- [When querying a package, Cargo tries only the original name, all hyphens, and all underscores to + handle misspellings.](https://github.com/rust-lang/cargo/pull/12083/) Previously, Cargo tried each + combination of hyphens and underscores, causing excessive requests to crates.io. +- Cargo now [disallows `RUSTUP_HOME`](https://github.com/rust-lang/cargo/pull/12101/) and + [`RUSTUP_TOOLCHAIN`](https://github.com/rust-lang/cargo/pull/12107/) in the `[env]` configuration + table. This is considered to be not a use case Cargo would like to support, since it will likely + cause problems or lead to confusion. + +<a id="1.71.0-Internal-Changes"></a> + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + + Version 1.70.0 (2023-06-01) ========================== diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 73f9deb3143..f6875d895d3 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -134,7 +134,7 @@ pub trait LayoutCalculator { scalar_valid_range: (Bound<u128>, Bound<u128>), discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool), discriminants: impl Iterator<Item = (VariantIdx, i128)>, - niche_optimize_enum: bool, + dont_niche_optimize_enum: bool, always_sized: bool, ) -> Option<LayoutS> { let dl = self.current_data_layout(); @@ -183,10 +183,10 @@ pub trait LayoutCalculator { // (Typechecking will reject discriminant-sizing attrs.) let v = present_first; - let kind = if is_enum || variants[v].is_empty() { + let kind = if is_enum || variants[v].is_empty() || always_sized { StructKind::AlwaysSized } else { - if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized } + StructKind::MaybeUnsized }; let mut st = self.univariant(dl, &variants[v], repr, kind)?; @@ -280,7 +280,7 @@ pub trait LayoutCalculator { } let calculate_niche_filling_layout = || -> Option<TmpLayout> { - if niche_optimize_enum { + if dont_niche_optimize_enum { return None; } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index a398fd80119..a7198fbf887 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2652,6 +2652,15 @@ pub struct NormalAttr { pub tokens: Option<LazyAttrTokenStream>, } +impl NormalAttr { + pub fn from_ident(ident: Ident) -> Self { + Self { + item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None }, + tokens: None, + } + } +} + #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct AttrItem { pub path: Path, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index db296aa44db..ca4a739abd7 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -25,7 +25,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; -use std::{fmt, iter}; +use std::{fmt, iter, mem}; /// When the main Rust parser encounters a syntax-extension invocation, it /// parses the arguments to the invocation as a token tree. This is a very @@ -410,8 +410,17 @@ impl TokenStream { t1.next().is_none() && t2.next().is_none() } - pub fn map_enumerated<F: FnMut(usize, &TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream { - TokenStream(Lrc::new(self.0.iter().enumerate().map(|(i, tree)| f(i, tree)).collect())) + /// Applies the supplied function to each `TokenTree` and its index in `self`, returning a new `TokenStream` + /// + /// It is equivalent to `TokenStream::new(self.trees().cloned().enumerate().map(|(i, tt)| f(i, tt)).collect())`. + pub fn map_enumerated_owned( + mut self, + mut f: impl FnMut(usize, TokenTree) -> TokenTree, + ) -> TokenStream { + let owned = Lrc::make_mut(&mut self.0); // clone if necessary + // rely on vec's in-place optimizations to avoid another allocation + *owned = mem::take(owned).into_iter().enumerate().map(|(i, tree)| f(i, tree)).collect(); + self } /// Create a token stream containing a single token with alone spacing. diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 29972dd76eb..dcaaaafedbe 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -673,14 +673,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs( inner_hir_id, &[Attribute { - kind: AttrKind::Normal(ptr::P(NormalAttr { - item: AttrItem { - path: Path::from_ident(Ident::new(sym::track_caller, span)), - args: AttrArgs::Empty, - tokens: None, - }, - tokens: None, - })), + kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(sym::track_caller, span)))), id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(), style: AttrStyle::Outer, span: unstable_span, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 08ee3761bac..ab68436c093 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -3,6 +3,7 @@ use super::ResolverAstLoweringExt; use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{FnDeclKind, LoweringContext, ParamMode}; +use hir::definitions::DefPathData; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; @@ -257,10 +258,11 @@ impl<'hir> LoweringContext<'_, 'hir> { ); let itctx = ImplTraitContext::Universal; - let (generics, decl) = this.lower_generics(generics, id, &itctx, |this| { - let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id) - }); + let (generics, decl) = + this.lower_generics(generics, header.constness, id, &itctx, |this| { + let ret_id = asyncness.opt_return_id(); + this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id) + }); let sig = hir::FnSig { decl, header: this.lower_fn_header(*header), @@ -295,6 +297,7 @@ impl<'hir> LoweringContext<'_, 'hir> { add_ty_alias_where_clause(&mut generics, *where_clauses, true); let (generics, ty) = self.lower_generics( &generics, + Const::No, id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { @@ -316,6 +319,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::Enum(enum_definition, generics) => { let (generics, variants) = self.lower_generics( generics, + Const::No, id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -329,6 +333,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::Struct(struct_def, generics) => { let (generics, struct_def) = self.lower_generics( generics, + Const::No, id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), @@ -338,6 +343,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::Union(vdata, generics) => { let (generics, vdata) = self.lower_generics( generics, + Const::No, id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), @@ -369,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // parent lifetime. let itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, id, &itctx, |this| { + self.lower_generics(ast_generics, *constness, id, &itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( trait_ref, @@ -410,8 +416,15 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } ItemKind::Trait(box Trait { is_auto, unsafety, generics, bounds, items }) => { + // FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible + let constness = attrs + .unwrap_or(&[]) + .iter() + .find(|x| x.has_name(sym::const_trait)) + .map_or(Const::No, |x| Const::Yes(x.span)); let (generics, (unsafety, items, bounds)) = self.lower_generics( generics, + constness, id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -431,6 +444,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::TraitAlias(generics, bounds) => { let (generics, bounds) = self.lower_generics( generics, + Const::No, id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -593,7 +607,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, i.id, &itctx, |this| { + self.lower_generics(generics, Const::No, i.id, &itctx, |this| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl( @@ -745,6 +759,7 @@ impl<'hir> LoweringContext<'_, 'hir> { add_ty_alias_where_clause(&mut generics, *where_clauses, false); let (generics, kind) = self.lower_generics( &generics, + Const::No, i.id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { @@ -843,6 +858,7 @@ impl<'hir> LoweringContext<'_, 'hir> { add_ty_alias_where_clause(&mut generics, *where_clauses, false); self.lower_generics( &generics, + Const::No, i.id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { @@ -1201,9 +1217,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); let itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, id, &itctx, |this| { - this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async) - }); + let (generics, decl) = + self.lower_generics(generics, sig.header.constness, id, &itctx, |this| { + this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async) + }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } @@ -1275,6 +1292,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_generics<T>( &mut self, generics: &Generics, + constness: Const, parent_node_id: NodeId, itctx: &ImplTraitContext, f: impl FnOnce(&mut Self) -> T, @@ -1372,6 +1390,87 @@ impl<'hir> LoweringContext<'_, 'hir> { let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds); predicates.extend(impl_trait_bounds.into_iter()); + // Desugar `~const` bound in generics into an additional `const host: bool` param + // if the effects feature is enabled. + if let Const::Yes(span) = constness && self.tcx.features().effects + // Do not add host param if it already has it (manually specified) + && !params.iter().any(|x| { + self.attrs.get(&x.hir_id.local_id).map_or(false, |attrs| { + attrs.iter().any(|x| x.has_name(sym::rustc_host)) + }) + }) + { + let param_node_id = self.next_node_id(); + let const_node_id = self.next_node_id(); + let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span); + let anon_const: LocalDefId = self.create_def(def_id, const_node_id, DefPathData::AnonConst, span); + + let hir_id = self.next_id(); + let const_id = self.next_id(); + let const_expr_id = self.next_id(); + let bool_id = self.next_id(); + + self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); + self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id))); + + let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(); + + let attrs = self.arena.alloc_from_iter([ + Attribute { + kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))), + span, + id: attr_id, + style: AttrStyle::Outer, + }, + ]); + self.attrs.insert(hir_id.local_id, attrs); + + let const_body = self.lower_body(|this| { + ( + &[], + hir::Expr { + hir_id: const_expr_id, + kind: hir::ExprKind::Lit( + this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }), + ), + span, + }, + ) + }); + + let param = hir::GenericParam { + def_id, + hir_id, + name: hir::ParamName::Plain(Ident { name: sym::host, span }), + span, + kind: hir::GenericParamKind::Const { + ty: self.arena.alloc(self.ty( + span, + hir::TyKind::Path(hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + res: Res::PrimTy(hir::PrimTy::Bool), + span, + segments: self.arena.alloc_from_iter([hir::PathSegment { + ident: Ident { name: sym::bool, span }, + hir_id: bool_id, + res: Res::PrimTy(hir::PrimTy::Bool), + args: None, + infer_args: false, + }]), + }), + )), + )), + default: Some(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body }), + }, + colon_span: None, + pure_wrt_drop: false, + source: hir::GenericParamSource::Generics, + }; + + params.push(param); + } + let lowered_generics = self.arena.alloc(hir::Generics { params: self.arena.alloc_from_iter(params), predicates: self.arena.alloc_from_iter(predicates), diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 6c01fd63b1e..225c38efb2c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::{ Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; -use rustc_middle::ty::adjustment::PointerCast; +use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, RegionVid, TyCtxt}; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{sym, DesugaringKind, Span}; @@ -584,7 +584,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, // If we see an unsized cast, then if it is our data we should check // whether it is being cast to a trait object. - Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), operand, ty) => { + Rvalue::Cast( + CastKind::PointerCoercion(PointerCoercion::Unsize), + operand, + ty, + ) => { match operand { Operand::Copy(place) | Operand::Move(place) => { if let Some(from) = place.as_local() { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 42e50fd0fad..d292611e6a2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1050,7 +1050,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some(def_id) => type_known_to_meet_bound_modulo_regions( &self.infcx, self.param_env, - tcx.mk_imm_ref(tcx.lifetimes.re_erased, ty), + Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty), def_id, ), _ => false, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8ec872e2057..617c85174cb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -508,7 +508,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let generic_arg = substs[param_index as usize]; let identity_substs = InternalSubsts::identity_for_item(self.infcx.tcx, adt.did()); - let base_ty = self.infcx.tcx.mk_adt(*adt, identity_substs); + let base_ty = Ty::new_adt(self.infcx.tcx, *adt, identity_substs); let base_generic_arg = identity_substs[param_index as usize]; let adt_desc = adt.descr(); diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 2a0cb49672b..e45d3a2c882 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1139,7 +1139,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { _ => arg.fold_with(self), } }); - tcx.mk_opaque(def_id, tcx.mk_substs_from_iter(substs)) + Ty::new_opaque(tcx, def_id, tcx.mk_substs_from_iter(substs)) } } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4a872eb251c..1a227f2d110 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -158,7 +158,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) .emit() }); - prev.ty = infcx.tcx.ty_error(guar); + prev.ty = Ty::new_error(infcx.tcx, guar); } // Pick a better span if there is one. // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. @@ -248,13 +248,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { instantiated_ty: OpaqueHiddenType<'tcx>, ) -> Ty<'tcx> { if let Some(e) = self.tainted_by_errors() { - return self.tcx.ty_error(e); + return Ty::new_error(self.tcx, e); } if let Err(guar) = check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span) { - return self.tcx.ty_error(guar); + return Ty::new_error(self.tcx, guar); } let definition_ty = instantiated_ty @@ -271,7 +271,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { definition_ty, ) { Ok(hidden_ty) => hidden_ty, - Err(guar) => self.tcx.ty_error(guar), + Err(guar) => Ty::new_error(self.tcx, guar), } } } @@ -313,7 +313,7 @@ fn check_opaque_type_well_formed<'tcx>( // Require that the hidden type actually fulfills all the bounds of the opaque type, even without // the bounds that the function supplies. - let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), identity_substs); + let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_substs); ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty) .map_err(|err| { infcx diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index c8ec1257d37..f22851d76b3 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -245,7 +245,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { .and(type_op::normalize::Normalize::new(ty)) .fully_perform(self.infcx, span) .unwrap_or_else(|guar| TypeOpOutput { - output: self.infcx.tcx.ty_error(guar), + output: Ty::new_error(self.infcx.tcx, guar), constraints: None, error_info: None, }); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 23c3b7b7016..a15e1065c81 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -28,7 +28,7 @@ use rustc_middle::mir::AssertKind; use rustc_middle::mir::*; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::adjustment::PointerCast; +use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::{SubstsRef, UserSubsts}; use rustc_middle::ty::visit::TypeVisitableExt; @@ -237,7 +237,7 @@ pub(crate) fn type_check<'mir, 'tcx>( decl.hidden_type.span, format!("could not resolve {:#?}", hidden_type.ty.kind()), ); - hidden_type.ty = infcx.tcx.ty_error(reported); + hidden_type.ty = Ty::new_error(infcx.tcx, reported); } (opaque_type_key, hidden_type) @@ -520,7 +520,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { for elem in place.projection.iter() { if place_ty.variant_index.is_none() { if let Err(guar) = place_ty.ty.error_reported() { - return PlaceTy::from_ty(self.tcx().ty_error(guar)); + return PlaceTy::from_ty(Ty::new_error(self.tcx(), guar)); } } place_ty = self.sanitize_projection(place_ty, elem, place, location, context); @@ -656,7 +656,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { PlaceTy::from_ty(match base_ty.kind() { ty::Array(inner, _) => { assert!(!from_end, "array subslices should not use from_end"); - tcx.mk_array(*inner, to - from) + Ty::new_array(tcx, *inner, to - from) } ty::Slice(..) => { assert!(from_end, "slice subslices should use from_end"); @@ -749,7 +749,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } fn error(&mut self) -> Ty<'tcx> { - self.tcx().ty_error_misc() + Ty::new_misc_error(self.tcx()) } fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance { @@ -1908,7 +1908,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_operand(op, location); match cast_kind { - CastKind::Pointer(PointerCast::ReifyFnPointer) => { + CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => { let fn_sig = op.ty(body, tcx).fn_sig(tcx); // The type that we see in the fcx is like @@ -1918,7 +1918,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // and hence may contain unnormalized results. let fn_sig = self.normalize(fn_sig, location); - let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig); + let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig); if let Err(terr) = self.eq_types( *ty, @@ -1937,12 +1937,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => { + CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(unsafety)) => { let sig = match op.ty(body, tcx).kind() { ty::Closure(_, substs) => substs.as_closure().sig(), _ => bug!(), }; - let ty_fn_ptr_from = tcx.mk_fn_ptr(tcx.signature_unclosure(sig, *unsafety)); + let ty_fn_ptr_from = + Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *unsafety)); if let Err(terr) = self.eq_types( *ty, @@ -1961,7 +1962,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - CastKind::Pointer(PointerCast::UnsafeFnPointer) => { + CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => { let fn_sig = op.ty(body, tcx).fn_sig(tcx); // The type that we see in the fcx is like @@ -1990,7 +1991,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - CastKind::Pointer(PointerCast::Unsize) => { + CastKind::PointerCoercion(PointerCoercion::Unsize) => { let &ty = ty; let trait_ref = ty::TraitRef::from_lang_item( tcx, @@ -2037,7 +2038,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } - CastKind::Pointer(PointerCast::MutToConstPointer) => { + CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => { let ty::RawPtr(ty::TypeAndMut { ty: ty_from, mutbl: hir::Mutability::Mut, @@ -2079,7 +2080,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - CastKind::Pointer(PointerCast::ArrayToPointer) => { + CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => { let ty_from = op.ty(body, tcx); let opt_ty_elem_mut = match ty_from.kind() { diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index c871703429a..7821b82bf2b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -685,7 +685,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { assert_eq!(self.mir_def.to_def_id(), def_id); let resume_ty = substs.as_generator().resume_ty(); let output = substs.as_generator().return_ty(); - let generator_ty = tcx.mk_generator(def_id, substs, movability); + let generator_ty = Ty::new_generator(tcx, def_id, substs, movability); let inputs_and_output = self.infcx.tcx.mk_type_list(&[generator_ty, resume_ty, output]); ty::Binder::dummy(inputs_and_output) diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 84e09cf0abe..199fa6861cf 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -665,7 +665,8 @@ pub(crate) fn codegen_drop<'tcx>( let arg_value = drop_place.place_ref( fx, - fx.layout_of(fx.tcx.mk_ref( + fx.layout_of(Ty::new_ref( + fx.tcx, fx.tcx.lifetimes.re_erased, TypeAndMut { ty, mutbl: crate::rustc_hir::Mutability::Mut }, )), diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index ce10780f9de..334b2780b49 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -2,7 +2,7 @@ use rustc_ast::InlineAsmOptions; use rustc_index::IndexVec; -use rustc_middle::ty::adjustment::PointerCast; +use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -571,7 +571,7 @@ fn codegen_stmt<'tcx>( lval.write_cvalue(fx, res); } Rvalue::Cast( - CastKind::Pointer(PointerCast::ReifyFnPointer), + CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer), ref operand, to_ty, ) => { @@ -596,17 +596,17 @@ fn codegen_stmt<'tcx>( } } Rvalue::Cast( - CastKind::Pointer(PointerCast::UnsafeFnPointer), + CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer), ref operand, to_ty, ) | Rvalue::Cast( - CastKind::Pointer(PointerCast::MutToConstPointer), + CastKind::PointerCoercion(PointerCoercion::MutToConstPointer), ref operand, to_ty, ) | Rvalue::Cast( - CastKind::Pointer(PointerCast::ArrayToPointer), + CastKind::PointerCoercion(PointerCoercion::ArrayToPointer), ref operand, to_ty, ) => { @@ -662,7 +662,7 @@ fn codegen_stmt<'tcx>( } } Rvalue::Cast( - CastKind::Pointer(PointerCast::ClosureFnPointer(_)), + CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)), ref operand, _to_ty, ) => { @@ -684,7 +684,11 @@ fn codegen_stmt<'tcx>( _ => bug!("{} cannot be cast to a fn ptr", operand.layout().ty), } } - Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), ref operand, _to_ty) => { + Rvalue::Cast( + CastKind::PointerCoercion(PointerCoercion::Unsize), + ref operand, + _to_ty, + ) => { let operand = codegen_operand(fx, operand); crate::unsize::coerce_unsized_into(fx, operand, lval); } @@ -706,7 +710,6 @@ fn codegen_stmt<'tcx>( let times = fx .monomorphize(times) .eval(fx.tcx, ParamEnv::reveal_all()) - .kind() .try_to_bits(fx.tcx.data_layout.pointer_size) .unwrap(); if operand.layout().size.bytes() == 0 { @@ -747,7 +750,7 @@ fn codegen_stmt<'tcx>( } Rvalue::ShallowInitBox(ref operand, content_ty) => { let content_ty = fx.monomorphize(content_ty); - let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty)); + let box_layout = fx.layout_of(Ty::new_box(fx.tcx, content_ty)); let operand = codegen_operand(fx, operand); let operand = operand.load_scalar(fx); lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); @@ -888,7 +891,7 @@ pub(crate) fn codegen_place<'tcx>( let ptr = cplace.to_ptr(); cplace = CPlace::for_ptr( ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * (from as i64)), - fx.layout_of(fx.tcx.mk_array(*elem_ty, to - from)), + fx.layout_of(Ty::new_array(fx.tcx, *elem_ty, to - from)), ); } ty::Slice(elem_ty) => { diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs index 13568b198db..b2bc289a5b6 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs @@ -92,7 +92,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>( match bin_op { BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(), BinOp::Mul if is_signed => { - let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); + let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]); let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); let lhs = lhs.load_scalar(fx); let rhs = rhs.load_scalar(fx); @@ -112,7 +112,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>( Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty))) } BinOp::Add | BinOp::Sub | BinOp::Mul => { - let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); + let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); let param_types = vec![ AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index a694bb26afb..67ea20112fe 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -99,7 +99,7 @@ fn clif_pair_type_from_ty<'tcx>( /// Is a pointer to this type a fat ptr? pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - let ptr_ty = tcx.mk_ptr(TypeAndMut { ty, mutbl: rustc_hir::Mutability::Not }); + let ptr_ty = Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: rustc_hir::Mutability::Not }); match &tcx.layout_of(ParamEnv::reveal_all().and(ptr_ty)).unwrap().abi { Abi::Scalar(_) => false, Abi::ScalarPair(_, _) => true, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index bbd5f4be783..24ad0083a22 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -386,7 +386,7 @@ fn llvm_add_sub<'tcx>( // carry0 | carry1 -> carry or borrow respectively let cb_out = fx.bcx.ins().bor(cb0, cb1); - let layout = fx.layout_of(fx.tcx.mk_tup(&[fx.tcx.types.u8, fx.tcx.types.u64])); + let layout = fx.layout_of(Ty::new_tup(fx.tcx, &[fx.tcx.types.u8, fx.tcx.types.u64])); let val = CValue::by_val_pair(cb_out, c, layout); ret.write_cvalue(fx, val); } diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index ac1a6cce096..8992f40fb90 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -270,7 +270,7 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( _ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs), }; - let out_layout = fx.layout_of(fx.tcx.mk_tup(&[in_lhs.layout().ty, fx.tcx.types.bool])); + let out_layout = fx.layout_of(Ty::new_tup(fx.tcx, &[in_lhs.layout().ty, fx.tcx.types.bool])); CValue::by_val_pair(res, has_overflow, out_layout) } diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index ff0e12410e7..6aeba13f639 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -1,6 +1,6 @@ -//! Codegen of the [`PointerCast::Unsize`] operation. +//! Codegen of the [`PointerCoercion::Unsize`] operation. //! -//! [`PointerCast::Unsize`]: `rustc_middle::ty::adjustment::PointerCast::Unsize` +//! [`PointerCoercion::Unsize`]: `rustc_middle::ty::adjustment::PointerCoercion::Unsize` use crate::prelude::*; diff --git a/compiler/rustc_codegen_gcc/src/coverageinfo.rs b/compiler/rustc_codegen_gcc/src/coverageinfo.rs index 872fc2472e2..849e9886ef3 100644 --- a/compiler/rustc_codegen_gcc/src/coverageinfo.rs +++ b/compiler/rustc_codegen_gcc/src/coverageinfo.rs @@ -1,69 +1,11 @@ -use gccjit::RValue; -use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; -use rustc_hir::def_id::DefId; -use rustc_middle::mir::coverage::{ - CodeRegion, - CounterValueReference, - ExpressionOperandId, - InjectedExpressionId, - Op, -}; +use rustc_codegen_ssa::traits::CoverageInfoBuilderMethods; +use rustc_middle::mir::Coverage; use rustc_middle::ty::Instance; use crate::builder::Builder; -use crate::context::CodegenCx; impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn set_function_source_hash( - &mut self, - _instance: Instance<'tcx>, - _function_source_hash: u64, - ) -> bool { - unimplemented!(); - } - - fn add_coverage_counter(&mut self, _instance: Instance<'tcx>, _id: CounterValueReference, _region: CodeRegion) -> bool { - // TODO(antoyo) - false - } - - fn add_coverage_counter_expression(&mut self, _instance: Instance<'tcx>, _id: InjectedExpressionId, _lhs: ExpressionOperandId, _op: Op, _rhs: ExpressionOperandId, _region: Option<CodeRegion>) -> bool { - // TODO(antoyo) - false - } - - fn add_coverage_unreachable(&mut self, _instance: Instance<'tcx>, _region: CodeRegion) -> bool { + fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) { // TODO(antoyo) - false - } -} - -impl<'gcc, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { - fn coverageinfo_finalize(&self) { - // TODO(antoyo) - } - - fn get_pgo_func_name_var(&self, _instance: Instance<'tcx>) -> RValue<'gcc> { - unimplemented!(); - } - - /// Functions with MIR-based coverage are normally codegenned _only_ if - /// called. LLVM coverage tools typically expect every function to be - /// defined (even if unused), with at least one call to LLVM intrinsic - /// `instrprof.increment`. - /// - /// Codegen a small function that will never be called, with one counter - /// that will never be incremented. - /// - /// For used/called functions, the coverageinfo was already added to the - /// `function_coverage_map` (keyed by function `Instance`) during codegen. - /// But in this case, since the unused function was _not_ previously - /// codegenned, collect the coverage `CodeRegion`s from the MIR and add - /// them. The first `CodeRegion` is used to add a single counter, with the - /// same counter ID used in the injected `instrprof.increment` intrinsic - /// call. Since the function is never called, all other `CodeRegion`s can be - /// added as `unreachable_region`s. - fn define_unused_fn(&self, _def_id: DefId) { - unimplemented!(); } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index a31fee39918..0b208be4e62 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -1147,19 +1147,19 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut // Define the type up front for the signature of the rust_try function. let tcx = cx.tcx; - let i8p = tcx.mk_mut_ptr(tcx.types.i8); + let i8p = Ty::new_mut_ptr(tcx,tcx.types.i8); // `unsafe fn(*mut i8) -> ()` - let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( + let try_fn_ty = Ty::new_fn_ptr(tcx,ty::Binder::dummy(tcx.mk_fn_sig( iter::once(i8p), - tcx.mk_unit(), + Ty::new_unit(tcx,), false, rustc_hir::Unsafety::Unsafe, Abi::Rust, ))); // `unsafe fn(*mut i8, *mut i8) -> ()` - let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( + let catch_fn_ty = Ty::new_fn_ptr(tcx,ty::Binder::dummy(tcx.mk_fn_sig( [i8p, i8p].iter().cloned(), - tcx.mk_unit(), + Ty::new_unit(tcx,), false, rustc_hir::Unsafety::Unsafe, Abi::Rust, diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 74f016cf90a..e0823888f67 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -283,7 +283,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // only wide pointer boxes are handled as pointers // thin pointer boxes with scalar allocators are handled by the general logic below ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { - let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty()); + let ptr_ty = Ty::new_mut_ptr(cx.tcx,self.ty.boxed_ty()); return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate); } _ => {} diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 39ff3a0ba2d..ad51f2d0958 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -8,6 +8,7 @@ test = false [dependencies] bitflags = "1.0" +cstr = "0.2" libc = "0.2" measureme = "10.0.0" object = { version = "0.31.1", default-features = false, features = [ diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 28be6d033f8..d221bad28ef 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -351,7 +351,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { continue; } PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { - let ptr_ty = cx.tcx.mk_mut_ptr(arg.layout.ty); + let ptr_ty = Ty::new_mut_ptr(cx.tcx, arg.layout.ty); let ptr_layout = cx.layout_of(ptr_ty); llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true)); llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 1, true)); diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index ad0636894b7..a57508815d6 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -77,7 +77,7 @@ pub(crate) unsafe fn codegen( llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); - let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr().cast()); + let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); @@ -129,7 +129,7 @@ pub(crate) unsafe fn codegen( attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]); llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); - let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr().cast()); + let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 94885b40cc1..d7dd98d7938 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -601,7 +601,7 @@ pub(crate) fn run_pass_manager( llvm::LLVMRustAddModuleFlag( module.module_llvm.llmod(), llvm::LLVMModFlagBehavior::Error, - c"LTOPostLink".as_ptr().cast(), + "LTOPostLink\0".as_ptr().cast(), 1, ); } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 998e3b300da..0f5e975445f 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -931,16 +931,16 @@ unsafe fn embed_bitcode( let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - c"rustc.embedded.module".as_ptr().cast(), + "rustc.embedded.module\0".as_ptr().cast(), ); llvm::LLVMSetInitializer(llglobal, llconst); let section = if is_apple { - c"__LLVM,__bitcode" + "__LLVM,__bitcode\0" } else if is_aix { - c".ipa" + ".ipa\0" } else { - c".llvmbc" + ".llvmbc\0" }; llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); @@ -950,15 +950,15 @@ unsafe fn embed_bitcode( let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - c"rustc.embedded.cmdline".as_ptr().cast(), + "rustc.embedded.cmdline\0".as_ptr().cast(), ); llvm::LLVMSetInitializer(llglobal, llconst); let section = if is_apple { - c"__LLVM,__cmdline" + "__LLVM,__cmdline\0" } else if is_aix { - c".info" + ".info\0" } else { - c".llvmcmd" + ".llvmcmd\0" }; llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 2f7eb08ad3d..5b2bbdb4bde 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -19,6 +19,8 @@ use crate::context::CodegenCx; use crate::llvm; use crate::value::Value; +use cstr::cstr; + use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; @@ -108,11 +110,11 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen // Create the llvm.used and llvm.compiler.used variables. if !cx.used_statics.borrow().is_empty() { - cx.create_used_variable_impl(c"llvm.used", &*cx.used_statics.borrow()); + cx.create_used_variable_impl(cstr!("llvm.used"), &*cx.used_statics.borrow()); } if !cx.compiler_used_statics.borrow().is_empty() { cx.create_used_variable_impl( - c"llvm.compiler.used", + cstr!("llvm.compiler.used"), &*cx.compiler_used_statics.borrow(), ); } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 9863ca35202..d55992bf092 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -6,6 +6,7 @@ use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True} use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; +use cstr::cstr; use libc::{c_char, c_uint}; use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; @@ -25,6 +26,7 @@ use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange}; use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target}; use smallvec::SmallVec; use std::borrow::Cow; +use std::ffi::CStr; use std::iter; use std::ops::Deref; use std::ptr; @@ -44,10 +46,13 @@ impl Drop for Builder<'_, '_, '_> { } } +// FIXME(eddyb) use a checked constructor when they become `const fn`. +const EMPTY_C_STR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") }; + /// Empty string, to be used where LLVM expects an instruction name, indicating /// that the instruction is to be left unnamed (i.e. numbered, in textual IR). // FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer. -const UNNAMED: *const c_char = c"".as_ptr(); +const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr(); impl<'ll, 'tcx> BackendTypes for Builder<'_, 'll, 'tcx> { type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value; @@ -1002,13 +1007,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> { + let name = cstr!("cleanuppad"); let ret = unsafe { llvm::LLVMBuildCleanupPad( self.llbuilder, parent, args.as_ptr(), args.len() as c_uint, - c"cleanuppad".as_ptr(), + name.as_ptr(), ) }; Funclet::new(ret.expect("LLVM does not have support for cleanuppad")) @@ -1022,13 +1028,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> { + let name = cstr!("catchpad"); let ret = unsafe { llvm::LLVMBuildCatchPad( self.llbuilder, parent, args.as_ptr(), args.len() as c_uint, - c"catchpad".as_ptr(), + name.as_ptr(), ) }; Funclet::new(ret.expect("LLVM does not have support for catchpad")) @@ -1040,13 +1047,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unwind: Option<&'ll BasicBlock>, handlers: &[&'ll BasicBlock], ) -> &'ll Value { + let name = cstr!("catchswitch"); let ret = unsafe { llvm::LLVMBuildCatchSwitch( self.llbuilder, parent, unwind, handlers.len() as c_uint, - c"catchswitch".as_ptr(), + name.as_ptr(), ) }; let ret = ret.expect("LLVM does not have support for catchswitch"); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 2087754c66b..df52f50f86f 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -8,6 +8,7 @@ use crate::llvm::{self, True}; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; +use cstr::cstr; use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -481,9 +482,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { .all(|&byte| byte == 0); let sect_name = if all_bytes_are_zero { - c"__DATA,__thread_bss" + cstr!("__DATA,__thread_bss") } else { - c"__DATA,__thread_data" + cstr!("__DATA,__thread_data") }; llvm::LLVMSetSection(g, sect_name.as_ptr()); } @@ -512,7 +513,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { let val = llvm::LLVMMetadataAsValue(self.llcx, meta); llvm::LLVMAddNamedMetadataOperand( self.llmod, - c"wasm.custom_sections".as_ptr().cast(), + "wasm.custom_sections\0".as_ptr().cast(), val, ); } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 287a22bc9a6..e1e0a442845 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -8,6 +8,7 @@ use crate::llvm_util; use crate::type_::Type; use crate::value::Value; +use cstr::cstr; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; @@ -223,42 +224,36 @@ pub unsafe fn create_module<'ll>( // If skipping the PLT is enabled, we need to add some module metadata // to ensure intrinsic calls don't use it. if !sess.needs_plt() { - llvm::LLVMRustAddModuleFlag( - llmod, - llvm::LLVMModFlagBehavior::Warning, - c"RtLibUseGOT".as_ptr().cast(), - 1, - ); + let avoid_plt = "RtLibUseGOT\0".as_ptr().cast(); + llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1); } // Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.) if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() { + let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast(); llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Override, - c"CFI Canonical Jump Tables".as_ptr().cast(), + canonical_jump_tables, 1, ); } // Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.) if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() { + let enable_split_lto_unit = "EnableSplitLTOUnit\0".as_ptr().cast(); llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Override, - c"EnableSplitLTOUnit".as_ptr().cast(), + enable_split_lto_unit, 1, ); } // Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.) if sess.is_sanitizer_kcfi_enabled() { - llvm::LLVMRustAddModuleFlag( - llmod, - llvm::LLVMModFlagBehavior::Override, - c"kcfi".as_ptr().cast(), - 1, - ); + let kcfi = "kcfi\0".as_ptr().cast(); + llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1); } // Control Flow Guard is currently only supported by the MSVC linker on Windows. @@ -270,7 +265,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Warning, - c"cfguard".as_ptr() as *const _, + "cfguard\0".as_ptr() as *const _, 1, ) } @@ -279,7 +274,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Warning, - c"cfguard".as_ptr() as *const _, + "cfguard\0".as_ptr() as *const _, 2, ) } @@ -297,26 +292,26 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, behavior, - c"branch-target-enforcement".as_ptr().cast(), + "branch-target-enforcement\0".as_ptr().cast(), bti.into(), ); llvm::LLVMRustAddModuleFlag( llmod, behavior, - c"sign-return-address".as_ptr().cast(), + "sign-return-address\0".as_ptr().cast(), pac_ret.is_some().into(), ); let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); llvm::LLVMRustAddModuleFlag( llmod, behavior, - c"sign-return-address-all".as_ptr().cast(), + "sign-return-address-all\0".as_ptr().cast(), pac_opts.leaf.into(), ); llvm::LLVMRustAddModuleFlag( llmod, behavior, - c"sign-return-address-with-bkey".as_ptr().cast(), + "sign-return-address-with-bkey\0".as_ptr().cast(), u32::from(pac_opts.key == PAuthKey::B), ); } else { @@ -332,7 +327,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Override, - c"cf-protection-branch".as_ptr().cast(), + "cf-protection-branch\0".as_ptr().cast(), 1, ) } @@ -340,7 +335,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Override, - c"cf-protection-return".as_ptr().cast(), + "cf-protection-return\0".as_ptr().cast(), 1, ) } @@ -349,7 +344,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Error, - c"Virtual Function Elim".as_ptr().cast(), + "Virtual Function Elim\0".as_ptr().cast(), 1, ); } @@ -481,13 +476,14 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) { + let section = cstr!("llvm.metadata"); let array = self.const_array(self.type_ptr_to(self.type_i8()), values); unsafe { let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); llvm::LLVMSetInitializer(g, array); llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage); - llvm::LLVMSetSection(g, c"llvm.metadata".as_ptr()); + llvm::LLVMSetSection(g, section.as_ptr()); } } } diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 1791ce4b315..1791ce4b315 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index e4da3b8de05..06844afd6b8 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,6 +1,7 @@ pub use super::ffi::*; use rustc_index::{IndexSlice, IndexVec}; +use rustc_middle::bug; use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, InjectedExpressionIndex, MappedExpressionIndex, Op, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 21a1ac34844..a1ff2aa6625 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,10 +1,10 @@ use crate::common::CodegenCx; use crate::coverageinfo; +use crate::coverageinfo::map_data::{Counter, CounterExpression}; use crate::llvm; use llvm::coverageinfo::CounterMappingRegion; -use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression}; -use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods}; +use rustc_codegen_ssa::traits::ConstMethods; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index cd261293e9b..42fdbd78618 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -3,13 +3,13 @@ use crate::llvm; use crate::abi::Abi; use crate::builder::Builder; use crate::common::CodegenCx; +use crate::coverageinfo::map_data::{CounterExpression, FunctionCoverage}; use libc::c_uint; use llvm::coverageinfo::CounterMappingRegion; -use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, FunctionCoverage}; use rustc_codegen_ssa::traits::{ - BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, - MiscMethods, StaticMethods, + BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods, + StaticMethods, }; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; @@ -17,16 +17,20 @@ use rustc_hir::def_id::DefId; use rustc_llvm::RustString; use rustc_middle::bug; use rustc_middle::mir::coverage::{ - CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op, + CodeRegion, CounterValueReference, CoverageKind, ExpressionOperandId, InjectedExpressionId, Op, }; +use rustc_middle::mir::Coverage; use rustc_middle::ty; -use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Instance; +use rustc_middle::ty::Ty; use std::cell::RefCell; use std::ffi::CString; +mod ffi; +pub(crate) mod map_data; pub mod mapgen; const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START; @@ -53,11 +57,17 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { } } -impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { - fn coverageinfo_finalize(&self) { +// These methods used to be part of trait `CoverageInfoMethods`, which no longer +// exists after most coverage code was moved out of SSA. +impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { + pub(crate) fn coverageinfo_finalize(&self) { mapgen::finalize(self) } + /// For LLVM codegen, returns a function-specific `Value` for a global + /// string, to hold the function name passed to LLVM intrinsic + /// `instrprof.increment()`. The `Value` is only created once per instance. + /// Multiple invocations with the same instance return the same `Value`. fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value { if let Some(coverage_context) = self.coverage_context() { debug!("getting pgo_func_name_var for instance={:?}", instance); @@ -94,6 +104,54 @@ impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { } impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { + fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) { + let bx = self; + + let Coverage { kind, code_region } = coverage.clone(); + match kind { + CoverageKind::Counter { function_source_hash, id } => { + if bx.set_function_source_hash(instance, function_source_hash) { + // If `set_function_source_hash()` returned true, the coverage map is enabled, + // so continue adding the counter. + if let Some(code_region) = code_region { + // Note: Some counters do not have code regions, but may still be referenced + // from expressions. In that case, don't add the counter to the coverage map, + // but do inject the counter intrinsic. + bx.add_coverage_counter(instance, id, code_region); + } + + let coverageinfo = bx.tcx().coverageinfo(instance.def); + + let fn_name = bx.get_pgo_func_name_var(instance); + let hash = bx.const_u64(function_source_hash); + let num_counters = bx.const_u32(coverageinfo.num_counters); + let index = bx.const_u32(id.zero_based_index()); + debug!( + "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", + fn_name, hash, num_counters, index, + ); + bx.instrprof_increment(fn_name, hash, num_counters, index); + } + } + CoverageKind::Expression { id, lhs, op, rhs } => { + bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region); + } + CoverageKind::Unreachable => { + bx.add_coverage_unreachable( + instance, + code_region.expect("unreachable regions always have code regions"), + ); + } + } + } +} + +// These methods used to be part of trait `CoverageInfoBuilderMethods`, but +// after moving most coverage code out of SSA they are now just ordinary methods. +impl<'tcx> Builder<'_, '_, 'tcx> { + /// Returns true if the function source hash was added to the coverage map (even if it had + /// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is + /// not enabled (a coverage map is not being generated). fn set_function_source_hash( &mut self, instance: Instance<'tcx>, @@ -115,6 +173,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } + /// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage` + /// is not enabled (a coverage map is not being generated). fn add_coverage_counter( &mut self, instance: Instance<'tcx>, @@ -137,6 +197,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } + /// Returns true if the expression was added to the coverage map; false if + /// `-C instrument-coverage` is not enabled (a coverage map is not being generated). fn add_coverage_counter_expression( &mut self, instance: Instance<'tcx>, @@ -163,6 +225,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } + /// Returns true if the region was added to the coverage map; false if `-C instrument-coverage` + /// is not enabled (a coverage map is not being generated). fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool { if let Some(coverage_context) = self.coverage_context() { debug!( @@ -199,8 +263,8 @@ fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance< tcx.symbol_name(instance).name, cx.fn_abi_of_fn_ptr( ty::Binder::dummy(tcx.mk_fn_sig( - [tcx.mk_unit()], - tcx.mk_unit(), + [Ty::new_unit(tcx)], + Ty::new_unit(tcx), false, hir::Unsafety::Unsafe, Abi::Rust, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 8be54b7eb71..37f30917609 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -38,6 +38,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, ' unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr().cast()) }; section_var.unwrap_or_else(|| { + let section_name = b".debug_gdb_scripts\0"; let mut section_contents = Vec::new(); // Add the pretty printers for the standard library first. @@ -70,7 +71,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, ' let section_var = cx .define_global(section_var_name, llvm_type) .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name)); - llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr().cast()); + llvm::LLVMSetSection(section_var, section_name.as_ptr().cast()); llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 4b88ab8a97a..d61400d3fa3 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -20,6 +20,7 @@ use crate::llvm::debuginfo::{ }; use crate::value::Value; +use cstr::cstr; use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo; use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind; use rustc_codegen_ssa::traits::*; @@ -167,7 +168,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( // a (fat) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`. debug_assert_eq!( cx.size_and_align_of(ptr_type), - cx.size_and_align_of(cx.tcx.mk_mut_ptr(pointee_type)) + cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type)) ); let pointee_type_di_node = type_di_node(cx, pointee_type); @@ -222,8 +223,11 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( // at all and instead emit regular struct debuginfo for it. We just // need to make sure that we don't break existing debuginfo consumers // by doing that (at least not without a warning period). - let layout_type = - if ptr_type.is_box() { cx.tcx.mk_mut_ptr(pointee_type) } else { ptr_type }; + let layout_type = if ptr_type.is_box() { + Ty::new_mut_ptr(cx.tcx, pointee_type) + } else { + ptr_type + }; let layout = cx.layout_of(layout_type); let addr_field = layout.field(cx, abi::FAT_PTR_ADDR); @@ -811,6 +815,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped); + let flags = "\0"; let output_filenames = tcx.output_filenames(()); let split_name = if tcx.sess.target_can_use_split_dwarf() { output_filenames @@ -847,7 +852,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( producer.as_ptr().cast(), producer.len(), tcx.sess.opts.optimize != config::OptLevel::No, - c"".as_ptr().cast(), + flags.as_ptr().cast(), 0, // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead // put the path supplied to `MCSplitDwarfFile` into the debug info of the final @@ -876,7 +881,8 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( ); let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata); - llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, c"llvm.gcov".as_ptr(), val); + let llvm_gcov_ident = cstr!("llvm.gcov"); + llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), val); } // Insert `llvm.ident` metadata on the wasm targets since that will @@ -889,7 +895,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( ); llvm::LLVMAddNamedMetadataOperand( debug_context.llmod, - c"llvm.ident".as_ptr(), + cstr!("llvm.ident").as_ptr(), llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1), ); } @@ -1295,7 +1301,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>( // All function pointers are described as opaque pointers. This could be improved in the future // by describing them as actual function pointers. - let void_pointer_ty = tcx.mk_imm_ptr(tcx.types.unit); + let void_pointer_ty = Ty::new_imm_ptr(tcx, tcx.types.unit); let void_pointer_type_di_node = type_di_node(cx, void_pointer_ty); let usize_di_node = type_di_node(cx, tcx.types.usize); let (pointer_size, pointer_align) = cx.size_and_align_of(void_pointer_ty); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index c2f16cad3fc..b924c771af7 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -113,7 +113,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { llvm::LLVMRustAddModuleFlag( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"Dwarf Version".as_ptr().cast(), + "Dwarf Version\0".as_ptr().cast(), dwarf_version, ); } else { @@ -121,16 +121,17 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { llvm::LLVMRustAddModuleFlag( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"CodeView".as_ptr().cast(), + "CodeView\0".as_ptr().cast(), 1, ) } // Prevent bitcode readers from deleting the debug info. + let ptr = "Debug Info Version\0".as_ptr(); llvm::LLVMRustAddModuleFlag( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"Debug Info Version".as_ptr().cast(), + ptr.cast(), llvm::LLVMRustDebugMetadataVersion(), ); } @@ -453,7 +454,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { ty::Array(ct, _) if (*ct == cx.tcx.types.u8) || cx.layout_of(*ct).is_zst() => { - cx.tcx.mk_imm_ptr(*ct) + Ty::new_imm_ptr(cx.tcx, *ct) } _ => t, }; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index 6bcd3e5bf58..7be83638676 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -82,8 +82,8 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>( ty::Foreign(_) => { // Assert that pointers to foreign types really are thin: debug_assert_eq!( - cx.size_of(cx.tcx.mk_imm_ptr(pointee_tail_ty)), - cx.size_of(cx.tcx.mk_imm_ptr(cx.tcx.types.u8)) + cx.size_of(Ty::new_imm_ptr(cx.tcx, pointee_tail_ty)), + cx.size_of(Ty::new_imm_ptr(cx.tcx, cx.tcx.types.u8)) ); None } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 31bafa87814..a254c86c291 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -873,23 +873,29 @@ fn get_rust_try_fn<'ll, 'tcx>( // Define the type up front for the signature of the rust_try function. let tcx = cx.tcx; - let i8p = tcx.mk_mut_ptr(tcx.types.i8); + let i8p = Ty::new_mut_ptr(tcx, tcx.types.i8); // `unsafe fn(*mut i8) -> ()` - let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( - [i8p], - tcx.mk_unit(), - false, - hir::Unsafety::Unsafe, - Abi::Rust, - ))); + let try_fn_ty = Ty::new_fn_ptr( + tcx, + ty::Binder::dummy(tcx.mk_fn_sig( + [i8p], + Ty::new_unit(tcx), + false, + hir::Unsafety::Unsafe, + Abi::Rust, + )), + ); // `unsafe fn(*mut i8, *mut i8) -> ()` - let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( - [i8p, i8p], - tcx.mk_unit(), - false, - hir::Unsafety::Unsafe, - Abi::Rust, - ))); + let catch_fn_ty = Ty::new_fn_ptr( + tcx, + ty::Binder::dummy(tcx.mk_fn_sig( + [i8p, i8p], + Ty::new_unit(tcx), + false, + hir::Unsafety::Unsafe, + Abi::Rust, + )), + ); // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32` let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig( [try_fn_ty, i8p, catch_fn_ty], diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 24968e00cc8..24ba28bbc82 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -11,7 +11,6 @@ #![feature(let_chains)] #![feature(never_type)] #![feature(impl_trait_in_assoc_type)] -#![feature(c_str_literals)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index b667bc4f6d4..3ad546b61e9 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -use rustc_codegen_ssa::coverageinfo::map as coverage_map; +use crate::coverageinfo::map_data as coverage_map; use super::debuginfo::{ DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator, @@ -585,6 +585,16 @@ pub enum ThreadLocalMode { LocalExec, } +/// LLVMRustTailCallKind +#[derive(Copy, Clone)] +#[repr(C)] +pub enum TailCallKind { + None, + Tail, + MustTail, + NoTail, +} + /// LLVMRustChecksumKind #[derive(Copy, Clone)] #[repr(C)] @@ -1196,6 +1206,7 @@ extern "C" { NameLen: size_t, ) -> Option<&Value>; pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool); + pub fn LLVMRustSetTailCallKind(CallInst: &Value, TKC: TailCallKind); // Operations on attributes pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 3339e4e07ed..58e97be34f2 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -337,12 +337,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { // only wide pointer boxes are handled as pointers // thin pointer boxes with scalar allocators are handled by the general logic below ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { - let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty()); + let ptr_ty = Ty::new_mut_ptr(cx.tcx, self.ty.boxed_ty()); return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate); } // `dyn* Trait` has the same ABI as `*mut dyn Trait` ty::Dynamic(bounds, region, ty::DynStar) => { - let ptr_ty = cx.tcx.mk_mut_ptr(cx.tcx.mk_dynamic(bounds, region, ty::Dyn)); + let ptr_ty = + Ty::new_mut_ptr(cx.tcx, Ty::new_dynamic(cx.tcx, bounds, region, ty::Dyn)); return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate); } _ => {} diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index b19398e68c2..8800caa71d6 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -73,7 +73,7 @@ fn emit_ptr_va_arg<'ll, 'tcx>( let layout = bx.cx.layout_of(target_ty); let (llty, size, align) = if indirect { ( - bx.cx.layout_of(bx.cx.tcx.mk_imm_ptr(target_ty)).llvm_type(bx.cx), + bx.cx.layout_of(Ty::new_imm_ptr(bx.cx.tcx, target_ty)).llvm_type(bx.cx), bx.cx.data_layout().pointer_size, bx.cx.data_layout().pointer_align, ) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f8ced6949d5..9133601ecd1 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -199,7 +199,7 @@ fn vtable_ptr_ty<'tcx, Cx: CodegenMethods<'tcx>>( cx.scalar_pair_element_backend_type( cx.layout_of(match kind { // vtable is the second field of `*mut dyn Trait` - ty::Dyn => cx.tcx().mk_mut_ptr(target), + ty::Dyn => Ty::new_mut_ptr(cx.tcx(), target), // vtable is the second field of `dyn* Trait` ty::DynStar => target, }), diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/mod.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/mod.rs deleted file mode 100644 index 569fd3f1a51..00000000000 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod ffi; -pub mod map; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index c26a7422fdd..be4c81638d6 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -48,7 +48,6 @@ pub mod back; pub mod base; pub mod codegen_attrs; pub mod common; -pub mod coverageinfo; pub mod debuginfo; pub mod errors; pub mod glue; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 93bed3a4a4a..9d1b3ce8266 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1505,9 +1505,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some(slot) = self.personality_slot { slot } else { - let layout = cx.layout_of( - cx.tcx().mk_tup(&[cx.tcx().mk_mut_ptr(cx.tcx().types.u8), cx.tcx().types.i32]), - ); + let layout = cx.layout_of(Ty::new_tup( + cx.tcx(), + &[Ty::new_mut_ptr(cx.tcx(), cx.tcx().types.u8), cx.tcx().types.i32], + )); let slot = PlaceRef::alloca(bx, layout); self.personality_slot = Some(slot); slot diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index f1fe495282a..ee70465966d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -1,13 +1,12 @@ use crate::traits::*; -use rustc_middle::mir::coverage::*; use rustc_middle::mir::Coverage; use rustc_middle::mir::SourceScope; use super::FunctionCx; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) { + pub fn codegen_coverage(&self, bx: &mut Bx, coverage: &Coverage, scope: SourceScope) { // Determine the instance that coverage data was originally generated for. let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) { self.monomorphize(inlined) @@ -15,41 +14,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.instance }; - let Coverage { kind, code_region } = coverage; - match kind { - CoverageKind::Counter { function_source_hash, id } => { - if bx.set_function_source_hash(instance, function_source_hash) { - // If `set_function_source_hash()` returned true, the coverage map is enabled, - // so continue adding the counter. - if let Some(code_region) = code_region { - // Note: Some counters do not have code regions, but may still be referenced - // from expressions. In that case, don't add the counter to the coverage map, - // but do inject the counter intrinsic. - bx.add_coverage_counter(instance, id, code_region); - } - - let coverageinfo = bx.tcx().coverageinfo(instance.def); - - let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_source_hash); - let num_counters = bx.const_u32(coverageinfo.num_counters); - let index = bx.const_u32(id.zero_based_index()); - debug!( - "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", - fn_name, hash, num_counters, index, - ); - bx.instrprof_increment(fn_name, hash, num_counters, index); - } - } - CoverageKind::Expression { id, lhs, op, rhs } => { - bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region); - } - CoverageKind::Unreachable => { - bx.add_coverage_unreachable( - instance, - code_region.expect("unreachable regions always have code regions"), - ); - } - } + // Handle the coverage info in a backend-specific way. + bx.add_coverage(instance, coverage); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index c6589a40392..4b27b64962d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -5,6 +5,7 @@ use rustc_middle::mir; use rustc_middle::ty; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; +use rustc_middle::ty::Ty; use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; @@ -327,8 +328,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let local_ref = &self.locals[local]; - // FIXME Should the return place be named? - let name = if bx.sess().fewer_names() || local == mir::RETURN_PLACE { + let name = if bx.sess().fewer_names() { None } else { Some(match whole_local_var.or(fallback_var.clone()) { @@ -421,9 +421,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| { // Create a variable which will be a pointer to the actual value - let ptr_ty = bx - .tcx() - .mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty }); + let ptr_ty = Ty::new_ptr( + bx.tcx(), + ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty }, + ); let ptr_layout = bx.layout_of(ptr_ty); let alloca = PlaceRef::alloca(bx, ptr_layout); bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount)); @@ -525,8 +526,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; for _ in 0..var.references { - var_ty = - bx.tcx().mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty }); + var_ty = Ty::new_ptr( + bx.tcx(), + ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty }, + ); } self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span) diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index a58a61cd567..ab493ae5c1f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { layout: TyAndLayout<'tcx>, ) -> Self { assert!(layout.is_unsized(), "tried to allocate indirect place for sized values"); - let ptr_ty = bx.cx().tcx().mk_mut_ptr(layout.ty); + let ptr_ty = Ty::new_mut_ptr(bx.cx().tcx(), layout.ty); let ptr_layout = bx.cx().layout_of(ptr_ty); Self::alloca(bx, ptr_layout) } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 2d3d0ec68b8..956f03d2578 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -11,7 +11,7 @@ use rustc_middle::mir; use rustc_middle::mir::Operand; use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; +use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, Ty, TyCtxt}; use rustc_session::config::OptLevel; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_target::abi::{self, FIRST_VARIANT}; @@ -32,7 +32,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_operand.val.store(bx, dest); } - mir::Rvalue::Cast(mir::CastKind::Pointer(PointerCast::Unsize), ref source, _) => { + mir::Rvalue::Cast( + mir::CastKind::PointerCoercion(PointerCoercion::Unsize), + ref source, + _, + ) => { // The destination necessarily contains a fat pointer, so if // it's a scalar pair, it's a fat pointer or newtype thereof. if bx.cx().is_backend_scalar_pair(dest.layout) { @@ -411,7 +415,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let lladdr = bx.ptrtoint(llptr, llcast_ty); OperandValue::Immediate(lladdr) } - mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => { + mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => { match *operand.layout.ty.kind() { ty::FnDef(def_id, substs) => { let instance = ty::Instance::resolve_for_fn_ptr( @@ -427,7 +431,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty), } } - mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)) => { + mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => { match *operand.layout.ty.kind() { ty::Closure(def_id, substs) => { let instance = Instance::resolve_closure( @@ -443,11 +447,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty), } } - mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => { + mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => { // This is a no-op at the LLVM level. operand.val } - mir::CastKind::Pointer(PointerCast::Unsize) => { + mir::CastKind::PointerCoercion(PointerCoercion::Unsize) => { assert!(bx.cx().is_backend_scalar_pair(cast)); let (lldata, llextra) = match operand.val { OperandValue::Pair(lldata, llextra) => { @@ -470,7 +474,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { base::unsize_ptr(bx, lldata, operand.layout.ty, cast.ty, llextra); OperandValue::Pair(lldata, llextra) } - mir::CastKind::Pointer(PointerCast::MutToConstPointer) + mir::CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) | mir::CastKind::PtrToPtr if bx.cx().is_backend_scalar_pair(operand.layout) => { @@ -504,8 +508,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra); OperandValue::Pair(lldata, llextra) } - mir::CastKind::Pointer( - PointerCast::MutToConstPointer | PointerCast::ArrayToPointer, + mir::CastKind::PointerCoercion( + PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, ) | mir::CastKind::IntToInt | mir::CastKind::FloatToInt @@ -581,7 +585,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Ref(_, bk, place) => { let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| { - tcx.mk_ref( + Ty::new_ref( + tcx, tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }, ) @@ -592,7 +597,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::CopyForDeref(place) => self.codegen_operand(bx, &Operand::Copy(place)), mir::Rvalue::AddressOf(mutability, place) => { let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| { - tcx.mk_ptr(ty::TypeAndMut { ty, mutbl: mutability }) + Ty::new_ptr(tcx, ty::TypeAndMut { ty, mutbl: mutability }) }; self.codegen_place_to_pointer(bx, place, mk_ptr) } @@ -644,7 +649,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { lhs.layout.ty, ); let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty); - let operand_ty = bx.tcx().mk_tup(&[val_ty, bx.tcx().types.bool]); + let operand_ty = Ty::new_tup(bx.tcx(), &[val_ty, bx.tcx().types.bool]); OperandRef { val: result, layout: bx.cx().layout_of(operand_ty) } } @@ -734,7 +739,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let lloperand = operand.immediate(); let content_ty = self.monomorphize(content_ty); - let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty)); + let box_layout = bx.cx().layout_of(Ty::new_box(bx.tcx(), content_ty)); let llty_ptr = bx.cx().backend_type(box_layout); let val = bx.pointercast(lloperand, llty_ptr); diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 314d364c0c2..899e41265bb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -65,7 +65,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } mir::StatementKind::Coverage(box ref coverage) => { - self.codegen_coverage(bx, coverage.clone(), statement.source_info.scope); + self.codegen_coverage(bx, coverage, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { let op_val = self.codegen_operand(bx, op); diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index e77201cf0c8..7e8de0ddc5b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -1,57 +1,11 @@ use super::BackendTypes; -use rustc_hir::def_id::DefId; -use rustc_middle::mir::coverage::*; +use rustc_middle::mir::Coverage; use rustc_middle::ty::Instance; -pub trait CoverageInfoMethods<'tcx>: BackendTypes { - fn coverageinfo_finalize(&self); - - /// Codegen a small function that will never be called, with one counter - /// that will never be incremented, that gives LLVM coverage tools a - /// function definition it needs in order to resolve coverage map references - /// to unused functions. This is necessary so unused functions will appear - /// as uncovered (coverage execution count `0`) in LLVM coverage reports. - fn define_unused_fn(&self, def_id: DefId); - - /// For LLVM codegen, returns a function-specific `Value` for a global - /// string, to hold the function name passed to LLVM intrinsic - /// `instrprof.increment()`. The `Value` is only created once per instance. - /// Multiple invocations with the same instance return the same `Value`. - fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; -} - pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { - /// Returns true if the function source hash was added to the coverage map (even if it had - /// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is - /// not enabled (a coverage map is not being generated). - fn set_function_source_hash( - &mut self, - instance: Instance<'tcx>, - function_source_hash: u64, - ) -> bool; - - /// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage` - /// is not enabled (a coverage map is not being generated). - fn add_coverage_counter( - &mut self, - instance: Instance<'tcx>, - index: CounterValueReference, - region: CodeRegion, - ) -> bool; - - /// Returns true if the expression was added to the coverage map; false if - /// `-C instrument-coverage` is not enabled (a coverage map is not being generated). - fn add_coverage_counter_expression( - &mut self, - instance: Instance<'tcx>, - id: InjectedExpressionId, - lhs: ExpressionOperandId, - op: Op, - rhs: ExpressionOperandId, - region: Option<CodeRegion>, - ) -> bool; - - /// Returns true if the region was added to the coverage map; false if `-C instrument-coverage` - /// is not enabled (a coverage map is not being generated). - fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool; + /// Handle the MIR coverage info in a backend-specific way. + /// + /// This can potentially be a no-op in backends that don't support + /// coverage instrumentation. + fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage); } diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index 782fdadbfb8..8cb58bd4c70 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -33,7 +33,7 @@ pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAs pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods}; pub use self::builder::{BuilderMethods, OverflowOp}; pub use self::consts::ConstMethods; -pub use self::coverageinfo::{CoverageInfoBuilderMethods, CoverageInfoMethods}; +pub use self::coverageinfo::CoverageInfoBuilderMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; pub use self::declare::PreDefineMethods; pub use self::intrinsic::IntrinsicCallMethods; @@ -59,7 +59,6 @@ pub trait CodegenMethods<'tcx>: + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods<'tcx> + PreDefineMethods<'tcx> @@ -75,7 +74,6 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods<'tcx> + PreDefineMethods<'tcx> diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 5cc1fa2a497..a3064b53db1 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -1,12 +1,10 @@ // Not in interpret to make sure we do not use private implementation details use crate::errors::MaxNumNodesInConstErr; -use crate::interpret::{ - intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, Scalar, -}; +use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, Scalar}; use rustc_middle::mir; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{source_map::DUMMY_SP, symbol::Symbol}; mod error; @@ -87,23 +85,24 @@ pub(crate) fn eval_to_valtree<'tcx>( } #[instrument(skip(tcx), level = "debug")] -pub(crate) fn try_destructure_mir_constant<'tcx>( +pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - val: mir::ConstantKind<'tcx>, -) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> { + val: ConstValue<'tcx>, + ty: Ty<'tcx>, +) -> Option<mir::DestructuredConstant<'tcx>> { + let param_env = ty::ParamEnv::reveal_all(); let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); - let op = ecx.eval_mir_constant(&val, None, None)?; + let op = ecx.const_val_to_op(val, ty, None).ok()?; // We go to `usize` as we cannot allocate anything bigger anyway. - let (field_count, variant, down) = match val.ty().kind() { + let (field_count, variant, down) = match ty.kind() { ty::Array(_, len) => (len.eval_target_usize(tcx, param_env) as usize, None, op), ty::Adt(def, _) if def.variants().is_empty() => { - throw_ub!(Unreachable) + return None; } ty::Adt(def, _) => { - let variant = ecx.read_discriminant(&op)?.1; - let down = ecx.operand_downcast(&op, variant)?; + let variant = ecx.read_discriminant(&op).ok()?.1; + let down = ecx.operand_downcast(&op, variant).ok()?; (def.variants()[variant].fields.len(), Some(variant), down) } ty::Tuple(substs) => (substs.len(), None, op), @@ -112,12 +111,12 @@ pub(crate) fn try_destructure_mir_constant<'tcx>( let fields_iter = (0..field_count) .map(|i| { - let field_op = ecx.operand_field(&down, i)?; + let field_op = ecx.operand_field(&down, i).ok()?; let val = op_to_const(&ecx, &field_op); - Ok(mir::ConstantKind::Val(val, field_op.layout.ty)) + Some((val, field_op.layout.ty)) }) - .collect::<InterpResult<'tcx, Vec<_>>>()?; + .collect::<Option<Vec<_>>>()?; let fields = tcx.arena.alloc_from_iter(fields_iter); - Ok(mir::DestructuredConstant { variant, fields }) + Some(mir::DestructuredConstant { variant, fields }) } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index b4db3dff3ff..83a072d6f8b 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -4,7 +4,7 @@ use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::mir::CastKind; -use rustc_middle::ty::adjustment::PointerCast; +use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut}; use rustc_target::abi::Integer; @@ -24,51 +24,52 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { cast_ty: Ty<'tcx>, dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - use rustc_middle::mir::CastKind::*; // FIXME: In which cases should we trigger UB when the source is uninit? match cast_kind { - Pointer(PointerCast::Unsize) => { + CastKind::PointerCoercion(PointerCoercion::Unsize) => { let cast_ty = self.layout_of(cast_ty)?; self.unsize_into(src, cast_ty, dest)?; } - PointerExposeAddress => { + CastKind::PointerExposeAddress => { let src = self.read_immediate(src)?; let res = self.pointer_expose_address_cast(&src, cast_ty)?; self.write_immediate(res, dest)?; } - PointerFromExposedAddress => { + CastKind::PointerFromExposedAddress => { let src = self.read_immediate(src)?; let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?; self.write_immediate(res, dest)?; } - IntToInt | IntToFloat => { + CastKind::IntToInt | CastKind::IntToFloat => { let src = self.read_immediate(src)?; let res = self.int_to_int_or_float(&src, cast_ty)?; self.write_immediate(res, dest)?; } - FloatToFloat | FloatToInt => { + CastKind::FloatToFloat | CastKind::FloatToInt => { let src = self.read_immediate(src)?; let res = self.float_to_float_or_int(&src, cast_ty)?; self.write_immediate(res, dest)?; } - FnPtrToPtr | PtrToPtr => { + CastKind::FnPtrToPtr | CastKind::PtrToPtr => { let src = self.read_immediate(&src)?; let res = self.ptr_to_ptr(&src, cast_ty)?; self.write_immediate(res, dest)?; } - Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer) => { + CastKind::PointerCoercion( + PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, + ) => { // These are NOPs, but can be wide pointers. let v = self.read_immediate(src)?; self.write_immediate(*v, dest)?; } - Pointer(PointerCast::ReifyFnPointer) => { + CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => { // All reifications must be monomorphic, bail out otherwise. ensure_monomorphic_enough(*self.tcx, src.layout.ty)?; @@ -90,7 +91,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - Pointer(PointerCast::UnsafeFnPointer) => { + CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => { let src = self.read_immediate(src)?; match cast_ty.kind() { ty::FnPtr(_) => { @@ -101,7 +102,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - Pointer(PointerCast::ClosureFnPointer(_)) => { + CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => { // All reifications must be monomorphic, bail out otherwise. ensure_monomorphic_enough(*self.tcx, src.layout.ty)?; @@ -122,7 +123,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - DynStar => { + CastKind::DynStar => { if let ty::Dynamic(data, _, ty::DynStar) = cast_ty.kind() { // Initial cast from sized to dyn trait let vtable = self.get_vtable_ptr(src.layout.ty, data.principal())?; @@ -136,7 +137,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - Transmute => { + CastKind::Transmute => { assert!(src.layout.is_sized()); assert!(dest.layout.is_sized()); if src.layout.size != dest.layout.size { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 4f10e4837ce..ed64a7655b5 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -170,7 +170,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::pref_align_of | sym::variant_count => self.tcx.types.usize, sym::needs_drop => self.tcx.types.bool, sym::type_id => self.tcx.types.u128, - sym::type_name => self.tcx.mk_static_str(), + sym::type_name => Ty::new_static_str(self.tcx.tcx), _ => bug!(), }; let val = self.ctfe_query(None, |tcx| { diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index e30af165501..5f89d652fab 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -106,7 +106,7 @@ impl<Prov: Provenance> std::fmt::Display for ImmTy<'_, Prov> { // Just print the ptr value. `pretty_print_const_scalar_ptr` would also try to // print what is points to, which would fail since it has no access to the local // memory. - cx.pretty_print_const_pointer(ptr, ty, true) + cx.pretty_print_const_pointer(ptr, ty) } } } @@ -633,7 +633,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - pub(super) fn const_val_to_op( + pub(crate) fn const_val_to_op( &self, val_val: ConstValue<'tcx>, ty: Ty<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 7bca7efdf5a..e04764636cc 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -22,7 +22,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx> { let (val, overflowed, ty) = self.overflowing_binary_op(op, &left, &right)?; debug_assert_eq!( - self.tcx.mk_tup(&[ty, self.tcx.types.bool]), + Ty::new_tup(self.tcx.tcx, &[ty, self.tcx.types.bool]), dest.layout.ty, "type mismatch for result of {:?}", op, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 2a31a59ad6c..ca1106384fd 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -9,6 +9,7 @@ use rustc_index::IndexSlice; use rustc_middle::mir; use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::Ty; use rustc_target::abi::{self, Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_VARIANT}; use super::{ @@ -395,7 +396,7 @@ where // (Transmuting is okay since this is an in-memory place. We also double-check the size // stays the same.) let (len, e_ty) = mplace.layout.ty.simd_size_and_type(*self.tcx); - let array = self.tcx.mk_array(e_ty, len); + let array = Ty::new_array(self.tcx.tcx, e_ty, len); let layout = self.layout_of(array)?; assert_eq!(layout.size, mplace.layout.size); Ok((MPlaceTy { layout, ..*mplace }, len)) @@ -699,8 +700,13 @@ where assert_eq!(src.layout.size, dest.layout.size); } + // Setting `nonoverlapping` here only has an effect when we don't hit the fast-path above, + // but that should at least match what LLVM does where `memcpy` is also only used when the + // type does not have Scalar/ScalarPair layout. + // (Or as the `Assign` docs put it, assignments "not producing primitives" must be + // non-overlapping.) self.mem_copy( - src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ false, + src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ true, ) } @@ -775,7 +781,8 @@ where let meta = Scalar::from_target_usize(u64::try_from(str.len()).unwrap(), self); let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) }; - let ty = self.tcx.mk_ref( + let ty = Ty::new_ref( + self.tcx.tcx, self.tcx.lifetimes.re_static, ty::TypeAndMut { ty: self.tcx.types.str_, mutbl }, ); diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 91da930db4f..d7d31fe1887 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -12,6 +12,7 @@ use either::{Left, Right}; use rustc_middle::mir; use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::Ty; use rustc_target::abi::{self, Abi, VariantIdx}; use super::{ @@ -317,7 +318,9 @@ where let (meta, ty) = match base.layout.ty.kind() { // It is not nice to match on the type, but that seems to be the only way to // implement this. - ty::Array(inner, _) => (MemPlaceMeta::None, self.tcx.mk_array(*inner, inner_len)), + ty::Array(inner, _) => { + (MemPlaceMeta::None, Ty::new_array(self.tcx.tcx, *inner, inner_len)) + } ty::Slice(..) => { let len = Scalar::from_target_usize(inner_len, self); (MemPlaceMeta::Meta(len), base.layout.ty) diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 719d8a14b41..15823a5975e 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -650,7 +650,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Adjust receiver argument. Layout can be any (thin) ptr. args[0] = ImmTy::from_immediate( Scalar::from_maybe_pointer(adjusted_receiver, self).into(), - self.layout_of(self.tcx.mk_mut_ptr(dyn_ty))?, + self.layout_of(Ty::new_mut_ptr(self.tcx.tcx, dyn_ty))?, ) .into(); trace!("Patched receiver operand to {:#?}", args[0]); @@ -703,7 +703,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let arg = ImmTy::from_immediate( place.to_ref(self), - self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?, + self.layout_of(Ty::new_mut_ptr(self.tcx.tcx, place.layout.ty))?, ); let ret = MPlaceTy::fake_alloc_zst(self.layout_of(self.tcx.types.unit)?); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 8314f53ba57..c126f749bf3 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -52,10 +52,8 @@ pub fn provide(providers: &mut Providers) { let (param_env, raw) = param_env_and_value.into_parts(); const_eval::eval_to_valtree(tcx, param_env, raw) }; - providers.try_destructure_mir_constant = |tcx, param_env_and_value| { - let (param_env, value) = param_env_and_value.into_parts(); - const_eval::try_destructure_mir_constant(tcx, param_env, value).ok() - }; + providers.try_destructure_mir_constant_for_diagnostics = + |tcx, (cv, ty)| const_eval::try_destructure_mir_constant_for_diagnostics(tcx, cv, ty); providers.valtree_to_const_val = |tcx, (ty, valtree)| { const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree) }; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 28cf9daf1c1..14540e8dfe7 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -9,8 +9,8 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; -use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt}; -use rustc_middle::ty::{Binder, TraitRef, TypeVisitableExt}; +use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt}; +use rustc_middle::ty::{TraitRef, TypeVisitableExt}; use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; @@ -521,12 +521,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } Rvalue::Cast( - CastKind::Pointer( - PointerCast::MutToConstPointer - | PointerCast::ArrayToPointer - | PointerCast::UnsafeFnPointer - | PointerCast::ClosureFnPointer(_) - | PointerCast::ReifyFnPointer, + CastKind::PointerCoercion( + PointerCoercion::MutToConstPointer + | PointerCoercion::ArrayToPointer + | PointerCoercion::UnsafeFnPointer + | PointerCoercion::ClosureFnPointer(_) + | PointerCoercion::ReifyFnPointer, ), _, _, @@ -534,7 +534,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // These are all okay; they only change the type, not the data. } - Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => { + Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), _, _) => { // Unsizing is implemented for CTFE. } @@ -755,10 +755,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } let trait_ref = TraitRef::from_method(tcx, trait_id, substs); - let poly_trait_pred = - Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst); + let trait_ref = trait_ref.with_constness(ty::BoundConstness::ConstIfConst); let obligation = - Obligation::new(tcx, ObligationCause::dummy(), param_env, poly_trait_pred); + Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); let implsrc = { let infcx = tcx.infer_ctxt().build(); @@ -776,11 +775,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } // Closure: Fn{Once|Mut} Ok(Some(ImplSource::Builtin(_))) - if poly_trait_pred.self_ty().skip_binder().is_closure() + if trait_ref.self_ty().is_closure() && tcx.fn_trait_kind_from_def_id(trait_id).is_some() => { let ty::Closure(closure_def_id, substs) = - *poly_trait_pred.self_ty().no_bound_vars().unwrap().kind() + *trait_ref.self_ty().kind() else { unreachable!() }; @@ -840,7 +839,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { tcx, ObligationCause::dummy_with_span(*fn_span), param_env, - poly_trait_pred, + trait_ref, ); // improve diagnostics by showing what failed. Our requirements are stricter this time diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 32bd9cda6f2..4eb278252c1 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -10,8 +10,8 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir::{self, CallSource}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::ty::TraitRef; use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty}; -use rustc_middle::ty::{Binder, TraitRef}; use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; @@ -137,12 +137,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { } } Adt(..) => { - let obligation = Obligation::new( - tcx, - ObligationCause::dummy(), - param_env, - Binder::dummy(trait_ref), - ); + let obligation = + Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); let infcx = tcx.infer_ctxt().build(); let mut selcx = SelectionContext::new(&infcx); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 36c76e53231..015a4aa94cd 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -223,7 +223,7 @@ impl Qualif for CustomEq { def: AdtDef<'tcx>, substs: SubstsRef<'tcx>, ) -> bool { - let ty = cx.tcx.mk_adt(def, substs); + let ty = Ty::new_adt(cx.tcx, def, substs); !ty.is_structural_eq_shallow(cx.tcx) } } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index dd80f745c2f..1b39a76e460 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -17,7 +17,7 @@ use rustc_middle::mir; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, List, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, List, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::Span; use rustc_index::{Idx, IndexSlice, IndexVec}; @@ -867,7 +867,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let ty = local_decls[place.local].ty; let span = statement.source_info.span; - let ref_ty = tcx.mk_ref( + let ref_ty = Ty::new_ref( + tcx, tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() }, ); diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 7ed73a3f6fe..4cc923cd935 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -67,8 +67,8 @@ impl<'tcx> MirPass<'tcx> for Validator { unwind_edge_count: 0, reachable_blocks: traversal::reachable_as_bitset(body), storage_liveness, - place_cache: Vec::new(), - value_cache: Vec::new(), + place_cache: FxHashSet::default(), + value_cache: FxHashSet::default(), }; checker.visit_body(body); checker.check_cleanup_control_flow(); @@ -95,8 +95,8 @@ struct TypeChecker<'a, 'tcx> { unwind_edge_count: usize, reachable_blocks: BitSet<BasicBlock>, storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>, - place_cache: Vec<PlaceRef<'tcx>>, - value_cache: Vec<u128>, + place_cache: FxHashSet<PlaceRef<'tcx>>, + value_cache: FxHashSet<u128>, } impl<'a, 'tcx> TypeChecker<'a, 'tcx> { @@ -650,7 +650,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // FIXME: Add Checks for these CastKind::PointerFromExposedAddress | CastKind::PointerExposeAddress - | CastKind::Pointer(_) => {} + | CastKind::PointerCoercion(_) => {} CastKind::IntToInt | CastKind::IntToFloat => { let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool(); let target_valid = target_type.is_numeric() || target_type.is_char(); @@ -951,10 +951,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.value_cache.clear(); self.value_cache.extend(targets.iter().map(|(value, _)| value)); - let all_len = self.value_cache.len(); - self.value_cache.sort_unstable(); - self.value_cache.dedup(); - let has_duplicates = all_len != self.value_cache.len(); + let has_duplicates = targets.iter().len() != self.value_cache.len(); if has_duplicates { self.fail( location, @@ -987,16 +984,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // passed by a reference to the callee. Consequently they must be non-overlapping. // Currently this simply checks for duplicate places. self.place_cache.clear(); - self.place_cache.push(destination.as_ref()); + self.place_cache.insert(destination.as_ref()); + let mut has_duplicates = false; for arg in args { if let Operand::Move(place) = arg { - self.place_cache.push(place.as_ref()); + has_duplicates |= !self.place_cache.insert(place.as_ref()); } } - let all_len = self.place_cache.len(); - let mut dedup = FxHashSet::default(); - self.place_cache.retain(|p| dedup.insert(*p)); - let has_duplicates = all_len != self.place_cache.len(); + if has_duplicates { self.fail( location, diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index 86a54f6befd..d7c295418ba 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -8,6 +8,3 @@ crate-type = ["dylib"] [dependencies] rustc_driver_impl = { path = "../rustc_driver_impl" } -# FIXME(Nilstrieb): 0.37.12 adds eventfd support for FreeBSD, -# but FreeBSD 12 does not support it: https://github.com/bytecodealliance/rustix/issues/716 -rustix = "=0.37.11" diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 4b4573ec2eb..9352fe3147e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -24,6 +24,7 @@ use rustc_data_structures::profiling::{ }; use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; +use rustc_errors::{markdown, ColorConfig}; use rustc_errors::{ DiagnosticMessage, ErrorGuaranteed, Handler, PResult, SubdiagnosticMessage, TerminalUrl, }; @@ -282,7 +283,7 @@ fn run_compiler( interface::set_thread_safe_mode(&sopts.unstable_opts); if let Some(ref code) = matches.opt_str("explain") { - handle_explain(&early_error_handler, diagnostics_registry(), code); + handle_explain(&early_error_handler, diagnostics_registry(), code, sopts.color); return Ok(()); } @@ -540,7 +541,7 @@ impl Compilation { } } -fn handle_explain(handler: &EarlyErrorHandler, registry: Registry, code: &str) { +fn handle_explain(handler: &EarlyErrorHandler, registry: Registry, code: &str, color: ColorConfig) { let upper_cased_code = code.to_ascii_uppercase(); let normalised = if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") }; @@ -564,7 +565,7 @@ fn handle_explain(handler: &EarlyErrorHandler, registry: Registry, code: &str) { text.push('\n'); } if io::stdout().is_terminal() { - show_content_with_pager(&text); + show_md_content_with_pager(&text, color); } else { safe_print!("{text}"); } @@ -575,34 +576,72 @@ fn handle_explain(handler: &EarlyErrorHandler, registry: Registry, code: &str) { } } -fn show_content_with_pager(content: &str) { +/// If color is always or auto, print formatted & colorized markdown. If color is never or +/// if formatted printing fails, print the raw text. +/// +/// Prefers a pager, falls back standard print +fn show_md_content_with_pager(content: &str, color: ColorConfig) { + let mut fallback_to_println = false; let pager_name = env::var_os("PAGER").unwrap_or_else(|| { if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") } }); - let mut fallback_to_println = false; + let mut cmd = Command::new(&pager_name); + // FIXME: find if other pagers accept color options + let mut print_formatted = if pager_name == "less" { + cmd.arg("-r"); + true + } else if ["bat", "catbat", "delta"].iter().any(|v| *v == pager_name) { + true + } else { + false + }; - match Command::new(pager_name).stdin(Stdio::piped()).spawn() { - Ok(mut pager) => { - if let Some(pipe) = pager.stdin.as_mut() { - if pipe.write_all(content.as_bytes()).is_err() { - fallback_to_println = true; - } - } + if color == ColorConfig::Never { + print_formatted = false; + } else if color == ColorConfig::Always { + print_formatted = true; + } + + let mdstream = markdown::MdStream::parse_str(content); + let bufwtr = markdown::create_stdout_bufwtr(); + let mut mdbuf = bufwtr.buffer(); + if mdstream.write_termcolor_buf(&mut mdbuf).is_err() { + print_formatted = false; + } - if pager.wait().is_err() { + if let Ok(mut pager) = cmd.stdin(Stdio::piped()).spawn() { + if let Some(pipe) = pager.stdin.as_mut() { + let res = if print_formatted { + pipe.write_all(mdbuf.as_slice()) + } else { + pipe.write_all(content.as_bytes()) + }; + + if res.is_err() { fallback_to_println = true; } } - Err(_) => { + + if pager.wait().is_err() { fallback_to_println = true; } + } else { + fallback_to_println = true; } // If pager fails for whatever reason, we should still print the content // to standard output if fallback_to_println { - safe_print!("{content}"); + let fmt_success = match color { + ColorConfig::Auto => io::stdout().is_terminal() && bufwtr.print(&mdbuf).is_ok(), + ColorConfig::Always => bufwtr.print(&mdbuf).is_ok(), + ColorConfig::Never => false, + }; + + if !fmt_success { + safe_print!("{content}"); + } } } diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index f3ee83fd4d2..51e1fe531dd 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -226,7 +226,7 @@ fn register_functions(bundle: &mut FluentBundle) { pub type LazyFallbackBundle = Lrc<Lazy<FluentBundle, impl FnOnce() -> FluentBundle>>; /// Return the default `FluentBundle` with standard "en-US" diagnostic messages. -#[instrument(level = "trace")] +#[instrument(level = "trace", skip(resources))] pub fn fallback_fluent_bundle( resources: Vec<&'static str>, with_directionality_markers: bool, @@ -242,7 +242,6 @@ pub fn fallback_fluent_bundle( for resource in resources { let resource = FluentResource::try_new(resource.to_string()) .expect("failed to parse fallback fluent resource"); - trace!(?resource); fallback_bundle.add_resource_overriding(resource); } diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index bd3033fcb3e..e8bcd7c1184 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -20,7 +20,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_type_ir = { path = "../rustc_type_ir" } unicode-width = "0.1.4" -termcolor = "1.0" +termcolor = "1.2.0" annotate-snippets = "0.9" termize = "0.1.1" serde = { version = "1.0.125", features = [ "derive" ] } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index d8c997b49a1..9d4d159fd96 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -616,7 +616,7 @@ pub enum ColorConfig { } impl ColorConfig { - fn to_color_choice(self) -> ColorChoice { + pub fn to_color_choice(self) -> ColorChoice { match self { ColorConfig::Always => { if io::stderr().is_terminal() { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 24d1cc8af82..b9db25103a3 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -61,6 +61,7 @@ pub mod emitter; pub mod error; pub mod json; mod lock; +pub mod markdown; pub mod registry; mod snippet; mod styled_buffer; diff --git a/compiler/rustc_errors/src/markdown/mod.rs b/compiler/rustc_errors/src/markdown/mod.rs new file mode 100644 index 00000000000..53b766dfcce --- /dev/null +++ b/compiler/rustc_errors/src/markdown/mod.rs @@ -0,0 +1,76 @@ +//! A simple markdown parser that can write formatted text to the terminal +//! +//! Entrypoint is `MdStream::parse_str(...)` +use std::io; + +use termcolor::{Buffer, BufferWriter, ColorChoice}; +mod parse; +mod term; + +/// An AST representation of a Markdown document +#[derive(Clone, Debug, Default, PartialEq)] +pub struct MdStream<'a>(Vec<MdTree<'a>>); + +impl<'a> MdStream<'a> { + /// Parse a markdown string to a tokenstream + #[must_use] + pub fn parse_str(s: &str) -> MdStream<'_> { + parse::entrypoint(s) + } + + /// Write formatted output to a termcolor buffer + pub fn write_termcolor_buf(&self, buf: &mut Buffer) -> io::Result<()> { + term::entrypoint(self, buf) + } +} + +/// Create a termcolor buffer with the `Always` color choice +pub fn create_stdout_bufwtr() -> BufferWriter { + BufferWriter::stdout(ColorChoice::Always) +} + +/// A single tokentree within a Markdown document +#[derive(Clone, Debug, PartialEq)] +pub enum MdTree<'a> { + /// Leaf types + Comment(&'a str), + CodeBlock { + txt: &'a str, + lang: Option<&'a str>, + }, + CodeInline(&'a str), + Strong(&'a str), + Emphasis(&'a str), + Strikethrough(&'a str), + PlainText(&'a str), + /// [Foo](www.foo.com) or simple anchor <www.foo.com> + Link { + disp: &'a str, + link: &'a str, + }, + /// `[Foo link][ref]` + RefLink { + disp: &'a str, + id: Option<&'a str>, + }, + /// [ref]: www.foo.com + LinkDef { + id: &'a str, + link: &'a str, + }, + /// Break bewtween two paragraphs (double `\n`), not directly parsed but + /// added later + ParagraphBreak, + /// Break bewtween two lines (single `\n`) + LineBreak, + HorizontalRule, + Heading(u8, MdStream<'a>), + OrderedListItem(u16, MdStream<'a>), + UnorderedListItem(MdStream<'a>), +} + +impl<'a> From<Vec<MdTree<'a>>> for MdStream<'a> { + fn from(value: Vec<MdTree<'a>>) -> Self { + Self(value) + } +} diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs new file mode 100644 index 00000000000..362a451fde6 --- /dev/null +++ b/compiler/rustc_errors/src/markdown/parse.rs @@ -0,0 +1,588 @@ +use crate::markdown::{MdStream, MdTree}; +use std::{iter, mem, str}; + +/// Short aliases that we can use in match patterns. If an end pattern is not +/// included, this type may be variable +const ANC_E: &[u8] = b">"; +const ANC_S: &[u8] = b"<"; +const BRK: &[u8] = b"---"; +const CBK: &[u8] = b"```"; +const CIL: &[u8] = b"`"; +const CMT_E: &[u8] = b"-->"; +const CMT_S: &[u8] = b"<!--"; +const EMP: &[u8] = b"_"; +const HDG: &[u8] = b"#"; +const LNK_CHARS: &str = "$-_.+!*'()/&?=:%"; +const LNK_E: &[u8] = b"]"; +const LNK_S: &[u8] = b"["; +const STG: &[u8] = b"**"; +const STK: &[u8] = b"~~"; +const UL1: &[u8] = b"* "; +const UL2: &[u8] = b"- "; + +/// Pattern replacements +const REPLACEMENTS: &[(&str, &str)] = &[ + ("(c)", "©"), + ("(C)", "©"), + ("(r)", "®"), + ("(R)", "®"), + ("(tm)", "™"), + ("(TM)", "™"), + (":crab:", "🦀"), + ("\n", " "), +]; + +/// `(extracted, remaining)` +type Parsed<'a> = (MdTree<'a>, &'a [u8]); +/// Output of a parse function +type ParseResult<'a> = Option<Parsed<'a>>; + +/// Parsing context +#[derive(Clone, Copy, Debug, PartialEq)] +struct Context { + /// If true, we are at a the topmost level (not recursing a nested tt) + top_block: bool, + /// Previous character + prev: Prev, +} + +/// Character class preceding this one +#[derive(Clone, Copy, Debug, PartialEq)] +enum Prev { + Newline, + /// Whitespace that is not a newline + Whitespace, + Escape, + Any, +} + +impl Default for Context { + /// Most common setting for non top-level parsing: not top block, not at + /// line start (yes leading whitespace, not escaped) + fn default() -> Self { + Self { top_block: false, prev: Prev::Whitespace } + } +} + +/// Flags to simple parser function +#[derive(Clone, Copy, Debug, PartialEq)] +enum ParseOpt { + /// Ignore escapes before closing pattern, trim content + TrimNoEsc, + None, +} + +/// Parse a buffer +pub fn entrypoint(txt: &str) -> MdStream<'_> { + let ctx = Context { top_block: true, prev: Prev::Newline }; + normalize(parse_recursive(txt.trim().as_bytes(), ctx), &mut Vec::new()) +} + +/// Parse a buffer with specified context +fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> { + use ParseOpt as Po; + use Prev::{Escape, Newline, Whitespace}; + + let mut stream: Vec<MdTree<'a>> = Vec::new(); + let Context { top_block: top_blk, mut prev } = ctx; + + // wip_buf is our entire unprocessed (unpushed) buffer, loop_buf is our to + // check buffer that shrinks with each loop + let mut wip_buf = buf; + let mut loop_buf = wip_buf; + + while !loop_buf.is_empty() { + let next_prev = match loop_buf[0] { + b'\n' => Newline, + b'\\' => Escape, + x if x.is_ascii_whitespace() => Whitespace, + _ => Prev::Any, + }; + + let res: ParseResult<'_> = match (top_blk, prev) { + (_, Newline | Whitespace) if loop_buf.starts_with(CMT_S) => { + parse_simple_pat(loop_buf, CMT_S, CMT_E, Po::TrimNoEsc, MdTree::Comment) + } + (true, Newline) if loop_buf.starts_with(CBK) => Some(parse_codeblock(loop_buf)), + (_, Newline | Whitespace) if loop_buf.starts_with(CIL) => parse_codeinline(loop_buf), + (true, Newline | Whitespace) if loop_buf.starts_with(HDG) => parse_heading(loop_buf), + (true, Newline) if loop_buf.starts_with(BRK) => { + Some((MdTree::HorizontalRule, parse_to_newline(loop_buf).1)) + } + (_, Newline | Whitespace) if loop_buf.starts_with(EMP) => { + parse_simple_pat(loop_buf, EMP, EMP, Po::None, MdTree::Emphasis) + } + (_, Newline | Whitespace) if loop_buf.starts_with(STG) => { + parse_simple_pat(loop_buf, STG, STG, Po::None, MdTree::Strong) + } + (_, Newline | Whitespace) if loop_buf.starts_with(STK) => { + parse_simple_pat(loop_buf, STK, STK, Po::None, MdTree::Strikethrough) + } + (_, Newline | Whitespace) if loop_buf.starts_with(ANC_S) => { + let tt_fn = |link| MdTree::Link { disp: link, link }; + let ret = parse_simple_pat(loop_buf, ANC_S, ANC_E, Po::None, tt_fn); + match ret { + Some((MdTree::Link { disp, .. }, _)) + if disp.chars().all(|ch| LNK_CHARS.contains(ch)) => + { + ret + } + _ => None, + } + } + (_, Newline) if (loop_buf.starts_with(UL1) || loop_buf.starts_with(UL2)) => { + Some(parse_unordered_li(loop_buf)) + } + (_, Newline) if ord_list_start(loop_buf).is_some() => Some(parse_ordered_li(loop_buf)), + (_, Newline | Whitespace) if loop_buf.starts_with(LNK_S) => { + parse_any_link(loop_buf, top_blk && prev == Prev::Newline) + } + (_, Escape | _) => None, + }; + + if let Some((tree, rest)) = res { + // We found something: push our WIP and then push the found tree + let prev_buf = &wip_buf[..(wip_buf.len() - loop_buf.len())]; + if !prev_buf.is_empty() { + let prev_str = str::from_utf8(prev_buf).unwrap(); + stream.push(MdTree::PlainText(prev_str)); + } + stream.push(tree); + + wip_buf = rest; + loop_buf = rest; + } else { + // Just move on to the next character + loop_buf = &loop_buf[1..]; + // If we are at the end and haven't found anything, just push plain text + if loop_buf.is_empty() && !wip_buf.is_empty() { + let final_str = str::from_utf8(wip_buf).unwrap(); + stream.push(MdTree::PlainText(final_str)); + } + }; + + prev = next_prev; + } + + MdStream(stream) +} + +/// The simplest kind of patterns: data within start and end patterns +fn parse_simple_pat<'a, F>( + buf: &'a [u8], + start_pat: &[u8], + end_pat: &[u8], + opts: ParseOpt, + create_tt: F, +) -> ParseResult<'a> +where + F: FnOnce(&'a str) -> MdTree<'a>, +{ + let ignore_esc = matches!(opts, ParseOpt::TrimNoEsc); + let trim = matches!(opts, ParseOpt::TrimNoEsc); + let (txt, rest) = parse_with_end_pat(&buf[start_pat.len()..], end_pat, ignore_esc)?; + let mut txt = str::from_utf8(txt).unwrap(); + if trim { + txt = txt.trim(); + } + Some((create_tt(txt), rest)) +} + +/// Parse backtick-wrapped inline code. Accounts for >1 backtick sets +fn parse_codeinline(buf: &[u8]) -> ParseResult<'_> { + let seps = buf.iter().take_while(|ch| **ch == b'`').count(); + let (txt, rest) = parse_with_end_pat(&buf[seps..], &buf[..seps], true)?; + Some((MdTree::CodeInline(str::from_utf8(txt).unwrap()), rest)) +} + +/// Parse a codeblock. Accounts for >3 backticks and language specification +fn parse_codeblock(buf: &[u8]) -> Parsed<'_> { + // account for ````code```` style + let seps = buf.iter().take_while(|ch| **ch == b'`').count(); + let end_sep = &buf[..seps]; + let mut working = &buf[seps..]; + + // Handle "````rust" style language specifications + let next_ws_idx = working.iter().take_while(|ch| !ch.is_ascii_whitespace()).count(); + + let lang = if next_ws_idx > 0 { + // Munch the lang + let tmp = str::from_utf8(&working[..next_ws_idx]).unwrap(); + working = &working[next_ws_idx..]; + Some(tmp) + } else { + None + }; + + let mut end_pat = vec![b'\n']; + end_pat.extend(end_sep); + + // Find first end pattern with nothing else on its line + let mut found = None; + for idx in (0..working.len()).filter(|idx| working[*idx..].starts_with(&end_pat)) { + let (eol_txt, rest) = parse_to_newline(&working[(idx + end_pat.len())..]); + if !eol_txt.iter().any(u8::is_ascii_whitespace) { + found = Some((&working[..idx], rest)); + break; + } + } + + let (txt, rest) = found.unwrap_or((working, &[])); + let txt = str::from_utf8(txt).unwrap().trim_matches('\n'); + + (MdTree::CodeBlock { txt, lang }, rest) +} + +fn parse_heading(buf: &[u8]) -> ParseResult<'_> { + let level = buf.iter().take_while(|ch| **ch == b'#').count(); + let buf = &buf[level..]; + + if level > 6 || (buf.len() > 1 && !buf[0].is_ascii_whitespace()) { + // Enforce max 6 levels and whitespace following the `##` pattern + return None; + } + + let (txt, rest) = parse_to_newline(&buf[1..]); + let ctx = Context { top_block: false, prev: Prev::Whitespace }; + let stream = parse_recursive(txt, ctx); + + Some((MdTree::Heading(level.try_into().unwrap(), stream), rest)) +} + +/// Bulleted list +fn parse_unordered_li(buf: &[u8]) -> Parsed<'_> { + debug_assert!(buf.starts_with(b"* ") || buf.starts_with(b"- ")); + let (txt, rest) = get_indented_section(&buf[2..]); + let ctx = Context { top_block: false, prev: Prev::Whitespace }; + let stream = parse_recursive(trim_ascii_start(txt), ctx); + (MdTree::UnorderedListItem(stream), rest) +} + +/// Numbered list +fn parse_ordered_li(buf: &[u8]) -> Parsed<'_> { + let (num, pos) = ord_list_start(buf).unwrap(); // success tested in caller + let (txt, rest) = get_indented_section(&buf[pos..]); + let ctx = Context { top_block: false, prev: Prev::Whitespace }; + let stream = parse_recursive(trim_ascii_start(txt), ctx); + (MdTree::OrderedListItem(num, stream), rest) +} + +/// Find first line that isn't empty or doesn't start with whitespace, that will +/// be our contents +fn get_indented_section(buf: &[u8]) -> (&[u8], &[u8]) { + let mut end = buf.len(); + for (idx, window) in buf.windows(2).enumerate() { + let &[ch, next_ch] = window else {unreachable!("always 2 elements")}; + if idx >= buf.len().saturating_sub(2) && next_ch == b'\n' { + // End of stream + end = buf.len().saturating_sub(1); + break; + } else if ch == b'\n' && (!next_ch.is_ascii_whitespace() || next_ch == b'\n') { + end = idx; + break; + } + } + + (&buf[..end], &buf[end..]) +} + +/// Verify a valid ordered list start (e.g. `1.`) and parse it. Returns the +/// parsed number and offset of character after the dot. +fn ord_list_start(buf: &[u8]) -> Option<(u16, usize)> { + let pos = buf.iter().take(10).position(|ch| *ch == b'.')?; + let n = str::from_utf8(&buf[..pos]).ok()?; + if !buf.get(pos + 1)?.is_ascii_whitespace() { + return None; + } + n.parse::<u16>().ok().map(|v| (v, pos + 2)) +} + +/// Parse links. `can_be_def` indicates that a link definition is possible (top +/// level, located at the start of a line) +fn parse_any_link(buf: &[u8], can_be_def: bool) -> ParseResult<'_> { + let (bracketed, rest) = parse_with_end_pat(&buf[1..], LNK_E, true)?; + if rest.is_empty() { + return None; + } + + let disp = str::from_utf8(bracketed).unwrap(); + match (can_be_def, rest[0]) { + (true, b':') => { + let (link, tmp) = parse_to_newline(&rest[1..]); + let link = str::from_utf8(link).unwrap().trim(); + Some((MdTree::LinkDef { id: disp, link }, tmp)) + } + (_, b'(') => parse_simple_pat(rest, b"(", b")", ParseOpt::TrimNoEsc, |link| MdTree::Link { + disp, + link, + }), + (_, b'[') => parse_simple_pat(rest, b"[", b"]", ParseOpt::TrimNoEsc, |id| { + MdTree::RefLink { disp, id: Some(id) } + }), + _ => Some((MdTree::RefLink { disp, id: None }, rest)), + } +} + +/// Find and consume an end pattern, return `(match, residual)` +fn parse_with_end_pat<'a>( + buf: &'a [u8], + end_sep: &[u8], + ignore_esc: bool, +) -> Option<(&'a [u8], &'a [u8])> { + // Find positions that start with the end seperator + for idx in (0..buf.len()).filter(|idx| buf[*idx..].starts_with(end_sep)) { + if !ignore_esc && idx > 0 && buf[idx - 1] == b'\\' { + continue; + } + return Some((&buf[..idx], &buf[idx + end_sep.len()..])); + } + None +} + +/// Resturn `(match, residual)` to end of line. The EOL is returned with the +/// residual. +fn parse_to_newline(buf: &[u8]) -> (&[u8], &[u8]) { + buf.iter().position(|ch| *ch == b'\n').map_or((buf, &[]), |pos| buf.split_at(pos)) +} + +/// Take a parsed stream and fix the little things +fn normalize<'a>(MdStream(stream): MdStream<'a>, linkdefs: &mut Vec<MdTree<'a>>) -> MdStream<'a> { + let mut new_stream = Vec::with_capacity(stream.len()); + let new_defs = stream.iter().filter(|tt| matches!(tt, MdTree::LinkDef { .. })); + linkdefs.extend(new_defs.cloned()); + + // Run plaintest expansions on types that need it, call this function on nested types + for item in stream { + match item { + MdTree::PlainText(txt) => expand_plaintext(txt, &mut new_stream, MdTree::PlainText), + MdTree::Strong(txt) => expand_plaintext(txt, &mut new_stream, MdTree::Strong), + MdTree::Emphasis(txt) => expand_plaintext(txt, &mut new_stream, MdTree::Emphasis), + MdTree::Strikethrough(txt) => { + expand_plaintext(txt, &mut new_stream, MdTree::Strikethrough); + } + MdTree::RefLink { disp, id } => new_stream.push(match_reflink(linkdefs, disp, id)), + MdTree::OrderedListItem(n, st) => { + new_stream.push(MdTree::OrderedListItem(n, normalize(st, linkdefs))); + } + MdTree::UnorderedListItem(st) => { + new_stream.push(MdTree::UnorderedListItem(normalize(st, linkdefs))); + } + MdTree::Heading(n, st) => new_stream.push(MdTree::Heading(n, normalize(st, linkdefs))), + _ => new_stream.push(item), + } + } + + // Remove non printing types, duplicate paragraph breaks, and breaks at start/end + new_stream.retain(|x| !matches!(x, MdTree::Comment(_) | MdTree::LinkDef { .. })); + new_stream.dedup_by(|r, l| matches!((r, l), (MdTree::ParagraphBreak, MdTree::ParagraphBreak))); + + if new_stream.first().is_some_and(is_break_ty) { + new_stream.remove(0); + } + if new_stream.last().is_some_and(is_break_ty) { + new_stream.pop(); + } + + // Remove paragraph breaks that shouldn't be there. w[1] is what will be + // removed in these cases. Note that these are the items to keep, not delete + // (for `retain`) + let to_keep: Vec<bool> = new_stream + .windows(3) + .map(|w| { + !((matches!(&w[1], MdTree::ParagraphBreak) + && matches!(should_break(&w[0], &w[2]), BreakRule::Always(1) | BreakRule::Never)) + || (matches!(&w[1], MdTree::PlainText(txt) if txt.trim().is_empty()) + && matches!( + should_break(&w[0], &w[2]), + BreakRule::Always(_) | BreakRule::Never + ))) + }) + .collect(); + let mut iter = iter::once(true).chain(to_keep).chain(iter::once(true)); + new_stream.retain(|_| iter.next().unwrap()); + + // Insert line or paragraph breaks where there should be some + let mut insertions = 0; + let to_insert: Vec<(usize, MdTree<'_>)> = new_stream + .windows(2) + .enumerate() + .filter_map(|(idx, w)| match should_break(&w[0], &w[1]) { + BreakRule::Always(1) => Some((idx, MdTree::LineBreak)), + BreakRule::Always(2) => Some((idx, MdTree::ParagraphBreak)), + _ => None, + }) + .map(|(idx, tt)| { + insertions += 1; + (idx + insertions, tt) + }) + .collect(); + to_insert.into_iter().for_each(|(idx, tt)| new_stream.insert(idx, tt)); + + MdStream(new_stream) +} + +/// Whether two types should or shouldn't have a paragraph break between them +#[derive(Clone, Copy, Debug, PartialEq)] +enum BreakRule { + Always(u8), + Never, + Optional, +} + +/// Blocks that automatically handle their own text wrapping +fn should_break(left: &MdTree<'_>, right: &MdTree<'_>) -> BreakRule { + use MdTree::*; + + match (left, right) { + // Separate these types with a single line + (HorizontalRule, _) + | (_, HorizontalRule) + | (OrderedListItem(_, _), OrderedListItem(_, _)) + | (UnorderedListItem(_), UnorderedListItem(_)) => BreakRule::Always(1), + // Condensed types shouldn't have an extra break on either side + (Comment(_) | ParagraphBreak | Heading(_, _), _) | (_, Comment(_) | ParagraphBreak) => { + BreakRule::Never + } + // Block types should always be separated by full breaks + (CodeBlock { .. } | OrderedListItem(_, _) | UnorderedListItem(_), _) + | (_, CodeBlock { .. } | Heading(_, _) | OrderedListItem(_, _) | UnorderedListItem(_)) => { + BreakRule::Always(2) + } + // Text types may or may not be separated by a break + ( + CodeInline(_) + | Strong(_) + | Emphasis(_) + | Strikethrough(_) + | PlainText(_) + | Link { .. } + | RefLink { .. } + | LinkDef { .. }, + CodeInline(_) + | Strong(_) + | Emphasis(_) + | Strikethrough(_) + | PlainText(_) + | Link { .. } + | RefLink { .. } + | LinkDef { .. }, + ) => BreakRule::Optional, + (LineBreak, _) | (_, LineBreak) => { + unreachable!("should have been removed during deduplication") + } + } +} + +/// Types that indicate some form of break +fn is_break_ty(val: &MdTree<'_>) -> bool { + matches!(val, MdTree::ParagraphBreak | MdTree::LineBreak) + // >1 break between paragraphs acts as a break + || matches!(val, MdTree::PlainText(txt) if txt.trim().is_empty()) +} + +/// Perform tranformations to text. This splits paragraphs, replaces patterns, +/// and corrects newlines. +/// +/// To avoid allocating strings (and using a different heavier tt type), our +/// replace method means split into three and append each. For this reason, any +/// viewer should treat consecutive `PlainText` types as belonging to the same +/// paragraph. +fn expand_plaintext<'a>( + txt: &'a str, + stream: &mut Vec<MdTree<'a>>, + mut f: fn(&'a str) -> MdTree<'a>, +) { + if txt.is_empty() { + return; + } else if txt == "\n" { + if let Some(tt) = stream.last() { + let tmp = MdTree::PlainText(" "); + if should_break(tt, &tmp) == BreakRule::Optional { + stream.push(tmp); + } + } + return; + } + let mut queue1 = Vec::new(); + let mut queue2 = Vec::new(); + let stream_start_len = stream.len(); + for paragraph in txt.split("\n\n") { + if paragraph.is_empty() { + stream.push(MdTree::ParagraphBreak); + continue; + } + let paragraph = trim_extra_ws(paragraph); + + queue1.clear(); + queue1.push(paragraph); + + for (from, to) in REPLACEMENTS { + queue2.clear(); + for item in &queue1 { + for s in item.split(from) { + queue2.extend(&[s, to]); + } + if queue2.len() > 1 { + let _ = queue2.pop(); // remove last unnecessary intersperse + } + } + mem::swap(&mut queue1, &mut queue2); + } + + // Make sure we don't double whitespace + queue1.retain(|s| !s.is_empty()); + for idx in 0..queue1.len() { + queue1[idx] = trim_extra_ws(queue1[idx]); + if idx < queue1.len() - 1 + && queue1[idx].ends_with(char::is_whitespace) + && queue1[idx + 1].starts_with(char::is_whitespace) + { + queue1[idx] = queue1[idx].trim_end(); + } + } + stream.extend(queue1.iter().copied().filter(|txt| !txt.is_empty()).map(&mut f)); + stream.push(MdTree::ParagraphBreak); + } + + if stream.len() - stream_start_len > 1 { + let _ = stream.pop(); // remove last unnecessary intersperse + } +} + +/// Turn reflinks (links with reference IDs) into normal standalone links using +/// listed link definitions +fn match_reflink<'a>(linkdefs: &[MdTree<'a>], disp: &'a str, match_id: Option<&str>) -> MdTree<'a> { + let to_match = match_id.unwrap_or(disp); // Match with the display name if there isn't an id + for def in linkdefs { + if let MdTree::LinkDef { id, link } = def { + if *id == to_match { + return MdTree::Link { disp, link }; + } + } + } + MdTree::Link { disp, link: "" } // link not found +} + +/// If there is more than one whitespace char at start or end, trim the extras +fn trim_extra_ws(mut txt: &str) -> &str { + let start_ws = + txt.bytes().position(|ch| !ch.is_ascii_whitespace()).unwrap_or(txt.len()).saturating_sub(1); + txt = &txt[start_ws..]; + let end_ws = txt + .bytes() + .rev() + .position(|ch| !ch.is_ascii_whitespace()) + .unwrap_or(txt.len()) + .saturating_sub(1); + &txt[..txt.len() - end_ws] +} + +/// If there is more than one whitespace char at start, trim the extras +fn trim_ascii_start(buf: &[u8]) -> &[u8] { + let count = buf.iter().take_while(|ch| ch.is_ascii_whitespace()).count(); + &buf[count..] +} + +#[cfg(test)] +#[path = "tests/parse.rs"] +mod tests; diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs new file mode 100644 index 00000000000..e45ba6d2cda --- /dev/null +++ b/compiler/rustc_errors/src/markdown/term.rs @@ -0,0 +1,189 @@ +use std::cell::Cell; +use std::io::{self, Write}; + +use termcolor::{Buffer, Color, ColorSpec, WriteColor}; + +use crate::markdown::{MdStream, MdTree}; + +const DEFAULT_COLUMN_WIDTH: usize = 140; + +thread_local! { + /// Track the position of viewable characters in our buffer + static CURSOR: Cell<usize> = Cell::new(0); + /// Width of the terminal + static WIDTH: Cell<usize> = Cell::new(DEFAULT_COLUMN_WIDTH); +} + +/// Print to terminal output to a buffer +pub fn entrypoint(stream: &MdStream<'_>, buf: &mut Buffer) -> io::Result<()> { + #[cfg(not(test))] + if let Some((w, _)) = termize::dimensions() { + WIDTH.with(|c| c.set(std::cmp::min(w, DEFAULT_COLUMN_WIDTH))); + } + write_stream(stream, buf, None, 0)?; + buf.write_all(b"\n") +} + +/// Write the buffer, reset to the default style after each +fn write_stream( + MdStream(stream): &MdStream<'_>, + buf: &mut Buffer, + default: Option<&ColorSpec>, + indent: usize, +) -> io::Result<()> { + match default { + Some(c) => buf.set_color(c)?, + None => buf.reset()?, + } + + for tt in stream { + write_tt(tt, buf, indent)?; + if let Some(c) = default { + buf.set_color(c)?; + } + } + + buf.reset()?; + Ok(()) +} + +pub fn write_tt(tt: &MdTree<'_>, buf: &mut Buffer, indent: usize) -> io::Result<()> { + match tt { + MdTree::CodeBlock { txt, lang: _ } => { + buf.set_color(ColorSpec::new().set_dimmed(true))?; + buf.write_all(txt.as_bytes())?; + } + MdTree::CodeInline(txt) => { + buf.set_color(ColorSpec::new().set_dimmed(true))?; + write_wrapping(buf, txt, indent, None)?; + } + MdTree::Strong(txt) => { + buf.set_color(ColorSpec::new().set_bold(true))?; + write_wrapping(buf, txt, indent, None)?; + } + MdTree::Emphasis(txt) => { + buf.set_color(ColorSpec::new().set_italic(true))?; + write_wrapping(buf, txt, indent, None)?; + } + MdTree::Strikethrough(txt) => { + buf.set_color(ColorSpec::new().set_strikethrough(true))?; + write_wrapping(buf, txt, indent, None)?; + } + MdTree::PlainText(txt) => { + write_wrapping(buf, txt, indent, None)?; + } + MdTree::Link { disp, link } => { + write_wrapping(buf, disp, indent, Some(link))?; + } + MdTree::ParagraphBreak => { + buf.write_all(b"\n\n")?; + reset_cursor(); + } + MdTree::LineBreak => { + buf.write_all(b"\n")?; + reset_cursor(); + } + MdTree::HorizontalRule => { + (0..WIDTH.with(Cell::get)).for_each(|_| buf.write_all(b"-").unwrap()); + reset_cursor(); + } + MdTree::Heading(n, stream) => { + let mut cs = ColorSpec::new(); + cs.set_fg(Some(Color::Cyan)); + match n { + 1 => cs.set_intense(true).set_bold(true).set_underline(true), + 2 => cs.set_intense(true).set_underline(true), + 3 => cs.set_intense(true).set_italic(true), + 4.. => cs.set_underline(true).set_italic(true), + 0 => unreachable!(), + }; + write_stream(stream, buf, Some(&cs), 0)?; + buf.write_all(b"\n")?; + } + MdTree::OrderedListItem(n, stream) => { + let base = format!("{n}. "); + write_wrapping(buf, &format!("{base:<4}"), indent, None)?; + write_stream(stream, buf, None, indent + 4)?; + } + MdTree::UnorderedListItem(stream) => { + let base = "* "; + write_wrapping(buf, &format!("{base:<4}"), indent, None)?; + write_stream(stream, buf, None, indent + 4)?; + } + // Patterns popped in previous step + MdTree::Comment(_) | MdTree::LinkDef { .. } | MdTree::RefLink { .. } => unreachable!(), + } + + buf.reset()?; + + Ok(()) +} + +/// End of that block, just wrap the line +fn reset_cursor() { + CURSOR.with(|cur| cur.set(0)); +} + +/// Change to be generic on Write for testing. If we have a link URL, we don't +/// count the extra tokens to make it clickable. +fn write_wrapping<B: io::Write>( + buf: &mut B, + text: &str, + indent: usize, + link_url: Option<&str>, +) -> io::Result<()> { + let ind_ws = &b" "[..indent]; + let mut to_write = text; + if let Some(url) = link_url { + // This is a nonprinting prefix so we don't increment our cursor + write!(buf, "\x1b]8;;{url}\x1b\\")?; + } + CURSOR.with(|cur| { + loop { + if cur.get() == 0 { + buf.write_all(ind_ws)?; + cur.set(indent); + } + let ch_count = WIDTH.with(Cell::get) - cur.get(); + let mut iter = to_write.char_indices(); + let Some((end_idx, _ch)) = iter.nth(ch_count) else { + // Write entire line + buf.write_all(to_write.as_bytes())?; + cur.set(cur.get()+to_write.chars().count()); + break; + }; + + if let Some((break_idx, ch)) = to_write[..end_idx] + .char_indices() + .rev() + .find(|(_idx, ch)| ch.is_whitespace() || ['_', '-'].contains(ch)) + { + // Found whitespace to break at + if ch.is_whitespace() { + writeln!(buf, "{}", &to_write[..break_idx])?; + to_write = to_write[break_idx..].trim_start(); + } else { + // Break at a `-` or `_` separator + writeln!(buf, "{}", &to_write.get(..break_idx + 1).unwrap_or(to_write))?; + to_write = to_write.get(break_idx + 1..).unwrap_or_default().trim_start(); + } + } else { + // No whitespace, we need to just split + let ws_idx = + iter.find(|(_, ch)| ch.is_whitespace()).map_or(to_write.len(), |(idx, _)| idx); + writeln!(buf, "{}", &to_write[..ws_idx])?; + to_write = to_write.get(ws_idx + 1..).map_or("", str::trim_start); + } + cur.set(0); + } + if link_url.is_some() { + buf.write_all(b"\x1b]8;;\x1b\\")?; + } + + Ok(()) + }) +} + +#[cfg(test)] +#[path = "tests/term.rs"] +mod tests; diff --git a/compiler/rustc_errors/src/markdown/tests/input.md b/compiler/rustc_errors/src/markdown/tests/input.md new file mode 100644 index 00000000000..7d207fc4220 --- /dev/null +++ b/compiler/rustc_errors/src/markdown/tests/input.md @@ -0,0 +1,50 @@ +# H1 Heading [with a link][remote-link] + +H1 content: **some words in bold** and `so does inline code` + +## H2 Heading + +H2 content: _some words in italic_ + +### H3 Heading + +H3 content: ~~strikethrough~~ text + +#### H4 Heading + +H4 content: A [simple link](https://docs.rs) and a [remote-link]. + +--- + +A section break was above. We can also do paragraph breaks: + +(new paragraph) and unordered lists: + +- Item 1 in `code` +- Item 2 in _italics_ + +Or ordered: + +1. Item 1 in **bold** +2. Item 2 with some long lines that should wrap: Lorem ipsum dolor sit amet, + consectetur adipiscing elit. Aenean ac mattis nunc. Phasellus elit quam, + pulvinar ac risus in, dictum vehicula turpis. Vestibulum neque est, accumsan + in cursus sit amet, dictum a nunc. Suspendisse aliquet, lorem eu eleifend + accumsan, magna neque sodales nisi, a aliquet lectus leo eu sem. + +--- + +## Code + +Both `inline code` and code blocks are supported: + +```rust +/// A rust enum +#[derive(Debug, PartialEq, Clone)] +enum Foo { + /// Start of line + Bar +} +``` + +[remote-link]: http://docs.rs diff --git a/compiler/rustc_errors/src/markdown/tests/output.stdout b/compiler/rustc_errors/src/markdown/tests/output.stdout new file mode 100644 index 00000000000..23c60d5c319 --- /dev/null +++ b/compiler/rustc_errors/src/markdown/tests/output.stdout @@ -0,0 +1,35 @@ +[0m[0m[1m[4m[38;5;14mH1 Heading [0m[0m[1m[4m[38;5;14m]8;;http://docs.rs\with a link]8;;\[0m[0m[1m[4m[38;5;14m[0m +[0mH1 content: [0m[0m[1msome words in bold[0m and [0m[0m[2mso does inline code[0m + +[0m[0m[4m[38;5;14mH2 Heading[0m[0m[4m[38;5;14m[0m +[0mH2 content: [0m[0m[3msome words in italic[0m + +[0m[0m[3m[38;5;14mH3 Heading[0m[0m[3m[38;5;14m[0m +[0mH3 content: [0m[0m[9mstrikethrough[0m text[0m + +[0m[0m[3m[4m[36mH4 Heading[0m[0m[3m[4m[36m[0m +[0mH4 content: A [0m]8;;https://docs.rs\simple link]8;;\[0m and a [0m]8;;http://docs.rs\remote-link]8;;\[0m.[0m +[0m--------------------------------------------------------------------------------------------------------------------------------------------[0m +[0mA section break was above. We can also do paragraph breaks:[0m + +[0m(new paragraph) and unordered lists:[0m + +[0m* [0mItem 1 in [0m[0m[2mcode[0m[0m[0m +[0m* [0mItem 2 in [0m[0m[3mitalics[0m[0m[0m + +[0mOr ordered:[0m + +[0m1. [0mItem 1 in [0m[0m[1mbold[0m[0m[0m +[0m2. [0mItem 2 with some long lines that should wrap: Lorem ipsum dolor sit amet,[0m consectetur adipiscing elit. Aenean ac mattis nunc. Phasellus + elit quam,[0m pulvinar ac risus in, dictum vehicula turpis. Vestibulum neque est, accumsan[0m in cursus sit amet, dictum a nunc. Suspendisse + aliquet, lorem eu eleifend[0m accumsan, magna neque sodales nisi, a aliquet lectus leo eu sem.[0m[0m[0m +[0m--------------------------------------------------------------------------------------------------------------------------------------------[0m +[0m[0m[4m[38;5;14mCode[0m[0m[4m[38;5;14m[0m +[0mBoth [0m[0m[2minline code[0m and code blocks are supported:[0m + +[0m[0m[2m/// A rust enum +#[derive(Debug, PartialEq, Clone)] +enum Foo { + /// Start of line + Bar +}[0m[0m diff --git a/compiler/rustc_errors/src/markdown/tests/parse.rs b/compiler/rustc_errors/src/markdown/tests/parse.rs new file mode 100644 index 00000000000..e39e8c89b35 --- /dev/null +++ b/compiler/rustc_errors/src/markdown/tests/parse.rs @@ -0,0 +1,312 @@ +use super::*; +use ParseOpt as PO; + +#[test] +fn test_parse_simple() { + let buf = "**abcd** rest"; + let (t, r) = parse_simple_pat(buf.as_bytes(), STG, STG, PO::None, MdTree::Strong).unwrap(); + assert_eq!(t, MdTree::Strong("abcd")); + assert_eq!(r, b" rest"); + + // Escaping should fail + let buf = r"**abcd\** rest"; + let res = parse_simple_pat(buf.as_bytes(), STG, STG, PO::None, MdTree::Strong); + assert!(res.is_none()); +} + +#[test] +fn test_parse_comment() { + let opt = PO::TrimNoEsc; + let buf = "<!-- foobar! -->rest"; + let (t, r) = parse_simple_pat(buf.as_bytes(), CMT_S, CMT_E, opt, MdTree::Comment).unwrap(); + assert_eq!(t, MdTree::Comment("foobar!")); + assert_eq!(r, b"rest"); + + let buf = r"<!-- foobar! \-->rest"; + let (t, r) = parse_simple_pat(buf.as_bytes(), CMT_S, CMT_E, opt, MdTree::Comment).unwrap(); + assert_eq!(t, MdTree::Comment(r"foobar! \")); + assert_eq!(r, b"rest"); +} + +#[test] +fn test_parse_heading() { + let buf1 = "# Top level\nrest"; + let (t, r) = parse_heading(buf1.as_bytes()).unwrap(); + assert_eq!(t, MdTree::Heading(1, vec![MdTree::PlainText("Top level")].into())); + assert_eq!(r, b"\nrest"); + + let buf1 = "# Empty"; + let (t, r) = parse_heading(buf1.as_bytes()).unwrap(); + assert_eq!(t, MdTree::Heading(1, vec![MdTree::PlainText("Empty")].into())); + assert_eq!(r, b""); + + // Combo + let buf2 = "### Top `level` _woo_\nrest"; + let (t, r) = parse_heading(buf2.as_bytes()).unwrap(); + assert_eq!( + t, + MdTree::Heading( + 3, + vec![ + MdTree::PlainText("Top "), + MdTree::CodeInline("level"), + MdTree::PlainText(" "), + MdTree::Emphasis("woo"), + ] + .into() + ) + ); + assert_eq!(r, b"\nrest"); +} + +#[test] +fn test_parse_code_inline() { + let buf1 = "`abcd` rest"; + let (t, r) = parse_codeinline(buf1.as_bytes()).unwrap(); + assert_eq!(t, MdTree::CodeInline("abcd")); + assert_eq!(r, b" rest"); + + // extra backticks, newline + let buf2 = "```ab\ncd``` rest"; + let (t, r) = parse_codeinline(buf2.as_bytes()).unwrap(); + assert_eq!(t, MdTree::CodeInline("ab\ncd")); + assert_eq!(r, b" rest"); + + // test no escaping + let buf3 = r"`abcd\` rest"; + let (t, r) = parse_codeinline(buf3.as_bytes()).unwrap(); + assert_eq!(t, MdTree::CodeInline(r"abcd\")); + assert_eq!(r, b" rest"); +} + +#[test] +fn test_parse_code_block() { + let buf1 = "```rust\ncode\ncode\n```\nleftovers"; + let (t, r) = parse_codeblock(buf1.as_bytes()); + assert_eq!(t, MdTree::CodeBlock { txt: "code\ncode", lang: Some("rust") }); + assert_eq!(r, b"\nleftovers"); + + let buf2 = "`````\ncode\ncode````\n`````\nleftovers"; + let (t, r) = parse_codeblock(buf2.as_bytes()); + assert_eq!(t, MdTree::CodeBlock { txt: "code\ncode````", lang: None }); + assert_eq!(r, b"\nleftovers"); +} + +#[test] +fn test_parse_link() { + let simple = "[see here](docs.rs) other"; + let (t, r) = parse_any_link(simple.as_bytes(), false).unwrap(); + assert_eq!(t, MdTree::Link { disp: "see here", link: "docs.rs" }); + assert_eq!(r, b" other"); + + let simple_toplevel = "[see here](docs.rs) other"; + let (t, r) = parse_any_link(simple_toplevel.as_bytes(), true).unwrap(); + assert_eq!(t, MdTree::Link { disp: "see here", link: "docs.rs" }); + assert_eq!(r, b" other"); + + let reference = "[see here] other"; + let (t, r) = parse_any_link(reference.as_bytes(), true).unwrap(); + assert_eq!(t, MdTree::RefLink { disp: "see here", id: None }); + assert_eq!(r, b" other"); + + let reference_full = "[see here][docs-rs] other"; + let (t, r) = parse_any_link(reference_full.as_bytes(), false).unwrap(); + assert_eq!(t, MdTree::RefLink { disp: "see here", id: Some("docs-rs") }); + assert_eq!(r, b" other"); + + let reference_def = "[see here]: docs.rs\nother"; + let (t, r) = parse_any_link(reference_def.as_bytes(), true).unwrap(); + assert_eq!(t, MdTree::LinkDef { id: "see here", link: "docs.rs" }); + assert_eq!(r, b"\nother"); +} + +const IND1: &str = r"test standard + ind + ind2 +not ind"; +const IND2: &str = r"test end of stream + 1 + 2 +"; +const IND3: &str = r"test empty lines + 1 + 2 + +not ind"; + +#[test] +fn test_indented_section() { + let (t, r) = get_indented_section(IND1.as_bytes()); + assert_eq!(str::from_utf8(t).unwrap(), "test standard\n ind\n ind2"); + assert_eq!(str::from_utf8(r).unwrap(), "\nnot ind"); + + let (txt, rest) = get_indented_section(IND2.as_bytes()); + assert_eq!(str::from_utf8(txt).unwrap(), "test end of stream\n 1\n 2"); + assert_eq!(str::from_utf8(rest).unwrap(), "\n"); + + let (txt, rest) = get_indented_section(IND3.as_bytes()); + assert_eq!(str::from_utf8(txt).unwrap(), "test empty lines\n 1\n 2"); + assert_eq!(str::from_utf8(rest).unwrap(), "\n\nnot ind"); +} + +const HBT: &str = r"# Heading + +content"; + +#[test] +fn test_heading_breaks() { + let expected = vec![ + MdTree::Heading(1, vec![MdTree::PlainText("Heading")].into()), + MdTree::PlainText("content"), + ] + .into(); + let res = entrypoint(HBT); + assert_eq!(res, expected); +} + +const NL1: &str = r"start + +end"; +const NL2: &str = r"start + + +end"; +const NL3: &str = r"start + + + +end"; + +#[test] +fn test_newline_breaks() { + let expected = + vec![MdTree::PlainText("start"), MdTree::ParagraphBreak, MdTree::PlainText("end")].into(); + for (idx, check) in [NL1, NL2, NL3].iter().enumerate() { + let res = entrypoint(check); + assert_eq!(res, expected, "failed {idx}"); + } +} + +const WRAP: &str = "plain _italics +italics_"; + +#[test] +fn test_wrap_pattern() { + let expected = vec![ + MdTree::PlainText("plain "), + MdTree::Emphasis("italics"), + MdTree::Emphasis(" "), + MdTree::Emphasis("italics"), + ] + .into(); + let res = entrypoint(WRAP); + assert_eq!(res, expected); +} + +const WRAP_NOTXT: &str = r"_italics_ +**bold**"; + +#[test] +fn test_wrap_notxt() { + let expected = + vec![MdTree::Emphasis("italics"), MdTree::PlainText(" "), MdTree::Strong("bold")].into(); + let res = entrypoint(WRAP_NOTXT); + assert_eq!(res, expected); +} + +const MIXED_LIST: &str = r"start +- _italics item_ +<!-- comment --> +- **bold item** + second line [link1](foobar1) + third line [link2][link-foo] +- :crab: + extra indent +end +[link-foo]: foobar2 +"; + +#[test] +fn test_list() { + let expected = vec![ + MdTree::PlainText("start"), + MdTree::ParagraphBreak, + MdTree::UnorderedListItem(vec![MdTree::Emphasis("italics item")].into()), + MdTree::LineBreak, + MdTree::UnorderedListItem( + vec![ + MdTree::Strong("bold item"), + MdTree::PlainText(" second line "), + MdTree::Link { disp: "link1", link: "foobar1" }, + MdTree::PlainText(" third line "), + MdTree::Link { disp: "link2", link: "foobar2" }, + ] + .into(), + ), + MdTree::LineBreak, + MdTree::UnorderedListItem( + vec![MdTree::PlainText("🦀"), MdTree::PlainText(" extra indent")].into(), + ), + MdTree::ParagraphBreak, + MdTree::PlainText("end"), + ] + .into(); + let res = entrypoint(MIXED_LIST); + assert_eq!(res, expected); +} + +const SMOOSHED: &str = r#" +start +### heading +1. ordered item +```rust +println!("Hello, world!"); +``` +`inline` +``end`` +"#; + +#[test] +fn test_without_breaks() { + let expected = vec![ + MdTree::PlainText("start"), + MdTree::ParagraphBreak, + MdTree::Heading(3, vec![MdTree::PlainText("heading")].into()), + MdTree::OrderedListItem(1, vec![MdTree::PlainText("ordered item")].into()), + MdTree::ParagraphBreak, + MdTree::CodeBlock { txt: r#"println!("Hello, world!");"#, lang: Some("rust") }, + MdTree::ParagraphBreak, + MdTree::CodeInline("inline"), + MdTree::PlainText(" "), + MdTree::CodeInline("end"), + ] + .into(); + let res = entrypoint(SMOOSHED); + assert_eq!(res, expected); +} + +const CODE_STARTLINE: &str = r#" +start +`code` +middle +`more code` +end +"#; + +#[test] +fn test_code_at_start() { + let expected = vec![ + MdTree::PlainText("start"), + MdTree::PlainText(" "), + MdTree::CodeInline("code"), + MdTree::PlainText(" "), + MdTree::PlainText("middle"), + MdTree::PlainText(" "), + MdTree::CodeInline("more code"), + MdTree::PlainText(" "), + MdTree::PlainText("end"), + ] + .into(); + let res = entrypoint(CODE_STARTLINE); + assert_eq!(res, expected); +} diff --git a/compiler/rustc_errors/src/markdown/tests/term.rs b/compiler/rustc_errors/src/markdown/tests/term.rs new file mode 100644 index 00000000000..3b31c6d6295 --- /dev/null +++ b/compiler/rustc_errors/src/markdown/tests/term.rs @@ -0,0 +1,90 @@ +use std::io::BufWriter; +use std::path::PathBuf; +use termcolor::{BufferWriter, ColorChoice}; + +use super::*; +use crate::markdown::MdStream; + +const INPUT: &str = include_str!("input.md"); +const OUTPUT_PATH: &[&str] = &[env!("CARGO_MANIFEST_DIR"), "src","markdown","tests","output.stdout"]; + +const TEST_WIDTH: usize = 80; + +// We try to make some words long to create corner cases +const TXT: &str = r"Lorem ipsum dolor sit amet, consecteturadipiscingelit. +Fusce-id-urna-sollicitudin, pharetra nisl nec, lobortis tellus. In at +metus hendrerit, tincidunteratvel, ultrices turpis. Curabitur_risus_sapien, +porta-sed-nunc-sed, ultricesposuerelacus. Sed porttitor quis +dolor non venenatis. Aliquam ut. "; + +const WRAPPED: &str = r"Lorem ipsum dolor sit amet, consecteturadipiscingelit. Fusce-id-urna- +sollicitudin, pharetra nisl nec, lobortis tellus. In at metus hendrerit, +tincidunteratvel, ultrices turpis. Curabitur_risus_sapien, porta-sed-nunc-sed, +ultricesposuerelacus. Sed porttitor quis dolor non venenatis. Aliquam ut. Lorem + ipsum dolor sit amet, consecteturadipiscingelit. Fusce-id-urna- + sollicitudin, pharetra nisl nec, lobortis tellus. In at metus hendrerit, + tincidunteratvel, ultrices turpis. Curabitur_risus_sapien, porta-sed-nunc- + sed, ultricesposuerelacus. Sed porttitor quis dolor non venenatis. Aliquam + ut. Sample link lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, +consecteturadipiscingelit. Fusce-id-urna-sollicitudin, pharetra nisl nec, +lobortis tellus. In at metus hendrerit, tincidunteratvel, ultrices turpis. +Curabitur_risus_sapien, porta-sed-nunc-sed, ultricesposuerelacus. Sed porttitor +quis dolor non venenatis. Aliquam ut. "; + +#[test] +fn test_wrapping_write() { + WIDTH.with(|w| w.set(TEST_WIDTH)); + let mut buf = BufWriter::new(Vec::new()); + let txt = TXT.replace("-\n","-").replace("_\n","_").replace('\n', " ").replace(" ", ""); + write_wrapping(&mut buf, &txt, 0, None).unwrap(); + write_wrapping(&mut buf, &txt, 4, None).unwrap(); + write_wrapping( + &mut buf, + "Sample link lorem ipsum dolor sit amet. ", + 4, + Some("link-address-placeholder"), + ) + .unwrap(); + write_wrapping(&mut buf, &txt, 0, None).unwrap(); + let out = String::from_utf8(buf.into_inner().unwrap()).unwrap(); + let out = out + .replace("\x1b\\", "") + .replace('\x1b', "") + .replace("]8;;", "") + .replace("link-address-placeholder", ""); + + for line in out.lines() { + assert!(line.len() <= TEST_WIDTH, "line length\n'{line}'") + } + + assert_eq!(out, WRAPPED); +} + +#[test] +fn test_output() { + // Capture `--bless` when run via ./x + let bless = std::env::var("RUSTC_BLESS").unwrap_or_default() == "1"; + let ast = MdStream::parse_str(INPUT); + let bufwtr = BufferWriter::stderr(ColorChoice::Always); + let mut buffer = bufwtr.buffer(); + ast.write_termcolor_buf(&mut buffer).unwrap(); + + let mut blessed = PathBuf::new(); + blessed.extend(OUTPUT_PATH); + + if bless { + std::fs::write(&blessed, buffer.into_inner()).unwrap(); + eprintln!("blessed output at {}", blessed.display()); + } else { + let output = buffer.into_inner(); + if std::fs::read(blessed).unwrap() != output { + // hack: I don't know any way to write bytes to the captured stdout + // that cargo test uses + let mut out = std::io::stdout(); + out.write_all(b"\n\nMarkdown output did not match. Expected:\n").unwrap(); + out.write_all(&output).unwrap(); + out.write_all(b"\n\n").unwrap(); + panic!("markdown output mismatch"); + } + } +} diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 4a8a14994ff..42cc0a6b143 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -223,8 +223,7 @@ fn expand_macro<'cx>( // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. if tts.len() == rhs.tts.len() { - tts = tts.map_enumerated(|i, tt| { - let mut tt = tt.clone(); + tts = tts.map_enumerated_owned(|i, mut tt| { let rhs_tt = &rhs.tts[i]; let ctxt = tt.span().ctxt(); match (&mut tt, rhs_tt) { diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 906c31c9a3d..5185820a727 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -391,6 +391,8 @@ declare_features! ( (active, doc_masked, "1.21.0", Some(44027), None), /// Allows `dyn* Trait` objects. (incomplete, dyn_star, "1.65.0", Some(102425), None), + // Uses generic effect parameters for ~const bounds + (active, effects, "CURRENT_RUSTC_VERSION", Some(102090), None), /// Allows `X..Y` patterns. (active, exclusive_range_pattern, "1.11.0", Some(37854), None), /// Allows exhaustive pattern matching on types that contain uninhabited types. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 3c5bff3812a..36600004404 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -723,6 +723,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ and it is only intended to be used in `alloc`." ), + rustc_attr!( + rustc_host, AttributeType::Normal, template!(Word), ErrorFollowing, + "#[rustc_host] annotates const generic parameters as the `host` effect param, \ + and it is only intended for internal use and as a desugaring." + ), + BuiltinAttribute { name: sym::rustc_diagnostic_item, // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index ad26c495c02..166760166c1 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -248,6 +248,9 @@ hir_analysis_static_specialize = cannot specialize on `'static` lifetime hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl +hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature + .note = this item must mention the opaque type in its signature in order to be able to register hidden types + hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]` hir_analysis_too_large_static = extern static is too large for the current architecture @@ -288,6 +291,11 @@ hir_analysis_unrecognized_intrinsic_function = unrecognized intrinsic function: `{$name}` .label = unrecognized intrinsic +hir_analysis_unused_associated_type_bounds = + unnecessary associated type bound for not object safe associated type + .note = this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. + .suggestion = remove this bound + hir_analysis_value_of_associated_struct_already_specified = the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified .label = re-bound here diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 89677141f38..b13de770137 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -363,7 +363,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ); emitted_bad_param_err = true; } - tcx.mk_bound( + Ty::new_bound( + tcx, ty::INNERMOST, ty::BoundTy { var: ty::BoundVar::from_usize(num_bound_vars), @@ -386,11 +387,10 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { .type_of(param.def_id) .no_bound_vars() .expect("ct params cannot have early bound vars"); - tcx.mk_const( - ty::ConstKind::Bound( - ty::INNERMOST, - ty::BoundVar::from_usize(num_bound_vars), - ), + ty::Const::new_bound( + tcx, + ty::INNERMOST, + ty::BoundVar::from_usize(num_bound_vars), ty, ) .into() @@ -528,14 +528,14 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } let reported = err.emit(); term = match def_kind { - hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(), - hir::def::DefKind::AssocConst => tcx - .const_error( - tcx.type_of(assoc_item_def_id) - .subst(tcx, projection_ty.skip_binder().substs), - reported, - ) - .into(), + hir::def::DefKind::AssocTy => Ty::new_error(tcx, reported).into(), + hir::def::DefKind::AssocConst => ty::Const::new_error( + tcx, + reported, + tcx.type_of(assoc_item_def_id) + .subst(tcx, projection_ty.skip_binder().substs), + ) + .into(), _ => unreachable!(), }; } @@ -559,7 +559,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { // type bound into a trait predicate, since we only want to add predicates // for the `Self` type. if !only_self_bounds.0 { - let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); + let param_ty = Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder()); self.add_bounds( param_ty, ast_bounds.iter(), diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index dc17ef7048d..ddf99853b2e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -357,7 +357,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let projection_ty = pred.skip_binder().projection_ty; let substs_with_infer_self = tcx.mk_substs_from_iter( - std::iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into()) + std::iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into()) .chain(projection_ty.substs.iter().skip(1)), ); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 1d5e4ac55f8..3d698462840 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -6,14 +6,13 @@ mod bounds; mod errors; pub mod generics; mod lint; +mod object_safety; use crate::astconv::errors::prohibit_assoc_ty_binding; use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args}; use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; -use crate::errors::{ - AmbiguousLifetimeBound, TraitObjectDeclaredWithNoTraits, TypeofReservedKeywordUsed, -}; +use crate::errors::{AmbiguousLifetimeBound, TypeofReservedKeywordUsed}; use crate::middle::resolve_bound_vars as rbv; use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; @@ -31,24 +30,17 @@ use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; -use rustc_middle::ty::DynKind; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{sym, Span, DUMMY_SP}; use rustc_target::spec::abi; -use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::wf::object_region_bounds; -use rustc_trait_selection::traits::{ - self, astconv_object_safety_violations, NormalizeExt, ObligationCtxt, -}; +use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt}; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; -use smallvec::{smallvec, SmallVec}; -use std::collections::BTreeSet; use std::fmt::Display; use std::slice; @@ -451,7 +443,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) { self.inferred_params.push(ty.span); - tcx.ty_error_misc().into() + Ty::new_misc_error(tcx).into() } else { self.astconv.ast_ty_to_ty(ty).into() } @@ -482,7 +474,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.astconv.ct_infer(ty, Some(param), inf.span).into() } else { self.inferred_params.push(inf.span); - tcx.const_error_misc(ty).into() + ty::Const::new_misc_error(tcx, ty).into() } } _ => unreachable!(), @@ -520,14 +512,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { _ => false, }) { // Avoid ICE #86756 when type error recovery goes awry. - return tcx.ty_error_misc().into(); + return Ty::new_misc_error(tcx).into(); } tcx.at(self.span).type_of(param.def_id).subst(tcx, substs).into() } else if infer_args { self.astconv.ty_infer(Some(param), self.span).into() } else { // We've already errored above about the mismatch. - tcx.ty_error_misc().into() + Ty::new_misc_error(tcx).into() } } GenericParamDefKind::Const { has_default } => { @@ -537,7 +529,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .no_bound_vars() .expect("const parameter types cannot be generic"); if let Err(guar) = ty.error_reported() { - return tcx.const_error(ty, guar).into(); + return ty::Const::new_error(tcx, guar, ty).into(); } if !infer_args && has_default { tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into() @@ -546,7 +538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.astconv.ct_infer(ty, Some(param), self.span).into() } else { // We've already errored above about the mismatch. - tcx.const_error_misc(ty).into() + ty::Const::new_misc_error(tcx, ty).into() } } } @@ -920,386 +912,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // referencing a single opaque type) get encoded as a type alias that normalization will // then actually instantiate the where bounds of. let alias_ty = self.tcx().mk_alias_ty(did, substs); - self.tcx().mk_alias(ty::Weak, alias_ty) + Ty::new_alias(self.tcx(), ty::Weak, alias_ty) } else { ty.subst(self.tcx(), substs) } } - fn conv_object_ty_poly_trait_ref( - &self, - span: Span, - hir_trait_bounds: &[hir::PolyTraitRef<'_>], - lifetime: &hir::Lifetime, - borrowed: bool, - representation: DynKind, - ) -> Ty<'tcx> { - let tcx = self.tcx(); - - let mut bounds = Bounds::default(); - let mut potential_assoc_types = Vec::new(); - let dummy_self = self.tcx().types.trait_object_dummy_self; - for trait_bound in hir_trait_bounds.iter().rev() { - if let GenericArgCountResult { - correct: - Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), - .. - } = self.instantiate_poly_trait_ref( - &trait_bound.trait_ref, - trait_bound.span, - ty::BoundConstness::NotConst, - ty::ImplPolarity::Positive, - dummy_self, - &mut bounds, - false, - // FIXME: This should be `true`, but we don't really handle - // associated type bounds or type aliases in objects in a way - // that makes this meaningful, I think. - OnlySelfBounds(false), - ) { - potential_assoc_types.extend(cur_potential_assoc_types); - } - } - - let mut trait_bounds = vec![]; - let mut projection_bounds = vec![]; - for (pred, span) in bounds.clauses() { - let bound_pred = pred.kind(); - match bound_pred.skip_binder() { - ty::ClauseKind::Trait(trait_pred) => { - assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); - trait_bounds.push(( - bound_pred.rebind(trait_pred.trait_ref), - span, - trait_pred.constness, - )); - } - ty::ClauseKind::Projection(proj) => { - projection_bounds.push((bound_pred.rebind(proj), span)); - } - ty::ClauseKind::TypeOutlives(_) => { - // Do nothing, we deal with regions separately - } - ty::ClauseKind::RegionOutlives(_) - | ty::ClauseKind::ConstArgHasType(..) - | ty::ClauseKind::WellFormed(_) - | ty::ClauseKind::ConstEvaluatable(_) => { - bug!() - } - } - } - - // Expand trait aliases recursively and check that only one regular (non-auto) trait - // is used and no 'maybe' bounds are used. - let expanded_traits = - traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b))); - - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits - .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) - .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); - if regular_traits.len() > 1 { - let first_trait = ®ular_traits[0]; - let additional_trait = ®ular_traits[1]; - let mut err = struct_span_err!( - tcx.sess, - additional_trait.bottom().1, - E0225, - "only auto traits can be used as additional traits in a trait object" - ); - additional_trait.label_with_exp_info( - &mut err, - "additional non-auto trait", - "additional use", - ); - first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use"); - err.help(format!( - "consider creating a new trait with all of these as supertraits and using that \ - trait here instead: `trait NewTrait: {} {{}}`", - regular_traits - .iter() - .map(|t| t.trait_ref().print_only_trait_path().to_string()) - .collect::<Vec<_>>() - .join(" + "), - )); - err.note( - "auto-traits like `Send` and `Sync` are traits that have special properties; \ - for more information on them, visit \ - <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>", - ); - err.emit(); - } - - if regular_traits.is_empty() && auto_traits.is_empty() { - let trait_alias_span = trait_bounds - .iter() - .map(|&(trait_ref, _, _)| trait_ref.def_id()) - .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) - .map(|trait_ref| tcx.def_span(trait_ref)); - let reported = - tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); - return tcx.ty_error(reported); - } - - // Check that there are no gross object safety violations; - // most importantly, that the supertraits don't contain `Self`, - // to avoid ICEs. - for item in ®ular_traits { - let object_safety_violations = - astconv_object_safety_violations(tcx, item.trait_ref().def_id()); - if !object_safety_violations.is_empty() { - let reported = report_object_safety_error( - tcx, - span, - item.trait_ref().def_id(), - &object_safety_violations, - ) - .emit(); - return tcx.ty_error(reported); - } - } - - // Use a `BTreeSet` to keep output in a more consistent order. - let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default(); - - let regular_traits_refs_spans = trait_bounds - .into_iter() - .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); - - for (base_trait_ref, span, constness) in regular_traits_refs_spans { - assert_eq!(constness, ty::BoundConstness::NotConst); - let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); - for pred in traits::elaborate(tcx, [base_pred]) { - debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); - - let bound_predicate = pred.kind(); - match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - let pred = bound_predicate.rebind(pred); - associated_types.entry(span).or_default().extend( - tcx.associated_items(pred.def_id()) - .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Type) - .filter(|item| item.opt_rpitit_info.is_none()) - .map(|item| item.def_id), - ); - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { - let pred = bound_predicate.rebind(pred); - // A `Self` within the original bound will be substituted with a - // `trait_object_dummy_self`, so check for that. - let references_self = match pred.skip_binder().term.unpack() { - ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), - ty::TermKind::Const(c) => { - c.ty().walk().any(|arg| arg == dummy_self.into()) - } - }; - - // If the projection output contains `Self`, force the user to - // elaborate it explicitly to avoid a lot of complexity. - // - // The "classically useful" case is the following: - // ``` - // trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput { - // type MyOutput; - // } - // ``` - // - // Here, the user could theoretically write `dyn MyTrait<Output = X>`, - // but actually supporting that would "expand" to an infinitely-long type - // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`. - // - // Instead, we force the user to write - // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See - // the discussion in #56288 for alternatives. - if !references_self { - // Include projections defined on supertraits. - projection_bounds.push((pred, span)); - } - } - _ => (), - } - } - } - - // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where <Self as Trait>::Assoc = Foo`. - // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated - // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a - // corresponding `Projection` clause - for (projection_bound, _) in &projection_bounds { - for def_ids in associated_types.values_mut() { - def_ids.remove(&projection_bound.projection_def_id()); - } - } - - self.complain_about_missing_associated_types( - associated_types, - potential_assoc_types, - hir_trait_bounds, - ); - - // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as - // `dyn Trait + Send`. - // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering - // the bounds - let mut duplicates = FxHashSet::default(); - auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id())); - debug!("regular_traits: {:?}", regular_traits); - debug!("auto_traits: {:?}", auto_traits); - - // Erase the `dummy_self` (`trait_object_dummy_self`) used above. - let existential_trait_refs = regular_traits.iter().map(|i| { - i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| { - assert_eq!(trait_ref.self_ty(), dummy_self); - - // Verify that `dummy_self` did not leak inside default type parameters. This - // could not be done at path creation, since we need to see through trait aliases. - let mut missing_type_params = vec![]; - let mut references_self = false; - let generics = tcx.generics_of(trait_ref.def_id); - let substs: Vec<_> = trait_ref - .substs - .iter() - .enumerate() - .skip(1) // Remove `Self` for `ExistentialPredicate`. - .map(|(index, arg)| { - if arg == dummy_self.into() { - let param = &generics.params[index]; - missing_type_params.push(param.name); - return tcx.ty_error_misc().into(); - } else if arg.walk().any(|arg| arg == dummy_self.into()) { - references_self = true; - return tcx.ty_error_misc().into(); - } - arg - }) - .collect(); - let substs = tcx.mk_substs(&substs); - - let span = i.bottom().1; - let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| { - hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id) - && hir_bound.span.contains(span) - }); - self.complain_about_missing_type_params( - missing_type_params, - trait_ref.def_id, - span, - empty_generic_args, - ); - - if references_self { - let def_id = i.bottom().0.def_id(); - let mut err = struct_span_err!( - tcx.sess, - i.bottom().1, - E0038, - "the {} `{}` cannot be made into an object", - tcx.def_descr(def_id), - tcx.item_name(def_id), - ); - err.note( - rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![]) - .error_msg(), - ); - err.emit(); - } - - ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs } - }) - }); - - let existential_projections = projection_bounds - .iter() - // We filter out traits that don't have `Self` as their self type above, - // we need to do the same for projections. - .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self) - .map(|(bound, _)| { - bound.map_bound(|mut b| { - assert_eq!(b.projection_ty.self_ty(), dummy_self); - - // Like for trait refs, verify that `dummy_self` did not leak inside default type - // parameters. - let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return true; - } - false - }); - if references_self { - let guar = tcx.sess.delay_span_bug( - span, - "trait object projection bounds reference `Self`", - ); - let substs: Vec<_> = b - .projection_ty - .substs - .iter() - .map(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return tcx.ty_error(guar).into(); - } - arg - }) - .collect(); - b.projection_ty.substs = tcx.mk_substs(&substs); - } - - ty::ExistentialProjection::erase_self_ty(tcx, b) - }) - }); - - let regular_trait_predicates = existential_trait_refs - .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); - let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { - ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) - }); - // N.b. principal, projections, auto traits - // FIXME: This is actually wrong with multiple principals in regards to symbol mangling - let mut v = regular_trait_predicates - .chain( - existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)), - ) - .chain(auto_trait_predicates) - .collect::<SmallVec<[_; 8]>>(); - v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); - v.dedup(); - let existential_predicates = tcx.mk_poly_existential_predicates(&v); - - // Use explicitly-specified region bound. - let region_bound = if !lifetime.is_elided() { - self.ast_region_to_region(lifetime, None) - } else { - self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { - if tcx.named_bound_var(lifetime.hir_id).is_some() { - self.ast_region_to_region(lifetime, None) - } else { - self.re_infer(None, span).unwrap_or_else(|| { - let mut err = struct_span_err!( - tcx.sess, - span, - E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound" - ); - let e = if borrowed { - // We will have already emitted an error E0106 complaining about a - // missing named lifetime in `&dyn Trait`, so we elide this one. - err.delay_as_bug() - } else { - err.emit() - }; - ty::Region::new_error(tcx, e) - }) - } - }) - }; - debug!("region_bound: {:?}", region_bound); - - let ty = tcx.mk_dynamic(existential_predicates, region_bound, representation); - debug!("trait_object_type: {:?}", ty); - ty - } - fn report_ambiguous_associated_type( &self, span: Span, @@ -1955,10 +1573,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match *ty.kind() { - ty::Bound(_, bv) => self.tcx.mk_placeholder(ty::PlaceholderType { - universe: self.universe, - bound: bv, - }), + ty::Bound(_, bv) => Ty::new_placeholder( + self.tcx, + ty::PlaceholderType { universe: self.universe, bound: bv }, + ), _ => ty.super_fold_with(self), } } @@ -1970,7 +1588,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert!(!ct.ty().has_escaping_bound_vars()); match ct.kind() { - ty::ConstKind::Bound(_, bv) => self.tcx.mk_const( + ty::ConstKind::Bound(_, bv) => ty::Const::new_placeholder( + self.tcx, ty::PlaceholderConst { universe: self.universe, bound: bv }, ct.ty(), ), @@ -2046,7 +1665,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .chain(substs.into_iter().skip(parent_substs.len())), ); - let ty = tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(assoc_item, substs)); + let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, substs)); return Ok(Some((ty, assoc_item))); } @@ -2231,7 +1850,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &[path_str], item_segment.ident.name, ); - return tcx.ty_error(reported) + return Ty::new_error(tcx,reported) }; debug!("qpath_to_ty: self_type={:?}", self_ty); @@ -2254,7 +1873,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("qpath_to_ty: trait_ref={:?}", trait_ref); - tcx.mk_projection(item_def_id, item_substs) + Ty::new_projection(tcx, item_def_id, item_substs) } pub fn prohibit_generics<'a>( @@ -2517,7 +2136,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.note("`impl Trait` types can't have type parameters"); }); let substs = self.ast_path_substs_for_ty(span, did, item_segment.0); - tcx.mk_opaque(did, substs) + Ty::new_opaque(tcx, did, substs) } Res::Def( DefKind::Enum @@ -2569,16 +2188,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { var: ty::BoundVar::from_u32(index), kind: ty::BoundTyKind::Param(def_id, name), }; - tcx.mk_bound(debruijn, br) + Ty::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(_)) => { let def_id = def_id.expect_local(); let item_def_id = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; - tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)) + Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id)) } - Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error(guar), + Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar), arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), } } @@ -2690,7 +2309,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { err.span_note(impl_.self_ty.span, "not a concrete type"); } - tcx.ty_error(err.emit()) + Ty::new_error(tcx, err.emit()) } else { ty } @@ -2731,9 +2350,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match prim_ty { hir::PrimTy::Bool => tcx.types.bool, hir::PrimTy::Char => tcx.types.char, - hir::PrimTy::Int(it) => tcx.mk_mach_int(ty::int_ty(it)), - hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(ty::uint_ty(uit)), - hir::PrimTy::Float(ft) => tcx.mk_mach_float(ty::float_ty(ft)), + hir::PrimTy::Int(it) => Ty::new_int(tcx, ty::int_ty(it)), + hir::PrimTy::Uint(uit) => Ty::new_uint(tcx, ty::uint_ty(uit)), + hir::PrimTy::Float(ft) => Ty::new_float(tcx, ty::float_ty(ft)), hir::PrimTy::Str => tcx.types.str_, } } @@ -2743,7 +2362,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .sess .delay_span_bug(path.span, "path with `Res::Err` but no error emitted"); self.set_tainted_by_errors(e); - self.tcx().ty_error(e) + Ty::new_error(self.tcx(), e) } _ => span_bug!(span, "unexpected resolution: {:?}", path.res), } @@ -2768,31 +2387,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let result_ty = match &ast_ty.kind { - hir::TyKind::Slice(ty) => tcx.mk_slice(self.ast_ty_to_ty(ty)), + hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.ast_ty_to_ty(ty)), hir::TyKind::Ptr(mt) => { - tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) + Ty::new_ptr(tcx, ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) } hir::TyKind::Ref(region, mt) => { let r = self.ast_region_to_region(region, None); debug!(?r); let t = self.ast_ty_to_ty_inner(mt.ty, true, false); - tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) + Ty::new_ref(tcx, r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } hir::TyKind::Never => tcx.types.never, hir::TyKind::Tup(fields) => { - tcx.mk_tup_from_iter(fields.iter().map(|t| self.ast_ty_to_ty(t))) + Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.ast_ty_to_ty(t))) } hir::TyKind::BareFn(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); - tcx.mk_fn_ptr(self.ty_of_fn( - ast_ty.hir_id, - bf.unsafety, - bf.abi, - bf.decl, - None, - Some(ast_ty), - )) + Ty::new_fn_ptr( + tcx, + self.ty_of_fn(ast_ty.hir_id, bf.unsafety, bf.abi, bf.decl, None, Some(ast_ty)), + ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { self.maybe_lint_bare_trait(ast_ty, in_path); @@ -2801,7 +2416,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { TraitObjectSyntax::DynStar => ty::DynStar, }; - self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr) + self.conv_object_ty_poly_trait_ref( + ast_ty.span, + ast_ty.hir_id, + bounds, + lifetime, + borrowed, + repr, + ) } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); @@ -2832,7 +2454,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let ty = self.ast_ty_to_ty_inner(qself, false, true); self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, qself, segment, false) .map(|(ty, _, _)| ty) - .unwrap_or_else(|guar| tcx.ty_error(guar)) + .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); @@ -2856,7 +2478,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }; - tcx.mk_array_with_const_len(self.ast_ty_to_ty(ty), length) + Ty::new_array_with_const_len(tcx, self.ast_ty_to_ty(ty), length) } hir::TyKind::Typeof(e) => { let ty_erased = tcx.type_of(e.def_id).subst_identity(); @@ -2880,7 +2502,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // handled specially and will not descend into this routine. self.ty_infer(None, ast_ty.span) } - hir::TyKind::Err(guar) => tcx.ty_error(*guar), + hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar), }; self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span); @@ -2917,7 +2539,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); debug!("impl_trait_ty_to_ty: substs={:?}", substs); - if in_trait { tcx.mk_projection(def_id, substs) } else { tcx.mk_opaque(def_id, substs) } + if in_trait { + Ty::new_projection(tcx, def_id, substs) + } else { + Ty::new_opaque(tcx, def_id, substs) + } } pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> { @@ -2986,7 +2612,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_ty_to_ty(output) } } - hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(), + hir::FnRetTy::DefaultReturn(..) => Ty::new_unit(tcx,), }; debug!(?output_ty); diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs new file mode 100644 index 00000000000..9227ee93451 --- /dev/null +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -0,0 +1,408 @@ +use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds}; +use crate::bounds::Bounds; +use crate::errors::TraitObjectDeclaredWithNoTraits; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::struct_span_err; +use rustc_hir as hir; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::DefId; +use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; +use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{DynKind, ToPredicate}; +use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::report_object_safety_error; +use rustc_trait_selection::traits::{self, astconv_object_safety_violations}; + +use smallvec::{smallvec, SmallVec}; +use std::collections::BTreeSet; + +use super::AstConv; + +impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { + pub(super) fn conv_object_ty_poly_trait_ref( + &self, + span: Span, + hir_id: hir::HirId, + hir_trait_bounds: &[hir::PolyTraitRef<'_>], + lifetime: &hir::Lifetime, + borrowed: bool, + representation: DynKind, + ) -> Ty<'tcx> { + let tcx = self.tcx(); + + let mut bounds = Bounds::default(); + let mut potential_assoc_types = Vec::new(); + let dummy_self = self.tcx().types.trait_object_dummy_self; + for trait_bound in hir_trait_bounds.iter().rev() { + if let GenericArgCountResult { + correct: + Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), + .. + } = self.instantiate_poly_trait_ref( + &trait_bound.trait_ref, + trait_bound.span, + ty::BoundConstness::NotConst, + ty::ImplPolarity::Positive, + dummy_self, + &mut bounds, + false, + // FIXME: This should be `true`, but we don't really handle + // associated type bounds or type aliases in objects in a way + // that makes this meaningful, I think. + OnlySelfBounds(false), + ) { + potential_assoc_types.extend(cur_potential_assoc_types); + } + } + + let mut trait_bounds = vec![]; + let mut projection_bounds = vec![]; + for (pred, span) in bounds.clauses() { + let bound_pred = pred.kind(); + match bound_pred.skip_binder() { + ty::ClauseKind::Trait(trait_pred) => { + assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); + trait_bounds.push(( + bound_pred.rebind(trait_pred.trait_ref), + span, + trait_pred.constness, + )); + } + ty::ClauseKind::Projection(proj) => { + projection_bounds.push((bound_pred.rebind(proj), span)); + } + ty::ClauseKind::TypeOutlives(_) => { + // Do nothing, we deal with regions separately + } + ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::ConstArgHasType(..) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) => { + bug!() + } + } + } + + // Expand trait aliases recursively and check that only one regular (non-auto) trait + // is used and no 'maybe' bounds are used. + let expanded_traits = + traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b))); + + let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits + .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) + .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); + if regular_traits.len() > 1 { + let first_trait = ®ular_traits[0]; + let additional_trait = ®ular_traits[1]; + let mut err = struct_span_err!( + tcx.sess, + additional_trait.bottom().1, + E0225, + "only auto traits can be used as additional traits in a trait object" + ); + additional_trait.label_with_exp_info( + &mut err, + "additional non-auto trait", + "additional use", + ); + first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use"); + err.help(format!( + "consider creating a new trait with all of these as supertraits and using that \ + trait here instead: `trait NewTrait: {} {{}}`", + regular_traits + .iter() + .map(|t| t.trait_ref().print_only_trait_path().to_string()) + .collect::<Vec<_>>() + .join(" + "), + )); + err.note( + "auto-traits like `Send` and `Sync` are traits that have special properties; \ + for more information on them, visit \ + <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>", + ); + err.emit(); + } + + if regular_traits.is_empty() && auto_traits.is_empty() { + let trait_alias_span = trait_bounds + .iter() + .map(|&(trait_ref, _, _)| trait_ref.def_id()) + .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) + .map(|trait_ref| tcx.def_span(trait_ref)); + let reported = + tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); + return Ty::new_error(tcx, reported); + } + + // Check that there are no gross object safety violations; + // most importantly, that the supertraits don't contain `Self`, + // to avoid ICEs. + for item in ®ular_traits { + let object_safety_violations = + astconv_object_safety_violations(tcx, item.trait_ref().def_id()); + if !object_safety_violations.is_empty() { + let reported = report_object_safety_error( + tcx, + span, + item.trait_ref().def_id(), + &object_safety_violations, + ) + .emit(); + return Ty::new_error(tcx, reported); + } + } + + // Use a `BTreeSet` to keep output in a more consistent order. + let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default(); + + let regular_traits_refs_spans = trait_bounds + .into_iter() + .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); + + for (base_trait_ref, span, constness) in regular_traits_refs_spans { + assert_eq!(constness, ty::BoundConstness::NotConst); + let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); + for pred in traits::elaborate(tcx, [base_pred]) { + debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); + + let bound_predicate = pred.kind(); + match bound_predicate.skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + let pred = bound_predicate.rebind(pred); + associated_types.entry(span).or_default().extend( + tcx.associated_items(pred.def_id()) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| item.opt_rpitit_info.is_none()) + .map(|item| item.def_id), + ); + } + ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { + let pred = bound_predicate.rebind(pred); + // A `Self` within the original bound will be substituted with a + // `trait_object_dummy_self`, so check for that. + let references_self = match pred.skip_binder().term.unpack() { + ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), + ty::TermKind::Const(c) => { + c.ty().walk().any(|arg| arg == dummy_self.into()) + } + }; + + // If the projection output contains `Self`, force the user to + // elaborate it explicitly to avoid a lot of complexity. + // + // The "classically useful" case is the following: + // ``` + // trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput { + // type MyOutput; + // } + // ``` + // + // Here, the user could theoretically write `dyn MyTrait<Output = X>`, + // but actually supporting that would "expand" to an infinitely-long type + // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`. + // + // Instead, we force the user to write + // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See + // the discussion in #56288 for alternatives. + if !references_self { + // Include projections defined on supertraits. + projection_bounds.push((pred, span)); + } + } + _ => (), + } + } + } + + // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where <Self as Trait>::Assoc = Foo`. + // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated + // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a + // corresponding `Projection` clause + for def_ids in associated_types.values_mut() { + for (projection_bound, span) in &projection_bounds { + let def_id = projection_bound.projection_def_id(); + def_ids.remove(&def_id); + if tcx.generics_require_sized_self(def_id) { + tcx.emit_spanned_lint( + UNUSED_ASSOCIATED_TYPE_BOUNDS, + hir_id, + *span, + crate::errors::UnusedAssociatedTypeBounds { span: *span }, + ); + } + } + // If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated + // type in the `dyn Trait`. + def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id)); + } + + self.complain_about_missing_associated_types( + associated_types, + potential_assoc_types, + hir_trait_bounds, + ); + + // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as + // `dyn Trait + Send`. + // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering + // the bounds + let mut duplicates = FxHashSet::default(); + auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id())); + debug!("regular_traits: {:?}", regular_traits); + debug!("auto_traits: {:?}", auto_traits); + + // Erase the `dummy_self` (`trait_object_dummy_self`) used above. + let existential_trait_refs = regular_traits.iter().map(|i| { + i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| { + assert_eq!(trait_ref.self_ty(), dummy_self); + + // Verify that `dummy_self` did not leak inside default type parameters. This + // could not be done at path creation, since we need to see through trait aliases. + let mut missing_type_params = vec![]; + let mut references_self = false; + let generics = tcx.generics_of(trait_ref.def_id); + let substs: Vec<_> = trait_ref + .substs + .iter() + .enumerate() + .skip(1) // Remove `Self` for `ExistentialPredicate`. + .map(|(index, arg)| { + if arg == dummy_self.into() { + let param = &generics.params[index]; + missing_type_params.push(param.name); + return Ty::new_misc_error(tcx).into(); + } else if arg.walk().any(|arg| arg == dummy_self.into()) { + references_self = true; + return Ty::new_misc_error(tcx).into(); + } + arg + }) + .collect(); + let substs = tcx.mk_substs(&substs); + + let span = i.bottom().1; + let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| { + hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id) + && hir_bound.span.contains(span) + }); + self.complain_about_missing_type_params( + missing_type_params, + trait_ref.def_id, + span, + empty_generic_args, + ); + + if references_self { + let def_id = i.bottom().0.def_id(); + let mut err = struct_span_err!( + tcx.sess, + i.bottom().1, + E0038, + "the {} `{}` cannot be made into an object", + tcx.def_descr(def_id), + tcx.item_name(def_id), + ); + err.note( + rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![]) + .error_msg(), + ); + err.emit(); + } + + ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs } + }) + }); + + let existential_projections = projection_bounds + .iter() + // We filter out traits that don't have `Self` as their self type above, + // we need to do the same for projections. + .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self) + .map(|(bound, _)| { + bound.map_bound(|mut b| { + assert_eq!(b.projection_ty.self_ty(), dummy_self); + + // Like for trait refs, verify that `dummy_self` did not leak inside default type + // parameters. + let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return true; + } + false + }); + if references_self { + let guar = tcx.sess.delay_span_bug( + span, + "trait object projection bounds reference `Self`", + ); + let substs: Vec<_> = b + .projection_ty + .substs + .iter() + .map(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return Ty::new_error(tcx, guar).into(); + } + arg + }) + .collect(); + b.projection_ty.substs = tcx.mk_substs(&substs); + } + + ty::ExistentialProjection::erase_self_ty(tcx, b) + }) + }); + + let regular_trait_predicates = existential_trait_refs + .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); + let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { + ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) + }); + // N.b. principal, projections, auto traits + // FIXME: This is actually wrong with multiple principals in regards to symbol mangling + let mut v = regular_trait_predicates + .chain( + existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)), + ) + .chain(auto_trait_predicates) + .collect::<SmallVec<[_; 8]>>(); + v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); + v.dedup(); + let existential_predicates = tcx.mk_poly_existential_predicates(&v); + + // Use explicitly-specified region bound. + let region_bound = if !lifetime.is_elided() { + self.ast_region_to_region(lifetime, None) + } else { + self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { + if tcx.named_bound_var(lifetime.hir_id).is_some() { + self.ast_region_to_region(lifetime, None) + } else { + self.re_infer(None, span).unwrap_or_else(|| { + let mut err = struct_span_err!( + tcx.sess, + span, + E0228, + "the lifetime bound for this object type cannot be deduced \ + from context; please supply an explicit bound" + ); + let e = if borrowed { + // We will have already emitted an error E0106 complaining about a + // missing named lifetime in `&dyn Trait`, so we elide this one. + err.delay_as_bug() + } else { + err.emit() + }; + ty::Region::new_error(tcx, e) + }) + } + }) + }; + debug!("region_bound: {:?}", region_bound); + + let ty = Ty::new_dynamic(tcx, existential_predicates, region_bound, representation); + debug!("trait_object_type: {:?}", ty); + ty + } +} diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 8aa9a2c2734..c07ac35cba3 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -148,8 +148,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { return None; } - let (normalized_ty, obligations) = - self.structurally_normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, [ty]))?; + let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection( + tcx, + tcx.lang_items().deref_target()?, + [ty], + ))?; debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); self.state.obligations.extend(obligations); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d232747b647..120545c8e5d 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -308,9 +308,9 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( { let substs = InternalSubsts::identity_for_item(tcx, def_id); let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() { - tcx.mk_projection(def_id.to_def_id(), substs) + Ty::new_projection(tcx, def_id.to_def_id(), substs) } else { - tcx.mk_opaque(def_id.to_def_id(), substs) + Ty::new_opaque(tcx, def_id.to_def_id(), substs) }; let mut visitor = ProhibitOpaqueVisitor { opaque_identity_ty, @@ -410,7 +410,7 @@ fn check_opaque_meets_bounds<'tcx>( let ocx = ObligationCtxt::new(&infcx); let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); - let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); + let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs); // `ReErased` regions appear in the "parent_substs" of closures/generators. // We're ignoring them here and replacing them with fresh region variables. @@ -722,7 +722,14 @@ pub(super) fn check_specialization_validity<'tcx>( let result = opt_result.unwrap_or(Ok(())); if let Err(parent_impl) = result { - report_forbidden_specialization(tcx, impl_item, parent_impl); + if !tcx.is_impl_trait_in_trait(impl_item) { + report_forbidden_specialization(tcx, impl_item, parent_impl); + } else { + tcx.sess.delay_span_bug( + DUMMY_SP, + format!("parent item: {:?} not marked as default", parent_impl), + ); + } } } @@ -1485,7 +1492,9 @@ fn opaque_type_cycle_error( } for closure_def_id in visitor.closures { - let Some(closure_local_did) = closure_def_id.as_local() else { continue; }; + let Some(closure_local_did) = closure_def_id.as_local() else { + continue; + }; let typeck_results = tcx.typeck(closure_local_did); let mut label_match = |ty: Ty<'_>, span| { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 3f5164e093d..22e576e345e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -271,7 +271,7 @@ fn compare_method_predicate_entailment<'tcx>( infer::HigherRankedType, tcx.fn_sig(impl_m.def_id).subst_identity(), ); - let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig)); + let unnormalized_impl_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig)); let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id); let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig); @@ -288,7 +288,7 @@ fn compare_method_predicate_entailment<'tcx>( // We also have to add the normalized trait signature // as we don't normalize during implied bounds computation. wf_tys.extend(trait_sig.inputs_and_output.iter()); - let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); + let trait_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(trait_sig)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); @@ -669,11 +669,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ) .fold_with(&mut collector); - debug_assert_ne!( - collector.types.len(), - 0, - "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`" - ); + if !unnormalized_trait_sig.output().references_error() { + debug_assert_ne!( + collector.types.len(), + 0, + "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`" + ); + } let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig); trait_sig.error_reported()?; @@ -803,7 +805,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( return_span, }) { Ok(ty) => ty, - Err(guar) => tcx.ty_error(guar), + Err(guar) => Ty::new_error(tcx, guar), }; collected_tys.insert(def_id, ty::EarlyBinder::bind(ty)); } @@ -812,7 +814,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( return_span, format!("could not fully resolve: {ty} => {err:?}"), ); - collected_tys.insert(def_id, ty::EarlyBinder::bind(tcx.ty_error(reported))); + collected_tys.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported))); } } } @@ -916,7 +918,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { _ => arg.try_fold_with(self)?, }); } - Ok(self.tcx.mk_opaque(def_id, self.tcx.mk_substs(&mapped_substs))) + Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_substs(&mapped_substs))) } else { t.try_super_fold_with(self) } @@ -2027,7 +2029,8 @@ pub(super) fn check_type_bounds<'tcx>( let kind = ty::BoundTyKind::Param(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Ty(kind); bound_vars.push(bound_var); - tcx.mk_bound( + Ty::new_bound( + tcx, ty::INNERMOST, ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind }, ) @@ -2047,11 +2050,10 @@ pub(super) fn check_type_bounds<'tcx>( GenericParamDefKind::Const { .. } => { let bound_var = ty::BoundVariableKind::Const; bound_vars.push(bound_var); - tcx.mk_const( - ty::ConstKind::Bound( - ty::INNERMOST, - ty::BoundVar::from_usize(bound_vars.len() - 1), - ), + ty::Const::new_bound( + tcx, + ty::INNERMOST, + ty::BoundVar::from_usize(bound_vars.len() - 1), tcx.type_of(param.def_id) .no_bound_vars() .expect("const parameter types cannot be generic"), diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 36c468e7789..1248f991cc4 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -11,7 +11,7 @@ use hir::def_id::DefId; use rustc_errors::{struct_span_err, DiagnosticMessage}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::spec::abi::Abi; @@ -53,14 +53,14 @@ fn equate_intrinsic_type<'tcx>( && gen_count_ok(own_counts.types, n_tps, "type") && gen_count_ok(own_counts.consts, 0, "const") { - let fty = tcx.mk_fn_ptr(sig); + let fty = Ty::new_fn_ptr(tcx, sig); let it_def_id = it.owner_id.def_id; let cause = ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType); require_same_types( tcx, &cause, ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env? - tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id).subst_identity()), + Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).subst_identity()), fty, ); } @@ -134,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir /// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`, /// and in `library/core/src/intrinsics.rs`. pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { - let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n))); + let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{}", n))); let intrinsic_id = it.owner_id.to_def_id(); let intrinsic_name = tcx.item_name(intrinsic_id); let name_str = intrinsic_name.as_str(); @@ -156,7 +156,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv }, ); let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]); - (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty) + (Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty) }) }; @@ -168,15 +168,15 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let (n_tps, inputs, output) = match split[1] { "cxchg" | "cxchgweak" => ( 1, - vec![tcx.mk_mut_ptr(param(0)), param(0), param(0)], - tcx.mk_tup(&[param(0), tcx.types.bool]), + vec![Ty::new_mut_ptr(tcx, param(0)), param(0), param(0)], + Ty::new_tup(tcx, &[param(0), tcx.types.bool]), ), - "load" => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)), - "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), + "load" => (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)), + "store" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)), "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax" - | "umin" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], param(0)), - "fence" | "singlethreadfence" => (0, Vec::new(), tcx.mk_unit()), + | "umin" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)), + "fence" | "singlethreadfence" => (0, Vec::new(), Ty::new_unit(tcx)), op => { tcx.sess.emit_err(UnrecognizedAtomicOperation { span: it.span, op }); return; @@ -188,19 +188,19 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let (n_tps, inputs, output) = match intrinsic_name { sym::abort => (0, Vec::new(), tcx.types.never), sym::unreachable => (0, Vec::new(), tcx.types.never), - sym::breakpoint => (0, Vec::new(), tcx.mk_unit()), + sym::breakpoint => (0, Vec::new(), Ty::new_unit(tcx)), sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => { (1, Vec::new(), tcx.types.usize) } sym::size_of_val | sym::min_align_of_val => { - (1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize) + (1, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize) } sym::rustc_peek => (1, vec![param(0)], param(0)), sym::caller_location => (0, vec![], tcx.caller_location_ty()), sym::assert_inhabited | sym::assert_zero_valid - | sym::assert_mem_uninitialized_valid => (1, Vec::new(), tcx.mk_unit()), - sym::forget => (1, vec![param(0)], tcx.mk_unit()), + | sym::assert_mem_uninitialized_valid => (1, Vec::new(), Ty::new_unit(tcx)), + sym::forget => (1, vec![param(0)], Ty::new_unit(tcx)), sym::transmute | sym::transmute_unchecked => (2, vec![param(0)], param(1)), sym::prefetch_read_data | sym::prefetch_write_data @@ -208,75 +208,79 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { | sym::prefetch_write_instruction => ( 1, vec![ - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), tcx.types.i32, ], - tcx.mk_unit(), + Ty::new_unit(tcx), ), - sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()), + sym::drop_in_place => (1, vec![Ty::new_mut_ptr(tcx, param(0))], Ty::new_unit(tcx)), sym::needs_drop => (1, Vec::new(), tcx.types.bool), - sym::type_name => (1, Vec::new(), tcx.mk_static_str()), + sym::type_name => (1, Vec::new(), Ty::new_static_str(tcx)), sym::type_id => (1, Vec::new(), tcx.types.u128), sym::offset => (2, vec![param(0), param(1)], param(0)), sym::arith_offset => ( 1, vec![ - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), tcx.types.isize, ], - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), ), sym::option_payload_ptr => { let option_def_id = tcx.require_lang_item(hir::LangItem::Option, None); let p0 = param(0); ( 1, - vec![tcx.mk_ptr(ty::TypeAndMut { - ty: tcx.mk_adt( - tcx.adt_def(option_def_id), - tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()), - ), - mutbl: hir::Mutability::Not, - })], - tcx.mk_ptr(ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }), + vec![Ty::new_ptr( + tcx, + ty::TypeAndMut { + ty: Ty::new_adt( + tcx, + tcx.adt_def(option_def_id), + tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()), + ), + mutbl: hir::Mutability::Not, + }, + )], + Ty::new_ptr(tcx, ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }), ) } sym::ptr_mask => ( 1, vec![ - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), tcx.types.usize, ], - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), ), sym::copy | sym::copy_nonoverlapping => ( 1, vec![ - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), tcx.types.usize, ], - tcx.mk_unit(), + Ty::new_unit(tcx), ), sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => ( 1, vec![ - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), tcx.types.usize, ], - tcx.mk_unit(), + Ty::new_unit(tcx), ), sym::write_bytes | sym::volatile_set_memory => ( 1, vec![ - tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), tcx.types.u8, tcx.types.usize, ], - tcx.mk_unit(), + Ty::new_unit(tcx), ), sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32), sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64), @@ -324,10 +328,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::roundevenf64 => (0, vec![tcx.types.f64], tcx.types.f64), sym::volatile_load | sym::unaligned_volatile_load => { - (1, vec![tcx.mk_imm_ptr(param(0))], param(0)) + (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)) } sym::volatile_store | sym::unaligned_volatile_store => { - (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()) + (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)) } sym::ctpop @@ -339,28 +343,34 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { | sym::bitreverse => (1, vec![param(0)], param(0)), sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { - (1, vec![param(0), param(0)], tcx.mk_tup(&[param(0), tcx.types.bool])) + (1, vec![param(0), param(0)], Ty::new_tup(tcx, &[param(0), tcx.types.bool])) } - sym::ptr_guaranteed_cmp => { - (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.u8) - } + sym::ptr_guaranteed_cmp => ( + 1, + vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))], + tcx.types.u8, + ), sym::const_allocate => { - (0, vec![tcx.types.usize, tcx.types.usize], tcx.mk_mut_ptr(tcx.types.u8)) + (0, vec![tcx.types.usize, tcx.types.usize], Ty::new_mut_ptr(tcx, tcx.types.u8)) } sym::const_deallocate => ( 0, - vec![tcx.mk_mut_ptr(tcx.types.u8), tcx.types.usize, tcx.types.usize], - tcx.mk_unit(), + vec![Ty::new_mut_ptr(tcx, tcx.types.u8), tcx.types.usize, tcx.types.usize], + Ty::new_unit(tcx), ), - sym::ptr_offset_from => { - (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize) - } - sym::ptr_offset_from_unsigned => { - (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.usize) - } + sym::ptr_offset_from => ( + 1, + vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))], + tcx.types.isize, + ), + sym::ptr_offset_from_unsigned => ( + 1, + vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))], + tcx.types.usize, + ), sym::unchecked_div | sym::unchecked_rem | sym::exact_div => { (1, vec![param(0), param(0)], param(0)) } @@ -379,12 +389,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { } sym::float_to_int_unchecked => (2, vec![param(0)], param(1)), - sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()), + sym::assume => (0, vec![tcx.types.bool], Ty::new_unit(tcx)), sym::likely => (0, vec![tcx.types.bool], tcx.types.bool), sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool), - sym::read_via_copy => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)), - sym::write_via_move => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), + sym::read_via_copy => (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)), + sym::write_via_move => { + (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)) + } sym::discriminant_value => { let assoc_items = tcx.associated_item_def_ids( @@ -395,48 +407,47 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }; ( 1, - vec![ - tcx.mk_imm_ref( - ty::Region::new_late_bound(tcx, ty::INNERMOST, br), - param(0), - ), - ], - tcx.mk_projection(discriminant_def_id, tcx.mk_substs(&[param(0).into()])), + vec![Ty::new_imm_ref( + tcx, + ty::Region::new_late_bound(tcx, ty::INNERMOST, br), + param(0), + )], + Ty::new_projection(tcx, discriminant_def_id, tcx.mk_substs(&[param(0).into()])), ) } kw::Try => { - let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); + let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8); let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( [mut_u8], - tcx.mk_unit(), + Ty::new_unit(tcx), false, hir::Unsafety::Normal, Abi::Rust, )); let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( [mut_u8, mut_u8], - tcx.mk_unit(), + Ty::new_unit(tcx), false, hir::Unsafety::Normal, Abi::Rust, )); ( 0, - vec![tcx.mk_fn_ptr(try_fn_ty), mut_u8, tcx.mk_fn_ptr(catch_fn_ty)], + vec![Ty::new_fn_ptr(tcx, try_fn_ty), mut_u8, Ty::new_fn_ptr(tcx, catch_fn_ty)], tcx.types.i32, ) } sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) { - Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()), + Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], Ty::new_unit(tcx)), None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) { Some((va_list_ref_ty, va_list_ty)) => { - let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty); - (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit()) + let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty); + (0, vec![va_list_ptr_ty, va_list_ref_ty], Ty::new_unit(tcx)) } None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, @@ -446,12 +457,17 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, - sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), + sym::nontemporal_store => { + (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)) + } sym::raw_eq => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }; - let param_ty = - tcx.mk_imm_ref(ty::Region::new_late_bound(tcx, ty::INNERMOST, br), param(0)); + let param_ty = Ty::new_imm_ref( + tcx, + ty::Region::new_late_bound(tcx, ty::INNERMOST, br), + param(0), + ); (1, vec![param_ty; 2], tcx.types.bool) } @@ -460,7 +476,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::const_eval_select => (4, vec![param(0), param(1), param(2)], param(3)), sym::vtable_size | sym::vtable_align => { - (0, vec![tcx.mk_imm_ptr(tcx.mk_unit())], tcx.types.usize) + (0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize) } other => { @@ -479,7 +495,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let param = |n| { let name = Symbol::intern(&format!("P{}", n)); - tcx.mk_ty_param(n, name) + Ty::new_param(tcx, n, name) }; let name = it.ident.name; @@ -521,7 +537,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)), sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)), sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)), - sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()), + sym::simd_scatter => (3, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)), sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)), sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)), sym::simd_cast @@ -550,7 +566,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) name if name.as_str().starts_with("simd_shuffle") => { match name.as_str()["simd_shuffle".len()..].parse() { Ok(n) => { - let params = vec![param(0), param(0), tcx.mk_array(tcx.types.u32, n)]; + let params = vec![param(0), param(0), Ty::new_array(tcx, tcx.types.u32, n)]; (2, params, param(1)) } Err(_) => { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 506fdccd6c2..d4748b7ef0b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -561,7 +561,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( // our example, the type was `Self`, which will also be // `Self` in the GAT. let ty_param = gat_generics.param_at(*ty_idx, tcx); - let ty_param = tcx.mk_ty_param(ty_param.index, ty_param.name); + let ty_param = Ty::new_param(tcx, ty_param.index, ty_param.name); // Same for the region. In our example, 'a corresponds // to the 'me parameter. let region_param = gat_generics.param_at(*region_a_idx, tcx); @@ -981,7 +981,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b // intermediate types must be sized. let needs_drop_copy = || { packed && { - let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity(); + let ty = tcx.type_of(variant.tail().did).subst_identity(); let ty = tcx.erase_regions(ty); if ty.has_infer() { tcx.sess diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 2441c8667d4..79cc43edff1 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -336,15 +336,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b }; - check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty)) + check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty)) } (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => { let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; - check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty)) + check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty)) } - (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty)), + (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => { + check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty)) + } (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index eb299a1ea79..025bab14021 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -343,7 +343,7 @@ fn emit_orphan_check_error<'tcx>( // That way if we had `Vec<MyType>`, we will properly attribute the // problem to `Vec<T>` and avoid confusing the user if they were to see // `MyType` in the error. - ty::Adt(def, _) => tcx.mk_adt(*def, ty::List::empty()), + ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()), _ => ty, }; let msg = |ty: &str, postfix: &str| { @@ -605,7 +605,9 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: } let self_ty_root = match self_ty.kind() { - ty::Adt(def, _) => tcx.mk_adt(*def, InternalSubsts::identity_for_item(tcx, def.did())), + ty::Adt(def, _) => { + Ty::new_adt(tcx, *def, InternalSubsts::identity_for_item(tcx, def.did())) + } _ => unimplemented!("unexpected self ty {:?}", self_ty), }; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index d7ac9e7ce73..f47df4f215b 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -380,7 +380,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - self.tcx().ty_error_with_message(span, "bad placeholder type") + Ty::new_error_with_message(self.tcx(), span, "bad placeholder type") } fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> { @@ -390,7 +390,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { // left alone. r => bug!("unexpected region: {r:?}"), }); - self.tcx().const_error_with_message(ty, span, "bad placeholder constant") + ty::Const::new_error_with_message(self.tcx(), ty, span, "bad placeholder constant") } fn projected_ty_from_poly_trait_ref( @@ -407,7 +407,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { item_segment, trait_ref.substs, ); - self.tcx().mk_projection(item_def_id, item_substs) + Ty::new_projection(self.tcx(), item_def_id, item_substs) } else { // There are no late-bound regions; we can just ignore the binder. let (mut mpart_sugg, mut inferred_sugg) = (None, None); @@ -471,14 +471,15 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } _ => {} } - self.tcx().ty_error(self.tcx().sess.emit_err( - errors::AssociatedTypeTraitUninferredGenericParams { + Ty::new_error( + self.tcx(), + self.tcx().sess.emit_err(errors::AssociatedTypeTraitUninferredGenericParams { span, inferred_sugg, bound, mpart_sugg, - }, - )) + }), + ) } } @@ -1239,7 +1240,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( } else { ty::Binder::dummy(tcx.mk_fn_sig( fn_sig.inputs().iter().copied(), - tcx.ty_error(guar), + Ty::new_error(tcx, guar), fn_sig.c_variadic, fn_sig.unsafety, fn_sig.abi, @@ -1332,7 +1333,7 @@ fn suggest_impl_trait<'tcx>( let item_ty = ocx.normalize( &ObligationCause::misc(span, def_id), param_env, - tcx.mk_projection(assoc_item_def_id, substs), + Ty::new_projection(tcx, assoc_item_def_id, substs), ); // FIXME(compiler-errors): We may benefit from resolving regions here. if ocx.select_where_possible().is_empty() diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 2206f640529..ccc9f808411 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{kw, Symbol}; -use rustc_span::Span; +use rustc_span::{sym, Span}; pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; @@ -101,6 +101,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { param_def_id_to_index, has_self: generics.has_self, has_late_bound_regions: generics.has_late_bound_regions, + host_effect_index: None, }; } else { // HACK(eddyb) this provides the correct generics when @@ -226,10 +227,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { let has_self = opt_self.is_some(); let mut parent_has_self = false; let mut own_start = has_self as u32; + let mut host_effect_index = None; let parent_count = parent_def_id.map_or(0, |def_id| { let generics = tcx.generics_of(def_id); assert!(!has_self); parent_has_self = generics.has_self; + host_effect_index = generics.host_effect_index; own_start = generics.count() as u32; generics.parent_count + generics.params.len() }); @@ -251,11 +254,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // Now create the real type and const parameters. let type_start = own_start - has_self as u32 + params.len() as u32; - let mut i = 0; + let mut i: u32 = 0; let mut next_index = || { let prev = i; i += 1; - prev as u32 + type_start + prev + type_start }; const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \ @@ -295,7 +298,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { }) } GenericParamKind::Const { default, .. } => { - if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() { + let is_host_param = tcx.has_attr(param.def_id, sym::rustc_host); + + if !matches!(allow_defaults, Defaults::Allowed) + && default.is_some() + // `rustc_host` effect params are allowed to have defaults. + && !is_host_param + { tcx.sess.span_err( param.span, "defaults for const parameters are only allowed in \ @@ -303,8 +312,18 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { ); } + let index = next_index(); + + if is_host_param { + if let Some(idx) = host_effect_index { + bug!("parent also has host effect param? index: {idx}, def: {def_id:?}"); + } + + host_effect_index = Some(parent_count + index as usize); + } + Some(ty::GenericParamDef { - index: next_index(), + index, name: param.name.ident().name, def_id: param.def_id.to_def_id(), pure_wrt_drop: param.pure_wrt_drop, @@ -356,6 +375,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { param_def_id_to_index, has_self: has_self || parent_has_self, has_late_bound_regions: has_late_bound_regions(tcx, node), + host_effect_index, } } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 8b3f98493c1..57f74172ed0 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -20,7 +20,8 @@ fn associated_type_bounds<'tcx>( ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Clause<'tcx>, Span)] { - let item_ty = tcx.mk_projection( + let item_ty = Ty::new_projection( + tcx, assoc_item_def_id.to_def_id(), InternalSubsts::identity_for_item(tcx, assoc_item_def_id), ); @@ -91,7 +92,8 @@ pub(super) fn explicit_item_bounds( tcx, opaque_def_id.expect_local(), opaque_ty.bounds, - tcx.mk_projection( + Ty::new_projection( + tcx, def_id.to_def_id(), ty::InternalSubsts::identity_for_item(tcx, def_id), ), @@ -117,9 +119,9 @@ pub(super) fn explicit_item_bounds( }) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() { - tcx.mk_projection(def_id.to_def_id(), substs) + Ty::new_projection(tcx, def_id.to_def_id(), substs) } else { - tcx.mk_opaque(def_id.to_def_id(), substs) + Ty::new_opaque(tcx, def_id.to_def_id(), substs) }; opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 1d00dc2a11d..12936664130 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -243,9 +243,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let name = param.name.ident().name; let param_const = ty::ParamConst::new(index, name); - let ct_ty = tcx.type_of(param.def_id.to_def_id()).subst_identity(); + let ct_ty = tcx + .type_of(param.def_id.to_def_id()) + .no_bound_vars() + .expect("const parameters cannot be generic"); - let ct = tcx.mk_const(param_const, ct_ty); + let ct = ty::Const::new_param(tcx, param_const, ct_ty); predicates.insert(( ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx), @@ -716,6 +719,7 @@ pub(super) fn type_param_predicates( (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident), ) -> ty::GenericPredicates<'_> { use rustc_hir::*; + use rustc_middle::ty::Ty; // In the AST, bounds can derive from two places. Either // written inline like `<T: Foo>` or in a where-clause like @@ -725,7 +729,7 @@ pub(super) fn type_param_predicates( let param_owner = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(param_owner); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; - let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)); + let ty = Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id)); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 97a3e01c52a..acd0bcd8e5c 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_session::lint; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::fmt; use crate::errors; @@ -338,7 +338,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { Scope::TraitRefBoundary { .. } => { // We should only see super trait lifetimes if there is a `Binder` above - assert!(supertrait_bound_vars.is_empty()); + // though this may happen when we call `poly_trait_ref_binder_info` with + // an (erroneous, #113423) associated return type bound in an impl header. + if !supertrait_bound_vars.is_empty() { + self.tcx.sess.delay_span_bug( + DUMMY_SP, + format!( + "found supertrait lifetimes without a binder to append \ + them to: {supertrait_bound_vars:?}" + ), + ); + } break (vec![], BinderScopeType::Normal); } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index bd92ee4b550..3755342aef5 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -16,6 +16,7 @@ mod opaque; fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { use hir::*; + use rustc_middle::ty::Ty; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let Node::AnonConst(_) = tcx.hir().get(hir_id) else { panic!() }; @@ -25,13 +26,13 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let (generics, arg_idx) = match parent_node { // Easy case: arrays repeat expressions. - Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) + Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) if constant.hir_id() == hir_id => { return tcx.types.usize } - Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => { + Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => { return tcx.typeck(def_id).node_type(e.hir_id) } Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) @@ -67,7 +68,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { ) => { let Some(trait_def_id) = trait_ref.trait_def_id() else { - return tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find trait"); + return Ty::new_error_with_message(tcx,tcx.def_span(def_id), "Could not find trait"); }; let assoc_items = tcx.associated_items(trait_def_id); let assoc_item = assoc_items.find_by_name_and_kind( @@ -79,7 +80,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .expect("const parameter types cannot be generic") } else { // FIXME(associated_const_equality): add a useful error message here. - tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find associated const on trait") + Ty::new_error_with_message(tcx,tcx.def_span(def_id), "Could not find associated const on trait") } } @@ -99,7 +100,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // arm would handle this. // // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU - Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => { + Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => { // Find the Item containing the associated type so we can create an ItemCtxt. // Using the ItemCtxt convert the HIR for the unresolved assoc type into a // ty which is a fully resolved projection. @@ -137,7 +138,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { (generics, arg_index) } else { // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU - return tcx.ty_error_with_message( + return Ty::new_error_with_message(tcx, tcx.def_span(def_id), "unexpected non-GAT usage of an anon const", ); @@ -154,7 +155,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // As there is no relevant param for `def_id`, we simply return // `None` here. let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else { - return tcx.ty_error_with_message( + return Ty::new_error_with_message(tcx, tcx.def_span(def_id), format!("unable to find type-dependent def for {:?}", parent_node_id), ); @@ -174,12 +175,12 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { (tcx.generics_of(type_dependent_def), idx) } - Node::Ty(&Ty { kind: TyKind::Path(_), .. }) + Node::Ty(&hir::Ty { kind: TyKind::Path(_), .. }) | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. }) | Node::TraitRef(..) | Node::Pat(_) => { let path = match parent_node { - Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. }) + Node::Ty(&hir::Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. }) | Node::TraitRef(&TraitRef { path, .. }) => &*path, Node::Expr(&Expr { kind: @@ -195,14 +196,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) { path } else { - return tcx.ty_error_with_message( + return Ty::new_error_with_message(tcx, tcx.def_span(def_id), format!("unable to find const parent for {} in pat {:?}", hir_id, pat), ); } } _ => { - return tcx.ty_error_with_message( + return Ty::new_error_with_message(tcx, tcx.def_span(def_id), format!("unexpected const parent path {:?}", parent_node), ); @@ -224,7 +225,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .position(|ct| ct.hir_id == hir_id) .map(|idx| (idx, seg))) }) else { - return tcx.ty_error_with_message( + return Ty::new_error_with_message(tcx, tcx.def_span(def_id), "no arg matching AnonConst in path", ); @@ -233,7 +234,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let generics = match tcx.res_generics_def_id(segment.res) { Some(def_id) => tcx.generics_of(def_id), None => { - return tcx.ty_error_with_message( + return Ty::new_error_with_message(tcx, tcx.def_span(def_id), format!("unexpected anon const res {:?} in path: {:?}", segment.res, path), ); @@ -243,7 +244,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { (generics, arg_index) } - _ => return tcx.ty_error_with_message( + _ => return Ty::new_error_with_message(tcx, tcx.def_span(def_id), format!("unexpected const parent in type_of(): {parent_node:?}"), ), @@ -269,7 +270,8 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { { tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic") } else { - return tcx.ty_error_with_message( + return Ty::new_error_with_message( + tcx, tcx.def_span(def_id), format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"), ); @@ -305,6 +307,9 @@ fn get_path_containing_arg_in_pat<'hir>( } pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty<'_>> { + use rustc_hir::*; + use rustc_middle::ty::Ty; + // If we are computing `type_of` the synthesized associated type for an RPITIT in the impl // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the // associated type in the impl. @@ -317,7 +322,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty return map[&assoc_item.trait_item_def_id.unwrap()]; } Err(_) => { - return ty::EarlyBinder::bind(tcx.ty_error_with_message( + return ty::EarlyBinder::bind(Ty::new_error_with_message( + tcx, DUMMY_SP, "Could not collect return position impl trait in trait tys", )); @@ -325,8 +331,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty } } - use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let icx = ItemCtxt::new(tcx, def_id); @@ -335,7 +339,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty Node::TraitItem(item) => match item.kind { TraitItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id.to_def_id(), substs) + Ty::new_fn_def(tcx, def_id.to_def_id(), substs) } TraitItemKind::Const(ty, body_id) => body_id .and_then(|body_id| { @@ -360,7 +364,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty Node::ImplItem(item) => match item.kind { ImplItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id.to_def_id(), substs) + Ty::new_fn_def(tcx, def_id.to_def_id(), substs) } ImplItemKind::Const(ty, body_id) => { if is_suggestable_infer_ty(ty) { @@ -417,18 +421,18 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty span: spans.into(), note: (), }); - tcx.ty_error(guar) + Ty::new_error(tcx, guar) } _ => icx.to_ty(*self_ty), }, ItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id.to_def_id(), substs) + Ty::new_fn_def(tcx, def_id.to_def_id(), substs) } ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { let def = tcx.adt_def(def_id); let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_adt(def, substs) + Ty::new_adt(tcx, def, substs) } ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias { .. }, @@ -469,10 +473,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty Node::ForeignItem(foreign_item) => match foreign_item.kind { ForeignItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id.to_def_id(), substs) + Ty::new_fn_def(tcx, def_id.to_def_id(), substs) } ForeignItemKind::Static(t, _) => icx.to_ty(t), - ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()), + ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()), }, Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def { @@ -481,7 +485,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty } VariantData::Tuple(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id.to_def_id(), substs) + Ty::new_fn_def(tcx, def_id.to_def_id(), substs) } }, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 4d96a7ff4c3..957a6bb3481 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -6,7 +6,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::DUMMY_SP; -use crate::errors::UnconstrainedOpaqueType; +use crate::errors::{TaitForwardCompat, UnconstrainedOpaqueType}; /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions /// laid for "higher-order pattern unification". @@ -84,7 +84,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local _ => "item", }, }); - tcx.ty_error(reported) + Ty::new_error(tcx, reported) } } @@ -128,7 +128,8 @@ impl TaitConstraintLocator<'_> { // ``` let tables = self.tcx.typeck(item_def_id); if let Some(guar) = tables.tainted_by_errors { - self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) }); + self.found = + Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) }); return; } @@ -138,6 +139,15 @@ impl TaitConstraintLocator<'_> { continue; } constrained = true; + if !self.tcx.opaque_types_defined_by(item_def_id).contains(&self.def_id) { + self.tcx.sess.emit_err(TaitForwardCompat { + span: hidden_type.span, + item_span: self + .tcx + .def_ident_span(item_def_id) + .unwrap_or_else(|| self.tcx.def_span(item_def_id)), + }); + } let concrete_type = self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params( opaque_type_key, @@ -162,7 +172,7 @@ impl TaitConstraintLocator<'_> { if let Some(prev) = &mut self.found { if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() { let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit(); - prev.ty = self.tcx.ty_error(guar); + prev.ty = Ty::new_error(self.tcx, guar); } } else { self.found = Some(concrete_type); @@ -258,7 +268,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( if let Some(guar) = tables.tainted_by_errors { // Some error in the owner fn prevented us from populating // the `concrete_opaque_types` table. - tcx.ty_error(guar) + Ty::new_error(tcx, guar) } else { // Fall back to the RPIT we inferred during HIR typeck if let Some(hir_opaque_ty) = hir_opaque_ty { @@ -270,7 +280,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( // so we can just make the hidden type be `!`. // For backwards compatibility reasons, we fall back to // `()` until we the diverging default is changed. - tcx.mk_diverging_default() + Ty::new_diverging_default(tcx) } } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index cb840592edd..c2d2e5f7e50 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -5,7 +5,7 @@ use rustc_errors::{ error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, }; -use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -184,6 +184,16 @@ pub struct UnconstrainedOpaqueType { pub what: &'static str, } +#[derive(Diagnostic)] +#[diag(hir_analysis_tait_forward_compat)] +#[note] +pub struct TaitForwardCompat { + #[primary_span] + pub span: Span, + #[note] + pub item_span: Span, +} + pub struct MissingTypeParams { pub span: Span, pub def_span: Span, @@ -900,3 +910,11 @@ pub(crate) enum LateBoundInApit { param_span: Span, }, } + +#[derive(LintDiagnostic)] +#[diag(hir_analysis_unused_associated_type_bounds)] +#[note] +pub struct UnusedAssociatedTypeBounds { + #[suggestion(code = "")] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index d2a1b1c1a42..a68832d96a6 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -319,16 +319,19 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { expected_return_type = main_fnsig.output(); } else { // standard () main return type - expected_return_type = ty::Binder::dummy(tcx.mk_unit()); + expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx)); } if error { return; } - let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| { - tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust) - })); + let se_ty = Ty::new_fn_ptr( + tcx, + expected_return_type.map_bound(|expected_return_type| { + tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust) + }), + ); require_same_types( tcx, @@ -339,7 +342,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ), param_env, se_ty, - tcx.mk_fn_ptr(main_fnsig), + Ty::new_fn_ptr(tcx, main_fnsig), ); } fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { @@ -397,13 +400,16 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { } } - let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( - [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))], - tcx.types.isize, - false, - hir::Unsafety::Normal, - Abi::Rust, - ))); + let se_ty = Ty::new_fn_ptr( + tcx, + ty::Binder::dummy(tcx.mk_fn_sig( + [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))], + tcx.types.isize, + false, + hir::Unsafety::Normal, + Abi::Rust, + )), + ); require_same_types( tcx, @@ -414,7 +420,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { ), ty::ParamEnv::empty(), // start should not have any where bounds. se_ty, - tcx.mk_fn_ptr(tcx.fn_sig(start_def_id).subst_identity()), + Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).subst_identity()), ); } _ => { diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 49aee6b59a2..066e7449189 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -7,7 +7,7 @@ use rustc_arena::DroplessArena; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, CrateVariancesMap, ImplTraitInTraitData, SubstsRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; use std::ops::ControlFlow; @@ -59,13 +59,6 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => { return variance_of_opaque(tcx, item_def_id); } - DefKind::AssocTy => { - if let Some(ImplTraitInTraitData::Trait { .. }) = - tcx.opt_rpitit_info(item_def_id.to_def_id()) - { - return variance_of_opaque(tcx, item_def_id); - } - } _ => {} } @@ -125,7 +118,8 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary // at all for RPITITs. ty::Alias(_, ty::AliasTy { def_id, substs, .. }) - if self.tcx.is_impl_trait_in_trait(*def_id) => + if self.tcx.is_impl_trait_in_trait(*def_id) + && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() => { self.visit_opaque(*def_id, substs) } diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index c7fa27da1ac..e8720a5da02 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -65,7 +65,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // us to give better error messages (pointing to a usually better // arm for inconsistent arms or to the whole match when a `()` type // is required). - Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety, + Expectation::ExpectHasType(ety) if ety != Ty::new_unit(self.tcx) => ety, _ => self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span: expr.span, diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index be908c41c94..f306653c1ab 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -6,8 +6,9 @@ use crate::type_error_struct; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, StashKey}; use rustc_hir as hir; -use rustc_hir::def::{self, CtorKind, Namespace, Res}; +use rustc_hir::def::{self, CtorKind, DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; +use rustc_hir::HirId; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::{ infer, @@ -232,12 +233,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(trait_def_id) = opt_trait_def_id else { continue }; let opt_input_type = opt_arg_exprs.map(|arg_exprs| { - self.tcx.mk_tup_from_iter(arg_exprs.iter().map(|e| { - self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: e.span, - }) - })) + Ty::new_tup_from_iter( + self.tcx, + arg_exprs.iter().map(|e| { + self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: e.span, + }) + }), + ) }); if let Some(ok) = self.lookup_method_in_trait( @@ -376,15 +380,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { let (fn_sig, def_id) = match *callee_ty.kind() { - ty::FnDef(def_id, subst) => { - let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, subst); + ty::FnDef(def_id, substs) => { + self.enforce_context_effects(call_expr.hir_id, call_expr.span, def_id, substs); + let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs); // Unit testing: function items annotated with // `#[rustc_evaluate_where_clauses]` trigger special output // to let us test the trait evaluation system. if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) { let predicates = self.tcx.predicates_of(def_id); - let predicates = predicates.instantiate(self.tcx, subst); + let predicates = predicates.instantiate(self.tcx, substs); for (predicate, predicate_span) in predicates { let obligation = Obligation::new( self.tcx, @@ -405,6 +410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } (fn_sig, Some(def_id)) } + // FIXME(effects): these arms should error because we can't enforce them ty::FnPtr(sig) => (sig, None), _ => { for arg in arg_exprs { @@ -432,7 +438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs); - return self.tcx.ty_error(err); + return Ty::new_error(self.tcx, err); } }; @@ -739,6 +745,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_sig.output() } + #[tracing::instrument(level = "debug", skip(self, span))] + pub(super) fn enforce_context_effects( + &self, + call_expr_hir: HirId, + span: Span, + callee_did: DefId, + callee_substs: SubstsRef<'tcx>, + ) { + let tcx = self.tcx; + + if !tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you { + return; + } + + // Compute the constness required by the context. + let context = tcx.hir().enclosing_body_owner(call_expr_hir); + let const_context = tcx.hir().body_const_context(context); + + let kind = tcx.def_kind(context.to_def_id()); + debug_assert_ne!(kind, DefKind::ConstParam); + + if tcx.has_attr(context.to_def_id(), sym::rustc_do_not_const_check) { + trace!("do not const check this context"); + return; + } + + let effect = match const_context { + Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => tcx.consts.false_, + Some(hir::ConstContext::ConstFn) => { + let substs = ty::InternalSubsts::identity_for_item(tcx, context); + substs.host_effect_param().expect("ConstContext::Maybe must have host effect param") + } + None => tcx.consts.true_, + }; + + let generics = tcx.generics_of(callee_did); + + trace!(?effect, ?generics, ?callee_substs); + + if let Some(idx) = generics.host_effect_index { + let param = callee_substs.const_at(idx); + let cause = self.misc(span); + match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) { + Ok(infer::InferOk { obligations, value: () }) => { + self.register_predicates(obligations); + } + Err(e) => { + // FIXME(effects): better diagnostic + self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit(); + } + } + } + } + fn confirm_overloaded_call( &self, call_expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index f1b3d13c24d..633933317c0 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -103,15 +103,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(match *t.kind() { ty::Slice(_) | ty::Str => Some(PointerKind::Length), ty::Dynamic(ref tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())), - ty::Adt(def, substs) if def.is_struct() => { - match def.non_enum_variant().fields.raw.last() { - None => Some(PointerKind::Thin), - Some(f) => { - let field_ty = self.field_ty(span, f, substs); - self.pointer_kind(field_ty, span)? - } + ty::Adt(def, substs) if def.is_struct() => match def.non_enum_variant().tail_opt() { + None => Some(PointerKind::Thin), + Some(f) => { + let field_ty = self.field_ty(span, f, substs); + self.pointer_kind(field_ty, span)? } - } + }, ty::Tuple(fields) => match fields.last() { None => Some(PointerKind::Thin), Some(&f) => self.pointer_kind(f, span)?, @@ -393,7 +391,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { && fcx .try_coerce( self.expr, - fcx.tcx.mk_ref( + Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, TypeAndMut { ty: expr_ty, mutbl }, ), @@ -410,7 +408,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { && fcx .try_coerce( self.expr, - fcx.tcx.mk_ref( + Ty::new_ref(fcx.tcx, expr_reg, TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut }, ), @@ -428,7 +426,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { && fcx .try_coerce( self.expr, - fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }), + Ty::new_ref(fcx.tcx,reg, TypeAndMut { ty: self.expr_ty, mutbl }), self.cast_ty, AllowTwoPhase::No, None, @@ -441,7 +439,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { && fcx .try_coerce( self.expr, - fcx.tcx.mk_ref( + Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, TypeAndMut { ty: self.expr_ty, mutbl }, ), @@ -765,7 +763,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { let res = fcx.try_coerce( self.expr, self.expr_ty, - fcx.tcx.mk_fn_ptr(f), + Ty::new_fn_ptr(fcx.tcx, f), AllowTwoPhase::No, None, ); @@ -957,7 +955,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // from a region pointer to a vector. // Coerce to a raw pointer so that we generate AddressOf in MIR. - let array_ptr_type = fcx.tcx.mk_ptr(m_expr); + let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr); fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) .unwrap_or_else(|_| { bug!( diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 0a1b639af51..8b57e311fc0 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -62,11 +62,11 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType); yield_ty } else { - tcx.mk_unit() + Ty::new_unit(tcx,) }; // Resume type defaults to `()` if the generator has no argument. - let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit()); + let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| Ty::new_unit(tcx,)); fcx.resume_yield_tys = Some((resume_ty, yield_ty)); } @@ -256,10 +256,10 @@ fn check_lang_start_fn<'tcx>( // for example `start`'s generic should be a type parameter let generics = tcx.generics_of(def_id); let fn_generic = generics.param_at(0, tcx); - let generic_ty = tcx.mk_ty_param(fn_generic.index, fn_generic.name); + let generic_ty = Ty::new_param(tcx, fn_generic.index, fn_generic.name); let expected_fn_sig = tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust); - let expected_ty = tcx.mk_fn_ptr(Binder::dummy(expected_fn_sig)); + let expected_ty = Ty::new_fn_ptr(tcx, Binder::dummy(expected_fn_sig)); // we emit the same error to suggest changing the arg no matter what's wrong with the arg let emit_main_fn_arg_err = || { @@ -316,9 +316,9 @@ fn check_lang_start_fn<'tcx>( if !argv_is_okay { let inner_ptr_ty = - tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: tcx.types.u8 }); + Ty::new_ptr(tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: tcx.types.u8 }); let expected_ty = - tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: inner_ptr_ty }); + Ty::new_ptr(tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: inner_ptr_ty }); tcx.sess.emit_err(LangStartIncorrectParam { param_span: decl.inputs[2].span, param_num: 3, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index c64b64e925a..78a9ac49de2 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -117,7 +117,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ); - return self.tcx.mk_generator( + return Ty::new_generator( + self.tcx, expr_def_id.to_def_id(), generator_substs.substs, movability, @@ -128,7 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the `closures` table. let sig = bound_sig.map_bound(|sig| { self.tcx.mk_fn_sig( - [self.tcx.mk_tup(sig.inputs())], + [Ty::new_tup(self.tcx, sig.inputs())], sig.output(), sig.c_variadic, sig.unsafety, @@ -155,12 +156,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ClosureSubstsParts { parent_substs, closure_kind_ty, - closure_sig_as_fn_ptr_ty: self.tcx.mk_fn_ptr(sig), + closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(self.tcx, sig), tupled_upvars_ty, }, ); - self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs) + Ty::new_closure(self.tcx, expr_def_id.to_def_id(), closure_substs.substs) } /// Given the expected type, figures out what it can about this closure we @@ -190,7 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (sig, kind) } ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates( - self.tcx.mk_ty_var(self.root_var(vid)), + Ty::new_var(self.tcx, self.root_var(vid)), self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)), ), ty::FnPtr(sig) => { @@ -806,7 +807,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { guar: ErrorGuaranteed, ) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; - let err_ty = self.tcx.ty_error(guar); + let err_ty = Ty::new_error(self.tcx, guar); let supplied_arguments = decl.inputs.iter().map(|a| { // Convert the types that the user supplied (if any), but ignore them. diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 9a037f7110e..dc58d99ed9d 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::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::{Obligation, PredicateObligation}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ - Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, + Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::RelateResult; @@ -192,7 +192,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let _ = self.commit_if_ok(|_| { self.at(&self.cause, self.param_env).eq(DefineOpaqueTypes::Yes, a, b) }); - return success(vec![], self.fcx.tcx.ty_error(guar), vec![]); + return success(vec![], Ty::new_error(self.fcx.tcx, guar), vec![]); } // Coercing from `!` to any type is allowed: @@ -440,7 +440,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } r_borrow_var.unwrap() }; - let derefd_ty_a = self.tcx.mk_ref( + let derefd_ty_a = Ty::new_ref( + self.tcx, r, TypeAndMut { ty: referent_ty, @@ -558,9 +559,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Adjustment { kind: Adjust::Deref(None), target: ty_a }, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)), - target: self - .tcx - .mk_ref(r_borrow, ty::TypeAndMut { mutbl: mutbl_b, ty: ty_a }), + target: Ty::new_ref( + self.tcx, + r_borrow, + ty::TypeAndMut { mutbl: mutbl_b, ty: ty_a }, + ), }, )) } @@ -571,7 +574,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Adjustment { kind: Adjust::Deref(None), target: ty_a }, Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)), - target: self.tcx.mk_ptr(ty::TypeAndMut { mutbl: mt_b, ty: ty_a }), + target: Ty::new_ptr(self.tcx, ty::TypeAndMut { mutbl: mt_b, ty: ty_a }), }, )) } @@ -589,7 +592,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { }; let coerce_target = self.next_ty_var(origin); let mut coercion = self.unify_and(coerce_target, target, |target| { - let unsize = Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target }; + let unsize = Adjustment { kind: Adjust::Pointer(PointerCoercion::Unsize), target }; match reborrow { None => vec![unsize], Some((ref deref, ref autoref)) => vec![deref.clone(), autoref.clone(), unsize], @@ -629,9 +632,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { while !queue.is_empty() { let obligation = queue.remove(0); debug!("coerce_unsized resolve step: {:?}", obligation); - let bound_predicate = obligation.predicate.kind(); - let trait_pred = match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) + let trait_pred = match obligation.predicate.kind().no_bound_vars() { + Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))) if traits.contains(&trait_pred.def_id()) => { if unsize_did == trait_pred.def_id() { @@ -649,7 +651,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { has_unsized_tuple_coercion = true; } } - bound_predicate.rebind(trait_pred) + trait_pred } _ => { coercion.obligations.push(obligation); @@ -661,8 +663,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Ok(None) => { if trait_pred.def_id() == unsize_did { let trait_pred = self.resolve_vars_if_possible(trait_pred); - let self_ty = trait_pred.skip_binder().self_ty(); - let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty(); + let self_ty = trait_pred.self_ty(); + let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty(); debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred); match (self_ty.kind(), unsize_ty.kind()) { (&ty::Infer(ty::TyVar(v)), ty::Dynamic(..)) @@ -847,7 +849,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { a, fn_ty_a, b, - simple(Adjust::Pointer(PointerCast::UnsafeFnPointer)), + simple(Adjust::Pointer(PointerCoercion::UnsafeFnPointer)), identity, ) } @@ -883,7 +885,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.at(&self.cause, self.param_env).normalize(a_sig); obligations.extend(o1); - let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig); + let a_fn_pointer = Ty::new_fn_ptr(self.tcx, a_sig); let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn( a_fn_pointer, a_sig, @@ -891,16 +893,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { |unsafe_ty| { vec![ Adjustment { - kind: Adjust::Pointer(PointerCast::ReifyFnPointer), + kind: Adjust::Pointer(PointerCoercion::ReifyFnPointer), target: a_fn_pointer, }, Adjustment { - kind: Adjust::Pointer(PointerCast::UnsafeFnPointer), + kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer), target: unsafe_ty, }, ] }, - simple(Adjust::Pointer(PointerCast::ReifyFnPointer)), + simple(Adjust::Pointer(PointerCoercion::ReifyFnPointer)), )?; obligations.extend(o2); @@ -945,12 +947,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let closure_sig = substs_a.as_closure().sig(); let unsafety = fn_ty.unsafety(); let pointer_ty = - self.tcx.mk_fn_ptr(self.tcx.signature_unclosure(closure_sig, unsafety)); + Ty::new_fn_ptr(self.tcx, self.tcx.signature_unclosure(closure_sig, unsafety)); debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty); self.unify_and( pointer_ty, b, - simple(Adjust::Pointer(PointerCast::ClosureFnPointer(unsafety))), + simple(Adjust::Pointer(PointerCoercion::ClosureFnPointer(unsafety))), ) } _ => self.unify_and(a, b, identity), @@ -973,7 +975,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { coerce_mutbls(mt_a.mutbl, mutbl_b)?; // Check that the types which they point at are compatible. - let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut { mutbl: mutbl_b, ty: mt_a.ty }); + let a_unsafe = Ty::new_ptr(self.tcx, ty::TypeAndMut { mutbl: mutbl_b, ty: mt_a.ty }); // Although references and unsafe ptrs have the same // representation, we still register an Adjust::DerefRef so that // regionck knows that the region for `a` must be valid here. @@ -985,7 +987,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ] }) } else if mt_a.mutbl != mutbl_b { - self.unify_and(a_unsafe, b, simple(Adjust::Pointer(PointerCast::MutToConstPointer))) + self.unify_and(a_unsafe, b, simple(Adjust::Pointer(PointerCoercion::MutToConstPointer))) } else { self.unify_and(a_unsafe, b, identity) } @@ -1015,7 +1017,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (adjustments, _) = self.register_infer_ok_obligations(ok); self.apply_adjustments(expr, adjustments); - Ok(if let Err(guar) = expr_ty.error_reported() { self.tcx.ty_error(guar) } else { target }) + Ok(if let Err(guar) = expr_ty.error_reported() { + Ty::new_error(self.tcx, guar) + } else { + target + }) } /// Same as `try_coerce()`, but without side-effects. @@ -1179,15 +1185,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|ok| self.register_infer_ok_obligations(ok))?; // Reify both sides and return the reified fn pointer type. - let fn_ptr = self.tcx.mk_fn_ptr(sig); + let fn_ptr = Ty::new_fn_ptr(self.tcx, sig); let prev_adjustment = match prev_ty.kind() { - ty::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer(a_sig.unsafety())), - ty::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer), + ty::Closure(..) => { + Adjust::Pointer(PointerCoercion::ClosureFnPointer(a_sig.unsafety())) + } + ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer), _ => unreachable!(), }; let next_adjustment = match new_ty.kind() { - ty::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer(b_sig.unsafety())), - ty::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer), + ty::Closure(..) => { + Adjust::Pointer(PointerCoercion::ClosureFnPointer(b_sig.unsafety())) + } + ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer), _ => unreachable!(), }; for expr in exprs.iter().map(|e| e.as_coercion_site()) { @@ -1430,7 +1440,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx, cause, None, - fcx.tcx.mk_unit(), + Ty::new_unit(fcx.tcx), Some(augment_error), label_unit_as_expected, ) @@ -1461,7 +1471,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // If we see any error types, just propagate that error // upwards. if let Err(guar) = (expression_ty, self.merged_ty()).error_reported() { - self.final_ty = Some(fcx.tcx.ty_error(guar)); + self.final_ty = Some(Ty::new_error(fcx.tcx, guar)); return; } @@ -1649,7 +1659,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let reported = err.emit_unless(unsized_return); - self.final_ty = Some(fcx.tcx.ty_error(reported)); + self.final_ty = Some(Ty::new_error(fcx.tcx, reported)); } } } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 47f3c6b8407..cc8198aab25 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1366,10 +1366,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // ``` let ref_ty = match mutability { hir::Mutability::Mut => { - self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, checked_ty) + Ty::new_mut_ref(self.tcx,self.tcx.lifetimes.re_static, checked_ty) } hir::Mutability::Not => { - self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, checked_ty) + Ty::new_imm_ref(self.tcx,self.tcx.lifetimes.re_static, checked_ty) } }; if self.can_coerce(ref_ty, expected) { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 52e3779cd41..72b29f7b6e9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] { target.to_owned() } else { - self.tcx().ty_error(reported) + Ty::new_error(self.tcx(), reported) }; } @@ -321,7 +321,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.types.never } else { // There was an error; make type-check fail. - tcx.ty_error_misc() + Ty::new_misc_error(tcx) } } ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), @@ -361,7 +361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected), ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr), ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src), - hir::ExprKind::Err(guar) => tcx.ty_error(guar), + hir::ExprKind::Err(guar) => Ty::new_error(tcx, guar), } } @@ -399,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } - oprnd_t = tcx.ty_error(err.emit()); + oprnd_t = Ty::new_error(tcx, err.emit()); } } hir::UnOp::Not => { @@ -449,10 +449,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tm = ty::TypeAndMut { ty, mutbl }; match kind { - _ if tm.ty.references_error() => self.tcx.ty_error_misc(), + _ if tm.ty.references_error() => Ty::new_misc_error(self.tcx), hir::BorrowKind::Raw => { self.check_named_place_expr(oprnd); - self.tcx.mk_ptr(tm) + Ty::new_ptr(self.tcx, tm) } hir::BorrowKind::Ref => { // Note: at this point, we cannot say what the best lifetime @@ -470,7 +470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // whose address was taken can actually be made to live as long // as it needs to live. let region = self.next_region_var(infer::AddrOfRegion(expr.span)); - self.tcx.mk_ref(region, tm) + Ty::new_ref(self.tcx, region, tm) } } } @@ -528,11 +528,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let e = self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); - tcx.ty_error(e) + Ty::new_error(tcx, e) } Res::Def(DefKind::Variant, _) => { let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value"); - tcx.ty_error(e) + Ty::new_error(tcx, e) } _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, }; @@ -620,7 +620,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(ctxt) => ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()), None => { // Avoid ICE when `break` is inside a closure (#65383). - return tcx.ty_error_with_message( + return Ty::new_error_with_message( + tcx, expr.span, "break was outside loop, but no error was emitted", ); @@ -631,7 +632,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the loop context is not a `loop { }`, then break with // a value is illegal, and `opt_coerce_to` will be `None`. // Just set expectation to error in that case. - let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.ty_error_misc()); + let coerce_to = opt_coerce_to.unwrap_or_else(|| Ty::new_misc_error(tcx)); // Recurse without `enclosing_breakables` borrowed. e_ty = self.check_expr_with_hint(e, coerce_to); @@ -639,7 +640,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // Otherwise, this is a break *without* a value. That's // always legal, and is equivalent to `break ()`. - e_ty = tcx.mk_unit(); + e_ty = Ty::new_unit(tcx); cause = self.misc(expr.span); } @@ -649,7 +650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); let Some(ctxt) = enclosing_breakables.opt_find_breakable(target_id) else { // Avoid ICE when `break` is inside a closure (#65383). - return tcx.ty_error_with_message( + return Ty::new_error_with_message(tcx, expr.span, "break was outside loop, but no error was emitted", ); @@ -707,7 +708,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this can only happen if the `break` was not // inside a loop at all, which is caught by the // loop-checking pass. - let err = self.tcx.ty_error_with_message( + let err = Ty::new_error_with_message( + self.tcx, expr.span, "break was outside loop, but no error was emitted", ); @@ -1072,7 +1074,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let result_ty = coerce.complete(self); - if let Err(guar) = cond_ty.error_reported() { self.tcx.ty_error(guar) } else { result_ty } + if let Err(guar) = cond_ty.error_reported() { + Ty::new_error(self.tcx, guar) + } else { + result_ty + } } /// Type check assignment expression `expr` of form `lhs = rhs`. @@ -1090,7 +1096,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The expected type is `bool` but this will result in `()` so we can reasonably // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`. // The likely cause of this is `if foo = bar { .. }`. - let actual_ty = self.tcx.mk_unit(); + let actual_ty = Ty::new_unit(self.tcx); let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap(); let lhs_ty = self.check_expr(&lhs); let rhs_ty = self.check_expr(&rhs); @@ -1148,7 +1154,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the assignment expression itself is ill-formed, don't // bother emitting another error let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error()); - return self.tcx.ty_error(reported); + return Ty::new_error(self.tcx, reported); } let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); @@ -1195,9 +1201,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); if let Err(guar) = (lhs_ty, rhs_ty).error_reported() { - self.tcx.ty_error(guar) + Ty::new_error(self.tcx, guar) } else { - self.tcx.mk_unit() + Ty::new_unit(self.tcx) } } @@ -1252,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // [1] self.tcx.sess.delay_span_bug(body.span, "no coercion, but loop may not break"); } - ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| self.tcx.mk_unit()) + ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| Ty::new_unit(self.tcx)) } /// Checks a method call. @@ -1274,6 +1280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to // trigger this codepath causing `structurally_resolve_type` to emit an error. + self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.substs); self.write_method_call(expr.hir_id, method); Ok(method) } @@ -1315,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Eagerly check for some obvious errors. if let Err(guar) = (t_expr, t_cast).error_reported() { - self.tcx.ty_error(guar) + Ty::new_error(self.tcx, guar) } else { // Defer other checks until we're done type checking. let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); @@ -1336,7 +1343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { deferred_cast_checks.push(cast_check); t_cast } - Err(guar) => self.tcx.ty_error(guar), + Err(guar) => Ty::new_error(self.tcx, guar), } } } @@ -1376,7 +1383,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let array_len = args.len() as u64; self.suggest_array_len(expr, array_len); - self.tcx.mk_array(element_ty, array_len) + Ty::new_array(self.tcx, element_ty, array_len) } fn suggest_array_len(&self, expr: &'tcx hir::Expr<'tcx>, array_len: u64) { @@ -1464,18 +1471,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Err(guar) = element_ty.error_reported() { - return tcx.ty_error(guar); + return Ty::new_error(tcx, guar); } self.check_repeat_element_needs_copy_bound(element, count, element_ty); self.register_wf_obligation( - tcx.mk_array_with_const_len(t, count).into(), + Ty::new_array_with_const_len(tcx, t, count).into(), expr.span, traits::WellFormed(None), ); - tcx.mk_array_with_const_len(t, count) + Ty::new_array_with_const_len(tcx, t, count) } fn check_repeat_element_needs_copy_bound( @@ -1538,9 +1545,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => self.check_expr_with_expectation(&e, NoExpectation), }); - let tuple = self.tcx.mk_tup_from_iter(elt_ts_iter); + let tuple = Ty::new_tup_from_iter(self.tcx, elt_ts_iter); if let Err(guar) = tuple.error_reported() { - self.tcx.ty_error(guar) + Ty::new_error(self.tcx, guar) } else { self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized); tuple @@ -1560,7 +1567,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(data) => data, Err(guar) => { self.check_struct_fields_on_error(fields, base_expr); - return self.tcx.ty_error(guar); + return Ty::new_error(self.tcx, guar); } }; @@ -1659,7 +1666,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }; - tcx.ty_error(guar) + Ty::new_error(tcx, guar) }; // Make sure to give a type to the field even if there's @@ -1771,7 +1778,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `MyStruct<'a, _, F2, C>`, as opposed to just `_`... // This is important to allow coercions to happen in // `other_struct` itself. See `coerce-in-base-expr.rs`. - let fresh_base_ty = self.tcx.mk_adt(*adt, fresh_substs); + let fresh_base_ty = Ty::new_adt(self.tcx, *adt, fresh_substs); self.check_expr_has_type_or_error( base_expr, self.resolve_vars_if_possible(fresh_base_ty), @@ -2313,7 +2320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { did, expected.only_has_type(self), ); - return self.tcx().ty_error(guar); + return Ty::new_error(self.tcx(), guar); } let guar = if field.name == kw::Empty { @@ -2399,7 +2406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit() }; - self.tcx().ty_error(guar) + Ty::new_error(self.tcx(), guar) } fn suggest_await_on_field_access( @@ -2931,7 +2938,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let reported = err.emit(); - self.tcx.ty_error(reported) + Ty::new_error(self.tcx, reported) } } } @@ -3005,7 +3012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let element_ty = ocx.normalize( &cause, self.param_env, - self.tcx.mk_projection(index_trait_output_def_id, impl_trait_ref.substs), + Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.substs), ); let errors = ocx.select_where_possible(); @@ -3053,14 +3060,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // information. Hence, we check the source of the yield expression here and check its // value's type against `()` (this check should always hold). None if src.is_await() => { - self.check_expr_coercible_to_type(&value, self.tcx.mk_unit(), None); - self.tcx.mk_unit() + self.check_expr_coercible_to_type(&value, Ty::new_unit(self.tcx), None); + Ty::new_unit(self.tcx) } _ => { self.tcx.sess.emit_err(YieldExprOutsideOfGenerator { span: expr.span }); // Avoid expressions without types during writeback (#78653). self.check_expr(value); - self.tcx.mk_unit() + Ty::new_unit(self.tcx) } } } @@ -3087,11 +3094,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.structurally_resolve_type(expr.span, ty); match *ty.kind() { ty::FnDef(..) => { - let fnptr_ty = self.tcx.mk_fn_ptr(ty.fn_sig(self.tcx)); + let fnptr_ty = Ty::new_fn_ptr(self.tcx, ty.fn_sig(self.tcx)); self.demand_coerce(expr, ty, fnptr_ty, None, AllowTwoPhase::No); } ty::Ref(_, base_ty, mutbl) => { - let ptr_ty = self.tcx.mk_ptr(ty::TypeAndMut { ty: base_ty, mutbl }); + let ptr_ty = Ty::new_ptr(self.tcx, ty::TypeAndMut { ty: base_ty, mutbl }); self.demand_coerce(expr, ty, ptr_ty, None, AllowTwoPhase::No); } _ => {} @@ -3126,7 +3133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if asm.options.contains(ast::InlineAsmOptions::NORETURN) { self.tcx.types.never } else { - self.tcx.mk_unit() + Ty::new_unit(self.tcx) } } diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index b7ae621c685..a76db6e73a1 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -104,7 +104,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // type, `?T` is not considered unsolved, but `?I` is. The // same is true for float variables.) let fallback = match ty.kind() { - _ if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error(e), + _ if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx,e), ty::Infer(ty::IntVar(_)) => self.tcx.types.i32, ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64, _ => match diverging_fallback.get(&ty) { @@ -287,7 +287,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { let mut diverging_fallback = FxHashMap::default(); diverging_fallback.reserve(diverging_vids.len()); for &diverging_vid in &diverging_vids { - let diverging_ty = self.tcx.mk_ty_var(diverging_vid); + let diverging_ty = Ty::new_var(self.tcx, diverging_vid); let root_vid = self.root_var(diverging_vid); let can_reach_non_diverging = coercion_graph .depth_first_search(root_vid) @@ -334,7 +334,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { diverging_fallback.insert(diverging_ty, self.tcx.types.unit); } else { debug!("fallback to ! - all diverging: {:?}", diverging_vid); - diverging_fallback.insert(diverging_ty, self.tcx.mk_diverging_default()); + diverging_fallback.insert(diverging_ty, Ty::new_diverging_default(self.tcx)); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index adf1b8e351f..9a80a9c9303 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -453,7 +453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> { match self.typeck_results.borrow().node_types().get(id) { Some(&t) => t, - None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error(e), + None if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx,e), None => { bug!( "no type for node {} in fcx {}", @@ -467,7 +467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn node_ty_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> { match self.typeck_results.borrow().node_types().get(id) { Some(&t) => Some(t), - None if let Some(e) = self.tainted_by_errors() => Some(self.tcx.ty_error(e)), + None if let Some(e) = self.tainted_by_errors() => Some(Ty::new_error(self.tcx,e)), None => None, } } @@ -558,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, self.tcx.typeck_root_def_id(expr_def_id.to_def_id()), ); - let witness = self.tcx.mk_generator_witness_mir(expr_def_id.to_def_id(), substs); + let witness = Ty::new_generator_witness_mir(self.tcx, expr_def_id.to_def_id(), substs); // Unify `interior` with `witness` and collect all the resulting obligations. let span = self.tcx.hir().body(body_id).value.span; @@ -703,7 +703,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub(in super::super) fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> { - let ty_error = self.tcx.ty_error_misc(); + let ty_error = Ty::new_misc_error(self.tcx); vec![ty_error; len] } @@ -1242,7 +1242,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } let reported = err.emit(); - return (tcx.ty_error(reported), res); + return (Ty::new_error(tcx, reported), res); } } } else { @@ -1485,7 +1485,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(normalized_ty) => normalized_ty, Err(errors) => { let guar = self.err_ctxt().report_fulfillment_errors(&errors); - return self.tcx.ty_error(guar); + return Ty::new_error(self.tcx,guar); } } } else { @@ -1512,7 +1512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit_inference_failure_err(self.body_id, sp, ty.into(), E0282, true) .emit() }); - let err = self.tcx.ty_error(e); + let err = Ty::new_error(self.tcx, e); self.demand_suptype(sp, err, ty); err } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 223aedefea3..ed9bb4945af 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { type BreakTy = ty::GenericArg<'tcx>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> { if let Some(origin) = self.0.type_var_origin(ty) - && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) = + && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind && let generics = self.0.tcx.generics_of(self.1) && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 7ce568ca48b..41f5fafe72f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); let ty = self.resolve_vars_if_possible(ty); if ty.has_non_region_infer() { - self.tcx.ty_error_misc() + Ty::new_misc_error(self.tcx) } else { self.tcx.erase_regions(ty) } @@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, - TupleArguments => vec![self.tcx.mk_tup(&err_inputs)], + TupleArguments => vec![Ty::new_tup(self.tcx, &err_inputs)], }; self.check_argument_types( @@ -114,7 +114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tuple_arguments, method.ok().map(|method| method.def_id), ); - return self.tcx.ty_error_misc(); + return Ty::new_misc_error(self.tcx); } let method = method.unwrap(); @@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } ty::FnDef(..) => { - let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); + let ptr_ty = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx)); let ptr_ty = self.resolve_vars_if_possible(ptr_ty); variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string()); } @@ -539,7 +539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .typeck_results .borrow() .expr_ty_adjusted_opt(*expr) - .unwrap_or_else(|| tcx.ty_error_misc()); + .unwrap_or_else(|| Ty::new_misc_error(tcx)); (self.resolve_vars_if_possible(ty), normalize_span(expr.span)) }) .collect(); @@ -648,7 +648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len() { // Wrap up the N provided arguments starting at this position in a tuple. - let provided_as_tuple = tcx.mk_tup_from_iter( + let provided_as_tuple = Ty::new_tup_from_iter(tcx, provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()), ); @@ -1309,14 +1309,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; match lit.node { - ast::LitKind::Str(..) => tcx.mk_static_str(), - ast::LitKind::ByteStr(ref v, _) => { - tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64)) - } + ast::LitKind::Str(..) => Ty::new_static_str(tcx), + ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref( + tcx, + tcx.lifetimes.re_static, + Ty::new_array(tcx, tcx.types.u8, v.len() as u64), + ), ast::LitKind::Byte(_) => tcx.types.u8, ast::LitKind::Char(_) => tcx.types.char, - ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(ty::int_ty(t)), - ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(ty::uint_ty(t)), + ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, ty::int_ty(t)), + ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, ty::uint_ty(t)), ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { ty::Int(_) | ty::Uint(_) => Some(ty), @@ -1328,7 +1330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_ty.unwrap_or_else(|| self.next_int_var()) } ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => { - tcx.mk_mach_float(ty::float_ty(t)) + Ty::new_float(tcx, ty::float_ty(t)) } ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => { let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { @@ -1338,12 +1340,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_ty.unwrap_or_else(|| self.next_float_var()) } ast::LitKind::Bool(_) => tcx.types.bool, - ast::LitKind::CStr(_, _) => tcx.mk_imm_ref( + ast::LitKind::CStr(_, _) => Ty::new_imm_ref( + tcx, tcx.lifetimes.re_static, tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span))) .skip_binder(), ), - ast::LitKind::Err => tcx.ty_error_misc(), + ast::LitKind::Err => Ty::new_misc_error(tcx), } } @@ -1513,7 +1516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::StmtKind::Item(_) => {} hir::StmtKind::Expr(ref expr) => { // Check with expected type of `()`. - self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| { + self.check_expr_has_type_or_error(&expr, Ty::new_unit(self.tcx), |err| { if expr.can_have_side_effects() { self.suggest_semicolon_at_end(expr.span, err); } @@ -1536,7 +1539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { - let unit = self.tcx.mk_unit(); + let unit = Ty::new_unit(self.tcx); let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); // if the block produces a `!` value, that can always be @@ -1649,7 +1652,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { blk.span, blk.hir_id, expected_ty, - self.tcx.mk_unit(), + Ty::new_unit(self.tcx), ); } if !self.consider_removing_semicolon(blk, expected_ty, err) { @@ -1795,7 +1798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { if let Err(guar) = ty.error_reported() { // Override the types everywhere with `err()` to avoid knock on errors. - let err = self.tcx.ty_error(guar); + let err = Ty::new_error(self.tcx, guar); self.write_ty(hir_id, err); self.write_ty(pat.hir_id, err); self.locals.borrow_mut().insert(hir_id, err); @@ -1823,8 +1826,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = self .astconv() .associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true); - let ty = - result.map(|(ty, _, _)| ty).unwrap_or_else(|guar| self.tcx().ty_error(guar)); + let ty = result + .map(|(ty, _, _)| ty) + .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar)); let ty = self.handle_raw_ty(path_span, ty); let result = result.map(|(_, kind, def_id)| (kind, def_id)); @@ -1978,7 +1982,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, traits::ObligationCause::dummy(), self.param_env, - ty::Binder::dummy(trait_ref), + trait_ref, ); match SelectionContext::new(&self).select(&obligation) { Ok(Some(traits::ImplSource::UserDefined(impl_source))) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index e035d233bf7..20b34df99b2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -191,7 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { - self.tcx.mk_ty_var(self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT)) + Ty::new_var(self.tcx, self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT)) } } @@ -295,7 +295,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { trait_ref.substs, ); - self.tcx().mk_projection(item_def_id, item_substs) + Ty::new_projection(self.tcx(), item_def_id, item_substs) } fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3a4fe334f88..79a7c016185 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -426,7 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for // `as_ref` and `as_deref` compatibility. let error_tys_equate_as_ref = error_tys.map_or(true, |(found, expected)| { - self.can_eq(self.param_env, self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, found), expected) + self.can_eq(self.param_env, Ty::new_imm_ref(self.tcx,self.tcx.lifetimes.re_erased, found), expected) }); // FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`, // but those checks need to be a bit more delicate and the benefit is diminishing. @@ -515,7 +515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.tcx.hir().is_inside_const_context(hir_id) || !expected.is_box() || found.is_box() { return false; } - if self.can_coerce(self.tcx.mk_box(found), expected) { + if self.can_coerce(Ty::new_box(self.tcx, found), expected) { let suggest_boxing = match found.kind() { ty::Tuple(tuple) if tuple.is_empty() => { SuggestBoxing::Unit { start: span.shrink_to_lo(), end: span } @@ -595,9 +595,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() { return false; } - let box_found = self.tcx.mk_box(found); - let pin_box_found = self.tcx.mk_lang_item(box_found, LangItem::Pin).unwrap(); - let pin_found = self.tcx.mk_lang_item(found, LangItem::Pin).unwrap(); + let box_found = Ty::new_box(self.tcx, found); + let pin_box_found = Ty::new_lang_item(self.tcx, box_found, LangItem::Pin).unwrap(); + let pin_found = Ty::new_lang_item(self.tcx, found, LangItem::Pin).unwrap(); match expected.kind() { ty::Adt(def, _) if Some(def.did()) == pin_did => { if self.can_coerce(pin_box_found, expected) { diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index fdbb153ec7d..86ea092bc40 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -312,7 +312,8 @@ pub fn resolve_interior<'a, 'tcx>( // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list_from_iter(type_causes.iter().map(|cause| cause.ty)); let bound_vars = fcx.tcx.mk_bound_variable_kinds(&bound_vars); - let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars)); + let witness = + Ty::new_generator_witness(fcx.tcx, ty::Binder::bind_with_vars(type_list, bound_vars)); drop(typeck_results); // Store the generator types and spans into the typeck results for this generator. @@ -361,7 +362,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { let ty = self.interior_visitor.fcx.typeck_results.borrow().node_type(id); let tcx = self.interior_visitor.fcx.tcx; - let ty = tcx.mk_ref( + let ty = Ty::new_ref( + tcx, // Use `ReErased` as `resolve_interior` is going to replace all the // regions anyway. tcx.lifetimes.re_erased, diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index 05e5db9f0f3..d5619af2aae 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -80,7 +80,7 @@ impl<'tcx> Inherited<'tcx> { let infcx = tcx .infer_ctxt() .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)) + .with_opaque_type_inference(DefiningAnchor::Bind(def_id)) .build(); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 6f7288ed7e5..6f82ffcfe4a 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -154,7 +154,7 @@ fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tc fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { let fallback = move || { let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id)); - tcx.ty_error_with_message(span, "diagnostic only typeck table used") + Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used") }; typeck_with_fallback(tcx, def_id, fallback) } diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 6c8589493cb..a1aa090841a 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -277,9 +277,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. let base = if let Some(deref) = overloaded { - let ref_ty = self - .tcx() - .mk_ref(deref.region, ty::TypeAndMut { ty: target, mutbl: deref.mutbl }); + let ref_ty = Ty::new_ref( + self.tcx(), + deref.region, + ty::TypeAndMut { ty: target, mutbl: deref.mutbl }, + ); self.cat_rvalue(expr.hir_id, expr.span, ref_ty) } else { previous()? @@ -489,7 +491,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let ty::Ref(region, _, mutbl) = *base_ty.kind() else { span_bug!(expr.span, "cat_overloaded_place: base is not a reference"); }; - let ref_ty = self.tcx().mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl }); + let ref_ty = Ty::new_ref(self.tcx(), region, ty::TypeAndMut { ty: place_ty, mutbl }); let base = self.cat_rvalue(expr.hir_id, expr.span, ref_ty); self.cat_deref(expr, base) diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 966cd6a389e..87edb803148 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -10,7 +10,7 @@ use rustc_hir_analysis::astconv::generics::{ use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}; use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{self, SubstsRef}; @@ -143,7 +143,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // a custom error in that case. if illegal_sized_bound.is_none() { self.add_obligations( - self.tcx.mk_fn_ptr(method_sig), + Ty::new_fn_ptr(self.tcx, method_sig), all_substs, method_predicates, pick.item.def_id, @@ -171,7 +171,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // time writing the results into the various typeck results. let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty); let Some((ty, n)) = autoderef.nth(pick.autoderefs) else { - return self.tcx.ty_error_with_message( + return Ty::new_error_with_message(self.tcx, rustc_span::DUMMY_SP, format!("failed autoderef {}", pick.autoderefs), ); @@ -187,7 +187,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // Type we're wrapping in a reference, used later for unsizing let base_ty = target; - target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target }); + target = Ty::new_ref(self.tcx, region, ty::TypeAndMut { mutbl, ty: target }); // Method call receivers are the primary use case // for two-phase borrows. @@ -200,31 +200,35 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { if unsize { let unsized_ty = if let ty::Array(elem_ty, _) = base_ty.kind() { - self.tcx.mk_slice(*elem_ty) + Ty::new_slice(self.tcx, *elem_ty) } else { bug!( "AutorefOrPtrAdjustment's unsize flag should only be set for array ty, found {}", base_ty ) }; - target = self - .tcx - .mk_ref(region, ty::TypeAndMut { mutbl: mutbl.into(), ty: unsized_ty }); - adjustments - .push(Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target }); + target = Ty::new_ref( + self.tcx, + region, + ty::TypeAndMut { mutbl: mutbl.into(), ty: unsized_ty }, + ); + adjustments.push(Adjustment { + kind: Adjust::Pointer(PointerCoercion::Unsize), + target, + }); } } Some(probe::AutorefOrPtrAdjustment::ToConstPtr) => { target = match target.kind() { &ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => { assert!(mutbl.is_mut()); - self.tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty }) + Ty::new_ptr(self.tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty }) } other => panic!("Cannot adjust receiver type {:?} to const ptr", other), }; adjustments.push(Adjustment { - kind: Adjust::Pointer(PointerCast::MutToConstPointer), + kind: Adjust::Pointer(PointerCoercion::MutToConstPointer), target, }); } diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index ebd7b3123eb..e52cea1889f 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -205,9 +205,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(span) = result.illegal_sized_bound { let mut needs_mut = false; if let ty::Ref(region, t_type, mutability) = self_ty.kind() { - let trait_type = self - .tcx - .mk_ref(*region, ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() }); + let trait_type = Ty::new_ref( + self.tcx, + *region, + ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() }, + ); // We probe again to see if there might be a borrow mutability discrepancy. match self.lookup_probe( segment.ident, @@ -464,7 +466,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); // Also add an obligation for the method type being well-formed. - let method_ty = tcx.mk_fn_ptr(ty::Binder::dummy(fn_sig)); + let method_ty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(fn_sig)); debug!( "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, obligation diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 5e28ad5fd58..03a3eebbdf5 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -465,7 +465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Error(guar) => guar, _ => bug!("unexpected bad final type in method autoderef"), }; - self.demand_eqtype(span, ty, self.tcx.ty_error(guar)); + self.demand_eqtype(span, ty, Ty::new_error(self.tcx, guar)); return Err(MethodError::NoMatch(NoMatchData { static_candidates: Vec::new(), unsatisfied_predicates: Vec::new(), @@ -551,7 +551,7 @@ fn method_autoderef_steps<'tcx>( steps.push(CandidateStep { self_ty: infcx.make_query_response_ignoring_pending_obligations( inference_vars, - infcx.tcx.mk_slice(*elem_ty), + Ty::new_slice(infcx.tcx, *elem_ty), ), autoderefs: dereferences, // this could be from an unsafe deref if we had @@ -1215,7 +1215,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // In general, during probing we erase regions. let region = tcx.lifetimes.re_erased; - let autoref_ty = tcx.mk_ref(region, ty::TypeAndMut { ty: self_ty, mutbl }); + let autoref_ty = Ty::new_ref(tcx, region, ty::TypeAndMut { ty: self_ty, mutbl }); self.pick_method(autoref_ty, unstable_candidates).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; @@ -1245,7 +1245,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }; let const_self_ty = ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }; - let const_ptr_ty = self.tcx.mk_ptr(const_self_ty); + let const_ptr_ty = Ty::new_ptr(self.tcx, const_self_ty); self.pick_method(const_ptr_ty, unstable_candidates).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; @@ -1441,8 +1441,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { trait_ref: ty::TraitRef<'tcx>, ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> { let cause = traits::ObligationCause::misc(self.span, self.body_id); - let predicate = ty::Binder::dummy(trait_ref); - let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, predicate); + let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, trait_ref); traits::SelectionContext::new(self).select(&obligation) } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 67fb7c1d48c..5f924f30936 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -211,7 +211,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() { if needs_mut { - let trait_type = self.tcx.mk_ref( + let trait_type = Ty::new_ref( + self.tcx, *region, ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() }, ); @@ -647,7 +648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let projection_ty = pred.skip_binder().projection_ty; let substs_with_infer_self = tcx.mk_substs_from_iter( - iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into()) + iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into()) .chain(projection_ty.substs.iter().skip(1)), ); @@ -2408,8 +2409,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // just this list. for (rcvr_ty, post) in &[ (rcvr_ty, ""), - (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "), - (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"), + (Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "), + (Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&"), ] { match self.lookup_probe_for_diagnostic( item_name, @@ -2444,10 +2445,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } for (rcvr_ty, pre) in &[ - (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"), - (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"), - (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"), - (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"), + (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::OwnedBox), "Box::new"), + (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin), "Pin::new"), + (Ty::new_diagnostic_item(self.tcx, *rcvr_ty, sym::Arc), "Arc::new"), + (Ty::new_diagnostic_item(self.tcx, *rcvr_ty, sym::Rc), "Rc::new"), ] { if let Some(new_rcvr_t) = *rcvr_ty && let Ok(pick) = self.lookup_probe_for_diagnostic( diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 4f3d1d45679..1eae258c1b2 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, op); - self.tcx.mk_unit() + Ty::new_unit(self.tcx) } else { return_ty }; @@ -297,7 +297,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // error types are considered "builtin" Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => { - self.tcx.ty_error_misc() + Ty::new_misc_error(self.tcx) } Err(errors) => { let (_, trait_def_id) = @@ -568,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let reported = err.emit(); - self.tcx.ty_error(reported) + Ty::new_error(self.tcx, reported) } }; @@ -752,7 +752,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } err.emit() }); - self.tcx.ty_error(guar) + Ty::new_error(self.tcx, guar) } } } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 96d03b47125..42f4531c0ef 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -394,8 +394,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut pat_ty = ty; if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind { let expected = self.structurally_resolve_type(span, expected); - if let ty::Ref(_, inner_ty, _) = expected.kind() - && matches!(inner_ty.kind(), ty::Slice(_)) + if let ty::Ref(_, inner_ty, _) = *expected.kind() + && self.try_structurally_resolve_type(span, inner_ty).is_slice() { let tcx = self.tcx; trace!(?lt.hir_id.local_id, "polymorphic byte string lit"); @@ -403,7 +403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .borrow_mut() .treat_byte_string_as_slice .insert(lt.hir_id.local_id); - pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8)); + pat_ty = Ty::new_imm_ref(tcx,tcx.lifetimes.re_static, Ty::new_slice(tcx,tcx.types.u8)); } } @@ -412,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expected = self.resolve_vars_if_possible(expected); pat_ty = match expected.kind() { ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => expected, - ty::Str => tcx.mk_static_str(), + ty::Str => Ty::new_static_str(tcx,), _ => pat_ty, }; } @@ -474,7 +474,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // There exists a side that didn't meet our criteria that the end-point // be of a numeric or char type, as checked in `calc_side` above. let guar = self.emit_err_pat_range(span, lhs, rhs); - return self.tcx.ty_error(guar); + return Ty::new_error(self.tcx, guar); } // Unify each side with `expected`. @@ -494,7 +494,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { demand_eqtype(&mut rhs, lhs); if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) { - return self.tcx.ty_error_misc(); + return Ty::new_misc_error(self.tcx); } // Find the unified type and check if it's of numeric or char type again. @@ -510,7 +510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *fail = true; } let guar = self.emit_err_pat_range(span, lhs, rhs); - return self.tcx.ty_error(guar); + return Ty::new_error(self.tcx, guar); } ty } @@ -848,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) { Ok(data) => data, Err(guar) => { - let err = self.tcx.ty_error(guar); + let err = Ty::new_error(self.tcx, guar); for field in fields { let ti = ti; self.check_pat(field.pat, err, def_bm, ti); @@ -864,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, def_bm, ti) { pat_ty } else { - self.tcx.ty_error_misc() + Ty::new_misc_error(self.tcx) } } @@ -884,12 +884,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Res::Err => { let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); - return tcx.ty_error(e); + return Ty::new_error(tcx, e); } Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => { let expected = "unit struct, unit variant or constant"; let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected); - return tcx.ty_error(e); + return Ty::new_error(tcx, e); } Res::SelfCtor(..) | Res::Def( @@ -1032,7 +1032,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let on_error = |e| { for pat in subpats { - self.check_pat(pat, tcx.ty_error(e), def_bm, ti); + self.check_pat(pat, Ty::new_error(tcx, e), def_bm, ti); } }; let report_unexpected_res = |res: Res| { @@ -1049,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); on_error(e); - return tcx.ty_error(e); + return Ty::new_error(tcx, e); } // Type-check the path. @@ -1057,7 +1057,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id); if !pat_ty.is_fn() { let e = report_unexpected_res(res); - return tcx.ty_error(e); + return Ty::new_error(tcx, e); } let variant = match res { @@ -1065,11 +1065,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); on_error(e); - return tcx.ty_error(e); + return Ty::new_error(tcx, e); } Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { let e = report_unexpected_res(res); - return tcx.ty_error(e); + return Ty::new_error(tcx, e); } Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res), _ => bug!("unexpected pattern resolution: {:?}", res), @@ -1112,7 +1112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let e = self.e0023(pat.span, res, qpath, subpats, &variant.fields.raw, expected, had_err); on_error(e); - return tcx.ty_error(e); + return Ty::new_error(tcx, e); } pat_ty } @@ -1303,16 +1303,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }); let element_tys = tcx.mk_type_list_from_iter(element_tys_iter); - let pat_ty = tcx.mk_tup(element_tys); + let pat_ty = Ty::new_tup(tcx, element_tys); if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) { let reported = err.emit(); // Walk subpatterns with an expected type of `err` in this case to silence // further errors being emitted when using the bindings. #50333 - let element_tys_iter = (0..max_len).map(|_| tcx.ty_error(reported)); + let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported)); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, tcx.ty_error(reported), def_bm, ti); + self.check_pat(elem, Ty::new_error(tcx, reported), def_bm, ti); } - tcx.mk_tup_from_iter(element_tys_iter) + Ty::new_tup_from_iter(tcx, element_tys_iter) } else { for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat(elem, element_tys[i], def_bm, ti); @@ -1357,7 +1357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Occupied(occupied) => { no_field_errors = false; let guar = self.error_field_already_bound(span, field.ident, *occupied.get()); - tcx.ty_error(guar) + Ty::new_error(tcx, guar) } Vacant(vacant) => { vacant.insert(span); @@ -1371,7 +1371,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap_or_else(|| { inexistent_fields.push(field); no_field_errors = false; - tcx.ty_error_misc() + Ty::new_misc_error(tcx) }) } }; @@ -1951,12 +1951,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::TypeInference, span: inner.span, }); - let box_ty = tcx.mk_box(inner_ty); + let box_ty = Ty::new_box(tcx, inner_ty); self.demand_eqtype_pat(span, expected, box_ty, ti); (box_ty, inner_ty) } Err(guar) => { - let err = tcx.ty_error(guar); + let err = Ty::new_error(tcx, guar); (err, err) } }; @@ -2007,7 +2007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } Err(guar) => { - let err = tcx.ty_error(guar); + let err = Ty::new_error(tcx, guar); (err, err) } }; @@ -2019,7 +2019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn new_ref_ty(&self, span: Span, mutbl: hir::Mutability, ty: Ty<'tcx>) -> Ty<'tcx> { let region = self.next_region_var(infer::PatternRegion(span)); let mt = ty::TypeAndMut { ty, mutbl }; - self.tcx.mk_ref(region, mt) + Ty::new_ref(self.tcx, region, mt) } /// Type check a slice pattern. @@ -2061,7 +2061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .error_reported() .err() .unwrap_or_else(|| self.error_expected_array_or_slice(span, expected, ti)); - let err = self.tcx.ty_error(guar); + let err = Ty::new_error(self.tcx, guar); (err, Some(err), err) } }; @@ -2108,7 +2108,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if let Some(pat_len) = len.checked_sub(min_len) { // The variable-length pattern was there, // so it has an array type with the remaining elements left as its size... - return (Some(self.tcx.mk_array(element_ty, pat_len)), arr_ty); + return (Some(Ty::new_array(self.tcx, element_ty, pat_len)), arr_ty); } else { // ...however, in this case, there were no remaining elements. // That is, the slice pattern requires more than the array type offers. @@ -2117,7 +2117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if slice.is_none() { // We have a pattern with a fixed length, // which we can use to infer the length of the array. - let updated_arr_ty = self.tcx.mk_array(element_ty, min_len); + let updated_arr_ty = Ty::new_array(self.tcx, element_ty, min_len); self.demand_eqtype(span, updated_arr_ty, arr_ty); return (None, updated_arr_ty); } else { @@ -2128,7 +2128,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // If we get here, we must have emitted an error. - (Some(self.tcx.ty_error(guar)), arr_ty) + (Some(Ty::new_error(self.tcx, guar)), arr_ty) } fn error_scrutinee_inconsistent_length( diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index b8aaaebb85e..fd43b475e3a 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -6,7 +6,7 @@ use rustc_hir as hir; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::InferOk; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCoercion}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::{sym, Ident}; @@ -90,7 +90,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } let reported = err.emit(); - Some((self.tcx.ty_error(reported), self.tcx.ty_error(reported))) + Some((Ty::new_error(self.tcx, reported), Ty::new_error(self.tcx, reported))) } /// To type-check `base_expr[index_expr]`, we progressively autoderef @@ -138,7 +138,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if unsize { // We only unsize arrays here. if let ty::Array(element_ty, _) = adjusted_ty.kind() { - self_ty = self.tcx.mk_slice(*element_ty); + self_ty = Ty::new_slice(self.tcx, *element_ty); } else { continue; } @@ -162,7 +162,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind() { adjustments.push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(*region, AutoBorrowMutability::Not)), - target: self.tcx.mk_ref( + target: Ty::new_ref( + self.tcx, *region, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: adjusted_ty }, ), @@ -172,7 +173,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if unsize { adjustments.push(Adjustment { - kind: Adjust::Pointer(PointerCast::Unsize), + kind: Adjust::Pointer(PointerCoercion::Unsize), target: method.sig.inputs()[0], }); } @@ -427,9 +428,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { allow_two_phase_borrow: AllowTwoPhase::No, }; adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)); - adjustment.target = self - .tcx - .mk_ref(*region, ty::TypeAndMut { ty: source, mutbl: mutbl.into() }); + adjustment.target = Ty::new_ref( + self.tcx, + *region, + ty::TypeAndMut { ty: source, mutbl: mutbl.into() }, + ); } source = adjustment.target; } @@ -438,7 +441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let [ .., Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, - Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), ref mut target }, + Adjustment { kind: Adjust::Pointer(PointerCoercion::Unsize), ref mut target }, ] = adjustments[..] { *target = method.sig.inputs()[0]; diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 9458099f56f..208c40a3932 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -300,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Build a tuple (U0..Un) of the final upvar types U0..Un // and unify the upvar tuple type in the closure with it: - let final_tupled_upvars_type = self.tcx.mk_tup(&final_upvar_tys); + let final_tupled_upvars_type = Ty::new_tup(self.tcx, &final_upvar_tys); self.demand_suptype(span, substs.tupled_upvars_ty(), final_tupled_upvars_type); let fake_reads = delegate @@ -314,8 +314,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().closure_size_eval.insert( closure_def_id, ClosureSizeProfileData { - before_feature_tys: self.tcx.mk_tup(&before_feature_tys), - after_feature_tys: self.tcx.mk_tup(&after_feature_tys), + before_feature_tys: Ty::new_tup(self.tcx, &before_feature_tys), + after_feature_tys: Ty::new_tup(self.tcx, &after_feature_tys), }, ); } @@ -1665,9 +1665,11 @@ fn apply_capture_kind_on_capture_ty<'tcx>( ) -> Ty<'tcx> { match capture_kind { ty::UpvarCapture::ByValue => ty, - ty::UpvarCapture::ByRef(kind) => { - tcx.mk_ref(region.unwrap(), ty::TypeAndMut { ty: ty, mutbl: kind.to_mutbl_lossy() }) - } + ty::UpvarCapture::ByRef(kind) => Ty::new_ref( + tcx, + region.unwrap(), + ty::TypeAndMut { ty: ty, mutbl: kind.to_mutbl_lossy() }, + ), } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 0cf3a4e877a..10645753609 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; @@ -232,7 +232,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // to access an nonexistent index. We assume that more relevant errors will // already have been emitted, so we only gate on this with an ICE if no // error has been emitted. (#64638) - self.fcx.tcx.ty_error_with_message( + Ty::new_error_with_message( + self.fcx.tcx, e.span, format!("bad index {:?} for base: `{:?}`", index, base), ) @@ -250,7 +251,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // Since this is "after" the other adjustment to be // discarded, we do an extra `pop()` if let Some(Adjustment { - kind: Adjust::Pointer(PointerCast::Unsize), .. + kind: Adjust::Pointer(PointerCoercion::Unsize), .. }) = a.pop() { // So the borrow discard actually happens here @@ -823,7 +824,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); let e = self.report_error(t); self.replaced_with_error = Some(e); - self.fcx.tcx.ty_error(e) + Ty::new_error(self.fcx.tcx, e) } } } @@ -840,7 +841,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> { debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct); let e = self.report_error(ct); self.replaced_with_error = Some(e); - self.fcx.tcx.const_error(ct.ty(), e) + ty::Const::new_error(self.fcx.tcx, e, ct.ty()) } } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index bf53a73f398..e57532e2de2 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -382,7 +382,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> { // any equated inference vars correctly! let root_vid = self.infcx.root_var(vid); if root_vid != vid { - t = self.infcx.tcx.mk_ty_var(root_vid); + t = Ty::new_var(self.infcx.tcx, root_vid); vid = root_vid; } @@ -497,7 +497,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> { // any equated inference vars correctly! let root_vid = self.infcx.root_const_var(vid); if root_vid != vid { - ct = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), ct.ty()); + ct = ty::Const::new_var(self.infcx.tcx, root_vid, ct.ty()); vid = root_vid; } @@ -785,7 +785,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { self.fold_ty(bound_to) } else { let var = self.canonical_var(info, ty_var.into()); - self.interner().mk_bound(self.binder_index, var.into()) + Ty::new_bound(self.tcx, self.binder_index, var.into()) } } @@ -804,10 +804,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { self.fold_const(bound_to) } else { let var = self.canonical_var(info, const_var.into()); - self.interner().mk_const( - ty::ConstKind::Bound(self.binder_index, var), - self.fold_ty(const_var.ty()), - ) + ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty())) } } } diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index c8c318c3f02..f765c41a367 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -26,7 +26,7 @@ use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVari use rustc_index::IndexVec; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::GenericArg; -use rustc_middle::ty::{self, List, TyCtxt}; +use rustc_middle::ty::{self, List, Ty, TyCtxt}; use rustc_span::source_map::Span; pub use rustc_middle::infer::canonical::*; @@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> { CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, bound }; - self.tcx.mk_placeholder(placeholder_mapped).into() + Ty::new_placeholder(self.tcx, placeholder_mapped).into() } CanonicalVarKind::Region(ui) => self @@ -155,7 +155,7 @@ impl<'tcx> InferCtxt<'tcx> { CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound }; - self.tcx.mk_const(placeholder_mapped, ty).into() + ty::Const::new_placeholder(self.tcx, placeholder_mapped, ty).into() } } } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 32054e6d125..9c3ab04deae 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -520,7 +520,7 @@ impl<'tcx> InferCtxt<'tcx> { self.at(cause, param_env) .eq( DefineOpaqueTypes::Yes, - self.tcx.mk_opaque(a.def_id.to_def_id(), a.substs), + Ty::new_opaque(self.tcx, a.def_id.to_def_id(), a.substs), b, )? .obligations, diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index fc6ff01c00c..a9cdb8c51cf 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -189,11 +189,11 @@ impl<'tcx> InferCtxt<'tcx> { // HACK: equating both sides with `[const error]` eagerly prevents us // from leaving unconstrained inference vars during things like impl // matching in the solver. - let a_error = self.tcx.const_error(a.ty(), guar); + let a_error = ty::Const::new_error(self.tcx, guar, a.ty()); if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() { return self.unify_const_variable(vid, a_error, relation.param_env()); } - let b_error = self.tcx.const_error(b.ty(), guar); + let b_error = ty::Const::new_error(self.tcx, guar, b.ty()); if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() { return self.unify_const_variable(vid, b_error, relation.param_env()); } @@ -322,8 +322,8 @@ impl<'tcx> InferCtxt<'tcx> { .unify_var_value(vid, Some(val)) .map_err(|e| int_unification_error(vid_is_expected, e))?; match val { - IntType(v) => Ok(self.tcx.mk_mach_int(v)), - UintType(v) => Ok(self.tcx.mk_mach_uint(v)), + IntType(v) => Ok(Ty::new_int(self.tcx, v)), + UintType(v) => Ok(Ty::new_uint(self.tcx, v)), } } @@ -338,7 +338,7 @@ impl<'tcx> InferCtxt<'tcx> { .float_unification_table() .unify_var_value(vid, Some(ty::FloatVarValue(val))) .map_err(|e| float_unification_error(vid_is_expected, e))?; - Ok(self.tcx.mk_mach_float(val)) + Ok(Ty::new_float(self.tcx, val)) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 15213c4b023..b826ced0453 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -315,7 +315,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime { span, - opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs), + opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs), opaque_ty_span: tcx.def_span(opaque_ty_key.def_id), }); diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index f3b2ec4c5e3..bb75ecc6adb 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -265,9 +265,9 @@ impl<'tcx> InferCtxt<'tcx> { kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into(), }, - parent: def_id.and_then(|def_id| { - InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id) - }), + parent: InferenceDiagnosticsParentData::for_def_id( + self.tcx, def_id, + ), }; } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index aad9885827d..a9b485a6f7e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -288,7 +288,7 @@ pub fn suggest_new_region_bound( // Get the identity type for this RPIT let did = item_id.owner_id.to_def_id(); - let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did)); + let ty = Ty::new_opaque(tcx, did, ty::InternalSubsts::identity_for_item(tcx, did)); if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg { GenericBound::Outlives(Lifetime { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index ce70bcc5c85..12d38ced030 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -41,8 +41,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // all of the region highlighting machinery only deals with those. let guar = self.emit_err( var_origin.span(), - self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(expected)), - self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(found)), + Ty::new_fn_ptr(self.cx.tcx,ty::Binder::dummy(expected)), + Ty::new_fn_ptr(self.cx.tcx,ty::Binder::dummy(found)), *trait_item_def_id, ); return Some(guar); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 07a9eff2dbe..e55e9e75fb6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -11,7 +11,7 @@ use rustc_errors::{ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, IsSuggestable, Region}; +use rustc_middle::ty::{self, IsSuggestable, Region, Ty}; use rustc_span::symbol::kw; use super::ObligationCauseAsDiagArg; @@ -304,7 +304,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let trait_substs = trait_ref .subst_identity() // Replace the explicit self type with `Self` for better suggestion rendering - .with_self_ty(self.tcx, self.tcx.mk_ty_param(0, kw::SelfUpper)) + .with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper)) .substs; let trait_item_substs = ty::InternalSubsts::identity_for_item(self.tcx, impl_item_def_id) .rebase_onto(self.tcx, impl_def_id, trait_substs); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index c9a8f8131df..63613b59020 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -257,7 +257,7 @@ impl<T> Trait<T> for X { ); } } - (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => { + (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::Fn | DefKind::Static(_) | DefKind::Const | DefKind::AssocFn | DefKind::AssocConst) => { if tcx.is_type_alias_impl_trait(alias.def_id) { if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) { let sp = tcx.def_ident_span(body_owner_def_id).unwrap_or_else(|| tcx.def_span(body_owner_def_id)); diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 0219167f6e5..05769b7907a 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { Entry::Vacant(entry) => { let index = self.const_freshen_count; self.const_freshen_count += 1; - let ct = self.infcx.tcx.mk_const(freshener(index), ty); + let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty); entry.insert(ct); ct } @@ -188,7 +188,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { match v { ty::TyVar(v) => { let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); - Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| self.infcx.tcx.mk_fresh_ty(n))) + Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| Ty::new_fresh(self.infcx.tcx, n))) } ty::IntVar(v) => Some( @@ -200,7 +200,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { .probe_value(v) .map(|v| v.to_type(self.infcx.tcx)), ty::IntVar(v), - |n| self.infcx.tcx.mk_fresh_int_ty(n), + |n| Ty::new_fresh_int(self.infcx.tcx, n), ), ), @@ -213,7 +213,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { .probe_value(v) .map(|v| v.to_type(self.infcx.tcx)), ty::FloatVar(v), - |n| self.infcx.tcx.mk_fresh_float_ty(n), + |n| Ty::new_fresh_float(self.infcx.tcx, n), ), ), diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs index d4a1dacde10..78025016757 100644 --- a/compiler/rustc_infer/src/infer/generalize.rs +++ b/compiler/rustc_infer/src/infer/generalize.rs @@ -277,7 +277,7 @@ where let origin = *inner.type_variables().var_origin(vid); let new_var_id = inner.type_variables().new_var(self.for_universe, origin); - let u = self.tcx().mk_ty_var(new_var_id); + let u = Ty::new_var(self.tcx(), new_var_id); // Record that we replaced `vid` with `new_var_id` as part of a generalization // operation. This is needed to detect cyclic types. To see why, see the @@ -398,7 +398,7 @@ where origin: var_value.origin, val: ConstVariableValue::Unknown { universe: self.for_universe }, }); - Ok(self.tcx().mk_const(new_var_id, c.ty())) + Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty())) } } } @@ -412,7 +412,11 @@ where substs, substs, )?; - Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty())) + Ok(ty::Const::new_unevaluated( + self.tcx(), + ty::UnevaluatedConst { def, substs }, + c.ty(), + )) } ty::ConstKind::Placeholder(placeholder) => { if self.for_universe.can_name(placeholder.universe) { diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index 974bc2f1153..510b1797d3c 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -6,7 +6,7 @@ use super::{HigherRankedType, InferCtxt}; use crate::infer::CombinedSnapshot; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc_middle::ty::{self, Binder, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { /// Checks whether `for<..> sub <: for<..> sup` holds. @@ -88,13 +88,14 @@ impl<'tcx> InferCtxt<'tcx> { ) }, types: &mut |bound_ty: ty::BoundTy| { - self.tcx.mk_placeholder(ty::PlaceholderType { - universe: next_universe, - bound: bound_ty, - }) + Ty::new_placeholder( + self.tcx, + ty::PlaceholderType { universe: next_universe, bound: bound_ty }, + ) }, consts: &mut |bound_var: ty::BoundVar, ty| { - self.tcx.mk_const( + ty::Const::new_placeholder( + self.tcx, ty::PlaceholderConst { universe: next_universe, bound: bound_var }, ty, ) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f1f5ac81fb7..fca32b73d1d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -725,19 +725,19 @@ impl<'tcx> InferCtxt<'tcx> { .type_variables() .unsolved_variables() .into_iter() - .map(|t| self.tcx.mk_ty_var(t)) + .map(|t| Ty::new_var(self.tcx, t)) .collect(); vars.extend( (0..inner.int_unification_table().len()) .map(|i| ty::IntVid { index: i as u32 }) .filter(|&vid| inner.int_unification_table().probe_value(vid).is_none()) - .map(|v| self.tcx.mk_int_var(v)), + .map(|v| Ty::new_int_var(self.tcx, v)), ); vars.extend( (0..inner.float_unification_table().len()) .map(|i| ty::FloatVid { index: i as u32 }) .filter(|&vid| inner.float_unification_table().probe_value(vid).is_none()) - .map(|v| self.tcx.mk_float_var(v)), + .map(|v| Ty::new_float_var(self.tcx, v)), ); vars } @@ -978,7 +978,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { - self.tcx.mk_ty_var(self.next_ty_var_id(origin)) + Ty::new_var(self.tcx, self.next_ty_var_id(origin)) } pub fn next_ty_var_id_in_universe( @@ -995,11 +995,11 @@ impl<'tcx> InferCtxt<'tcx> { universe: ty::UniverseIndex, ) -> Ty<'tcx> { let vid = self.next_ty_var_id_in_universe(origin, universe); - self.tcx.mk_ty_var(vid) + Ty::new_var(self.tcx, vid) } pub fn next_const_var(&self, ty: Ty<'tcx>, origin: ConstVariableOrigin) -> ty::Const<'tcx> { - self.tcx.mk_const(self.next_const_var_id(origin), ty) + ty::Const::new_var(self.tcx, self.next_const_var_id(origin), ty) } pub fn next_const_var_in_universe( @@ -1013,7 +1013,7 @@ impl<'tcx> InferCtxt<'tcx> { .borrow_mut() .const_unification_table() .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } }); - self.tcx.mk_const(vid, ty) + ty::Const::new_var(self.tcx, vid, ty) } pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> { @@ -1028,7 +1028,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn next_int_var(&self) -> Ty<'tcx> { - self.tcx.mk_int_var(self.next_int_var_id()) + Ty::new_int_var(self.tcx, self.next_int_var_id()) } fn next_float_var_id(&self) -> FloatVid { @@ -1036,7 +1036,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn next_float_var(&self) -> Ty<'tcx> { - self.tcx.mk_float_var(self.next_float_var_id()) + Ty::new_float_var(self.tcx, self.next_float_var_id()) } /// Creates a fresh region variable with the next available index. @@ -1110,13 +1110,13 @@ impl<'tcx> InferCtxt<'tcx> { TypeVariableOrigin { kind: TypeVariableOriginKind::TypeParameterDefinition( param.name, - Some(param.def_id), + param.def_id, ), span, }, ); - self.tcx.mk_ty_var(ty_var_id).into() + Ty::new_var(self.tcx, ty_var_id).into() } GenericParamDefKind::Const { .. } => { let origin = ConstVariableOrigin { @@ -1131,15 +1131,15 @@ impl<'tcx> InferCtxt<'tcx> { origin, val: ConstVariableValue::Unknown { universe: self.universe() }, }); - self.tcx - .mk_const( - const_var_id, - self.tcx - .type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - ) - .into() + ty::Const::new_var( + self.tcx, + const_var_id, + self.tcx + .type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"), + ) + .into() } } } @@ -1265,7 +1265,7 @@ impl<'tcx> InferCtxt<'tcx> { if let Some(value) = inner.int_unification_table().probe_value(vid) { value.to_type(self.tcx) } else { - self.tcx.mk_int_var(inner.int_unification_table().find(vid)) + Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid)) } } @@ -1276,7 +1276,7 @@ impl<'tcx> InferCtxt<'tcx> { if let Some(value) = inner.float_unification_table().probe_value(vid) { value.to_type(self.tcx) } else { - self.tcx.mk_float_var(inner.float_unification_table().find(vid)) + Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid)) } } @@ -1472,7 +1472,7 @@ impl<'tcx> InferCtxt<'tcx> { span: Option<Span>, ) -> Result<ty::Const<'tcx>, ErrorHandled> { match self.const_eval_resolve(param_env, unevaluated, span) { - Ok(Some(val)) => Ok(self.tcx.mk_const(val, ty)), + Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, ty)), Ok(None) => { let tcx = self.tcx; let def_id = unevaluated.def; @@ -1945,13 +1945,16 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>( self.idx += 1; idx }; - self.tcx.mk_placeholder(ty::PlaceholderType { - universe: ty::UniverseIndex::ROOT, - bound: ty::BoundTy { - var: ty::BoundVar::from_u32(idx), - kind: ty::BoundTyKind::Anon, + Ty::new_placeholder( + self.tcx, + ty::PlaceholderType { + universe: ty::UniverseIndex::ROOT, + bound: ty::BoundTy { + var: ty::BoundVar::from_u32(idx), + kind: ty::BoundTyKind::Anon, + }, }, - }) + ) } else { t.super_fold_with(self) } @@ -1964,7 +1967,8 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>( if ty.has_non_region_param() || ty.has_non_region_infer() { bug!("const `{c}`'s type should not reference params or types"); } - self.tcx.mk_const( + ty::Const::new_placeholder( + self.tcx, ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, bound: ty::BoundVar::from_u32({ diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 3098b8bc2f9..5927f79a183 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -473,17 +473,6 @@ where } } - ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => { - // Skip lifetime parameters that are not captures. - let variances = self.tcx.variances_of(proj.def_id); - - for (v, s) in std::iter::zip(variances, proj.substs.iter()) { - if *v != ty::Variance::Bivariant { - s.visit_with(self); - } - } - } - _ => { ty.super_visit_with(self); } diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index 75455533181..38e74e53868 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -21,29 +21,18 @@ impl<'tcx> InferCtxt<'tcx> { recursion_depth: usize, obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> Ty<'tcx> { - if self.next_trait_solver() { - // FIXME(-Ztrait-solver=next): Instead of branching here, - // completely change the normalization routine with the new solver. - // - // The new solver correctly handles projection equality so this hack - // is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate` - // not `PredicateKind::Clause(ClauseKind::Projection(..))` as in the new solver - // `Projection` is used as `normalizes-to` which will fail for `<T as Trait>::Assoc eq ?0`. - return projection_ty.to_ty(self.tcx); - } else { - let def_id = projection_ty.def_id; - let ty_var = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::NormalizeProjectionType, - span: self.tcx.def_span(def_id), - }); - let projection = - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection( - ty::ProjectionPredicate { projection_ty, term: ty_var.into() }, - ))); - let obligation = - Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); - obligations.push(obligation); - ty_var - } + debug_assert!(!self.next_trait_solver()); + let def_id = projection_ty.def_id; + let ty_var = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::NormalizeProjectionType, + span: self.tcx.def_span(def_id), + }); + let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection( + ty::ProjectionPredicate { projection_ty, term: ty_var.into() }, + ))); + let obligation = + Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); + obligations.push(obligation); + ty_var } } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index d9f9d2aabdb..27e1ed56f31 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -118,7 +118,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { (&ty::Error(e), _) | (_, &ty::Error(e)) => { infcx.set_tainted_by_errors(e); - Ok(self.tcx().ty_error(e)) + Ok(Ty::new_error(self.tcx(), e)) } ( diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 9f85f9207e8..01c11d16345 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -123,7 +123,7 @@ pub enum TypeVariableOriginKind { NormalizeProjectionType, TypeInference, OpaqueTypeInference(DefId), - TypeParameterDefinition(Symbol, Option<DefId>), + TypeParameterDefinition(Symbol, DefId), /// One of the upvars or closure kind parameters in a `ClosureSubsts` /// (before it has been determined). diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index b5a7d0326a8..9f440f39849 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -25,9 +25,11 @@ impl<'tcx> InferCtxt<'tcx> { "impl has stricter requirements than trait" ); - if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) { - let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); - err.span_label(span, format!("definition of `{}` from trait", item_name)); + if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) { + if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) { + let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); + err.span_label(span, format!("definition of `{}` from trait", item_name)); + } } err.span_label(error_span, format!("impl has extra requirement {}", requirement)); diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 6da490a90ee..626dd9359a1 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -62,7 +62,8 @@ impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> { } pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; -pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; +pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>; +pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; impl<'tcx> PredicateObligation<'tcx> { /// Flips the polarity of the inner predicate. @@ -86,7 +87,7 @@ impl<'tcx> PredicateObligation<'tcx> { } } -impl<'tcx> TraitObligation<'tcx> { +impl<'tcx> PolyTraitObligation<'tcx> { /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. pub fn is_const(&self) -> bool { matches!( @@ -193,7 +194,7 @@ impl<'tcx> FulfillmentError<'tcx> { } } -impl<'tcx> TraitObligation<'tcx> { +impl<'tcx> PolyTraitObligation<'tcx> { pub fn polarity(&self) -> ty::ImplPolarity { self.predicate.skip_binder().polarity } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 3aeed93baf2..074ff7ec97f 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -3,7 +3,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{self, Obligation, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_middle::ty::{self, ToPredicate, TyCtxt}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -344,7 +344,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { } Component::Param(p) => { - let ty = tcx.mk_ty_param(p.index, p.name); + let ty = Ty::new_param(tcx, p.index, p.name); Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min))) } diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index d511d2b1280..29335a8c0f4 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -367,13 +367,6 @@ impl Cursor<'_> { Some(|terminated| Byte { terminated }), ), - // c-string literal, raw c-string literal or identifier. - 'c' => self.c_or_byte_string( - |terminated| CStr { terminated }, - |n_hashes| RawCStr { n_hashes }, - None, - ), - // Identifier (this should be checked after other variant that can // start as identifier). c if is_id_start(c) => self.ident_or_unknown_prefix(), diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c24760263bf..b821933e908 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -674,21 +674,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } let def = cx.tcx.adt_def(item.owner_id); - (def, cx.tcx.mk_adt(def, ty::List::empty())) + (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } hir::ItemKind::Union(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(item.owner_id); - (def, cx.tcx.mk_adt(def, ty::List::empty())) + (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } hir::ItemKind::Enum(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(item.owner_id); - (def, cx.tcx.mk_adt(def, ty::List::empty())) + (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } _ => return, }; diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 13164b0b339..3761754f3ae 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1345,7 +1345,7 @@ impl<'tcx> LateContext<'tcx> { tcx.associated_items(trait_id) .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) .and_then(|assoc| { - let proj = tcx.mk_projection(assoc.def_id, [self_ty]); + let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]); tcx.try_normalize_erasing_regions(self.param_env, proj).ok() }) } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 79253cbc8b4..145de494835 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -533,6 +533,10 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) { if let GenericParamKind::Const { .. } = param.kind { + // `rustc_host` params are explicitly allowed to be lowercase. + if cx.tcx.has_attr(param.def_id, sym::rustc_host) { + return; + } NonUpperCaseGlobals::check_upper_case(cx, "const parameter", ¶m.name.ident()); } } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 63a56806a45..09a1651c2f5 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { } let proj_ty = - cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs); + Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.substs); // For every instance of the projection type in the bounds, // replace them with the term we're assigning to the associated // type in our opaque type. @@ -144,7 +144,8 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { OPAQUE_HIDDEN_INFERRED_BOUND, pred_span, OpaqueHiddenInferredBoundLint { - ty: cx.tcx.mk_opaque( + ty: Ty::new_opaque( + cx.tcx, def_id, ty::InternalSubsts::identity_for_item(cx.tcx, def_id), ), diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 0ae0306b5ac..2509d493a4c 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -862,12 +862,12 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t }; return get_nullable_type(cx, inner_field_ty); } - ty::Int(ty) => tcx.mk_mach_int(ty), - ty::Uint(ty) => tcx.mk_mach_uint(ty), - ty::RawPtr(ty_mut) => tcx.mk_ptr(ty_mut), + ty::Int(ty) => Ty::new_int(tcx, ty), + ty::Uint(ty) => Ty::new_uint(tcx, ty), + ty::RawPtr(ty_mut) => Ty::new_ptr(tcx, ty_mut), // As these types are always non-null, the nullable equivalent of // Option<T> of these types are their raw pointer counterparts. - ty::Ref(_region, ty, mutbl) => tcx.mk_ptr(ty::TypeAndMut { ty, mutbl }), + ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty::TypeAndMut { ty, mutbl }), ty::FnPtr(..) => { // There is no nullable equivalent for Rust's function pointers -- you // must use an Option<fn(..) -> _> to represent it. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index ef82a6c17ee..87c542dc2e2 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3409,6 +3409,7 @@ declare_lint_pass! { UNSTABLE_SYNTAX_PRE_EXPANSION, UNSUPPORTED_CALLING_CONVENTIONS, UNUSED_ASSIGNMENTS, + UNUSED_ASSOCIATED_TYPE_BOUNDS, UNUSED_ATTRIBUTES, UNUSED_CRATE_DEPENDENCIES, UNUSED_EXTERN_CRATES, @@ -3469,6 +3470,32 @@ declare_lint! { } declare_lint! { + /// The `unused_associated_type_bounds` lint is emitted when an + /// associated type bound is added to a trait object, but the associated + /// type has a `where Self: Sized` bound, and is thus unavailable on the + /// trait object anyway. + /// + /// ### Example + /// + /// ```rust + /// trait Foo { + /// type Bar where Self: Sized; + /// } + /// type Mop = dyn Foo<Bar = ()>; + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Just like methods with `Self: Sized` bounds are unavailable on trait + /// objects, associated types can be removed from the trait object. + pub UNUSED_ASSOCIATED_TYPE_BOUNDS, + Warn, + "detects unused `Foo = Bar` bounds in `dyn Trait<Foo = Bar>`" +} + +declare_lint! { /// The `unused_doc_comments` lint detects doc comments that aren't used /// by `rustdoc`. /// diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 553fe6cf087..bb7510b3a53 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -121,6 +121,32 @@ extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name, return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen))); } +enum class LLVMRustTailCallKind { + None, + Tail, + MustTail, + NoTail, +}; + +static CallInst::TailCallKind fromRust(LLVMRustTailCallKind Kind) { + switch (Kind) { + case LLVMRustTailCallKind::None: + return CallInst::TailCallKind::TCK_None; + case LLVMRustTailCallKind::Tail: + return CallInst::TailCallKind::TCK_Tail; + case LLVMRustTailCallKind::MustTail: + return CallInst::TailCallKind::TCK_MustTail; + case LLVMRustTailCallKind::NoTail: + return CallInst::TailCallKind::TCK_NoTail; + default: + report_fatal_error("bad CallInst::TailCallKind."); + } +} + +extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call, LLVMRustTailCallKind TCK) { + unwrap<CallInst>(Call)->setTailCallKind(fromRust(TCK)); +} + extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, const char *Name, size_t NameLen, diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 1b19ed9ad14..d5e8330b3f6 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -433,7 +433,8 @@ impl<'tcx> CanonicalVarValues<'tcx> { |(i, info)| -> ty::GenericArg<'tcx> { match info.kind { CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => { - tcx.mk_bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into()).into() + Ty::new_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i).into()) + .into() } CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { let br = ty::BoundRegion { @@ -443,12 +444,13 @@ impl<'tcx> CanonicalVarValues<'tcx> { ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into() } CanonicalVarKind::Const(_, ty) - | CanonicalVarKind::PlaceholderConst(_, ty) => tcx - .mk_const( - ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), - ty, - ) - .into(), + | CanonicalVarKind::PlaceholderConst(_, ty) => ty::Const::new_bound( + tcx, + ty::INNERMOST, + ty::BoundVar::from_usize(i), + ty, + ) + .into(), } }, )), diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 991b9f01985..85fb9214d9d 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -90,15 +90,15 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { impl ToType for ty::IntVarValue { fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { - ty::IntType(i) => tcx.mk_mach_int(i), - ty::UintType(i) => tcx.mk_mach_uint(i), + ty::IntType(i) => Ty::new_int(tcx, i), + ty::UintType(i) => Ty::new_uint(tcx, i), } } } impl ToType for ty::FloatVarValue { fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.mk_mach_float(self.0) + Ty::new_float(tcx, self.0) } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index ad1c93c31e9..28c50587800 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1913,7 +1913,7 @@ impl<'tcx> Operand<'tcx> { substs: impl IntoIterator<Item = GenericArg<'tcx>>, span: Span, ) -> Self { - let ty = tcx.mk_fn_def(def_id, substs); + let ty = Ty::new_fn_def(tcx, def_id, substs); Operand::Constant(Box::new(Constant { span, user_ty: None, @@ -2014,7 +2014,7 @@ impl<'tcx> Rvalue<'tcx> { | CastKind::IntToFloat | CastKind::FnPtrToPtr | CastKind::PtrToPtr - | CastKind::Pointer(_) + | CastKind::PointerCoercion(_) | CastKind::PointerFromExposedAddress | CastKind::DynStar | CastKind::Transmute, @@ -2329,10 +2329,10 @@ impl<'tcx> ConstantKind<'tcx> { pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { match self { Self::Ty(c) => { - if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) { + if let Some(val) = c.try_eval_for_mir(tcx, param_env) { match val { Ok(val) => Self::Val(val, c.ty()), - Err(guar) => Self::Ty(tcx.const_error(self.ty(), guar)), + Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())), } } else { self @@ -2344,7 +2344,9 @@ impl<'tcx> ConstantKind<'tcx> { match tcx.const_eval_resolve(param_env, uneval, None) { Ok(val) => Self::Val(val, ty), Err(ErrorHandled::TooGeneric) => self, - Err(ErrorHandled::Reported(guar)) => Self::Ty(tcx.const_error(ty, guar.into())), + Err(ErrorHandled::Reported(guar)) => { + Self::Ty(ty::Const::new_error(tcx, guar.into(), ty)) + } } } } @@ -2510,7 +2512,7 @@ impl<'tcx> ConstantKind<'tcx> { let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.item_name(def_id); - let ty_const = tcx.mk_const(ty::ParamConst::new(index, name), ty); + let ty_const = ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty); debug!(?ty_const); return Self::Ty(ty_const); @@ -2774,7 +2776,7 @@ impl<'tcx> Display for ConstantKind<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { match *self { ConstantKind::Ty(c) => pretty_print_const(c, fmt, true), - ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true), + ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt), // FIXME(valtrees): Correctly print mir constants. ConstantKind::Unevaluated(..) => { fmt.write_str("_")?; @@ -2804,13 +2806,16 @@ fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Resul write!(fmt, "b\"{}\"", byte_str.escape_ascii()) } -fn comma_sep<'tcx>(fmt: &mut Formatter<'_>, elems: Vec<ConstantKind<'tcx>>) -> fmt::Result { +fn comma_sep<'tcx>( + fmt: &mut Formatter<'_>, + elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>, +) -> fmt::Result { let mut first = true; - for elem in elems { + for (ct, ty) in elems { if !first { fmt.write_str(", ")?; } - fmt.write_str(&format!("{}", elem))?; + pretty_print_const_value(ct, ty, fmt)?; first = false; } Ok(()) @@ -2821,7 +2826,6 @@ fn pretty_print_const_value<'tcx>( ct: ConstValue<'tcx>, ty: Ty<'tcx>, fmt: &mut Formatter<'_>, - print_ty: bool, ) -> fmt::Result { use crate::ty::print::PrettyPrinter; @@ -2865,7 +2869,7 @@ fn pretty_print_const_value<'tcx>( } } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { - let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap(); + let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap(); // cast is ok because we already checked for pointer size (32 or 64 bit) above let range = AllocRange { start: offset, size: Size::from_bytes(n) }; let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap(); @@ -2880,16 +2884,11 @@ fn pretty_print_const_value<'tcx>( // introducing ICEs (e.g. via `layout_of`) from missing bounds. // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized` // to be able to destructure the tuple into `(0u8, *mut T)` - // - // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the - // correct `ty::ParamEnv` to allow printing *all* constant values. (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => { let ct = tcx.lift(ct).unwrap(); let ty = tcx.lift(ty).unwrap(); - if let Some(contents) = tcx.try_destructure_mir_constant( - ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)), - ) { - let fields = contents.fields.to_vec(); + if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics((ct, ty)) { + let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec(); match *ty.kind() { ty::Array(..) => { fmt.write_str("[")?; @@ -2928,12 +2927,14 @@ fn pretty_print_const_value<'tcx>( None => { fmt.write_str(" {{ ")?; let mut first = true; - for (field_def, field) in iter::zip(&variant_def.fields, fields) + for (field_def, (ct, ty)) in + iter::zip(&variant_def.fields, fields) { if !first { fmt.write_str(", ")?; } - fmt.write_str(&format!("{}: {}", field_def.name, field))?; + write!(fmt, "{}: ", field_def.name)?; + pretty_print_const_value(ct, ty, fmt)?; first = false; } fmt.write_str(" }}")?; @@ -2943,20 +2944,13 @@ fn pretty_print_const_value<'tcx>( _ => unreachable!(), } return Ok(()); - } else { - // Fall back to debug pretty printing for invalid constants. - fmt.write_str(&format!("{:?}", ct))?; - if print_ty { - fmt.write_str(&format!(": {}", ty))?; - } - return Ok(()); - }; + } } (ConstValue::Scalar(scalar), _) => { let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); cx.print_alloc_ids = true; let ty = tcx.lift(ty).unwrap(); - cx = cx.pretty_print_const_scalar(scalar, ty, print_ty)?; + cx = cx.pretty_print_const_scalar(scalar, ty)?; fmt.write_str(&cx.into_buffer())?; return Ok(()); } @@ -2971,12 +2965,8 @@ fn pretty_print_const_value<'tcx>( // their fields instead of just dumping the memory. _ => {} } - // fallback - fmt.write_str(&format!("{:?}", ct))?; - if print_ty { - fmt.write_str(&format!(": {}", ty))?; - } - Ok(()) + // Fall back to debug pretty printing for invalid constants. + write!(fmt, "{ct:?}: {ty}") }) } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 13a1011e328..613b132ff2d 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,6 +1,6 @@ //! Values computed by queries that use MIR. -use crate::mir::ConstantKind; +use crate::mir::interpret::ConstValue; use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordSet; @@ -444,7 +444,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { #[derive(Copy, Clone, Debug, HashStable)] pub struct DestructuredConstant<'tcx> { pub variant: Option<VariantIdx>, - pub fields: &'tcx [ConstantKind<'tcx>], + pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)], } /// Coverage information summarized from a MIR if instrumented for source code coverage (see diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index abb3b3d953b..7f1d3820341 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -7,7 +7,7 @@ use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection}; use crate::mir::coverage::{CodeRegion, CoverageKind}; use crate::traits::Reveal; -use crate::ty::adjustment::PointerCast; +use crate::ty::adjustment::PointerCoercion; use crate::ty::subst::SubstsRef; use crate::ty::{self, List, Ty}; use crate::ty::{Region, UserTypeAnnotationIndex}; @@ -1230,9 +1230,9 @@ pub enum CastKind { /// An address-to-pointer cast that picks up an exposed provenance. /// See the docs on `from_exposed_addr` for more details. PointerFromExposedAddress, - /// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are + /// Pointer related casts that are done by coercions. Note that reference-to-raw-ptr casts are /// translated into `&raw mut/const *r`, i.e., they are not actually casts. - Pointer(PointerCast), + PointerCoercion(PointerCoercion), /// Cast into a dyn* object. DynStar, IntToInt, diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 65dff193c80..8618a531527 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -95,11 +95,13 @@ impl<'tcx> PlaceTy<'tcx> { ProjectionElem::Subslice { from, to, from_end } => { PlaceTy::from_ty(match self.ty.kind() { ty::Slice(..) => self.ty, - ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64), + ty::Array(inner, _) if !from_end => { + Ty::new_array(tcx, *inner, (to - from) as u64) + } ty::Array(inner, size) if from_end => { let size = size.eval_target_usize(tcx, param_env); let len = size - from - to; - tcx.mk_array(*inner, len) + Ty::new_array(tcx, *inner, len) } _ => bug!("cannot subslice non-array type: `{:?}`", self), }) @@ -162,16 +164,16 @@ impl<'tcx> Rvalue<'tcx> { match *self { Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), Rvalue::Repeat(ref operand, count) => { - tcx.mk_array_with_const_len(operand.ty(local_decls, tcx), count) + Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count) } Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did), Rvalue::Ref(reg, bk, ref place) => { let place_ty = place.ty(local_decls, tcx).ty; - tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() }) + Ty::new_ref(tcx, reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() }) } Rvalue::AddressOf(mutability, ref place) => { let place_ty = place.ty(local_decls, tcx).ty; - tcx.mk_ptr(ty::TypeAndMut { ty: place_ty, mutbl: mutability }) + Ty::new_ptr(tcx, ty::TypeAndMut { ty: place_ty, mutbl: mutability }) } Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, @@ -184,7 +186,7 @@ impl<'tcx> Rvalue<'tcx> { let lhs_ty = lhs.ty(local_decls, tcx); let rhs_ty = rhs.ty(local_decls, tcx); let ty = op.ty(tcx, lhs_ty, rhs_ty); - tcx.mk_tup(&[ty, tcx.types.bool]) + Ty::new_tup(tcx, &[ty, tcx.types.bool]) } Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), @@ -192,17 +194,17 @@ impl<'tcx> Rvalue<'tcx> { tcx.types.usize } Rvalue::Aggregate(ref ak, ref ops) => match **ak { - AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64), + AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), AggregateKind::Tuple => { - tcx.mk_tup_from_iter(ops.iter().map(|op| op.ty(local_decls, tcx))) + Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx))) } AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs), - AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs), + AggregateKind::Closure(did, substs) => Ty::new_closure(tcx, did, substs), AggregateKind::Generator(did, substs, movability) => { - tcx.mk_generator(did, substs, movability) + Ty::new_generator(tcx, did, substs, movability) } }, - Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty), + Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, } } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 4006a6cd1cc..28e699cd269 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -2,6 +2,7 @@ use crate::infer::canonical::Canonical; use crate::mir; +use crate::mir::interpret::ConstValue; use crate::traits; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::{TyAndLayout, ValidityRequirement}; @@ -317,11 +318,11 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) { } } -impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { +impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) { type CacheSelector = DefaultCacheSelector<Self>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - tcx.def_span(self.1.def_id()) + tcx.def_span(self.1.def_id) } } @@ -333,6 +334,14 @@ impl<'tcx> Key for (ty::Const<'tcx>, FieldIdx) { } } +impl<'tcx> Key for (ConstValue<'tcx>, Ty<'tcx>) { + type CacheSelector = DefaultCacheSelector<Self>; + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> { type CacheSelector = DefaultCacheSelector<Self>; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6f942e0bc86..a059590e6ad 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1087,11 +1087,13 @@ rustc_queries! { } /// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index - /// and its field values. - query try_destructure_mir_constant( - key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> + /// and its field values. This should only be used for pretty printing. + query try_destructure_mir_constant_for_diagnostics( + key: (ConstValue<'tcx>, Ty<'tcx>) ) -> Option<mir::DestructuredConstant<'tcx>> { desc { "destructuring MIR constant"} + no_hash + eval_always } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { @@ -1276,7 +1278,7 @@ rustc_queries! { } query codegen_select_candidate( - key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) + key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { cache_on_disk_if { true } desc { |tcx| "computing candidate for `{}`", key.1 } @@ -2197,6 +2199,10 @@ rustc_queries! { desc { "getting cfg-ed out item names" } separate_provide_extern } + + query generics_require_sized_self(def_id: DefId) -> bool { + desc { "check whether the item has a `where Self: Sized` bound" } + } } rustc_query_append! { define_callbacks! } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 0f3ad6d0151..e9af5070e5e 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -18,7 +18,7 @@ use rustc_index::IndexVec; use rustc_middle::middle::region; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp}; -use rustc_middle::ty::adjustment::PointerCast; +use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarSubsts}; use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation}; @@ -329,9 +329,10 @@ pub enum ExprKind<'tcx> { NeverToAny { source: ExprId, }, - /// A pointer cast. More information can be found in [`PointerCast`]. - Pointer { - cast: PointerCast, + /// A pointer coercion. More information can be found in [`PointerCoercion`]. + /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`]. + PointerCoercion { + cast: PointerCoercion, source: ExprId, }, /// A `loop` expression. diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 9cc07677e0e..14bc1ac0ce7 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -65,7 +65,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp Cast { source } => visitor.visit_expr(&visitor.thir()[source]), Use { source } => visitor.visit_expr(&visitor.thir()[source]), NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), - Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), + PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), Let { expr, .. } => { visitor.visit_expr(&visitor.thir()[expr]); } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 69d826bbe7a..c7d2e4c22d2 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -588,6 +588,10 @@ pub enum SelectionError<'tcx> { /// Signaling that an error has already been emitted, to avoid /// multiple errors being shown. ErrorReporting, + /// Computing an opaque type's hidden type caused an error (e.g. a cycle error). + /// We can thus not know whether the hidden type implements an auto trait, so + /// we should not presume anything about it. + OpaqueTypeAutoTraitLeakageUnknown(DefId), } #[derive(Clone, Debug, TypeVisitable, Lift)] diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index cbc68fde9d9..09517200b0d 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -81,7 +81,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { Err(TypeError::Sorts(relate::expected_found(self, a, b))) } - (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)), + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)), _ => relate::structurally_relate_tys(self, a, b), } diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index a39631da936..ffee7ba28c3 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -53,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> { fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> { let ct = match c.kind() { ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) { - Err(e) => self.tcx.const_error(c.ty(), e), + Err(e) => ty::Const::new_error(self.tcx, e, c.ty()), Ok(Some(bac)) => { let substs = self.tcx.erase_regions(uv.substs); let bac = bac.subst(self.tcx, substs); diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index cd0f7e8daf1..76931ceaa69 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -6,7 +6,7 @@ use rustc_span::Span; use rustc_target::abi::FieldIdx; #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] -pub enum PointerCast { +pub enum PointerCoercion { /// Go from a fn-item type to a fn-pointer type. ReifyFnPointer, @@ -99,7 +99,7 @@ pub enum Adjust<'tcx> { /// Take the address and produce either a `&` or `*` pointer. Borrow(AutoBorrow<'tcx>), - Pointer(PointerCast), + Pointer(PointerCoercion), /// Cast into a dyn* object. DynStar, @@ -132,7 +132,7 @@ impl<'tcx> OverloadedDeref<'tcx> { .find(|m| m.kind == ty::AssocKind::Fn) .unwrap() .def_id; - tcx.mk_fn_def(method_def_id, [source]) + Ty::new_fn_def(tcx, method_def_id, [source]) } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 22bed6ad1c5..6adbb44a153 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -344,7 +344,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> { fn decode(decoder: &mut D) -> Self { let consts: ty::ConstData<'tcx> = Decodable::decode(decoder); - decoder.interner().mk_const(consts.kind, consts.ty) + decoder.interner().mk_ct_from_kind(consts.kind, consts.ty) } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index aecb46556b0..1cbfe99f87f 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,7 +1,8 @@ use crate::middle::resolve_bound_vars as rbv; -use crate::mir::interpret::LitToConstInput; -use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar}; +use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::intern::Interned; +use rustc_error_messages::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; @@ -13,8 +14,13 @@ mod valtree; pub use int::*; pub use kind::*; +use rustc_span::ErrorGuaranteed; +use rustc_span::DUMMY_SP; +use rustc_target::abi::Size; pub use valtree::*; +use super::sty::ConstKind; + /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_pass_by_value] @@ -30,6 +36,16 @@ pub struct ConstData<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstData<'_>, 40); +enum EvalMode { + Typeck, + Mir, +} + +enum EvalResult<'tcx> { + ValTree(ty::ValTree<'tcx>), + ConstVal(ConstValue<'tcx>), +} + impl<'tcx> Const<'tcx> { #[inline] pub fn ty(self) -> Ty<'tcx> { @@ -38,7 +54,98 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn kind(self) -> ConstKind<'tcx> { - self.0.kind + self.0.kind.clone() + } + + #[inline] + pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + tcx.mk_ct_from_kind(kind, ty) + } + + #[inline] + pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Param(param), ty) + } + + #[inline] + pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty) + } + + #[inline] + pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty) + } + + #[inline] + pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(infer), ty) + } + + #[inline] + pub fn new_bound( + tcx: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, + ty: Ty<'tcx>, + ) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty) + } + + #[inline] + pub fn new_placeholder( + tcx: TyCtxt<'tcx>, + placeholder: ty::PlaceholderConst<'tcx>, + ty: Ty<'tcx>, + ) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty) + } + + #[inline] + pub fn new_unevaluated( + tcx: TyCtxt<'tcx>, + uv: ty::UnevaluatedConst<'tcx>, + ty: Ty<'tcx>, + ) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty) + } + + #[inline] + pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Value(val), ty) + } + + #[inline] + pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Expr(expr), ty) + } + + #[inline] + pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Error(e), ty) + } + + /// Like [Ty::new_error] but for constants. + #[track_caller] + pub fn new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new_error_with_message( + tcx, + ty, + DUMMY_SP, + "ty::ConstKind::Error constructed but no error reported", + ) + } + + /// Like [Ty::new_error_with_message] but for constants. + #[track_caller] + pub fn new_error_with_message<S: Into<MultiSpan>>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + span: S, + msg: &'static str, + ) -> Const<'tcx> { + let reported = tcx.sess.delay_span_bug(span, msg); + Const::new_error(tcx, reported, ty) } /// Literals and const generic parameters are eagerly converted to a constant, everything else @@ -60,7 +167,8 @@ impl<'tcx> Const<'tcx> { match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, - None => tcx.mk_const( + None => ty::Const::new_unevaluated( + tcx, ty::UnevaluatedConst { def: def.to_def_id(), substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()), @@ -126,13 +234,19 @@ impl<'tcx> Const<'tcx> { let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.item_name(def_id); - Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty)) + Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty)) + } + Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { + Some(ty::Const::new_bound( + tcx, + debruijn, + ty::BoundVar::from_u32(index), + param_ty, + )) + } + Some(rbv::ResolvedArg::Error(guar)) => { + Some(ty::Const::new_error(tcx, guar, param_ty)) } - Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const( - ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)), - param_ty, - )), - Some(rbv::ResolvedArg::Error(guar)) => Some(tcx.const_error(param_ty, guar)), arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id), } } @@ -155,7 +269,8 @@ impl<'tcx> Const<'tcx> { .layout_of(ty) .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e)) .size; - tcx.mk_const( + ty::Const::new_value( + tcx, ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()), ty.value, ) @@ -164,7 +279,7 @@ impl<'tcx> Const<'tcx> { #[inline] /// Creates an interned zst constant. pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { - tcx.mk_const(ty::ValTree::zst(), ty) + ty::Const::new_value(tcx, ty::ValTree::zst(), ty) } #[inline] @@ -192,12 +307,12 @@ impl<'tcx> Const<'tcx> { assert_eq!(self.ty(), ty); let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env - self.kind().eval(tcx, param_env).try_to_bits(size) + self.eval(tcx, param_env).try_to_bits(size) } #[inline] pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { - self.kind().eval(tcx, param_env).try_to_bool() + self.eval(tcx, param_env).try_to_bool() } #[inline] @@ -206,17 +321,17 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option<u64> { - self.kind().eval(tcx, param_env).try_to_target_usize(tcx) + self.eval(tcx, param_env).try_to_target_usize(tcx) } #[inline] /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the /// unevaluated constant. pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> { - if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) { + if let Some(val) = self.try_eval_for_typeck(tcx, param_env) { match val { - Ok(val) => tcx.mk_const(val, self.ty()), - Err(guar) => tcx.const_error(self.ty(), guar), + Ok(val) => ty::Const::new_value(tcx, val, self.ty()), + Err(guar) => ty::Const::new_error(tcx, guar, self.ty()), } } else { // Either the constant isn't evaluatable or ValTree creation failed. @@ -238,6 +353,138 @@ impl<'tcx> Const<'tcx> { .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } + #[inline] + /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary + /// return `None`. + // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. + pub fn try_eval_for_mir( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> { + match self.try_eval_inner(tcx, param_env, EvalMode::Mir) { + Some(Ok(EvalResult::ValTree(_))) => unreachable!(), + Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)), + Some(Err(e)) => Some(Err(e)), + None => None, + } + } + + #[inline] + /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary + /// return `None`. + // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. + pub fn try_eval_for_typeck( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> { + match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) { + Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)), + Some(Ok(EvalResult::ConstVal(_))) => unreachable!(), + Some(Err(e)) => Some(Err(e)), + None => None, + } + } + + #[inline] + fn try_eval_inner( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + eval_mode: EvalMode, + ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> { + assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); + if let ConstKind::Unevaluated(unevaluated) = self.kind() { + use crate::mir::interpret::ErrorHandled; + + // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` + // also does later, but we want to do it before checking for + // inference variables. + // Note that we erase regions *before* calling `with_reveal_all_normalized`, + // so that we don't try to invoke this query with + // any region variables. + + // HACK(eddyb) when the query key would contain inference variables, + // attempt using identity substs and `ParamEnv` instead, that will succeed + // when the expression doesn't depend on any parameters. + // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that + // we can call `infcx.const_eval_resolve` which handles inference variables. + let param_env_and = if (param_env, unevaluated).has_non_region_infer() { + tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { + def: unevaluated.def, + substs: InternalSubsts::identity_for_item(tcx, unevaluated.def), + }) + } else { + tcx.erase_regions(param_env) + .with_reveal_all_normalized(tcx) + .and(tcx.erase_regions(unevaluated)) + }; + + // FIXME(eddyb) maybe the `const_eval_*` methods should take + // `ty::ParamEnvAnd` instead of having them separate. + let (param_env, unevaluated) = param_env_and.into_parts(); + // try to resolve e.g. associated constants to their definition on an impl, and then + // evaluate the const. + match eval_mode { + EvalMode::Typeck => { + match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) { + // NOTE(eddyb) `val` contains no lifetimes/types/consts, + // and we use the original type, so nothing from `substs` + // (which may be identity substs, see above), + // can leak through `val` into the const we return. + Ok(val) => Some(Ok(EvalResult::ValTree(val?))), + Err(ErrorHandled::TooGeneric) => None, + Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), + } + } + EvalMode::Mir => { + match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { + // NOTE(eddyb) `val` contains no lifetimes/types/consts, + // and we use the original type, so nothing from `substs` + // (which may be identity substs, see above), + // can leak through `val` into the const we return. + Ok(val) => Some(Ok(EvalResult::ConstVal(val))), + Err(ErrorHandled::TooGeneric) => None, + Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), + } + } + } + } else { + None + } + } + + #[inline] + pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> { + if let ConstKind::Value(val) = self.kind() { Some(val) } else { None } + } + + #[inline] + pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> { + self.try_to_value()?.try_to_scalar() + } + + #[inline] + pub fn try_to_scalar_int(self) -> Option<ScalarInt> { + self.try_to_value()?.try_to_scalar_int() + } + + #[inline] + pub fn try_to_bits(self, size: Size) -> Option<u128> { + self.try_to_scalar_int()?.to_bits(size).ok() + } + + #[inline] + pub fn try_to_bool(self) -> Option<bool> { + self.try_to_scalar_int()?.try_into().ok() + } + + #[inline] + pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { + self.try_to_value()?.try_to_target_usize(tcx) + } + pub fn is_ct_infer(self) -> bool { matches!(self.kind(), ty::ConstKind::Infer(_)) } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 1dd4f8a2437..a6bf7491118 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,17 +1,11 @@ use super::Const; use crate::mir; -use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::ty::abstract_const::CastKind; -use crate::ty::subst::{InternalSubsts, SubstsRef}; -use crate::ty::ParamEnv; -use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::subst::SubstsRef; +use crate::ty::{self, List, Ty}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_target::abi::Size; - -use super::ScalarInt; /// An unevaluated (potentially generic) constant used in the type-system. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] @@ -41,45 +35,6 @@ impl<'tcx> UnevaluatedConst<'tcx> { } } -/// Represents a constant in Rust. -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] -#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] -#[derive(derive_more::From)] -pub enum ConstKind<'tcx> { - /// A const generic parameter. - Param(ty::ParamConst), - - /// Infer the value of the const. - Infer(InferConst<'tcx>), - - /// Bound const variable, used only when preparing a trait query. - Bound(ty::DebruijnIndex, ty::BoundVar), - - /// A placeholder const - universally quantified higher-ranked const. - Placeholder(ty::PlaceholderConst<'tcx>), - - /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other - /// variants when the code is monomorphic enough for that. - Unevaluated(UnevaluatedConst<'tcx>), - - /// Used to hold computed value. - Value(ty::ValTree<'tcx>), - - /// A placeholder for a const which could not be computed; this is - /// propagated to avoid useless error messages. - #[from(ignore)] - Error(ErrorGuaranteed), - - /// Expr which contains an expression which has partially evaluated items. - Expr(Expr<'tcx>), -} - -impl<'tcx> From<ty::ConstVid<'tcx>> for ConstKind<'tcx> { - fn from(const_vid: ty::ConstVid<'tcx>) -> Self { - InferConst::Var(const_vid).into() - } -} - #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] pub enum Expr<'tcx> { @@ -93,39 +48,7 @@ pub enum Expr<'tcx> { static_assert_size!(Expr<'_>, 24); #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ConstKind<'_>, 32); - -impl<'tcx> ConstKind<'tcx> { - #[inline] - pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> { - if let ConstKind::Value(val) = self { Some(val) } else { None } - } - - #[inline] - pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> { - self.try_to_value()?.try_to_scalar() - } - - #[inline] - pub fn try_to_scalar_int(self) -> Option<ScalarInt> { - self.try_to_value()?.try_to_scalar_int() - } - - #[inline] - pub fn try_to_bits(self, size: Size) -> Option<u128> { - self.try_to_scalar_int()?.to_bits(size).ok() - } - - #[inline] - pub fn try_to_bool(self) -> Option<bool> { - self.try_to_scalar_int()?.try_into().ok() - } - - #[inline] - pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { - self.try_to_value()?.try_to_target_usize(tcx) - } -} +static_assert_size!(super::ConstKind<'_>, 32); /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] @@ -144,124 +67,3 @@ impl<CTX> HashStable<CTX> for InferConst<'_> { } } } - -enum EvalMode { - Typeck, - Mir, -} - -enum EvalResult<'tcx> { - ValTree(ty::ValTree<'tcx>), - ConstVal(ConstValue<'tcx>), -} - -impl<'tcx> ConstKind<'tcx> { - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the - /// unevaluated constant. - pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self { - self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value) - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_mir( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Mir) { - Some(Ok(EvalResult::ValTree(_))) => unreachable!(), - Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_typeck( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) { - Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)), - Some(Ok(EvalResult::ConstVal(_))) => unreachable!(), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - fn try_eval_inner( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - eval_mode: EvalMode, - ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> { - assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); - if let ConstKind::Unevaluated(unevaluated) = self { - use crate::mir::interpret::ErrorHandled; - - // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` - // also does later, but we want to do it before checking for - // inference variables. - // Note that we erase regions *before* calling `with_reveal_all_normalized`, - // so that we don't try to invoke this query with - // any region variables. - - // HACK(eddyb) when the query key would contain inference variables, - // attempt using identity substs and `ParamEnv` instead, that will succeed - // when the expression doesn't depend on any parameters. - // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that - // we can call `infcx.const_eval_resolve` which handles inference variables. - let param_env_and = if (param_env, unevaluated).has_non_region_infer() { - tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { - def: unevaluated.def, - substs: InternalSubsts::identity_for_item(tcx, unevaluated.def), - }) - } else { - tcx.erase_regions(param_env) - .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(unevaluated)) - }; - - // FIXME(eddyb) maybe the `const_eval_*` methods should take - // `ty::ParamEnvAnd` instead of having them separate. - let (param_env, unevaluated) = param_env_and.into_parts(); - // try to resolve e.g. associated constants to their definition on an impl, and then - // evaluate the const. - match eval_mode { - EvalMode::Typeck => { - match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `substs` - // (which may be identity substs, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ValTree(val?))), - Err(ErrorHandled::TooGeneric) => None, - Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), - } - } - EvalMode::Mir => { - match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `substs` - // (which may be identity substs, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ConstVal(val))), - Err(ErrorHandled::TooGeneric) => None, - Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), - } - } - } - } else { - None - } - } -} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1c610d6891b..035e978f64c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -25,10 +25,10 @@ use crate::traits::solve::{ ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData, }; use crate::ty::{ - self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, FloatTy, FloatVar, - FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, - ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, - ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility, + self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind, + ImplPolarity, InferTy, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, + Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, + TyVid, TypeAndMut, Visibility, }; use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; use rustc_ast::{self as ast, attr}; @@ -70,10 +70,9 @@ use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx} use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; -use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags}; +use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; use std::any::Any; -use std::assert_matches::debug_assert_matches; use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; @@ -108,6 +107,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PredicateKind = ty::PredicateKind<'tcx>; type AllocId = crate::mir::interpret::AllocId; + type InferConst = ty::InferConst<'tcx>; + type AliasConst = ty::UnevaluatedConst<'tcx>; + type ParamConst = ty::ParamConst; + type BoundConst = ty::BoundVar; + type PlaceholderConst = ty::PlaceholderConst<'tcx>; + type ValueConst = ty::ValTree<'tcx>; + type ExprConst = ty::Expr<'tcx>; + type EarlyBoundRegion = ty::EarlyBoundRegion; type BoundRegion = ty::BoundRegion; type FreeRegion = ty::FreeRegion; @@ -320,6 +327,8 @@ pub struct CommonLifetimes<'tcx> { pub struct CommonConsts<'tcx> { pub unit: Const<'tcx>, + pub true_: Const<'tcx>, + pub false_: Const<'tcx>, } impl<'tcx> CommonTypes<'tcx> { @@ -417,6 +426,14 @@ impl<'tcx> CommonConsts<'tcx> { kind: ty::ConstKind::Value(ty::ValTree::zst()), ty: types.unit, }), + true_: mk_const(ty::ConstData { + kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)), + ty: types.bool, + }), + false_: mk_const(ty::ConstData { + kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)), + ty: types.bool, + }), } } } @@ -709,58 +726,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` - #[track_caller] - pub fn ty_error(self, reported: ErrorGuaranteed) -> Ty<'tcx> { - self.mk_ty_from_kind(Error(reported)) - } - - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. - #[track_caller] - pub fn ty_error_misc(self) -> Ty<'tcx> { - self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported") - } - - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to - /// ensure it gets used. - #[track_caller] - pub fn ty_error_with_message<S: Into<MultiSpan>>( - self, - span: S, - msg: impl Into<DiagnosticMessage>, - ) -> Ty<'tcx> { - let reported = self.sess.delay_span_bug(span, msg); - self.mk_ty_from_kind(Error(reported)) - } - - /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed` - #[track_caller] - pub fn const_error(self, ty: Ty<'tcx>, reported: ErrorGuaranteed) -> Const<'tcx> { - self.mk_const(ty::ConstKind::Error(reported), ty) - } - - /// Like [TyCtxt::ty_error] but for constants. - #[track_caller] - pub fn const_error_misc(self, ty: Ty<'tcx>) -> Const<'tcx> { - self.const_error_with_message( - ty, - DUMMY_SP, - "ty::ConstKind::Error constructed but no error reported", - ) - } - - /// Like [TyCtxt::ty_error_with_message] but for constants. - #[track_caller] - pub fn const_error_with_message<S: Into<MultiSpan>>( - self, - ty: Ty<'tcx>, - span: S, - msg: &'static str, - ) -> Const<'tcx> { - let reported = self.sess.delay_span_bug(span, msg); - self.mk_const(ty::ConstKind::Error(reported), ty) - } - pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool { self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg) } @@ -1154,7 +1119,8 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `&'static core::panic::Location<'static>`. pub fn caller_location_ty(self) -> Ty<'tcx> { - self.mk_imm_ref( + Ty::new_imm_ref( + self, self.lifetimes.re_static, self.type_of(self.require_lang_item(LangItem::PanicLocation, None)) .subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])), @@ -1552,7 +1518,10 @@ impl<'tcx> TyCtxt<'tcx> { /// unsafe. pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { assert_eq!(sig.unsafety(), hir::Unsafety::Normal); - self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig })) + Ty::new_fn_ptr( + self, + sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }), + ) } /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name` @@ -1626,18 +1595,6 @@ impl<'tcx> TyCtxt<'tcx> { }) } - // Avoid this in favour of more specific `mk_*` methods, where possible. - #[allow(rustc::usage_of_ty_tykind)] - #[inline] - pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> { - self.interners.intern_ty( - st, - self.sess, - // This is only used to create a stable hashing context. - &self.untracked, - ) - } - #[inline] pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { self.interners.intern_predicate( @@ -1657,174 +1614,6 @@ impl<'tcx> TyCtxt<'tcx> { if pred.kind() != binder { self.mk_predicate(binder) } else { pred } } - pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> { - match tm { - IntTy::Isize => self.types.isize, - IntTy::I8 => self.types.i8, - IntTy::I16 => self.types.i16, - IntTy::I32 => self.types.i32, - IntTy::I64 => self.types.i64, - IntTy::I128 => self.types.i128, - } - } - - pub fn mk_mach_uint(self, tm: UintTy) -> Ty<'tcx> { - match tm { - UintTy::Usize => self.types.usize, - UintTy::U8 => self.types.u8, - UintTy::U16 => self.types.u16, - UintTy::U32 => self.types.u32, - UintTy::U64 => self.types.u64, - UintTy::U128 => self.types.u128, - } - } - - pub fn mk_mach_float(self, tm: FloatTy) -> Ty<'tcx> { - match tm { - FloatTy::F32 => self.types.f32, - FloatTy::F64 => self.types.f64, - } - } - - #[inline] - pub fn mk_static_str(self) -> Ty<'tcx> { - self.mk_imm_ref(self.lifetimes.re_static, self.types.str_) - } - - #[inline] - pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - // Take a copy of substs so that we own the vectors inside. - self.mk_ty_from_kind(Adt(def, substs)) - } - - #[inline] - pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> { - self.mk_ty_from_kind(Foreign(def_id)) - } - - fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> { - let adt_def = self.adt_def(wrapper_def_id); - let substs = - InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), - GenericParamDefKind::Type { has_default, .. } => { - if param.index == 0 { - ty_param.into() - } else { - assert!(has_default); - self.type_of(param.def_id).subst(self, substs).into() - } - } - }); - self.mk_ty_from_kind(Adt(adt_def, substs)) - } - - #[inline] - pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(LangItem::OwnedBox, None); - self.mk_generic_adt(def_id, ty) - } - - #[inline] - pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> { - let def_id = self.lang_items().get(item)?; - Some(self.mk_generic_adt(def_id, ty)) - } - - #[inline] - pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> { - let def_id = self.get_diagnostic_item(name)?; - Some(self.mk_generic_adt(def_id, ty)) - } - - #[inline] - pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(LangItem::MaybeUninit, None); - self.mk_generic_adt(def_id, ty) - } - - #[inline] - pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(RawPtr(tm)) - } - - #[inline] - pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(Ref(r, tm.ty, tm.mutbl)) - } - - #[inline] - pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) - } - - #[inline] - pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not }) - } - - #[inline] - pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut }) - } - - #[inline] - pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not }) - } - - #[inline] - pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { - self.mk_ty_from_kind(Array(ty, ty::Const::from_target_usize(self, n))) - } - - #[inline] - pub fn mk_array_with_const_len(self, ty: Ty<'tcx>, ct: Const<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(Array(ty, ct)) - } - - #[inline] - pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(Slice(ty)) - } - - #[inline] - pub fn mk_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - if ts.is_empty() { - self.types.unit - } else { - self.mk_ty_from_kind(Tuple(self.mk_type_list(&ts))) - } - } - - pub fn mk_tup_from_iter<I, T>(self, iter: I) -> T::Output - where - I: Iterator<Item = T>, - T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>, - { - T::collect_and_apply(iter, |ts| self.mk_tup(ts)) - } - - #[inline] - pub fn mk_unit(self) -> Ty<'tcx> { - self.types.unit - } - - #[inline] - pub fn mk_diverging_default(self) -> Ty<'tcx> { - if self.features().never_type_fallback { self.types.never } else { self.types.unit } - } - - #[inline] - pub fn mk_fn_def( - self, - def_id: DefId, - substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, - ) -> Ty<'tcx> { - let substs = self.check_and_mk_substs(def_id, substs); - self.mk_ty_from_kind(FnDef(def_id, substs)) - } - #[inline(always)] pub(crate) fn check_and_mk_substs( self, @@ -1856,131 +1645,20 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(FnPtr(fty)) - } - - #[inline] - pub fn mk_dynamic( - self, - obj: &'tcx List<PolyExistentialPredicate<'tcx>>, - reg: ty::Region<'tcx>, - repr: DynKind, - ) -> Ty<'tcx> { - self.mk_ty_from_kind(Dynamic(obj, reg, repr)) - } - - #[inline] - pub fn mk_projection( - self, - item_def_id: DefId, - substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, - ) -> Ty<'tcx> { - self.mk_alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)) - } - - #[inline] - pub fn mk_closure(self, def_id: DefId, closure_substs: SubstsRef<'tcx>) -> Ty<'tcx> { - debug_assert_eq!( - closure_substs.len(), - self.generics_of(self.typeck_root_def_id(def_id)).count() + 3, - "closure constructed with incorrect substitutions" - ); - self.mk_ty_from_kind(Closure(def_id, closure_substs)) - } - - #[inline] - pub fn mk_generator( - self, - def_id: DefId, - generator_substs: SubstsRef<'tcx>, - movability: hir::Movability, - ) -> Ty<'tcx> { - debug_assert_eq!( - generator_substs.len(), - self.generics_of(self.typeck_root_def_id(def_id)).count() + 5, - "generator constructed with incorrect number of substitutions" - ); - self.mk_ty_from_kind(Generator(def_id, generator_substs, movability)) - } - - #[inline] - pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>) -> Ty<'tcx> { - self.mk_ty_from_kind(GeneratorWitness(types)) - } - - /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. - pub fn mk_task_context(self) -> Ty<'tcx> { - let context_did = self.require_lang_item(LangItem::Context, None); - let context_adt_ref = self.adt_def(context_did); - let context_substs = self.mk_substs(&[self.lifetimes.re_erased.into()]); - let context_ty = self.mk_adt(context_adt_ref, context_substs); - self.mk_mut_ref(self.lifetimes.re_erased, context_ty) - } - - #[inline] - pub fn mk_generator_witness_mir(self, id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(GeneratorWitnessMIR(id, substs)) - } - - #[inline] - pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> { - self.intern_const(ty::ConstData { kind: kind.into(), ty }) - } - - #[inline] - pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> { - // Use a pre-interned one when possible. - self.types - .ty_vars - .get(v.as_usize()) - .copied() - .unwrap_or_else(|| self.mk_ty_from_kind(Infer(TyVar(v)))) - } - - #[inline] - pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> { - self.mk_ty_from_kind(Infer(IntVar(v))) - } - - #[inline] - pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> { - self.mk_ty_from_kind(Infer(FloatVar(v))) - } - - #[inline] - pub fn mk_fresh_ty(self, n: u32) -> Ty<'tcx> { - // Use a pre-interned one when possible. - self.types - .fresh_tys - .get(n as usize) - .copied() - .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshTy(n)))) - } - - #[inline] - pub fn mk_fresh_int_ty(self, n: u32) -> Ty<'tcx> { - // Use a pre-interned one when possible. - self.types - .fresh_int_tys - .get(n as usize) - .copied() - .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshIntTy(n)))) - } - - #[inline] - pub fn mk_fresh_float_ty(self, n: u32) -> Ty<'tcx> { - // Use a pre-interned one when possible. - self.types - .fresh_float_tys - .get(n as usize) - .copied() - .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshFloatTy(n)))) + pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + self.intern_const(ty::ConstData { kind, ty }) } + // Avoid this in favour of more specific `Ty::new_*` methods, where possible. + #[allow(rustc::usage_of_ty_tykind)] #[inline] - pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> { - self.mk_ty_from_kind(Param(ParamTy { index, name })) + pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> { + self.interners.intern_ty( + st, + self.sess, + // This is only used to create a stable hashing context. + &self.untracked, + ) } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { @@ -1988,45 +1666,18 @@ impl<'tcx> TyCtxt<'tcx> { GenericParamDefKind::Lifetime => { ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into() } - GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(), - GenericParamDefKind::Const { .. } => self - .mk_const( - ParamConst { index: param.index, name: param.name }, - self.type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - ) - .into(), + GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(), + GenericParamDefKind::Const { .. } => ty::Const::new_param( + self, + ParamConst { index: param.index, name: param.name }, + self.type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"), + ) + .into(), } } - #[inline] - pub fn mk_bound(self, index: ty::DebruijnIndex, bound_ty: ty::BoundTy) -> Ty<'tcx> { - self.mk_ty_from_kind(Bound(index, bound_ty)) - } - - #[inline] - pub fn mk_placeholder(self, placeholder: ty::PlaceholderType) -> Ty<'tcx> { - self.mk_ty_from_kind(Placeholder(placeholder)) - } - - #[inline] - pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> { - debug_assert_matches!( - (kind, self.def_kind(alias_ty.def_id)), - (ty::Opaque, DefKind::OpaqueTy) - | (ty::Projection | ty::Inherent, DefKind::AssocTy) - | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) - | (ty::Weak, DefKind::TyAlias) - ); - self.mk_ty_from_kind(Alias(kind, alias_ty)) - } - - #[inline] - pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs)) - } - pub fn mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> { self.mk_place_elem(place, PlaceElem::Field(f, ty)) } @@ -2377,21 +2028,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -impl<'tcx> TyCtxtAt<'tcx> { - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. - #[track_caller] - pub fn ty_error_misc(self) -> Ty<'tcx> { - self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported") - } - - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to - /// ensure it gets used. - #[track_caller] - pub fn ty_error_with_message(self, msg: impl Into<DiagnosticMessage>) -> Ty<'tcx> { - self.tcx.ty_error_with_message(self.span, msg) - } -} - /// Parameter attributes that can only be determined by examining the body of a function instead /// of just its signature. /// diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index d89baa9c88d..a0b17c374e4 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -559,7 +559,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { Infer(InferTy::TyVar(_)) if self.infer_suggestable => t, FnDef(def_id, substs) => { - self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) + Ty::new_fn_ptr(self.tcx, self.tcx.fn_sig(def_id).subst(self.tcx, substs)) } // FIXME(compiler-errors): We could replace these with infer, I guess. diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 149ce29b8d9..77cf6bee79d 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -348,10 +348,14 @@ impl<'tcx> TyCtxt<'tcx> { ) }, types: &mut |t: ty::BoundTy| { - self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind }) + Ty::new_bound( + self, + ty::INNERMOST, + ty::BoundTy { var: shift_bv(t.var), kind: t.kind }, + ) }, consts: &mut |c, ty: Ty<'tcx>| { - self.mk_const(ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), ty) + ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c), ty) }, }, ) @@ -393,14 +397,14 @@ impl<'tcx> TyCtxt<'tcx> { let kind = entry .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon)) .expect_ty(); - self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind }) + Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind }) } fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> { let entry = self.map.entry(bv); let index = entry.index(); let var = ty::BoundVar::from_usize(index); let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const(); - self.tcx.mk_const(ty::ConstKind::Bound(ty::INNERMOST, var), ty) + ty::Const::new_bound(self.tcx, ty::INNERMOST, var, ty) } } @@ -462,7 +466,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> { match *ty.kind() { ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_bound(debruijn, bound_ty) + Ty::new_bound(self.tcx, debruijn, bound_ty) } _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self), @@ -475,7 +479,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> { && debruijn >= self.current_index { let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty()) + ty::Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty()) } else { ct.super_fold_with(self) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 58fd6e1aa27..6c7125c4cb7 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, TyCtxt}; +use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { @@ -101,10 +101,12 @@ impl GenericParamDef { ) -> ty::GenericArg<'tcx> { match &self.kind { ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(), - ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(), - ty::GenericParamDefKind::Const { .. } => { - tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into() - } + ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(), + ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error( + tcx, + tcx.type_of(self.def_id).subst(tcx, preceding_substs), + ) + .into(), } } } @@ -133,6 +135,9 @@ pub struct Generics { pub has_self: bool, pub has_late_bound_regions: Option<Span>, + + // The index of the host effect when substituted. (i.e. might be index to parent substs) + pub host_effect_index: Option<usize>, } impl<'tcx> Generics { diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index 018fa227154..295cb146461 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -170,7 +170,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { match self { Self::ConstIsZero(c) => { let c = ty::EarlyBinder::bind(c).subst(tcx, substs); - let pred = match c.kind().try_to_target_usize(tcx) { + let pred = match c.try_to_target_usize(tcx) { Some(0) => Self::True, Some(1..) => Self::False, None => Self::ConstIsZero(c), diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 4223502848e..b92d84152b4 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -197,7 +197,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP // If we can evaluate the array length before having a `ParamEnv`, then // we can simplify the predicate. This is an optimization. - Array(ty, len) => match len.kind().try_to_target_usize(tcx) { + Array(ty, len) => match len.try_to_target_usize(tcx) { Some(0) => InhabitedPredicate::True, Some(1..) => ty.inhabited_predicate(tcx), None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index c0d591430f7..ae57e954ff4 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -410,8 +410,8 @@ impl<'tcx> Instance<'tcx> { ) -> Instance<'tcx> { match ty::Instance::resolve(tcx, param_env, def_id, substs) { Ok(Some(instance)) => instance, - _ => bug!( - "failed to resolve instance for {}", + instance => bug!( + "failed to resolve instance for {}: {instance:#?}", tcx.def_path_str_with_substs(def_id, substs) ), } @@ -552,7 +552,7 @@ impl<'tcx> Instance<'tcx> { tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER); let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller }; - let self_ty = tcx.mk_closure(closure_did, substs); + let self_ty = Ty::new_closure(tcx, closure_did, substs); let sig = substs.as_closure().sig(); let sig = @@ -680,7 +680,7 @@ fn polymorphize<'tcx>( if substs == polymorphized_substs { ty } else { - self.tcx.mk_closure(def_id, polymorphized_substs) + Ty::new_closure(self.tcx, def_id, polymorphized_substs) } } ty::Generator(def_id, substs, movability) => { @@ -689,7 +689,7 @@ fn polymorphize<'tcx>( if substs == polymorphized_substs { ty } else { - self.tcx.mk_generator(def_id, polymorphized_substs, movability) + Ty::new_generator(self.tcx, def_id, polymorphized_substs, movability) } } _ => ty.super_fold_with(self), diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 9485106e95e..d95b05ef754 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; -use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagnosticMessage; use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic}; use rustc_hir as hir; @@ -133,7 +133,7 @@ impl PrimitiveExt for Primitive { F32 => tcx.types.f32, F64 => tcx.types.f64, // FIXME(erikdesjardins): handle non-default addrspace ptr sizes - Pointer(_) => tcx.mk_mut_ptr(tcx.mk_unit()), + Pointer(_) => Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)), } } @@ -480,13 +480,11 @@ fn mul_sorted_consts<'tcx>( b: ty::Const<'tcx>, ) -> Option<ty::Const<'tcx>> { use crate::mir::BinOp::Mul; - use ty::ConstKind::Expr; - use ty::Expr::Binop; let mut work = vec![a, b]; let mut done = vec![]; while let Some(n) = work.pop() { - if let Expr(Binop(Mul, l, r)) = n.kind() { + if let ConstKind::Expr(ty::Expr::Binop(Mul, l, r)) = n.kind() { work.push(l); work.push(r) } else { @@ -517,7 +515,7 @@ fn mul_sorted_consts<'tcx>( done.sort_unstable(); // create a single tree from the buffer - done.into_iter().reduce(|acc, n| tcx.mk_const(Expr(Binop(Mul, n, acc)), n.ty())) + done.into_iter().reduce(|acc, n| ty::Const::new_expr(tcx, ty::Expr::Binop(Mul, n, acc), n.ty())) } pub trait HasTyCtxt<'tcx>: HasDataLayout { @@ -812,11 +810,11 @@ where // (which may have no non-DST form), and will work as long // as the `Abi` or `FieldsShape` is checked by users. if i == 0 { - let nil = tcx.mk_unit(); + let nil = Ty::new_unit(tcx); let unit_ptr_ty = if this.ty.is_unsafe_ptr() { - tcx.mk_mut_ptr(nil) + Ty::new_mut_ptr(tcx, nil) } else { - tcx.mk_mut_ref(tcx.lifetimes.re_static, nil) + Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil) }; // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing @@ -829,7 +827,11 @@ where } let mk_dyn_vtable = || { - tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3)) + Ty::new_imm_ref( + tcx, + tcx.lifetimes.re_static, + Ty::new_array(tcx, tcx.types.usize, 3), + ) /* FIXME: use actual fn pointers Warning: naively computing the number of entries in the vtable by counting the methods on the trait + methods on @@ -838,9 +840,9 @@ where Increase this counter if you tried to implement this but failed to do it without duplicating a lot of code from other places in the compiler: 2 - tcx.mk_tup(&[ - tcx.mk_array(tcx.types.usize, 3), - tcx.mk_array(Option<fn()>), + Ty::new_tup(tcx,&[ + Ty::new_array(tcx,tcx.types.usize, 3), + Ty::new_array(tcx,Option<fn()>), ]) */ }; @@ -852,7 +854,7 @@ where { let metadata = tcx.normalize_erasing_regions( cx.param_env(), - tcx.mk_projection(metadata_def_id, [pointee]), + Ty::new_projection(tcx,metadata_def_id, [pointee]), ); // Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it @@ -927,15 +929,14 @@ where ty::Dynamic(_, _, ty::DynStar) => { if i == 0 { - TyMaybeWithLayout::Ty(tcx.mk_mut_ptr(tcx.types.unit)) + TyMaybeWithLayout::Ty(Ty::new_mut_ptr(tcx, tcx.types.unit)) } else if i == 1 { // FIXME(dyn-star) same FIXME as above applies here too - TyMaybeWithLayout::Ty( - tcx.mk_imm_ref( - tcx.lifetimes.re_static, - tcx.mk_array(tcx.types.usize, 3), - ), - ) + TyMaybeWithLayout::Ty(Ty::new_imm_ref( + tcx, + tcx.lifetimes.re_static, + Ty::new_array(tcx, tcx.types.usize, 3), + )) } else { bug!("no field {i} on dyn*") } @@ -980,10 +981,8 @@ where }) } ty::FnPtr(fn_sig) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| PointeeInfo { - size: layout.size, - align: layout.align.abi, - safe: None, + tcx.layout_of(param_env.and(Ty::new_fn_ptr(tcx, fn_sig))).ok().map(|layout| { + PointeeInfo { size: layout.size, align: layout.align.abi, safe: None } }) } ty::Ref(_, ty, mt) if offset.bytes() == 0 => { @@ -1111,12 +1110,11 @@ where /// /// This takes two primary parameters: /// -/// * `codegen_fn_attr_flags` - these are flags calculated as part of the -/// codegen attrs for a defined function. For function pointers this set of -/// flags is the empty set. This is only applicable for Rust-defined -/// functions, and generally isn't needed except for small optimizations where -/// we try to say a function which otherwise might look like it could unwind -/// doesn't actually unwind (such as for intrinsics and such). +/// * `fn_def_id` - the `DefId` of the function. If this is provided then we can +/// determine more precisely if the function can unwind. If this is not provided +/// then we will only infer whether the function can unwind or not based on the +/// ABI of the function. For example, a function marked with `#[rustc_nounwind]` +/// is known to not unwind even if it's using Rust ABI. /// /// * `abi` - this is the ABI that the function is defined with. This is the /// primary factor for determining whether a function can unwind or not. @@ -1148,11 +1146,6 @@ where /// aborts the process. /// * This affects whether functions have the LLVM `nounwind` attribute, which /// affects various optimizations and codegen. -/// -/// FIXME: this is actually buggy with respect to Rust functions. Rust functions -/// compiled with `-Cpanic=unwind` and referenced from another crate compiled -/// with `-Cpanic=abort` will look like they can't unwind when in fact they -/// might (from a foreign exception or similar). #[inline] #[tracing::instrument(level = "debug", skip(tcx))] pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 48388be2f46..aa8bfd3178c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -66,6 +66,10 @@ use std::{fmt, str}; pub use crate::ty::diagnostics::*; pub use rustc_type_ir::AliasKind::*; +pub use rustc_type_ir::ConstKind::{ + Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt, + Placeholder as PlaceholderCt, Unevaluated, Value, +}; pub use rustc_type_ir::DynKind::*; pub use rustc_type_ir::InferTy::*; pub use rustc_type_ir::RegionKind::*; @@ -81,7 +85,7 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, @@ -93,7 +97,7 @@ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, - BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, + BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstKind, ConstVid, EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, @@ -1302,6 +1306,13 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { + self.without_const() + } +} + impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { @@ -2024,6 +2035,22 @@ impl VariantDef { &self.fields[FieldIdx::from_u32(0)] } + + /// Returns the last field in this variant, if present. + #[inline] + pub fn tail_opt(&self) -> Option<&FieldDef> { + self.fields.raw.last() + } + + /// Returns the last field in this variant. + /// + /// # Panics + /// + /// Panics, if the variant has no fields. + #[inline] + pub fn tail(&self) -> &FieldDef { + self.tail_opt().expect("expected unsized ADT to have a tail field") + } } impl PartialEq for VariantDef { diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index d1ed7be3d2e..b10921eff08 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -150,17 +150,17 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { match *ty.kind() { ty::Closure(def_id, substs) => { let substs = self.fold_closure_substs(def_id, substs); - self.tcx.mk_closure(def_id, substs) + Ty::new_closure(self.tcx, def_id, substs) } ty::Generator(def_id, substs, movability) => { let substs = self.fold_closure_substs(def_id, substs); - self.tcx.mk_generator(def_id, substs, movability) + Ty::new_generator(self.tcx, def_id, substs, movability) } ty::GeneratorWitnessMIR(def_id, substs) => { let substs = self.fold_closure_substs(def_id, substs); - self.tcx.mk_generator_witness_mir(def_id, substs) + Ty::new_generator_witness_mir(self.tcx, def_id, substs) } ty::Param(param) => { @@ -186,7 +186,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { .emit(); } - self.interner().ty_error_misc() + Ty::new_misc_error(self.tcx) } } } @@ -216,7 +216,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { }) .emit_unless(self.ignore_errors); - self.interner().const_error(ct.ty(), guar) + ty::Const::new_error(self.tcx, guar, ct.ty()) } } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f912ff04496..96cf36eb996 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1228,7 +1228,7 @@ pub trait PrettyPrinter<'tcx>: // in order to place the projections inside the `<...>`. if !resugared { // Use a type that can't appear in defaults of type parameters. - let dummy_cx = cx.tcx().mk_fresh_ty(0); + let dummy_cx = Ty::new_fresh(cx.tcx(), 0); let principal = principal.with_self_ty(cx.tcx(), dummy_cx); let args = cx @@ -1393,11 +1393,12 @@ pub trait PrettyPrinter<'tcx>: self, scalar: Scalar, ty: Ty<'tcx>, - print_ty: bool, ) -> Result<Self::Const, Self::Error> { match scalar { - Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty), - Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty), + Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty), + Scalar::Int(int) => { + self.pretty_print_const_scalar_int(int, ty, /* print_ty */ true) + } } } @@ -1405,7 +1406,6 @@ pub trait PrettyPrinter<'tcx>: mut self, ptr: Pointer, ty: Ty<'tcx>, - print_ty: bool, ) -> Result<Self::Const, Self::Error> { define_scoped_cx!(self); @@ -1459,7 +1459,7 @@ pub trait PrettyPrinter<'tcx>: _ => {} } // Any pointer values not covered by a branch above - self = self.pretty_print_const_pointer(ptr, ty, print_ty)?; + self = self.pretty_print_const_pointer(ptr, ty)?; Ok(self) } @@ -1527,24 +1527,18 @@ pub trait PrettyPrinter<'tcx>: /// This is overridden for MIR printing because we only want to hide alloc ids from users, not /// from MIR where it is actually useful. fn pretty_print_const_pointer<Prov: Provenance>( - mut self, + self, _: Pointer<Prov>, ty: Ty<'tcx>, - print_ty: bool, ) -> Result<Self::Const, Self::Error> { - if print_ty { - self.typed_value( - |mut this| { - this.write_str("&_")?; - Ok(this) - }, - |this| this.print_type(ty), - ": ", - ) - } else { - self.write_str("&_")?; - Ok(self) - } + self.typed_value( + |mut this| { + this.write_str("&_")?; + Ok(this) + }, + |this| this.print_type(ty), + ": ", + ) } fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> { @@ -1601,7 +1595,8 @@ pub trait PrettyPrinter<'tcx>: } // Aggregates, printed as array/tuple/struct/variant construction syntax. (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => { - let contents = self.tcx().destructure_const(self.tcx().mk_const(valtree, ty)); + let contents = + self.tcx().destructure_const(ty::Const::new_value(self.tcx(), valtree, ty)); let fields = contents.fields.iter().copied(); match *ty.kind() { ty::Array(..) => { @@ -2155,7 +2150,6 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self, p: Pointer<Prov>, ty: Ty<'tcx>, - print_ty: bool, ) -> Result<Self::Const, Self::Error> { let print = |mut this: Self| { define_scoped_cx!(this); @@ -2166,11 +2160,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { } Ok(this) }; - if print_ty { - self.typed_value(print, |this| this.print_type(ty), ": ") - } else { - print(self) - } + self.typed_value(print, |this| this.print_type(ty), ": ") } } @@ -2746,7 +2736,7 @@ define_print_and_forward_display! { ty::ExistentialTraitRef<'tcx> { // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx().mk_fresh_ty(0); + let dummy_self = Ty::new_fresh(cx.tcx(),0); let trait_ref = self.with_self_ty(cx.tcx(), dummy_self); p!(print(trait_ref.print_only_trait_path())) } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 85d09cfbc72..5741832c980 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -408,7 +408,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( bug!("bound types encountered in structurally_relate_tys") } - (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)), + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)), (&ty::Never, _) | (&ty::Char, _) @@ -428,10 +428,10 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => { let substs = relation.relate_item_substs(a_def.did(), a_substs, b_substs)?; - Ok(tcx.mk_adt(a_def, substs)) + Ok(Ty::new_adt(tcx, a_def, substs)) } - (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)), + (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)), (&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr)) if a_repr == b_repr => @@ -439,7 +439,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { relation.relate(a_region, b_region) })?; - Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr)) + Ok(Ty::new_dynamic(tcx, relation.relate(a_obj, b_obj)?, region_bound, a_repr)) } (&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _)) @@ -449,7 +449,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( // the (anonymous) type of the same generator expression. So // all of their regions should be equated. let substs = relation.relate(a_substs, b_substs)?; - Ok(tcx.mk_generator(a_id, substs, movability)) + Ok(Ty::new_generator(tcx, a_id, substs, movability)) } (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { @@ -459,7 +459,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( let b_types = b_types.map_bound(GeneratorWitness); // Then remove the GeneratorWitness for the result let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0); - Ok(tcx.mk_generator_witness(types)) + Ok(Ty::new_generator_witness(tcx, types)) } (&ty::GeneratorWitnessMIR(a_id, a_substs), &ty::GeneratorWitnessMIR(b_id, b_substs)) @@ -469,7 +469,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( // the (anonymous) type of the same generator expression. So // all of their regions should be equated. let substs = relation.relate(a_substs, b_substs)?; - Ok(tcx.mk_generator_witness_mir(a_id, substs)) + Ok(Ty::new_generator_witness_mir(tcx, a_id, substs)) } (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => { @@ -477,12 +477,12 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( // the (anonymous) type of the same closure expression. So // all of their regions should be equated. let substs = relation.relate(a_substs, b_substs)?; - Ok(tcx.mk_closure(a_id, &substs)) + Ok(Ty::new_closure(tcx, a_id, &substs)) } (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; - Ok(tcx.mk_ptr(mt)) + Ok(Ty::new_ptr(tcx, mt)) } (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { @@ -490,13 +490,13 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; - Ok(tcx.mk_ref(r, mt)) + Ok(Ty::new_ref(tcx, r, mt)) } (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { let t = relation.relate(a_t, b_t)?; match relation.relate(sz_a, sz_b) { - Ok(sz) => Ok(tcx.mk_array_with_const_len(t, sz)), + Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)), Err(err) => { // Check whether the lengths are both concrete/known values, // but are unequal, for better diagnostics. @@ -519,12 +519,15 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Slice(a_t), &ty::Slice(b_t)) => { let t = relation.relate(a_t, b_t)?; - Ok(tcx.mk_slice(t)) + Ok(Ty::new_slice(tcx, t)) } (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { - Ok(tcx.mk_tup_from_iter(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?) + Ok(Ty::new_tup_from_iter( + tcx, + iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)), + )?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) } else { @@ -536,12 +539,12 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( if a_def_id == b_def_id => { let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?; - Ok(tcx.mk_fn_def(a_def_id, substs)) + Ok(Ty::new_fn_def(tcx, a_def_id, substs)) } (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => { let fty = relation.relate(a_fty, b_fty)?; - Ok(tcx.mk_fn_ptr(fty)) + Ok(Ty::new_fn_ptr(tcx, fty)) } // The substs of opaque types may not all be invariant, so we have @@ -559,7 +562,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( b_substs, false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle )?; - Ok(tcx.mk_opaque(a_def_id, substs)) + Ok(Ty::new_opaque(tcx, a_def_id, substs)) } // Alias tend to mostly already be handled downstream due to normalization. @@ -569,7 +572,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( if a_kind == b_kind { let alias_ty = relation.relate(a_data, b_data)?; // assert_eq!(a_kind, b_kind); - Ok(tcx.mk_alias(a_kind, alias_ty)) + Ok(Ty::new_alias(tcx, a_kind, alias_ty)) } else { Err(TypeError::Sorts(expected_found(relation, a, b))) } @@ -627,7 +630,11 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( au.substs, bu.substs, )?; - return Ok(tcx.mk_const(ty::UnevaluatedConst { def: au.def, substs }, a.ty())); + return Ok(ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst { def: au.def, substs }, + a.ty(), + )); } // Before calling relate on exprs, it is necessary to ensure that the nested consts // have identical types. @@ -668,8 +675,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( } _ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))), }; - let kind = ty::ConstKind::Expr(expr); - return Ok(tcx.mk_const(kind, a.ty())); + return Ok(ty::Const::new_expr(tcx, expr, a.ty())); } _ => false, }; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index f195b062a62..7220d133f68 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -11,6 +11,7 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; use rustc_index::{Idx, IndexVec}; use rustc_target::abi::TyAndLayout; +use rustc_type_ir::ConstKind; use std::fmt; use std::ops::ControlFlow; @@ -241,24 +242,6 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> { } } -impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use ty::ConstKind::*; - match self { - Param(param) => write!(f, "{param:?}"), - Infer(var) => write!(f, "{var:?}"), - Bound(debruijn, var) => rustc_type_ir::debug_bound_var(f, *debruijn, *var), - Placeholder(placeholder) => write!(f, "{placeholder:?}"), - Unevaluated(uv) => { - f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish() - } - Value(valtree) => write!(f, "{valtree:?}"), - Error(_) => write!(f, "{{const error}}"), - Expr(expr) => write!(f, "{expr:?}"), - } - } -} - impl fmt::Debug for ty::BoundTy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { @@ -349,7 +332,7 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::IntVarValue, crate::ty::ParamConst, crate::ty::ParamTy, - crate::ty::adjustment::PointerCast, + crate::ty::adjustment::PointerCoercion, crate::ty::RegionVid, crate::ty::UniverseIndex, crate::ty::Variance, @@ -728,9 +711,20 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> { folder: &mut F, ) -> Result<Self, F::Error> { let ty = self.ty().try_fold_with(folder)?; - let kind = self.kind().try_fold_with(folder)?; + let kind = match self.kind() { + ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?), + ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?), + ConstKind::Bound(d, b) => { + ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?) + } + ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?), + ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), + ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), + ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), + ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), + }; if ty != self.ty() || kind != self.kind() { - Ok(folder.interner().mk_const(kind, ty)) + Ok(folder.interner().mk_ct_from_kind(kind, ty)) } else { Ok(self) } @@ -743,7 +737,19 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> { visitor: &mut V, ) -> ControlFlow<V::BreakTy> { self.ty().visit_with(visitor)?; - self.kind().visit_with(visitor) + match self.kind() { + ConstKind::Param(p) => p.visit_with(visitor), + ConstKind::Infer(i) => i.visit_with(visitor), + ConstKind::Bound(d, b) => { + d.visit_with(visitor)?; + b.visit_with(visitor) + } + ConstKind::Placeholder(p) => p.visit_with(visitor), + ConstKind::Unevaluated(uv) => uv.visit_with(visitor), + ConstKind::Value(v) => v.visit_with(visitor), + ConstKind::Error(e) => e.visit_with(visitor), + ConstKind::Expr(e) => e.visit_with(visitor), + } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index bb6d49e1773..94746fbdc19 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -15,6 +15,7 @@ use hir::def::DefKind; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; +use rustc_error_messages::DiagnosticMessage; use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -25,6 +26,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_target::spec::abi::{self, Abi}; +use std::assert_matches::debug_assert_matches; use std::borrow::Cow; use std::cmp::Ordering; use std::fmt; @@ -33,13 +35,17 @@ use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; use rustc_type_ir::sty::TyKind::*; -use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; +use rustc_type_ir::{CollectAndApply, ConstKind as IrConstKind}; +use rustc_type_ir::{DynKind, RegionKind as IrRegionKind}; + +use super::GenericParamDefKind; // Re-export the `TyKind` from `rustc_type_ir` here for convenience #[rustc_diagnostic_item = "TyKind"] pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>; pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>; +pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] @@ -1239,7 +1245,7 @@ impl<'tcx> AliasTy<'tcx> { } pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.mk_alias(self.kind(tcx), self) + Ty::new_alias(tcx, self.kind(tcx), self) } } @@ -1430,7 +1436,7 @@ impl<'tcx> ParamTy { #[inline] pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.mk_ty_param(self.index, self.name) + Ty::new_param(tcx, self.index, self.name) } pub fn span_from_generics(&self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span { @@ -1871,6 +1877,390 @@ impl<'tcx> Region<'tcx> { } } +/// Constructors for `Ty` +impl<'tcx> Ty<'tcx> { + // Avoid this in favour of more specific `new_*` methods, where possible. + #[allow(rustc::usage_of_ty_tykind)] + #[inline] + pub fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> { + tcx.mk_ty_from_kind(st) + } + + #[inline] + pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Ty<'tcx> { + Ty::new(tcx, TyKind::Infer(infer)) + } + + #[inline] + pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::TyVid) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .ty_vars + .get(v.as_usize()) + .copied() + .unwrap_or_else(|| Ty::new(tcx, Infer(TyVar(v)))) + } + + #[inline] + pub fn new_int_var(tcx: TyCtxt<'tcx>, v: ty::IntVid) -> Ty<'tcx> { + Ty::new_infer(tcx, IntVar(v)) + } + + #[inline] + pub fn new_float_var(tcx: TyCtxt<'tcx>, v: ty::FloatVid) -> Ty<'tcx> { + Ty::new_infer(tcx, FloatVar(v)) + } + + #[inline] + pub fn new_fresh(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshTy(n))) + } + + #[inline] + pub fn new_fresh_int(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_int_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshIntTy(n))) + } + + #[inline] + pub fn new_fresh_float(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_float_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n))) + } + + #[inline] + pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> { + tcx.mk_ty_from_kind(Param(ParamTy { index, name })) + } + + #[inline] + pub fn new_bound( + tcx: TyCtxt<'tcx>, + index: ty::DebruijnIndex, + bound_ty: ty::BoundTy, + ) -> Ty<'tcx> { + Ty::new(tcx, Bound(index, bound_ty)) + } + + #[inline] + pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Ty<'tcx> { + Ty::new(tcx, Placeholder(placeholder)) + } + + #[inline] + pub fn new_alias( + tcx: TyCtxt<'tcx>, + kind: ty::AliasKind, + alias_ty: ty::AliasTy<'tcx>, + ) -> Ty<'tcx> { + debug_assert_matches!( + (kind, tcx.def_kind(alias_ty.def_id)), + (ty::Opaque, DefKind::OpaqueTy) + | (ty::Projection | ty::Inherent, DefKind::AssocTy) + | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) + | (ty::Weak, DefKind::TyAlias) + ); + Ty::new(tcx, Alias(kind, alias_ty)) + } + + #[inline] + pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, substs)) + } + + /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` + pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Ty<'tcx> { + Ty::new(tcx, Error(reported)) + } + + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. + #[track_caller] + pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported") + } + + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to + /// ensure it gets used. + #[track_caller] + pub fn new_error_with_message<S: Into<MultiSpan>>( + tcx: TyCtxt<'tcx>, + span: S, + msg: impl Into<DiagnosticMessage>, + ) -> Ty<'tcx> { + let reported = tcx.sess.delay_span_bug(span, msg); + Ty::new(tcx, Error(reported)) + } + + #[inline] + pub fn new_int(tcx: TyCtxt<'tcx>, i: ty::IntTy) -> Ty<'tcx> { + use ty::IntTy::*; + match i { + Isize => tcx.types.isize, + I8 => tcx.types.i8, + I16 => tcx.types.i16, + I32 => tcx.types.i32, + I64 => tcx.types.i64, + I128 => tcx.types.i128, + } + } + + #[inline] + pub fn new_uint(tcx: TyCtxt<'tcx>, ui: ty::UintTy) -> Ty<'tcx> { + use ty::UintTy::*; + match ui { + Usize => tcx.types.usize, + U8 => tcx.types.u8, + U16 => tcx.types.u16, + U32 => tcx.types.u32, + U64 => tcx.types.u64, + U128 => tcx.types.u128, + } + } + + #[inline] + pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> { + use ty::FloatTy::*; + match f { + F32 => tcx.types.f32, + F64 => tcx.types.f64, + } + } + + #[inline] + pub fn new_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Ref(r, tm.ty, tm.mutbl)) + } + + #[inline] + pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) + } + + #[inline] + pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Not }) + } + + #[inline] + pub fn new_ptr(tcx: TyCtxt<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, RawPtr(tm)) + } + + #[inline] + pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) + } + + #[inline] + pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Not }) + } + + #[inline] + pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Adt(def, substs)) + } + + #[inline] + pub fn new_foreign(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { + Ty::new(tcx, Foreign(def_id)) + } + + #[inline] + pub fn new_array(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { + Ty::new(tcx, Array(ty, ty::Const::from_target_usize(tcx, n))) + } + + #[inline] + pub fn new_array_with_const_len( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + ct: ty::Const<'tcx>, + ) -> Ty<'tcx> { + Ty::new(tcx, Array(ty, ct)) + } + + #[inline] + pub fn new_slice(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Slice(ty)) + } + + #[inline] + pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> { + if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(&ts))) } + } + + pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>, + { + T::collect_and_apply(iter, |ts| Ty::new_tup(tcx, ts)) + } + + #[inline] + pub fn new_fn_def( + tcx: TyCtxt<'tcx>, + def_id: DefId, + substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + ) -> Ty<'tcx> { + let substs = tcx.check_and_mk_substs(def_id, substs); + Ty::new(tcx, FnDef(def_id, substs)) + } + + #[inline] + pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, FnPtr(fty)) + } + + #[inline] + pub fn new_dynamic( + tcx: TyCtxt<'tcx>, + obj: &'tcx List<PolyExistentialPredicate<'tcx>>, + reg: ty::Region<'tcx>, + repr: DynKind, + ) -> Ty<'tcx> { + Ty::new(tcx, Dynamic(obj, reg, repr)) + } + + #[inline] + pub fn new_projection( + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + ) -> Ty<'tcx> { + Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, substs)) + } + + #[inline] + pub fn new_closure( + tcx: TyCtxt<'tcx>, + def_id: DefId, + closure_substs: SubstsRef<'tcx>, + ) -> Ty<'tcx> { + debug_assert_eq!( + closure_substs.len(), + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3, + "closure constructed with incorrect substitutions" + ); + Ty::new(tcx, Closure(def_id, closure_substs)) + } + + #[inline] + pub fn new_generator( + tcx: TyCtxt<'tcx>, + def_id: DefId, + generator_substs: SubstsRef<'tcx>, + movability: hir::Movability, + ) -> Ty<'tcx> { + debug_assert_eq!( + generator_substs.len(), + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, + "generator constructed with incorrect number of substitutions" + ); + Ty::new(tcx, Generator(def_id, generator_substs, movability)) + } + + #[inline] + pub fn new_generator_witness( + tcx: TyCtxt<'tcx>, + types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>, + ) -> Ty<'tcx> { + Ty::new(tcx, GeneratorWitness(types)) + } + + #[inline] + pub fn new_generator_witness_mir( + tcx: TyCtxt<'tcx>, + id: DefId, + substs: SubstsRef<'tcx>, + ) -> Ty<'tcx> { + Ty::new(tcx, GeneratorWitnessMIR(id, substs)) + } + + // misc + + #[inline] + pub fn new_unit(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + tcx.types.unit + } + + #[inline] + pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_) + } + + #[inline] + pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + if tcx.features().never_type_fallback { tcx.types.never } else { tcx.types.unit } + } + + // lang and diagnostic tys + + fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> { + let adt_def = tcx.adt_def(wrapper_def_id); + let substs = + InternalSubsts::for_item(tcx, wrapper_def_id, |param, substs| match param.kind { + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), + GenericParamDefKind::Type { has_default, .. } => { + if param.index == 0 { + ty_param.into() + } else { + assert!(has_default); + tcx.type_of(param.def_id).subst(tcx, substs).into() + } + } + }); + Ty::new(tcx, Adt(adt_def, substs)) + } + + #[inline] + pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> { + let def_id = tcx.lang_items().get(item)?; + Some(Ty::new_generic_adt(tcx, def_id, ty)) + } + + #[inline] + pub fn new_diagnostic_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> { + let def_id = tcx.get_diagnostic_item(name)?; + Some(Ty::new_generic_adt(tcx, def_id, ty)) + } + + #[inline] + pub fn new_box(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = tcx.require_lang_item(LangItem::OwnedBox, None); + Ty::new_generic_adt(tcx, def_id, ty) + } + + #[inline] + pub fn new_maybe_uninit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None); + Ty::new_generic_adt(tcx, def_id, ty) + } + + /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. + pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + let context_did = tcx.require_lang_item(LangItem::Context, None); + let context_adt_ref = tcx.adt_def(context_did); + let context_substs = tcx.mk_substs(&[tcx.lifetimes.re_erased.into()]); + let context_ty = Ty::new_adt(tcx, context_adt_ref, context_substs); + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty) + } +} + /// Type utilities impl<'tcx> Ty<'tcx> { #[inline(always)] @@ -2314,7 +2704,7 @@ impl<'tcx> Ty<'tcx> { let assoc_items = tcx.associated_item_def_ids( tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), ); - tcx.mk_projection(assoc_items[0], tcx.mk_substs(&[self.into()])) + Ty::new_projection(tcx, assoc_items[0], tcx.mk_substs(&[self.into()])) } ty::Bool diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 111b1d009b3..4d5f5b8658c 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -11,6 +11,7 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; +use rustc_span::sym; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; @@ -451,6 +452,10 @@ impl<'tcx> InternalSubsts<'tcx> { pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> { tcx.mk_substs_from_iter(self.iter().take(generics.count())) } + + pub fn host_effect_param(&'tcx self) -> Option<ty::Const<'tcx>> { + self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host)) + } } impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index bb08deff294..e2e4a2dbdc8 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -223,14 +223,14 @@ impl<'tcx> TyCtxt<'tcx> { }; let reported = self.sess.emit_err(crate::error::RecursionLimitReached { ty, suggested_limit }); - return self.ty_error(reported); + return Ty::new_error(self, reported); } match *ty.kind() { ty::Adt(def, substs) => { if !def.is_struct() { break; } - match def.non_enum_variant().fields.raw.last() { + match def.non_enum_variant().tail_opt() { Some(field) => { f(); ty = field.ty(self, substs); @@ -304,7 +304,7 @@ impl<'tcx> TyCtxt<'tcx> { (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def && a_def.is_struct() => { - if let Some(f) = a_def.non_enum_variant().fields.raw.last() { + if let Some(f) = a_def.non_enum_variant().tail_opt() { a = f.ty(self, a_substs); b = f.ty(self, b_substs); } else { @@ -610,12 +610,12 @@ impl<'tcx> TyCtxt<'tcx> { closure_substs: SubstsRef<'tcx>, env_region: ty::Region<'tcx>, ) -> Option<Ty<'tcx>> { - let closure_ty = self.mk_closure(closure_def_id, closure_substs); + let closure_ty = Ty::new_closure(self, closure_def_id, closure_substs); let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; let env_ty = match closure_kind { - ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty), - ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty), + ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty), + ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty), ty::ClosureKind::FnOnce => closure_ty, }; Some(env_ty) @@ -656,12 +656,12 @@ impl<'tcx> TyCtxt<'tcx> { pub fn thread_local_ptr_ty(self, def_id: DefId) -> Ty<'tcx> { let static_ty = self.type_of(def_id).subst_identity(); if self.is_mutable_static(def_id) { - self.mk_mut_ptr(static_ty) + Ty::new_mut_ptr(self, static_ty) } else if self.is_foreign_item(def_id) { - self.mk_imm_ptr(static_ty) + Ty::new_imm_ptr(self, static_ty) } else { // FIXME: These things don't *really* have 'static lifetime. - self.mk_imm_ref(self.lifetimes.re_static, static_ty) + Ty::new_imm_ref(self, self.lifetimes.re_static, static_ty) } } @@ -676,11 +676,11 @@ impl<'tcx> TyCtxt<'tcx> { // Make sure that accesses to unsafe statics end up using raw pointers. // For thread-locals, this needs to be kept in sync with `Rvalue::ty`. if self.is_mutable_static(def_id) { - self.mk_mut_ptr(static_ty) + Ty::new_mut_ptr(self, static_ty) } else if self.is_foreign_item(def_id) { - self.mk_imm_ptr(static_ty) + Ty::new_imm_ptr(self, static_ty) } else { - self.mk_imm_ref(self.lifetimes.re_erased, static_ty) + Ty::new_imm_ref(self, self.lifetimes.re_erased, static_ty) } } @@ -854,7 +854,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { let hidden_ty = bty.subst(self.tcx, substs); self.fold_ty(hidden_ty); } - let expanded_ty = self.tcx.mk_generator_witness_mir(def_id, substs); + let expanded_ty = Ty::new_generator_witness_mir(self.tcx, def_id, substs); self.expanded_cache.insert((def_id, substs), expanded_ty); expanded_ty } @@ -1306,7 +1306,7 @@ pub fn needs_drop_components<'tcx>( ty::Array(elem_ty, size) => { match needs_drop_components(*elem_ty, target_layout) { Ok(v) if v.is_empty() => Ok(v), - res => match size.kind().try_to_bits(target_layout.pointer_size) { + res => match size.try_to_bits(target_layout.pointer_size) { // Arrays of size zero don't need drop, even if their element // type does. Some(0) => Ok(SmallVec::new()), diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 8758cd04d67..b0961d91787 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -16,7 +16,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Ty<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self { // SAFETY: This is never called when `Self` is not `Ty<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. - unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error_misc()) } + unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(Ty::new_misc_error(tcx)) } } } @@ -34,7 +34,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::SymbolName<'_> { impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::Binder<'_, ty::FnSig<'_>> { fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo<DepKind>]) -> Self { - let err = tcx.ty_error_misc(); + let err = Ty::new_misc_error(tcx); let arity = if let Some(frame) = stack.get(0) && frame.query.dep_kind == DepKind::fn_sig diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 73d5eb62750..3fe751ae0a5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -52,7 +52,7 @@ pub fn as_constant_inner<'tcx>( match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { Ok(c) => c, Err(LitToConstError::Reported(guar)) => { - ConstantKind::Ty(tcx.const_error(ty, guar)) + ConstantKind::Ty(ty::Const::new_error(tcx, guar, ty)) } Err(LitToConstError::TypeError) => { bug!("encountered type error in `lit_to_mir_constant`") @@ -84,7 +84,7 @@ pub fn as_constant_inner<'tcx>( Constant { user_ty, span, literal } } ExprKind::ConstParam { param, def_id: _ } => { - let const_param = tcx.mk_const(ty::ConstKind::Param(param), expr.ty); + let const_param = ty::Const::new_param(tcx, param, expr.ty); let literal = ConstantKind::Ty(const_param); Constant { user_ty: None, span, literal } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 783f6e2085c..60acd279f9e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -535,7 +535,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Cast { .. } | ExprKind::Use { .. } | ExprKind::NeverToAny { .. } - | ExprKind::Pointer { .. } + | ExprKind::PointerCoercion { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } | ExprKind::AddressOf { .. } @@ -683,7 +683,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ProjectionElem::Deref => { let fake_borrow_deref_ty = base_place.ty(&self.local_decls, tcx).ty; let fake_borrow_ty = - tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty); + Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fake_borrow_deref_ty); let fake_borrow_temp = self.local_decls.push(LocalDecl::new(fake_borrow_ty, expr_span)); let projection = tcx.mk_place_elems(&base_place.projection); diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 27b1b58d2e9..32ffb990be6 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -162,7 +162,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { [], expr_span, ); - let storage = this.temp(tcx.mk_mut_ptr(tcx.types.u8), expr_span); + let storage = this.temp(Ty::new_mut_ptr(tcx, tcx.types.u8), expr_span); let success = this.cfg.start_new_block(); this.cfg.terminate( block, @@ -300,7 +300,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let cast_kind = mir_cast_kind(ty, expr.ty); block.and(Rvalue::Cast(cast_kind, source, expr.ty)) } - ExprKind::Pointer { cast, source } => { + ExprKind::PointerCoercion { cast, source } => { let source = unpack!( block = this.as_operand( block, @@ -310,7 +310,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { NeedsTemporary::No ) ); - block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty)) + block.and(Rvalue::Cast(CastKind::PointerCoercion(cast), source, expr.ty)) } ExprKind::Array { ref fields } => { // (*) We would (maybe) be closer to codegen if we @@ -564,7 +564,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let bool_ty = self.tcx.types.bool; let rvalue = match op { BinOp::Add | BinOp::Sub | BinOp::Mul if self.check_overflow && ty.is_integral() => { - let result_tup = self.tcx.mk_tup(&[ty, bool_ty]); + let result_tup = Ty::new_tup(self.tcx, &[ty, bool_ty]); let result_value = self.temp(result_tup, span); self.cfg.push_assign( @@ -598,7 +598,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let (unsigned_rhs, unsigned_ty) = match rhs_ty.kind() { ty::Uint(_) => (rhs.to_copy(), rhs_ty), ty::Int(int_width) => { - let uint_ty = self.tcx.mk_mach_uint(int_width.to_unsigned()); + let uint_ty = Ty::new_uint(self.tcx, int_width.to_unsigned()); let rhs_temp = self.temp(uint_ty, span); self.cfg.push_assign( block, diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index 2fe9cac6378..e07ba6b6e93 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -63,7 +63,7 @@ impl Category { | ExprKind::Binary { .. } | ExprKind::Box { .. } | ExprKind::Cast { .. } - | ExprKind::Pointer { .. } + | ExprKind::PointerCoercion { .. } | ExprKind::Repeat { .. } | ExprKind::Assign { .. } | ExprKind::AssignOp { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 91c464252f1..e30fdcbbe18 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -556,7 +556,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Binary { .. } | ExprKind::Box { .. } | ExprKind::Cast { .. } - | ExprKind::Pointer { .. } + | ExprKind::PointerCoercion { .. } | ExprKind::Repeat { .. } | ExprKind::Array { .. } | ExprKind::Tuple { .. } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 6df06df5c60..10770213c9a 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1751,7 +1751,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { projection: tcx.mk_place_elems(matched_place_ref.projection), }; let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty; - let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty); + let fake_borrow_ty = + Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fake_borrow_deref_ty); let mut fake_borrow_temp = LocalDecl::new(fake_borrow_ty, temp_span); fake_borrow_temp.internal = self.local_decls[matched_place.local].internal; fake_borrow_temp.local_info = ClearCrossCrate::Set(Box::new(LocalInfo::FakeBorrow)); @@ -2250,7 +2251,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This variable isn't mutated but has a name, so has to be // immutable to avoid the unused mut lint. mutability: Mutability::Not, - ty: tcx.mk_imm_ref(tcx.lifetimes.re_erased, var_ty), + ty: Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, var_ty), user_ty: None, source_info, internal: false, diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index f431023f2b6..e6806177dec 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::GenericArg; -use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; +use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -244,8 +244,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bug!("matching on `String` went through without enabling string_deref_patterns"); } let re_erased = tcx.lifetimes.re_erased; - let ref_string = self.temp(tcx.mk_imm_ref(re_erased, ty), test.span); - let ref_str_ty = tcx.mk_imm_ref(re_erased, tcx.types.str_); + let ref_string = self.temp(Ty::new_imm_ref(tcx,re_erased, ty), test.span); + let ref_str_ty = Ty::new_imm_ref(tcx,re_erased, tcx.types.str_); let ref_str = self.temp(ref_str_ty, test.span); let deref = tcx.require_lang_item(LangItem::Deref, None); let method = trait_method(tcx, deref, sym::deref, [ty]); @@ -415,7 +415,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (Some((region, elem_ty, _)), _) | (None, Some((region, elem_ty, _))) => { let tcx = self.tcx; // make both a slice - ty = tcx.mk_imm_ref(*region, tcx.mk_slice(*elem_ty)); + ty = Ty::new_imm_ref(tcx, *region, Ty::new_slice(tcx, *elem_ty)); if opt_ref_ty.is_some() { let temp = self.temp(ty, source_info.span); self.cfg.push_assign( @@ -423,7 +423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, temp, Rvalue::Cast( - CastKind::Pointer(PointerCast::Unsize), + CastKind::PointerCoercion(PointerCoercion::Unsize), Operand::Copy(val), ty, ), @@ -436,7 +436,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, slice, - Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), expect, ty), + Rvalue::Cast( + CastKind::PointerCoercion(PointerCoercion::Unsize), + expect, + ty, + ), ); expect = Operand::Move(slice); } @@ -449,7 +453,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // non_scalar_compare called on non-reference type let temp = self.temp(ty, source_info.span); self.cfg.push_assign(block, source_info, temp, Rvalue::Use(expect)); - let ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, ty); + let ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, ty); let ref_temp = self.temp(ref_ty, source_info.span); self.cfg.push_assign( @@ -871,7 +875,7 @@ fn trait_method<'tcx>( .find(|item| item.kind == ty::AssocKind::Fn) .expect("trait method not found"); - let method_ty = tcx.mk_fn_def(item.def_id, substs); + let method_ty = Ty::new_fn_def(tcx, item.def_id, substs); ConstantKind::zero_sized(method_ty) } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 49cbe3e2c9b..d828e71c7ac 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -614,7 +614,7 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo let generator_kind = tcx.generator_kind(def); let body_owner_kind = tcx.hir().body_owner_kind(def); - let ty = tcx.ty_error(err); + let ty = Ty::new_error(tcx, err); let num_params = match body_owner_kind { hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(), hir::BodyOwnerKind::Closure => { @@ -942,7 +942,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match self.unit_temp { Some(tmp) => tmp, None => { - let ty = self.tcx.mk_unit(); + let ty = Ty::new_unit(self.tcx); let fn_span = self.fn_span; let tmp = self.temp(ty, fn_span); self.unit_temp = Some(tmp); diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 7c0fbc6f81c..72374102c8c 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -91,6 +91,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::{Expr, LintLevel}; +use rustc_middle::ty::Ty; use rustc_span::{Span, DUMMY_SP}; #[derive(Debug)] @@ -724,7 +725,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue` // statement. fn add_dummy_assignment(&mut self, span: Span, block: BasicBlock, source_info: SourceInfo) { - let local_decl = LocalDecl::new(self.tcx.mk_unit(), span).internal(); + let local_decl = LocalDecl::new(Ty::new_unit(self.tcx), span).internal(); let temp_place = Place::from(self.local_decls.push(local_decl)); self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx); } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 105564b7874..6b2b140fa25 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -303,7 +303,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | ExprKind::NeverToAny { .. } | ExprKind::PlaceTypeAscription { .. } | ExprKind::ValueTypeAscription { .. } - | ExprKind::Pointer { .. } + | ExprKind::PointerCoercion { .. } | ExprKind::Repeat { .. } | ExprKind::StaticRef { .. } | ExprKind::ThreadLocalRef { .. } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index a7be8e3c903..fbb74650faa 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -79,5 +79,5 @@ pub(crate) fn lit_to_const<'tcx>( _ => return Err(LitToConstError::TypeError), }; - Ok(tcx.mk_const(valtree, ty)) + Ok(ty::Const::new_value(tcx, valtree, ty)) } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 791c10c1748..37537683f0d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -13,7 +13,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::{self, BinOp, BorrowKind, UnOp}; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ - Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast, + Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{ @@ -125,11 +125,16 @@ impl<'tcx> Cx<'tcx> { }; let kind = match adjustment.kind { - Adjust::Pointer(PointerCast::Unsize) => { + Adjust::Pointer(PointerCoercion::Unsize) => { adjust_span(&mut expr); - ExprKind::Pointer { cast: PointerCast::Unsize, source: self.thir.exprs.push(expr) } + ExprKind::PointerCoercion { + cast: PointerCoercion::Unsize, + source: self.thir.exprs.push(expr), + } + } + Adjust::Pointer(cast) => { + ExprKind::PointerCoercion { cast, source: self.thir.exprs.push(expr) } } - Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.thir.exprs.push(expr) }, Adjust::NeverToAny if adjustment.target.is_never() => return expr, Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) }, Adjust::Deref(None) => { @@ -143,9 +148,11 @@ impl<'tcx> Cx<'tcx> { expr = Expr { temp_lifetime, - ty: self - .tcx - .mk_ref(deref.region, ty::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }), + ty: Ty::new_ref( + self.tcx, + deref.region, + ty::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }, + ), span, kind: ExprKind::Borrow { borrow_kind: deref.mutbl.to_borrow_kind(), @@ -190,9 +197,9 @@ impl<'tcx> Cx<'tcx> { // Special cased so that we can type check that the element // type of the source matches the pointed to type of the // destination. - ExprKind::Pointer { + ExprKind::PointerCoercion { source: self.mirror_expr(source), - cast: PointerCast::ArrayToPointer, + cast: PointerCoercion::ArrayToPointer, } } else { // check whether this is casting an enum variant discriminant @@ -208,17 +215,18 @@ impl<'tcx> Cx<'tcx> { // so we wouldn't have to compute and store the actual value let hir::ExprKind::Path(ref qpath) = source.kind else { - return ExprKind::Cast { source: self.mirror_expr(source)}; + return ExprKind::Cast { source: self.mirror_expr(source) }; }; let res = self.typeck_results().qpath_res(qpath, source.hir_id); let ty = self.typeck_results().node_type(source.hir_id); let ty::Adt(adt_def, substs) = ty.kind() else { - return ExprKind::Cast { source: self.mirror_expr(source)}; + return ExprKind::Cast { source: self.mirror_expr(source) }; }; - let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res else { - return ExprKind::Cast { source: self.mirror_expr(source)}; + let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res + else { + return ExprKind::Cast { source: self.mirror_expr(source) }; }; let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); @@ -308,7 +316,7 @@ impl<'tcx> Cx<'tcx> { let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e)); let tupled_args = Expr { - ty: tcx.mk_tup_from_iter(arg_tys), + ty: Ty::new_tup_from_iter(tcx, arg_tys), temp_lifetime, span: expr.span, kind: ExprKind::Tuple { fields: self.mirror_exprs(args) }, @@ -351,19 +359,35 @@ impl<'tcx> Cx<'tcx> { }); } } - let adt_data = - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind { - // Tuple-like ADTs are represented as ExprKind::Call. We convert them here. - expr_ty.ty_adt_def().and_then(|adt_def| match path.res { - Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => { + + // Tuple-like ADTs are represented as ExprKind::Call. We convert them here. + let adt_data = if let hir::ExprKind::Path(ref qpath) = fun.kind + && let Some(adt_def) = expr_ty.ty_adt_def() { + match qpath { + hir::QPath::Resolved(_, ref path) => { + match path.res { + Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => { + Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))) + } + Res::SelfCtor(..) => Some((adt_def, FIRST_VARIANT)), + _ => None, + } + } + hir::QPath::TypeRelative(_ty, _) => { + if let Some((DefKind::Ctor(_, CtorKind::Fn), ctor_id)) = + self.typeck_results().type_dependent_def(fun.hir_id) + { Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))) + } else { + None } - Res::SelfCtor(..) => Some((adt_def, FIRST_VARIANT)), - _ => None, - }) - } else { - None - }; + + } + _ => None, + } + } else { + None + }; if let Some((adt_def, index)) = adt_data { let substs = self.typeck_results().node_substs(fun.hir_id); let user_provided_types = self.typeck_results().user_provided_types(); @@ -855,7 +879,11 @@ impl<'tcx> Cx<'tcx> { let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id)); debug!("method_callee: user_ty={:?}", user_ty); ( - self.tcx().mk_fn_def(def_id, self.typeck_results().node_substs(expr.hir_id)), + Ty::new_fn_def( + self.tcx(), + def_id, + self.typeck_results().node_substs(expr.hir_id), + ), user_ty, ) } @@ -1008,7 +1036,7 @@ impl<'tcx> Cx<'tcx> { let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else { span_bug!(span, "overloaded_place: receiver is not a reference"); }; - let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl }); + let ref_ty = Ty::new_ref(self.tcx, region, ty::TypeAndMut { ty: place_ty, mutbl }); // construct the complete expression `foo()` for the overloaded call, // which will yield the &T type diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index d00fb754c64..e6a98d1aab0 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -15,7 +15,7 @@ use rustc_hir::HirId; use rustc_hir::Node; use rustc_middle::middle::region; use rustc_middle::thir::*; -use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; +use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt}; use rustc_span::Span; pub(crate) fn thir_body( @@ -40,7 +40,7 @@ pub(crate) fn thir_body( // It will always be `()` in this case. if tcx.def_kind(owner_def) == DefKind::Generator && body.params.is_empty() { cx.thir.params.push(Param { - ty: tcx.mk_unit(), + ty: Ty::new_unit(tcx), pat: None, ty_span: None, self_kind: None, diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index a2e00d3bfc5..050b01294b4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -380,7 +380,9 @@ impl<'tcx> ConstToPat<'tcx> { ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() { // `&str` is represented as a valtree, let's keep using this // optimization for now. - ty::Str => PatKind::Constant { value: mir::ConstantKind::Ty(tcx.mk_const(cv, ty)) }, + ty::Str => PatKind::Constant { + value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)), + }, // Backwards compatibility hack: support references to non-structural types, // but hard error if we aren't behind a double reference. We could just use // the fallback code path below, but that would allow *more* of this fishy @@ -427,7 +429,7 @@ impl<'tcx> ConstToPat<'tcx> { // arrays. let pointee_ty = match *pointee_ty.kind() { ty::Array(elem_ty, _) if self.treat_byte_string_as_slice => { - tcx.mk_slice(elem_ty) + Ty::new_slice(tcx, elem_ty) } _ => *pointee_ty, }; @@ -438,9 +440,9 @@ impl<'tcx> ConstToPat<'tcx> { } } }, - ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => { - PatKind::Constant { value: mir::ConstantKind::Ty(tcx.mk_const(cv, ty)) } - } + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => PatKind::Constant { + value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)), + }, ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(), _ => { self.saw_const_match_error.set(true); diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index c30c4b65939..60099592784 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -525,7 +525,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .tcx .const_eval_global_id_for_typeck(param_env_reveal_all, cid, Some(span)) .map(|val| match val { - Some(valtree) => mir::ConstantKind::Ty(self.tcx.mk_const(valtree, ty)), + Some(valtree) => mir::ConstantKind::Ty(ty::Const::new_value(self.tcx, valtree, ty)), None => mir::ConstantKind::Val( self.tcx .const_eval_global_id(param_env_reveal_all, cid, Some(span)) @@ -631,7 +631,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) { - self.const_to_pat(ConstantKind::Ty(self.tcx.mk_const(valtree, ty)), id, span, None).kind + self.const_to_pat( + ConstantKind::Ty(ty::Const::new_value(self.tcx, valtree, ty)), + id, + span, + None, + ) + .kind } else { // If that fails, convert it to an opaque constant pattern. match tcx.const_eval_resolve(self.param_env, uneval, None) { diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 0b6029bf388..8d7c624a805 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -301,7 +301,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { self.print_expr(*source, depth_lvl + 2); print_indented!(self, "}", depth_lvl); } - Pointer { cast, source } => { + PointerCoercion { cast, source } => { print_indented!(self, "Pointer {", depth_lvl); print_indented!(self, format!("cast: {:?}", cast), depth_lvl + 1); print_indented!(self, "source:", depth_lvl + 1); diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index c0102b15a16..0540a5e943b 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -423,7 +423,7 @@ where let unique_ty = adt.non_enum_variant().fields[FieldIdx::new(0)].ty(self.tcx(), substs); let unique_variant = unique_ty.ty_adt_def().unwrap().non_enum_variant(); let nonnull_ty = unique_variant.fields[FieldIdx::from_u32(0)].ty(self.tcx(), substs); - let ptr_ty = self.tcx().mk_imm_ptr(substs[0].expect_ty()); + let ptr_ty = Ty::new_imm_ptr(self.tcx(), substs[0].expect_ty()); let unique_place = self.tcx().mk_place_field(self.place, FieldIdx::new(0), unique_ty); let nonnull_place = self.tcx().mk_place_field(unique_place, FieldIdx::new(0), nonnull_ty); @@ -628,10 +628,13 @@ where let drop_fn = tcx.associated_item_def_ids(drop_trait)[0]; let ty = self.place_ty(self.place); - let ref_ty = - tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut }); + let ref_ty = Ty::new_ref( + tcx, + tcx.lifetimes.re_erased, + ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut }, + ); let ref_place = self.new_temp(ref_ty); - let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); + let unit_temp = Place::from(self.new_temp(Ty::new_unit(tcx))); let result = BasicBlockData { statements: vec![self.assign( @@ -693,7 +696,7 @@ where let move_ = |place: Place<'tcx>| Operand::Move(place); let tcx = self.tcx(); - let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mut }); + let ptr_ty = Ty::new_ptr(tcx, ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mut }); let ptr = Place::from(self.new_temp(ptr_ty)); let can_go = Place::from(self.new_temp(tcx.types.bool)); let one = self.constant_usize(1); diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 05c54ab3097..4892ace53e3 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -155,7 +155,7 @@ fn insert_alignment_check<'tcx>( new_block: BasicBlock, ) { // Cast the pointer to a *const () - let const_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not }); + let const_raw_ptr = Ty::new_ptr(tcx, TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not }); let rvalue = Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer), const_raw_ptr); let thin_ptr = local_decls.push(LocalDecl::with_source_info(const_raw_ptr, source_info)).into(); block_data diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index f31653caa49..cc0d7d51b60 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -21,7 +21,7 @@ pub fn build_ptr_tys<'tcx>( let substs = tcx.mk_substs(&[pointee.into()]); let unique_ty = tcx.type_of(unique_did).subst(tcx, substs); let nonnull_ty = tcx.type_of(nonnull_did).subst(tcx, substs); - let ptr_ty = tcx.mk_imm_ptr(pointee); + let ptr_ty = Ty::new_imm_ptr(tcx, pointee); (unique_ty, nonnull_ty, ptr_ty) } diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 029fb2e9ba0..264bc61f1b3 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -413,8 +413,11 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let gen_ty = body.local_decls.raw[1].ty; - let ref_gen_ty = - tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty: gen_ty, mutbl: Mutability::Mut }); + let ref_gen_ty = Ty::new_ref( + tcx, + tcx.lifetimes.re_erased, + ty::TypeAndMut { ty: gen_ty, mutbl: Mutability::Mut }, + ); // Replace the by value generator argument body.local_decls.raw[1].ty = ref_gen_ty; @@ -429,7 +432,7 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body let pin_did = tcx.require_lang_item(LangItem::Pin, Some(body.span)); let pin_adt_ref = tcx.adt_def(pin_did); let substs = tcx.mk_substs(&[ref_gen_ty.into()]); - let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs); + let pin_ref_gen_ty = Ty::new_adt(tcx, pin_adt_ref, substs); // Replace the by ref generator argument body.local_decls.raw[1].ty = pin_ref_gen_ty; @@ -481,7 +484,7 @@ fn replace_local<'tcx>( /// still using the `ResumeTy` indirection for the time being, and that indirection /// is removed here. After this transform, the generator body only knows about `&mut Context<'_>`. fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let context_mut_ref = tcx.mk_task_context(); + let context_mut_ref = Ty::new_task_context(tcx); // replace the type of the `resume` argument replace_resume_ty_local(tcx, body, Local::new(2), context_mut_ref); @@ -1130,13 +1133,13 @@ fn create_generator_drop_shim<'tcx>( } // Replace the return variable - body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(tcx.mk_unit(), source_info); + body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(Ty::new_unit(tcx), source_info); make_generator_state_argument_indirect(tcx, &mut body); // Change the generator argument from &mut to *mut body.local_decls[SELF_ARG] = LocalDecl::with_source_info( - tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), + Ty::new_ptr(tcx, ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), source_info, ); @@ -1493,7 +1496,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let state_substs = tcx.mk_substs(&[yield_ty.into(), body.return_ty().into()]); (state_adt_ref, state_substs) }; - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_substs); // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local // RETURN_PLACE then is a fresh unused local with type ret_ty. @@ -1509,8 +1512,11 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // case there is no `Assign` to it that the transform can turn into a store to the generator // state. After the yield the slot in the generator state would then be uninitialized. let resume_local = Local::new(2); - let resume_ty = - if is_async_kind { tcx.mk_task_context() } else { body.local_decls[resume_local].ty }; + let resume_ty = if is_async_kind { + Ty::new_task_context(tcx) + } else { + body.local_decls[resume_local].ty + }; let new_resume_local = replace_local(resume_local, resume_ty, body, tcx); // When first entering the generator, move the resume argument into its new local. diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 430a6f6cef5..8ed4706e172 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -141,7 +141,7 @@ impl EnumSizeOpt { self.candidate(tcx, param_env, ty, &mut alloc_cache)?; let alloc = tcx.global_alloc(alloc_id).unwrap_memory(); - let tmp_ty = tcx.mk_array(tcx.types.usize, num_variants as u64); + let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64); let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); let store_live = Statement { @@ -208,8 +208,9 @@ impl EnumSizeOpt { ))), }; - let dst = - Place::from(local_decls.push(LocalDecl::new(tcx.mk_mut_ptr(ty), span))); + let dst = Place::from( + local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span)), + ); let dst_ptr = Statement { source_info, @@ -219,7 +220,7 @@ impl EnumSizeOpt { ))), }; - let dst_cast_ty = tcx.mk_mut_ptr(tcx.types.u8); + let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8); let dst_cast_place = Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); @@ -231,8 +232,9 @@ impl EnumSizeOpt { ))), }; - let src = - Place::from(local_decls.push(LocalDecl::new(tcx.mk_imm_ptr(ty), span))); + let src = Place::from( + local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span)), + ); let src_ptr = Statement { source_info, @@ -242,7 +244,7 @@ impl EnumSizeOpt { ))), }; - let src_cast_ty = tcx.mk_imm_ptr(tcx.types.u8); + let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8); let src_cast_place = Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 3d61d33ce35..6c3b7c58fab 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -41,7 +41,7 @@ fn compute_slice_length<'tcx>( for (local, rvalue, _) in ssa.assignments(body) { match rvalue { Rvalue::Cast( - CastKind::Pointer(ty::adjustment::PointerCast::Unsize), + CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize), operand, cast_ty, ) => { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 500595e9f50..b176db3c9e0 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -485,7 +485,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { let tcx = self.tcx; // `func == Clone::clone(&ty) -> ty` - let func_ty = tcx.mk_fn_def(self.def_id, [ty]); + let func_ty = Ty::new_fn_def(tcx, self.def_id, [ty]); let func = Operand::Constant(Box::new(Constant { span: self.span, user_ty: None, @@ -494,7 +494,11 @@ impl<'tcx> CloneShimBuilder<'tcx> { let ref_loc = self.make_place( Mutability::Not, - tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }), + Ty::new_ref( + tcx, + tcx.lifetimes.re_erased, + ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }, + ), ); // `let ref_loc: &ty = &src;` @@ -644,7 +648,7 @@ fn build_call_shim<'tcx>( let untuple_args = sig.inputs(); // Create substitutions for the `Self` and `Args` generic parameters of the shim body. - let arg_tup = tcx.mk_tup(untuple_args); + let arg_tup = Ty::new_tup(tcx, untuple_args); (Some([ty.into(), arg_tup.into()]), Some(untuple_args)) } else { @@ -680,9 +684,9 @@ fn build_call_shim<'tcx>( *self_arg = match rcvr_adjustment.unwrap() { Adjustment::Identity => fnty, Adjustment::Deref { source } => match source { - DerefSource::ImmRef => tcx.mk_imm_ref(tcx.lifetimes.re_erased, fnty), - DerefSource::MutRef => tcx.mk_mut_ref(tcx.lifetimes.re_erased, fnty), - DerefSource::MutPtr => tcx.mk_mut_ptr(fnty), + DerefSource::ImmRef => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fnty), + DerefSource::MutRef => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fnty), + DerefSource::MutPtr => Ty::new_mut_ptr(tcx, fnty), }, Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {instance:?}"), }; @@ -696,7 +700,7 @@ fn build_call_shim<'tcx>( let mut inputs_and_output = sig.inputs_and_output.to_vec(); let self_arg = &mut inputs_and_output[0]; debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param); - *self_arg = tcx.mk_mut_ptr(*self_arg); + *self_arg = Ty::new_mut_ptr(tcx, *self_arg); sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); } @@ -720,7 +724,8 @@ fn build_call_shim<'tcx>( // let rcvr = &mut rcvr; let ref_rcvr = local_decls.push( LocalDecl::new( - tcx.mk_ref( + Ty::new_ref( + tcx, tcx.lifetimes.re_erased, ty::TypeAndMut { ty: sig.inputs()[0], mutbl: hir::Mutability::Mut }, ), @@ -946,7 +951,7 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t let rvalue = Rvalue::Cast( CastKind::FnPtrToPtr, Operand::Move(Place::from(Local::new(1))), - tcx.mk_imm_ptr(tcx.types.unit), + Ty::new_imm_ptr(tcx, tcx.types.unit), ); let stmt = Statement { source_info, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 4a5953c1149..242269e9d1a 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -176,7 +176,7 @@ use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::mir::visit::Visitor as MirVisitor; use rustc_middle::mir::{self, Local, Location}; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast}; +use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{ @@ -231,8 +231,8 @@ impl<'tcx> UsageMap<'tcx> { assert!(self.used_map.insert(user_item, used_items).is_none()); } - pub fn get_user_items(&self, item: MonoItem<'tcx>) -> Option<&[MonoItem<'tcx>]> { - self.user_map.get(&item).map(|items| items.as_slice()) + pub fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] { + self.user_map.get(&item).map(|items| items.as_slice()).unwrap_or(&[]) } /// Internally iterate over all inlined items used by `item`. @@ -617,7 +617,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { // have to instantiate all methods of the trait being cast to, so we // can build the appropriate vtable. mir::Rvalue::Cast( - mir::CastKind::Pointer(PointerCast::Unsize), + mir::CastKind::PointerCoercion(PointerCoercion::Unsize), ref operand, target_ty, ) @@ -643,7 +643,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { } } mir::Rvalue::Cast( - mir::CastKind::Pointer(PointerCast::ReifyFnPointer), + mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer), ref operand, _, ) => { @@ -652,7 +652,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { visit_fn_use(self.tcx, fn_ty, false, span, &mut self.output); } mir::Rvalue::Cast( - mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)), + mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)), ref operand, _, ) => { diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 89dadc782f2..5f05020acae 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -31,12 +31,12 @@ fn custom_coerce_unsize_info<'tcx>( source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> CustomCoerceUnsized { - let trait_ref = ty::Binder::dummy(ty::TraitRef::from_lang_item( + let trait_ref = ty::TraitRef::from_lang_item( tcx.tcx, LangItem::CoerceUnsized, tcx.span, [source_ty, target_ty], - )); + ); match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) { Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData { diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index e663f4486f7..da76cf2236c 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -187,7 +187,13 @@ where } // Ensure CGUs are sorted by name, so that we get deterministic results. - assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str())))); + if !codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))) { + let mut names = String::new(); + for cgu in codegen_units.iter() { + names += &format!("- {}\n", cgu.name()); + } + bug!("unsorted CGUs:\n{names}"); + } codegen_units } @@ -421,9 +427,9 @@ fn merge_codegen_units<'tcx>( // zero-padded suffixes, which means they are automatically sorted by // names. The numeric suffix width depends on the number of CGUs, which // is always greater than zero: - // - [1,9] CGUS: `0`, `1`, `2`, ... - // - [10,99] CGUS: `00`, `01`, `02`, ... - // - [100,999] CGUS: `000`, `001`, `002`, ... + // - [1,9] CGUs: `0`, `1`, `2`, ... + // - [10,99] CGUs: `00`, `01`, `02`, ... + // - [100,999] CGUs: `000`, `001`, `002`, ... // - etc. // // If we didn't zero-pad the sorted-by-name order would be `XYZ-cgu.0`, @@ -452,7 +458,7 @@ fn internalize_symbols<'tcx>( /// used to keep track of that. #[derive(Clone, PartialEq, Eq, Debug)] enum MonoItemPlacement { - SingleCgu { cgu_name: Symbol }, + SingleCgu(Symbol), MultipleCgus, } @@ -460,7 +466,7 @@ fn internalize_symbols<'tcx>( let single_codegen_unit = codegen_units.len() == 1; if !single_codegen_unit { - for cgu in codegen_units.iter_mut() { + for cgu in codegen_units.iter() { for item in cgu.items().keys() { // If there is more than one codegen unit, we need to keep track // in which codegen units each monomorphization is placed. @@ -468,13 +474,13 @@ fn internalize_symbols<'tcx>( Entry::Occupied(e) => { let placement = e.into_mut(); debug_assert!(match *placement { - MonoItemPlacement::SingleCgu { cgu_name } => cgu_name != cgu.name(), + MonoItemPlacement::SingleCgu(cgu_name) => cgu_name != cgu.name(), MonoItemPlacement::MultipleCgus => true, }); *placement = MonoItemPlacement::MultipleCgus; } Entry::Vacant(e) => { - e.insert(MonoItemPlacement::SingleCgu { cgu_name: cgu.name() }); + e.insert(MonoItemPlacement::SingleCgu(cgu.name())); } } } @@ -484,7 +490,7 @@ fn internalize_symbols<'tcx>( // For each internalization candidates in each codegen unit, check if it is // used from outside its defining codegen unit. for cgu in codegen_units { - let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() }; + let home_cgu = MonoItemPlacement::SingleCgu(cgu.name()); for (item, linkage_and_visibility) in cgu.items_mut() { if !internalization_candidates.contains(item) { @@ -495,20 +501,20 @@ fn internalize_symbols<'tcx>( if !single_codegen_unit { debug_assert_eq!(mono_item_placements[item], home_cgu); - if let Some(user_items) = cx.usage_map.get_user_items(*item) { - if user_items - .iter() - .filter_map(|user_item| { - // Some user mono items might not have been - // instantiated. We can safely ignore those. - mono_item_placements.get(user_item) - }) - .any(|placement| *placement != home_cgu) - { - // Found a user from another CGU, so skip to the next item - // without marking this one as internal. - continue; - } + if cx + .usage_map + .get_user_items(*item) + .iter() + .filter_map(|user_item| { + // Some user mono items might not have been + // instantiated. We can safely ignore those. + mono_item_placements.get(user_item) + }) + .any(|placement| *placement != home_cgu) + { + // Found a user from another CGU, so skip to the next item + // without marking this one as internal. + continue; } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3783ec41b7e..1470180dea7 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2182,7 +2182,11 @@ impl<'a> Parser<'a> { // `extern ABI fn` || self.check_keyword_case(kw::Extern, case) && self.look_ahead(1, |t| t.can_begin_literal_maybe_minus()) - && self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) + && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) || + // this branch is only for better diagnostic in later, `pub` is not allowed here + (self.may_recover() + && self.look_ahead(2, |t| t.is_keyword(kw::Pub)) + && self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case)))) } /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index b2bc33c7e0d..4adb4eb7475 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -126,18 +126,13 @@ where #[cold] #[inline(never)] -fn mk_cycle<Q, Qcx>( - query: Q, - qcx: Qcx, - cycle_error: CycleError<Qcx::DepKind>, - handler: HandleCycleError, -) -> Q::Value +fn mk_cycle<Q, Qcx>(query: Q, qcx: Qcx, cycle_error: CycleError<Qcx::DepKind>) -> Q::Value where Q: QueryConfig<Qcx>, Qcx: QueryContext, { let error = report_cycle(qcx.dep_context().sess(), &cycle_error); - handle_cycle_error(query, qcx, &cycle_error, error, handler) + handle_cycle_error(query, qcx, &cycle_error, error) } fn handle_cycle_error<Q, Qcx>( @@ -145,14 +140,13 @@ fn handle_cycle_error<Q, Qcx>( qcx: Qcx, cycle_error: &CycleError<Qcx::DepKind>, mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, - handler: HandleCycleError, ) -> Q::Value where Q: QueryConfig<Qcx>, Qcx: QueryContext, { use HandleCycleError::*; - match handler { + match query.handle_cycle_error() { Error => { error.emit(); query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle) @@ -277,7 +271,7 @@ where &qcx.current_query_job(), span, ); - (mk_cycle(query, qcx, error, query.handle_cycle_error()), None) + (mk_cycle(query, qcx, error), None) } #[inline(always)] @@ -314,7 +308,7 @@ where (v, Some(index)) } - Err(cycle) => (mk_cycle(query, qcx, cycle, query.handle_cycle_error()), None), + Err(cycle) => (mk_cycle(query, qcx, cycle), None), } } diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs index b6e2cfa3dca..ce551078cc0 100644 --- a/compiler/rustc_query_system/src/values.rs +++ b/compiler/rustc_query_system/src/values.rs @@ -6,10 +6,13 @@ pub trait Value<Tcx: DepContext, D: DepKind>: Sized { } impl<Tcx: DepContext, T, D: DepKind> Value<Tcx, D> for T { - default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo<D>]) -> T { + default fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo<D>]) -> T { tcx.sess().abort_if_errors(); // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's // non-trivial to define it earlier. - panic!("Value::from_cycle_error called without errors"); + panic!( + "<{} as Value>::from_cycle_error called without errors: {cycle:#?}", + std::any::type_name::<T>() + ); } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 72777733345..e6ceedddfa1 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -6,10 +6,10 @@ //! Imports are also considered items and placed into modules here, but not resolved yet. use crate::def_collector::collect_definitions; -use crate::imports::{Import, ImportKind}; +use crate::imports::{ImportData, ImportKind}; use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; -use crate::{errors, BindingKey, MacroData}; +use crate::{errors, BindingKey, MacroData, NameBindingData}; use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError}; use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError}; @@ -31,15 +31,14 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::cell::Cell; -use std::ptr; type Res = def::Res<NodeId>; impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Module<'a>, ty::Visibility<Id>, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { - arenas.alloc_name_binding(NameBinding { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { + arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Module(self.0), ambiguity: None, vis: self.1.to_def_id(), @@ -50,8 +49,8 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a> } impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { - arenas.alloc_name_binding(NameBinding { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { + arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(self.0), ambiguity: None, vis: self.1.to_def_id(), @@ -71,7 +70,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let binding = def.to_name_binding(self.arenas); let key = self.new_disambiguated_key(ident, ns); if let Err(old_binding) = self.try_define(parent, key, binding) { - self.report_conflict(parent, ident, ns, old_binding, &binding); + self.report_conflict(parent, ident, ns, old_binding, binding); } } @@ -142,8 +141,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(def_id) => self.macro_def_scope(def_id), None => expn_id .as_local() - .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id)) - .unwrap_or(&self.graph_root), + .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id).copied()) + .unwrap_or(self.graph_root), } } @@ -354,7 +353,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { vis: ty::Visibility, ) { let current_module = self.parent_scope.module; - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind, parent_scope: self.parent_scope, module_path, @@ -378,7 +377,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { if !type_ns_only || ns == TypeNS { let key = BindingKey::new(target, ns); let mut resolution = this.resolution(current_module, key).borrow_mut(); - resolution.add_single_import(import); + resolution.single_imports.insert(import); } }); } @@ -848,7 +847,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { (used, Some(ModuleOrUniformRoot::Module(module)), binding) }) .unwrap_or((true, None, self.r.dummy_binding)); - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id }, root_id: item.id, parent_scope: self.parent_scope, @@ -864,7 +863,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { }); self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); - if ptr::eq(parent, self.r.graph_root) { + if parent == self.r.graph_root { if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { if expansion != LocalExpnId::ROOT && orig_name.is_some() @@ -996,7 +995,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn add_macro_use_binding( &mut self, name: Symbol, - binding: &'a NameBinding<'a>, + binding: NameBinding<'a>, span: Span, allow_shadowing: bool, ) { @@ -1058,7 +1057,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } let macro_use_import = |this: &Self, span| { - this.r.arenas.alloc_import(Import { + this.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroUse, root_id: item.id, parent_scope: this.parent_scope, @@ -1228,7 +1227,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.set_binding_parent_module(binding, parent_scope.module); self.r.all_macro_rules.insert(ident.name, res); if is_macro_export { - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroExport, root_id: item.id, parent_scope: self.parent_scope, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d9e4974626d..d3dcdfa4275 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,5 +1,3 @@ -use std::ptr; - use rustc_ast::expand::StrippedCfgItem; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; @@ -182,13 +180,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - pub(crate) fn report_conflict<'b>( + pub(crate) fn report_conflict( &mut self, parent: Module<'_>, ident: Ident, ns: Namespace, - new_binding: &NameBinding<'b>, - old_binding: &NameBinding<'b>, + new_binding: NameBinding<'a>, + old_binding: NameBinding<'a>, ) { // Error on the second of two conflicting names if old_binding.span.lo() > new_binding.span.lo() { @@ -262,7 +260,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; - let can_suggest = |binding: &NameBinding<'_>, import: &self::Import<'_>| { + let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| { !binding.span.is_dummy() && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport) }; @@ -272,22 +270,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (Import { import: new, .. }, Import { import: old, .. }) if { (new.has_attributes || old.has_attributes) - && can_suggest(old_binding, old) - && can_suggest(new_binding, new) + && can_suggest(old_binding, *old) + && can_suggest(new_binding, *new) } => { if old.has_attributes { - Some((new, new_binding.span, true)) + Some((*new, new_binding.span, true)) } else { - Some((old, old_binding.span, true)) + Some((*old, old_binding.span, true)) } } // Otherwise prioritize the new binding. - (Import { import, .. }, other) if can_suggest(new_binding, import) => { - Some((import, new_binding.span, other.is_import())) + (Import { import, .. }, other) if can_suggest(new_binding, *import) => { + Some((*import, new_binding.span, other.is_import())) } - (other, Import { import, .. }) if can_suggest(old_binding, import) => { - Some((import, old_binding.span, other.is_import())) + (other, Import { import, .. }) if can_suggest(old_binding, *import) => { + Some((*import, old_binding.span, other.is_import())) } _ => None, }; @@ -341,7 +339,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &self, err: &mut Diagnostic, name: Symbol, - import: &Import<'_>, + import: Import<'_>, binding_span: Span, ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { @@ -413,7 +411,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn add_suggestion_for_duplicate_nested_use( &self, err: &mut Diagnostic, - import: &Import<'_>, + import: Import<'_>, binding_span: Span, ) { assert!(import.is_nested()); @@ -455,7 +453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, finalize: Option<Finalize>, path: &[Segment], - second_binding: Option<&NameBinding<'_>>, + second_binding: Option<NameBinding<'_>>, ) { let Some(Finalize { node_id, root_span, .. }) = finalize else { return; @@ -1198,7 +1196,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // avoid suggesting anything with a hygienic name if ident.name == lookup_ident.name && ns == namespace - && !ptr::eq(in_module, parent_scope.module) + && in_module != parent_scope.module && !ident.span.normalize_to_macros_2_0().from_expansion() { let res = name_binding.res(); @@ -1515,7 +1513,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { true } - fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String { + fn binding_description(&self, b: NameBinding<'_>, ident: Ident, from_prelude: bool) -> String { let res = b.res(); if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) { // These already contain the "built-in" prefix or look bad with it. @@ -1555,7 +1553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err.span_label(ident.span, "ambiguous name"); err.note(format!("ambiguous because of {}", kind.descr())); - let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { + let mut could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude); let note_msg = format!("`{ident}` could{also} refer to {what}"); @@ -1595,7 +1593,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// If the binding refers to a tuple struct constructor with fields, /// returns the span of its fields. - fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> { + fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> { if let NameBindingKind::Res(Res::Def( DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id, @@ -1622,7 +1620,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr }; let import_descr = nonimport_descr.clone() + " import"; let get_descr = - |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; + |b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; // Print the primary message. let descr = get_descr(binding); @@ -1702,7 +1700,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => None, }; - let first = ptr::eq(binding, first_binding); + let first = binding == first_binding; let msg = format!( "{and_refers_to}the {item} `{name}`{which} is defined here{dots}", and_refers_to = if first { "" } else { "...and refers to " }, @@ -1732,7 +1730,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn find_similarly_named_module_or_crate( &mut self, ident: Symbol, - current_module: &Module<'a>, + current_module: Module<'a>, ) -> Option<Symbol> { let mut candidates = self .extern_prelude @@ -1742,7 +1740,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.module_map .iter() .filter(|(_, module)| { - current_module.is_ancestor_of(module) && !ptr::eq(current_module, *module) + current_module.is_ancestor_of(**module) && current_module != **module }) .flat_map(|(_, module)| module.kind.name()), ) @@ -1762,7 +1760,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { opt_ns: Option<Namespace>, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, ribs: Option<&PerNS<Vec<Rib<'a>>>>, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<NameBinding<'a>>, module: Option<ModuleOrUniformRoot<'a>>, failed_segment_idx: usize, ident: Ident, @@ -1945,7 +1943,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } suggestion = suggestion.or_else(|| { - self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map( + self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map( |sugg| { ( vec![(ident.span, sugg.to_string())], @@ -2114,7 +2112,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// ``` pub(crate) fn check_for_module_export_macro( &mut self, - import: &'a Import<'a>, + import: Import<'a>, module: ModuleOrUniformRoot<'a>, ident: Ident, ) -> Option<(Option<Suggestion>, Option<String>)> { @@ -2126,9 +2124,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { crate_module = parent; } - if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) { - // Don't make a suggestion if the import was already from the root of the - // crate. + if module == ModuleOrUniformRoot::Module(crate_module) { + // Don't make a suggestion if the import was already from the root of the crate. return None; } diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 4863c9f4790..eb210532f51 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -5,7 +5,6 @@ use rustc_ast::visit::Visitor; use rustc_ast::Crate; use rustc_ast::EnumDef; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::intern::Interned; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::middle::privacy::Level; @@ -13,12 +12,10 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility}; use rustc_middle::ty::Visibility; use std::mem; -type ImportId<'a> = Interned<'a, NameBinding<'a>>; - #[derive(Clone, Copy)] enum ParentId<'a> { Def(LocalDefId), - Import(ImportId<'a>), + Import(NameBinding<'a>), } impl ParentId<'_> { @@ -36,7 +33,7 @@ pub(crate) struct EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { /// While walking import chains we need to track effective visibilities per-binding, and def id /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple /// bindings can correspond to a single def id in imports. So we keep a separate table. - import_effective_visibilities: EffectiveVisibilities<ImportId<'a>>, + import_effective_visibilities: EffectiveVisibilities<NameBinding<'a>>, // It's possible to recalculate this at any point, but it's relatively expensive. current_private_vis: Visibility, changed: bool, @@ -47,7 +44,7 @@ impl Resolver<'_, '_> { self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local() } - fn private_vis_import(&mut self, binding: ImportId<'_>) -> Visibility { + fn private_vis_import(&mut self, binding: NameBinding<'_>) -> Visibility { let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; Visibility::Restricted( import @@ -75,7 +72,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { pub(crate) fn compute_effective_visibilities<'c>( r: &'r mut Resolver<'a, 'tcx>, krate: &'c Crate, - ) -> FxHashSet<Interned<'a, NameBinding<'a>>> { + ) -> FxHashSet<NameBinding<'a>> { let mut visitor = EffectiveVisibilitiesVisitor { r, def_effective_visibilities: Default::default(), @@ -133,8 +130,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { // lint. For all bindings added to the table this way `is_ambiguity` returns true. let mut parent_id = ParentId::Def(module_id); while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { - let binding_id = ImportId::new_unchecked(binding); - self.update_import(binding_id, parent_id); + self.update_import(binding, parent_id); if binding.ambiguity.is_some() { // Stop at the root ambiguity, further bindings in the chain should not @@ -143,7 +139,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { break; } - parent_id = ParentId::Import(binding_id); + parent_id = ParentId::Import(binding); binding = nested_binding; } @@ -192,7 +188,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } - fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) { + fn update_import(&mut self, binding: NameBinding<'a>, parent_id: ParentId<'a>) { let nominal_vis = binding.vis.expect_local(); let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 36f01676e7e..520fab1f0c8 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -11,8 +11,6 @@ use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContex use rustc_span::symbol::{kw, Ident}; use rustc_span::{Span, DUMMY_SP}; -use std::ptr; - use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::late::{ ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind, @@ -20,7 +18,7 @@ use crate::late::{ use crate::macros::{sub_namespace_match, MacroRulesScope}; use crate::BindingKey; use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize}; -use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot}; +use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res}; use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak}; @@ -284,7 +282,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option<Finalize>, ribs: &[Rib<'a>], - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<NameBinding<'a>>, ) -> Option<LexicalScopeBinding<'a>> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; @@ -378,8 +376,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option<Finalize>, force: bool, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option<NameBinding<'a>>, + ) -> Result<NameBinding<'a>, Determinacy> { bitflags::bitflags! { struct Flags: u8 { const MACRO_RULES = 1 << 0; @@ -415,7 +413,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // } // So we have to save the innermost solution and continue searching in outer scopes // to detect potential ambiguities. - let mut innermost_result: Option<(&NameBinding<'_>, Flags)> = None; + let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None; let mut determinacy = Determinacy::Determined; // Go through all the scopes and try to resolve the name. @@ -538,7 +536,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ), ); } - let misc_flags = if ptr::eq(module, this.graph_root) { + let misc_flags = if module == this.graph_root { Flags::MISC_SUGGEST_CRATE } else if module.is_normal() { Flags::MISC_SUGGEST_SELF @@ -717,7 +715,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ident: Ident, ns: Namespace, parent_scope: &ParentScope<'a>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ) -> Result<NameBinding<'a>, Determinacy> { self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None) .map_err(|(determinacy, _)| determinacy) } @@ -730,8 +728,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option<Finalize>, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option<NameBinding<'a>>, + ) -> Result<NameBinding<'a>, Determinacy> { self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding) .map_err(|(determinacy, _)| determinacy) } @@ -744,8 +742,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option<Finalize>, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { + ignore_binding: Option<NameBinding<'a>>, + ) -> Result<NameBinding<'a>, (Determinacy, Weak)> { let tmp_parent_scope; let mut adjusted_parent_scope = parent_scope; match module { @@ -782,8 +780,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option<Finalize>, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option<NameBinding<'a>>, + ) -> Result<NameBinding<'a>, Determinacy> { self.resolve_ident_in_module_unadjusted_ext( module, ident, @@ -809,8 +807,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { finalize: Option<Finalize>, // This binding should be ignored during in-module resolution, so that we don't get // "self-confirming" import resolutions during import validation and checking. - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { + ignore_binding: Option<NameBinding<'a>>, + ) -> Result<NameBinding<'a>, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, ModuleOrUniformRoot::CrateRootAndExternPrelude => { @@ -873,13 +871,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // binding if it exists. What we really want here is having two separate scopes in // a module - one for non-globs and one for globs, but until that's done use this // hack to avoid inconsistent resolution ICEs during import validation. - let binding = - [resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| { - match (binding, ignore_binding) { - (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None, - _ => binding, - } - }); + let binding = [resolution.binding, resolution.shadowed_glob] + .into_iter() + .find_map(|binding| if binding == ignore_binding { None } else { binding }); if let Some(Finalize { path_span, report_private, .. }) = finalize { let Some(binding) = binding else { @@ -917,11 +911,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT { - if let NameBindingKind::Import { - import: Import { kind: ImportKind::MacroExport, .. }, - .. - } = binding.kind - { + if let NameBindingKind::Import { import, .. } = binding.kind + && matches!(import.kind, ImportKind::MacroExport) { self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); } } @@ -930,7 +921,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Ok(binding); } - let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { + let check_usable = |this: &mut Self, binding: NameBinding<'a>| { let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } }; @@ -955,7 +946,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let Some(ignored) = ignore_binding && let NameBindingKind::Import { import, .. } = ignored.kind && - ptr::eq(import, &**single_import) { + import == *single_import { // Ignore not just the binding itself, but if it has a shadowed_glob, // ignore that, too, because this loop is supposed to only process // named imports. @@ -1352,7 +1343,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { opt_ns: Option<Namespace>, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, finalize: Option<Finalize>, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<NameBinding<'a>>, ) -> PathResult<'a> { self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding) } @@ -1364,7 +1355,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option<Finalize>, ribs: Option<&PerNS<Vec<Rib<'a>>>>, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<NameBinding<'a>>, ) -> PathResult<'a> { let mut module = None; let mut allow_super = true; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 074f761c53b..d37fe783bba 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -12,7 +12,7 @@ use crate::{fluent_generated as fluent, Namespace::*}; use crate::{module_to_string, names_to_string, ImportSuggestion}; use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; -use crate::{NameBinding, NameBindingKind, PathResult}; +use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult}; use rustc_ast::NodeId; use rustc_data_structures::fx::FxHashSet; @@ -35,7 +35,7 @@ use rustc_span::Span; use smallvec::SmallVec; use std::cell::Cell; -use std::{mem, ptr}; +use std::mem; type Res = def::Res<NodeId>; @@ -48,9 +48,9 @@ pub(crate) enum ImportKind<'a> { /// `target` in `use prefix::source as target`. target: Ident, /// Bindings to which `source` refers to. - source_bindings: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>, + source_bindings: PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>, /// Bindings introduced by `target`. - target_bindings: PerNS<Cell<Option<&'a NameBinding<'a>>>>, + target_bindings: PerNS<Cell<Option<NameBinding<'a>>>>, /// `true` for `...::{self [as target]}` imports, `false` otherwise. type_ns_only: bool, /// Did this import result from a nested import? ie. `use foo::{bar, baz};` @@ -135,7 +135,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { /// One import. #[derive(Debug, Clone)] -pub(crate) struct Import<'a> { +pub(crate) struct ImportData<'a> { pub kind: ImportKind<'a>, /// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id` @@ -172,7 +172,11 @@ pub(crate) struct Import<'a> { pub used: Cell<bool>, } -impl<'a> Import<'a> { +/// All imports are unique and allocated on a same arena, +/// so we can use referential equality to compare them. +pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>; + +impl<'a> ImportData<'a> { pub(crate) fn is_glob(&self) -> bool { matches!(self.kind, ImportKind::Glob { .. }) } @@ -214,15 +218,15 @@ impl<'a> Import<'a> { pub(crate) struct NameResolution<'a> { /// Single imports that may define the name in the namespace. /// Imports are arena-allocated, so it's ok to use pointers as keys. - pub single_imports: FxHashSet<Interned<'a, Import<'a>>>, + pub single_imports: FxHashSet<Import<'a>>, /// The least shadowable known binding for this name, or None if there are no known bindings. - pub binding: Option<&'a NameBinding<'a>>, - pub shadowed_glob: Option<&'a NameBinding<'a>>, + pub binding: Option<NameBinding<'a>>, + pub shadowed_glob: Option<NameBinding<'a>>, } impl<'a> NameResolution<'a> { /// Returns the binding for the name if it is known or None if it not known. - pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> { + pub(crate) fn binding(&self) -> Option<NameBinding<'a>> { self.binding.and_then(|binding| { if !binding.is_glob_import() || self.single_imports.is_empty() { Some(binding) @@ -231,10 +235,6 @@ impl<'a> NameResolution<'a> { } }) } - - pub(crate) fn add_single_import(&mut self, import: &'a Import<'a>) { - self.single_imports.insert(Interned::new_unchecked(import)); - } } /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved @@ -250,15 +250,12 @@ struct UnresolvedImportError { // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;` // are permitted for backward-compatibility under a deprecation lint. -fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBinding<'_>) -> bool { +fn pub_use_of_private_extern_crate_hack(import: Import<'_>, binding: NameBinding<'_>) -> bool { match (&import.kind, &binding.kind) { - ( - ImportKind::Single { .. }, - NameBindingKind::Import { - import: Import { kind: ImportKind::ExternCrate { .. }, .. }, - .. - }, - ) => import.expect_vis().is_public(), + (ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. }) => { + matches!(binding_import.kind, ImportKind::ExternCrate { .. }) + && import.expect_vis().is_public() + } _ => false, } } @@ -266,11 +263,7 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Given a binding and an import that resolves to it, /// return the corresponding binding defined by the import. - pub(crate) fn import( - &self, - binding: &'a NameBinding<'a>, - import: &'a Import<'a>, - ) -> &'a NameBinding<'a> { + pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> { let import_vis = import.expect_vis().to_def_id(); let vis = if binding.vis.is_at_least(import_vis, self.tcx) || pub_use_of_private_extern_crate_hack(import, binding) @@ -288,7 +281,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - self.arenas.alloc_name_binding(NameBinding { + self.arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Import { binding, import, used: Cell::new(false) }, ambiguity: None, span: import.span, @@ -302,8 +295,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, module: Module<'a>, key: BindingKey, - binding: &'a NameBinding<'a>, - ) -> Result<(), &'a NameBinding<'a>> { + binding: NameBinding<'a>, + ) -> Result<(), NameBinding<'a>> { let res = binding.res(); self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); @@ -372,12 +365,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn ambiguity( &self, kind: AmbiguityKind, - primary_binding: &'a NameBinding<'a>, - secondary_binding: &'a NameBinding<'a>, - ) -> &'a NameBinding<'a> { - self.arenas.alloc_name_binding(NameBinding { + primary_binding: NameBinding<'a>, + secondary_binding: NameBinding<'a>, + ) -> NameBinding<'a> { + self.arenas.alloc_name_binding(NameBindingData { ambiguity: Some((secondary_binding, kind)), - ..primary_binding.clone() + ..(*primary_binding).clone() }) } @@ -395,13 +388,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let t = f(self, resolution); - match resolution.binding() { - _ if old_binding.is_some() => return t, - None => return t, - Some(binding) => match old_binding { - Some(old_binding) if ptr::eq(old_binding, binding) => return t, - _ => (binding, t), - }, + if old_binding.is_none() && let Some(binding) = resolution.binding() { + (binding, t) + } else { + return t; } }; @@ -414,7 +404,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => continue, }; if self.is_accessible_from(binding.vis, scope) { - let imported_binding = self.import(binding, import); + let imported_binding = self.import(binding, *import); let key = BindingKey { ident, ..key }; let _ = self.try_define(import.parent_scope.module, key, imported_binding); } @@ -425,7 +415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics. - fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) { + fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) { if let ImportKind::Single { target, ref target_bindings, .. } = import.kind { if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none())) { @@ -463,7 +453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { prev_indeterminate_count = indeterminate_count; indeterminate_count = 0; for import in mem::take(&mut self.indeterminate_imports) { - let import_indeterminate_count = self.resolve_import(&import); + let import_indeterminate_count = self.resolve_import(import); indeterminate_count += import_indeterminate_count; match import_indeterminate_count { 0 => self.determined_imports.push(import), @@ -475,7 +465,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn finalize_imports(&mut self) { for module in self.arenas.local_modules().iter() { - self.finalize_resolutions_in(module); + self.finalize_resolutions_in(*module); } let mut seen_spans = FxHashSet::default(); @@ -546,17 +536,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn check_hidden_glob_reexports( &mut self, - exported_ambiguities: FxHashSet<Interned<'a, NameBinding<'a>>>, + exported_ambiguities: FxHashSet<NameBinding<'a>>, ) { for module in self.arenas.local_modules().iter() { - for (key, resolution) in self.resolutions(module).borrow().iter() { + for (key, resolution) in self.resolutions(*module).borrow().iter() { let resolution = resolution.borrow(); if let Some(binding) = resolution.binding { if let NameBindingKind::Import { import, .. } = binding.kind && let Some((amb_binding, _)) = binding.ambiguity && binding.res() != Res::Err - && exported_ambiguities.contains(&Interned::new_unchecked(binding)) + && exported_ambiguities.contains(&binding) { self.lint_buffer.buffer_lint_with_diagnostic( AMBIGUOUS_GLOB_REEXPORTS, @@ -612,7 +602,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn throw_unresolved_import_error(&mut self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) { + fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) { if errors.is_empty() { return; } @@ -704,7 +694,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Meanwhile, if resolve successful, the resolved bindings are written /// into the module. - fn resolve_import(&mut self, import: &'a Import<'a>) -> usize { + fn resolve_import(&mut self, import: Import<'a>) -> usize { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&import.module_path), @@ -784,7 +774,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let key = BindingKey::new(target, ns); this.update_resolution(parent, key, |_, resolution| { - resolution.single_imports.remove(&Interned::new_unchecked(import)); + resolution.single_imports.remove(&import); }); } } @@ -798,7 +788,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Optionally returns an unresolved import error. This error is buffered and used to /// consolidate multiple unresolved import errors into a single diagnostic. - fn finalize_import(&mut self, import: &'a Import<'a>) -> Option<UnresolvedImportError> { + fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> { let orig_vis = import.vis.take(); let ignore_binding = match &import.kind { ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(), @@ -824,7 +814,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_macro_resolutions`. if let Some(initial_module) = import.imported_module.get() { - if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { + if module != initial_module && no_ambiguity { span_bug!(import.span, "inconsistent resolution for an import"); } } else if self.privacy_errors.is_empty() { @@ -926,7 +916,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let ModuleOrUniformRoot::Module(module) = module { - if ptr::eq(module, import.parent_scope.module) { + if module == import.parent_scope.module { // Importing a module into itself is not allowed. return Some(UnresolvedImportError { span: import.span, @@ -1242,9 +1232,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn check_for_redundant_imports( &mut self, ident: Ident, - import: &'a Import<'a>, - source_bindings: &PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>, - target_bindings: &PerNS<Cell<Option<&'a NameBinding<'a>>>>, + import: Import<'a>, + source_bindings: &PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>, + target_bindings: &PerNS<Cell<Option<NameBinding<'a>>>>, target: Ident, ) { // This function is only called for single imports. @@ -1305,7 +1295,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_glob_import(&mut self, import: &'a Import<'a>) { + fn resolve_glob_import(&mut self, import: Import<'a>) { // This function is only called for glob imports. let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() }; @@ -1319,7 +1309,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if module.is_trait() { self.tcx.sess.create_err(ItemsInTraitsAreNotImportable { span: import.span }).emit(); return; - } else if ptr::eq(module, import.parent_scope.module) { + } else if module == import.parent_scope.module { return; } else if is_prelude { self.prelude = Some(module); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 97feb3ddc11..f6c7aecf8b0 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1284,7 +1284,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ident: Ident, ns: Namespace, finalize: Option<Finalize>, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<NameBinding<'a>>, ) -> Option<LexicalScopeBinding<'a>> { self.r.resolve_ident_in_lexical_scope( ident, @@ -2972,7 +2972,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>, { // If there is a TraitRef in scope for an impl, then the method must be in the trait. - let Some((module, _)) = &self.current_trait_ref else { return; }; + let Some((module, _)) = self.current_trait_ref else { return; }; ident.span.normalize_to_macros_2_0_and_adjust(module.expansion); let key = BindingKey::new(ident, ns); let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8b65a892b5e..78ef72a7e34 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1600,7 +1600,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { return None; } - let resolutions = self.r.resolutions(module); + let resolutions = self.r.resolutions(*module); let targets = resolutions .borrow() .iter() diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index cc4cb9fa30c..da3d86a4718 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -14,6 +14,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(never_type)] +#![feature(rustc_attrs)] #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] #![allow(rustc::potential_query_instability)] @@ -61,10 +62,10 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; -use std::{fmt, ptr}; +use std::fmt; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; -use imports::{Import, ImportKind, NameResolution}; +use imports::{Import, ImportData, ImportKind, NameResolution}; use late::{HasGenericParams, PathSource, PatternSource}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; @@ -352,7 +353,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment { /// forward. #[derive(Debug)] enum LexicalScopeBinding<'a> { - Item(&'a NameBinding<'a>), + Item(NameBinding<'a>), Res(Res), } @@ -365,7 +366,7 @@ impl<'a> LexicalScopeBinding<'a> { } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] enum ModuleOrUniformRoot<'a> { /// Regular module. Module(Module<'a>), @@ -383,23 +384,6 @@ enum ModuleOrUniformRoot<'a> { CurrentScope, } -impl ModuleOrUniformRoot<'_> { - fn same_def(lhs: Self, rhs: Self) -> bool { - match (lhs, rhs) { - (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => { - ptr::eq(lhs, rhs) - } - ( - ModuleOrUniformRoot::CrateRootAndExternPrelude, - ModuleOrUniformRoot::CrateRootAndExternPrelude, - ) - | (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) - | (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true, - _ => false, - } - } -} - #[derive(Debug)] enum PathResult<'a> { Module(ModuleOrUniformRoot<'a>), @@ -518,11 +502,11 @@ struct ModuleData<'a> { /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, - glob_importers: RefCell<Vec<&'a Import<'a>>>, - globs: RefCell<Vec<&'a Import<'a>>>, + glob_importers: RefCell<Vec<Import<'a>>>, + globs: RefCell<Vec<Import<'a>>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. - traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>, + traits: RefCell<Option<Box<[(Ident, NameBinding<'a>)]>>>, /// Span of the module itself. Used for error reporting. span: Span, @@ -530,7 +514,11 @@ struct ModuleData<'a> { expansion: ExpnId, } -type Module<'a> = &'a ModuleData<'a>; +/// All modules are unique and allocated on a same arena, +/// so we can use referential equality to compare them. +#[derive(Clone, Copy, PartialEq)] +#[rustc_pass_by_value] +struct Module<'a>(Interned<'a, ModuleData<'a>>); impl<'a> ModuleData<'a> { fn new( @@ -558,11 +546,13 @@ impl<'a> ModuleData<'a> { expansion, } } +} - fn for_each_child<'tcx, R, F>(&'a self, resolver: &mut R, mut f: F) +impl<'a> Module<'a> { + fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F) where R: AsMut<Resolver<'a, 'tcx>>, - F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>), + F: FnMut(&mut R, Ident, Namespace, NameBinding<'a>), { for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { if let Some(binding) = name_resolution.borrow().binding { @@ -572,7 +562,7 @@ impl<'a> ModuleData<'a> { } /// This modifies `self` in place. The traits will be stored in `self.traits`. - fn ensure_traits<'tcx, R>(&'a self, resolver: &mut R) + fn ensure_traits<'tcx, R>(self, resolver: &mut R) where R: AsMut<Resolver<'a, 'tcx>>, { @@ -591,7 +581,7 @@ impl<'a> ModuleData<'a> { } } - fn res(&self) -> Option<Res> { + fn res(self) -> Option<Res> { match self.kind { ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), _ => None, @@ -599,11 +589,11 @@ impl<'a> ModuleData<'a> { } // Public for rustdoc. - fn def_id(&self) -> DefId { + fn def_id(self) -> DefId { self.opt_def_id().expect("`ModuleData::def_id` is called on a block module") } - fn opt_def_id(&self) -> Option<DefId> { + fn opt_def_id(self) -> Option<DefId> { match self.kind { ModuleKind::Def(_, def_id, _) => Some(def_id), _ => None, @@ -611,15 +601,15 @@ impl<'a> ModuleData<'a> { } // `self` resolves to the first module ancestor that `is_normal`. - fn is_normal(&self) -> bool { + fn is_normal(self) -> bool { matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _)) } - fn is_trait(&self) -> bool { + fn is_trait(self) -> bool { matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _)) } - fn nearest_item_scope(&'a self) -> Module<'a> { + fn nearest_item_scope(self) -> Module<'a> { match self.kind { ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => { self.parent.expect("enum or trait module without a parent") @@ -630,15 +620,15 @@ impl<'a> ModuleData<'a> { /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module). /// This may be the crate root. - fn nearest_parent_mod(&self) -> DefId { + fn nearest_parent_mod(self) -> DefId { match self.kind { ModuleKind::Def(DefKind::Mod, def_id, _) => def_id, _ => self.parent.expect("non-root module without parent").nearest_parent_mod(), } } - fn is_ancestor_of(&self, mut other: &Self) -> bool { - while !ptr::eq(self, other) { + fn is_ancestor_of(self, mut other: Self) -> bool { + while self != other { if let Some(parent) = other.parent { other = parent; } else { @@ -649,7 +639,15 @@ impl<'a> ModuleData<'a> { } } -impl<'a> fmt::Debug for ModuleData<'a> { +impl<'a> std::ops::Deref for Module<'a> { + type Target = ModuleData<'a>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a> fmt::Debug for Module<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.res()) } @@ -657,20 +655,24 @@ impl<'a> fmt::Debug for ModuleData<'a> { /// Records a possibly-private value, type, or module definition. #[derive(Clone, Debug)] -struct NameBinding<'a> { +struct NameBindingData<'a> { kind: NameBindingKind<'a>, - ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>, + ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>, expansion: LocalExpnId, span: Span, vis: ty::Visibility<DefId>, } +/// All name bindings are unique and allocated on a same arena, +/// so we can use referential equality to compare them. +type NameBinding<'a> = Interned<'a, NameBindingData<'a>>; + trait ToNameBinding<'a> { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>; + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a>; } -impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { - fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { +impl<'a> ToNameBinding<'a> for NameBinding<'a> { + fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> NameBinding<'a> { self } } @@ -679,7 +681,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { enum NameBindingKind<'a> { Res(Res), Module(Module<'a>), - Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell<bool> }, + Import { binding: NameBinding<'a>, import: Import<'a>, used: Cell<bool> }, } impl<'a> NameBindingKind<'a> { @@ -692,7 +694,7 @@ impl<'a> NameBindingKind<'a> { #[derive(Debug)] struct PrivacyError<'a> { ident: Ident, - binding: &'a NameBinding<'a>, + binding: NameBinding<'a>, dedup_span: Span, outermost_res: Option<(Res, Ident)>, parent_scope: ParentScope<'a>, @@ -761,13 +763,13 @@ enum AmbiguityErrorMisc { struct AmbiguityError<'a> { kind: AmbiguityKind, ident: Ident, - b1: &'a NameBinding<'a>, - b2: &'a NameBinding<'a>, + b1: NameBinding<'a>, + b2: NameBinding<'a>, misc1: AmbiguityErrorMisc, misc2: AmbiguityErrorMisc, } -impl<'a> NameBinding<'a> { +impl<'a> NameBindingData<'a> { fn module(&self) -> Option<Module<'a>> { match self.kind { NameBindingKind::Module(module) => Some(module), @@ -805,14 +807,12 @@ impl<'a> NameBinding<'a> { fn is_extern_crate(&self) -> bool { match self.kind { - NameBindingKind::Import { - import: &Import { kind: ImportKind::ExternCrate { .. }, .. }, - .. - } => true, - NameBindingKind::Module(&ModuleData { - kind: ModuleKind::Def(DefKind::Mod, def_id, _), - .. - }) => def_id.is_crate_root(), + NameBindingKind::Import { import, .. } => { + matches!(import.kind, ImportKind::ExternCrate { .. }) + } + NameBindingKind::Module(module) + if let ModuleKind::Def(DefKind::Mod, def_id, _) = module.kind + => def_id.is_crate_root(), _ => false, } } @@ -855,7 +855,7 @@ impl<'a> NameBinding<'a> { fn may_appear_after( &self, invoc_parent_expansion: LocalExpnId, - binding: &NameBinding<'_>, + binding: NameBinding<'_>, ) -> bool { // self > max(invoc, binding) => !(self <= invoc || self <= binding) // Expansions are partially ordered, so "may appear after" is an inversion of @@ -872,7 +872,7 @@ impl<'a> NameBinding<'a> { #[derive(Default, Clone)] struct ExternPreludeEntry<'a> { - extern_crate_item: Option<&'a NameBinding<'a>>, + extern_crate_item: Option<NameBinding<'a>>, introduced_by_item: bool, } @@ -917,10 +917,10 @@ pub struct Resolver<'a, 'tcx> { field_visibility_spans: FxHashMap<DefId, Vec<Span>>, /// All imports known to succeed or fail. - determined_imports: Vec<&'a Import<'a>>, + determined_imports: Vec<Import<'a>>, /// All non-determined imports. - indeterminate_imports: Vec<&'a Import<'a>>, + indeterminate_imports: Vec<Import<'a>>, // Spans for local variables found during pattern resolution. // Used for suggestions during error reporting. @@ -962,7 +962,7 @@ pub struct Resolver<'a, 'tcx> { /// language items. empty_module: Module<'a>, module_map: FxHashMap<DefId, Module<'a>>, - binding_parent_modules: FxHashMap<Interned<'a, NameBinding<'a>>, Module<'a>>, + binding_parent_modules: FxHashMap<NameBinding<'a>, Module<'a>>, underscore_disambiguator: u32, @@ -984,7 +984,7 @@ pub struct Resolver<'a, 'tcx> { macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, arenas: &'a ResolverArenas<'a>, - dummy_binding: &'a NameBinding<'a>, + dummy_binding: NameBinding<'a>, used_extern_options: FxHashSet<Symbol>, macro_names: FxHashSet<Ident>, @@ -993,7 +993,7 @@ pub struct Resolver<'a, 'tcx> { /// the surface (`macro` items in libcore), but are actually attributes or derives. builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>, registered_tools: &'tcx RegisteredTools, - macro_use_prelude: FxHashMap<Symbol, &'a NameBinding<'a>>, + macro_use_prelude: FxHashMap<Symbol, NameBinding<'a>>, macro_map: FxHashMap<DefId, MacroData>, dummy_ext_bang: Lrc<SyntaxExtension>, dummy_ext_derive: Lrc<SyntaxExtension>, @@ -1005,7 +1005,7 @@ pub struct Resolver<'a, 'tcx> { proc_macro_stubs: FxHashSet<LocalDefId>, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: - Vec<(Ident, MacroKind, ParentScope<'a>, Option<&'a NameBinding<'a>>)>, + Vec<(Ident, MacroKind, ParentScope<'a>, Option<NameBinding<'a>>)>, multi_segment_macro_resolutions: Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>, Option<Res>)>, builtin_attrs: Vec<(Ident, ParentScope<'a>)>, @@ -1030,7 +1030,7 @@ pub struct Resolver<'a, 'tcx> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap<Symbol, Span>, - potentially_unused_imports: Vec<&'a Import<'a>>, + potentially_unused_imports: Vec<Import<'a>>, /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. @@ -1085,7 +1085,7 @@ pub struct Resolver<'a, 'tcx> { pub struct ResolverArenas<'a> { modules: TypedArena<ModuleData<'a>>, local_modules: RefCell<Vec<Module<'a>>>, - imports: TypedArena<Import<'a>>, + imports: TypedArena<ImportData<'a>>, name_resolutions: TypedArena<RefCell<NameResolution<'a>>>, ast_paths: TypedArena<ast::Path>, dropless: DroplessArena, @@ -1101,8 +1101,13 @@ impl<'a> ResolverArenas<'a> { no_implicit_prelude: bool, module_map: &mut FxHashMap<DefId, Module<'a>>, ) -> Module<'a> { - let module = - self.modules.alloc(ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude)); + let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( + parent, + kind, + expn_id, + span, + no_implicit_prelude, + )))); let def_id = module.opt_def_id(); if def_id.map_or(true, |def_id| def_id.is_local()) { self.local_modules.borrow_mut().push(module); @@ -1115,11 +1120,11 @@ impl<'a> ResolverArenas<'a> { fn local_modules(&'a self) -> std::cell::Ref<'a, Vec<Module<'a>>> { self.local_modules.borrow() } - fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> { - self.dropless.alloc(name_binding) + fn alloc_name_binding(&'a self, name_binding: NameBindingData<'a>) -> NameBinding<'a> { + Interned::new_unchecked(self.dropless.alloc(name_binding)) } - fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> { - self.imports.alloc(import) + fn alloc_import(&'a self, import: ImportData<'a>) -> Import<'a> { + Interned::new_unchecked(self.imports.alloc(import)) } fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> { self.name_resolutions.alloc(Default::default()) @@ -1314,7 +1319,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { macro_expanded_macro_export_errors: BTreeSet::new(), arenas, - dummy_binding: arenas.alloc_name_binding(NameBinding { + dummy_binding: arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(Res::Err), ambiguity: None, expansion: LocalExpnId::ROOT, @@ -1624,7 +1629,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.maybe_unused_trait_imports.insert(def_id); import_ids.push(def_id); } - self.add_to_glob_map(&import, trait_name); + self.add_to_glob_map(*import, trait_name); kind = &binding.kind; } import_ids @@ -1646,7 +1651,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module.populate_on_access.set(false); self.build_reduced_graph_external(module); } - &module.lazy_resolutions + &module.0.0.lazy_resolutions } fn resolution( @@ -1679,12 +1684,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false } - fn record_use( - &mut self, - ident: Ident, - used_binding: &'a NameBinding<'a>, - is_lexical_scope: bool, - ) { + fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical_scope: bool) { if let Some((b2, kind)) = used_binding.ambiguity { let ambiguity_error = AmbiguityError { kind, @@ -1704,10 +1704,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if let Some(crate_item) = entry.extern_crate_item { - if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { - return; - } + if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) { + return; } } } @@ -1716,13 +1714,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(id) = import.id() { self.used_imports.insert(id); } - self.add_to_glob_map(&import, ident); + self.add_to_glob_map(import, ident); self.record_use(ident, binding, false); } } #[inline] - fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) { + fn add_to_glob_map(&mut self, import: Import<'_>, ident: Ident) { if let ImportKind::Glob { id, .. } = import.kind { let def_id = self.local_def_id(id); self.glob_map.entry(def_id).or_default().insert(ident.name); @@ -1831,11 +1829,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { vis.is_accessible_from(module.nearest_parent_mod(), self.tcx) } - fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) { - if let Some(old_module) = - self.binding_parent_modules.insert(Interned::new_unchecked(binding), module) - { - if !ptr::eq(module, old_module) { + fn set_binding_parent_module(&mut self, binding: NameBinding<'a>, module: Module<'a>) { + if let Some(old_module) = self.binding_parent_modules.insert(binding, module) { + if module != old_module { span_bug!(binding.span, "parent module is reset for binding"); } } @@ -1843,25 +1839,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn disambiguate_macro_rules_vs_modularized( &self, - macro_rules: &'a NameBinding<'a>, - modularized: &'a NameBinding<'a>, + macro_rules: NameBinding<'a>, + modularized: NameBinding<'a>, ) -> bool { // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules" // is disambiguated to mitigate regressions from macro modularization. // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general. match ( - self.binding_parent_modules.get(&Interned::new_unchecked(macro_rules)), - self.binding_parent_modules.get(&Interned::new_unchecked(modularized)), + self.binding_parent_modules.get(¯o_rules), + self.binding_parent_modules.get(&modularized), ) { (Some(macro_rules), Some(modularized)) => { macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod() - && modularized.is_ancestor_of(macro_rules) + && modularized.is_ancestor_of(*macro_rules) } _ => false, } } - fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<&'a NameBinding<'a>> { + fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<NameBinding<'a>> { if ident.is_path_segment_keyword() { // Make sure `self`, `super` etc produce an error when passed to here. return None; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d33e8d40b63..d16b7902f60 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -42,7 +42,7 @@ type Res = def::Res<NodeId>; /// Not modularized, can shadow previous `macro_rules` bindings, etc. #[derive(Debug)] pub(crate) struct MacroRulesBinding<'a> { - pub(crate) binding: &'a NameBinding<'a>, + pub(crate) binding: NameBinding<'a>, /// `macro_rules` scope into which the `macro_rules` item was planted. pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'a>, pub(crate) ident: Ident, @@ -870,7 +870,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn prohibit_imported_non_macro_attrs( &self, - binding: Option<&'a NameBinding<'a>>, + binding: Option<NameBinding<'a>>, res: Option<Res>, span: Span, ) { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 43846e65bca..593983f117d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -743,6 +743,14 @@ pub enum TraitSolver { NextCoherence, } +#[derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum DumpSolverProofTree { + Always, + OnError, + #[default] + Never, +} + pub enum Input { /// Load source code from a file. File(PathBuf), @@ -1019,6 +1027,7 @@ impl Default for Options { json_future_incompat: false, pretty: None, working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()), + color: ColorConfig::Auto, } } } @@ -2515,6 +2524,8 @@ pub fn build_session_options( let error_format = parse_error_format(handler, matches, color, json_rendered); + handler.abort_if_error_and_set_error_format(error_format); + let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { handler.early_error("`--diagnostic-width` must be an positive integer"); }); @@ -2799,6 +2810,7 @@ pub fn build_session_options( json_future_incompat, pretty, working_dir, + color, } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 05d3e71074a..7840a0ecf0b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -4,6 +4,7 @@ use crate::search_paths::SearchPath; use crate::utils::NativeLib; use crate::{lint, EarlyErrorHandler}; use rustc_data_structures::profiling::TimePassesFormat; +use rustc_errors::ColorConfig; use rustc_errors::{LanguageIdentifier, TerminalUrl}; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet}; use rustc_target::spec::{ @@ -212,6 +213,7 @@ top_level_options!( /// The (potentially remapped) working directory working_dir: RealFileName [TRACKED], + color: ColorConfig [UNTRACKED], } ); @@ -418,6 +420,7 @@ mod desc { "a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`"; pub const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; + pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`"; } mod parse { @@ -1237,6 +1240,19 @@ mod parse { }; true } + + pub(crate) fn parse_dump_solver_proof_tree( + slot: &mut DumpSolverProofTree, + v: Option<&str>, + ) -> bool { + match v { + None | Some("always") => *slot = DumpSolverProofTree::Always, + Some("never") => *slot = DumpSolverProofTree::Never, + Some("on-error") => *slot = DumpSolverProofTree::OnError, + _ => return false, + }; + true + } } options! { @@ -1462,8 +1478,11 @@ options! { "output statistics about monomorphization collection"), dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED], "the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"), - dump_solver_proof_tree: bool = (false, parse_bool, [UNTRACKED], - "dump a proof tree for every goal evaluated by the new trait solver"), + dump_solver_proof_tree: DumpSolverProofTree = (DumpSolverProofTree::Never, parse_dump_solver_proof_tree, [UNTRACKED], + "dump a proof tree for every goal evaluated by the new trait solver. If the flag is specified without any options after it + then it defaults to `always`. If the flag is not specified at all it defaults to `on-request`."), + dump_solver_proof_tree_use_cache: Option<bool> = (None, parse_opt_bool, [UNTRACKED], + "determines whether dumped proof trees use the global cache"), dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED], "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), dylib_lto: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 80360a3c73f..a6e6de5f785 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -8,6 +8,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle", optional = true } rustc_span = { path = "../rustc_span", optional = true } tracing = "0.1" +scoped-tls = "1.0" [features] default = [ diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index b00f0a1c153..fb03633b99b 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -19,3 +19,6 @@ pub mod stable_mir; // Make this module private for now since external users should not call these directly. mod rustc_smir; + +#[macro_use] +extern crate scoped_tls; diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 874e34bef60..85d5bb00c4e 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,7 +7,8 @@ //! //! For now, we are developing everything inside `rustc`, thus, we keep this module private. -use crate::stable_mir::{self, ty::TyKind, Context}; +use crate::stable_mir::ty::{FloatTy, IntTy, RigidTy, TyKind, UintTy}; +use crate::stable_mir::{self, Context}; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; @@ -69,11 +70,28 @@ pub struct Tables<'tcx> { impl<'tcx> Tables<'tcx> { fn rustc_ty_to_ty(&mut self, ty: Ty<'tcx>) -> TyKind { match ty.kind() { - ty::Bool => TyKind::Bool, - ty::Char => todo!(), - ty::Int(_) => todo!(), - ty::Uint(_) => todo!(), - ty::Float(_) => todo!(), + ty::Bool => TyKind::RigidTy(RigidTy::Bool), + ty::Char => TyKind::RigidTy(RigidTy::Char), + ty::Int(int_ty) => match int_ty { + ty::IntTy::Isize => TyKind::RigidTy(RigidTy::Int(IntTy::Isize)), + ty::IntTy::I8 => TyKind::RigidTy(RigidTy::Int(IntTy::I8)), + ty::IntTy::I16 => TyKind::RigidTy(RigidTy::Int(IntTy::I16)), + ty::IntTy::I32 => TyKind::RigidTy(RigidTy::Int(IntTy::I32)), + ty::IntTy::I64 => TyKind::RigidTy(RigidTy::Int(IntTy::I64)), + ty::IntTy::I128 => TyKind::RigidTy(RigidTy::Int(IntTy::I128)), + }, + ty::Uint(uint_ty) => match uint_ty { + ty::UintTy::Usize => TyKind::RigidTy(RigidTy::Uint(UintTy::Usize)), + ty::UintTy::U8 => TyKind::RigidTy(RigidTy::Uint(UintTy::U8)), + ty::UintTy::U16 => TyKind::RigidTy(RigidTy::Uint(UintTy::U16)), + ty::UintTy::U32 => TyKind::RigidTy(RigidTy::Uint(UintTy::U32)), + ty::UintTy::U64 => TyKind::RigidTy(RigidTy::Uint(UintTy::U64)), + ty::UintTy::U128 => TyKind::RigidTy(RigidTy::Uint(UintTy::U128)), + }, + ty::Float(float_ty) => match float_ty { + ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)), + ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)), + }, ty::Adt(_, _) => todo!(), ty::Foreign(_) => todo!(), ty::Str => todo!(), @@ -90,9 +108,9 @@ impl<'tcx> Tables<'tcx> { ty::GeneratorWitness(_) => todo!(), ty::GeneratorWitnessMIR(_, _) => todo!(), ty::Never => todo!(), - ty::Tuple(fields) => { - TyKind::Tuple(fields.iter().map(|ty| self.intern_ty(ty)).collect()) - } + ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( + fields.iter().map(|ty| self.intern_ty(ty)).collect(), + )), ty::Alias(_, _) => todo!(), ty::Param(_) => todo!(), ty::Bound(_, _) => todo!(), diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index 612777b9c75..5e599a77bcd 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -100,18 +100,17 @@ pub trait Context { fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>)); } -thread_local! { - /// A thread local variable that stores a pointer to the tables mapping between TyCtxt - /// datastructures and stable MIR datastructures. - static TLV: Cell<*mut ()> = const { Cell::new(std::ptr::null_mut()) }; -} +// A thread local variable that stores a pointer to the tables mapping between TyCtxt +// datastructures and stable MIR datastructures +scoped_thread_local! (static TLV: Cell<*mut ()>); pub fn run(mut context: impl Context, f: impl FnOnce()) { - assert!(TLV.get().is_null()); + assert!(!TLV.is_set()); fn g<'a>(mut context: &mut (dyn Context + 'a), f: impl FnOnce()) { - TLV.set(&mut context as *mut &mut _ as _); - f(); - TLV.replace(std::ptr::null_mut()); + let ptr: *mut () = &mut context as *mut &mut _ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); } g(&mut context, f); } @@ -119,9 +118,10 @@ pub fn run(mut context: impl Context, f: impl FnOnce()) { /// Loads the current context and calls a function with it. /// Do not nest these, as that will ICE. pub(crate) fn with<R>(f: impl FnOnce(&mut dyn Context) -> R) -> R { - let ptr = TLV.replace(std::ptr::null_mut()) as *mut &mut dyn Context; - assert!(!ptr.is_null()); - let ret = f(unsafe { *ptr }); - TLV.set(ptr as _); - ret + assert!(TLV.is_set()); + TLV.with(|tlv| { + let ptr = tlv.get(); + assert!(!ptr.is_null()); + f(unsafe { *(ptr as *mut &mut dyn Context) }) + }) } diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index f27801b0f6c..3181af46e9c 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -9,7 +9,43 @@ impl Ty { } } +#[derive(Clone, Debug)] pub enum TyKind { + RigidTy(RigidTy), +} + +#[derive(Clone, Debug)] +pub enum RigidTy { Bool, + Char, + Int(IntTy), + Uint(UintTy), + Float(FloatTy), Tuple(Vec<Ty>), } + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum IntTy { + Isize, + I8, + I16, + I32, + I64, + I128, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum UintTy { + Usize, + U8, + U16, + U32, + U64, + U128, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum FloatTy { + F32, + F64, +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c58d85b99f7..5c6d43e50ea 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -656,6 +656,7 @@ symbols! { dyn_trait, e, edition_panic, + effects, eh_catch_typeinfo, eh_personality, emit, @@ -758,7 +759,6 @@ symbols! { from_desugaring, from_fn, from_iter, - from_method, from_output, from_residual, from_size_align_unchecked, @@ -793,6 +793,7 @@ symbols! { hexagon_target_feature, hidden, homogeneous_aggregate, + host, html_favicon_url, html_logo_url, html_no_source, @@ -1284,6 +1285,7 @@ symbols! { rustc_evaluate_where_clauses, rustc_expected_cgu_reuse, rustc_has_incoherent_inherent_impls, + rustc_host, rustc_if_this_changed, rustc_inherit_overflow_checks, rustc_insignificant_dtor, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 254ede4e6a0..ec7032cd3bf 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -230,7 +230,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { self.write_str("[")?; self = self.print_type(ty)?; self.write_str("; ")?; - if let Some(size) = size.kind().try_to_bits(self.tcx().data_layout.pointer_size) { + if let Some(size) = size.try_to_bits(self.tcx().data_layout.pointer_size) { write!(self, "{size}")? } else if let ty::ConstKind::Param(param) = size.kind() { self = param.print(self)? diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 85825513ce9..3b46275ec41 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -112,7 +112,7 @@ fn encode_const<'tcx>( let _ = write!(s, "{value}"); } - if let Some(scalar_int) = c.kind().try_to_scalar_int() { + if let Some(scalar_int) = c.try_to_scalar_int() { let signed = c.ty().is_signed(); match scalar_int.size().bits() { 8 if signed => push_signed_value(&mut s, scalar_int.try_to_i8().unwrap(), 0), @@ -504,8 +504,7 @@ fn encode_ty<'tcx>( let _ = write!( s, "{}", - &len.kind() - .try_to_scalar() + &len.try_to_scalar() .unwrap() .to_u64() .unwrap_or_else(|_| panic!("failed to convert length to u64")) @@ -644,7 +643,7 @@ fn encode_ty<'tcx>( s.push_str("u3refI"); s.push_str(&encode_ty(tcx, *ty0, dict, options)); s.push('E'); - compress(dict, DictKey::Ty(tcx.mk_imm_ref(*region, *ty0), TyQ::None), &mut s); + compress(dict, DictKey::Ty(Ty::new_imm_ref(tcx, *region, *ty0), TyQ::None), &mut s); if ty.is_mutable_ptr() { s = format!("{}{}", "U3mut", &s); compress(dict, DictKey::Ty(ty, TyQ::Mut), &mut s); @@ -740,7 +739,7 @@ fn transform_substs<'tcx>( options: TransformTyOptions, ) -> SubstsRef<'tcx> { let substs = substs.iter().map(|subst| match subst.unpack() { - GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(), + GenericArgKind::Type(ty) if ty.is_c_void(tcx) => Ty::new_unit(tcx).into(), GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(), _ => subst, }); @@ -810,29 +809,28 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio _ if ty.is_unit() => {} ty::Tuple(tys) => { - ty = tcx.mk_tup_from_iter(tys.iter().map(|ty| transform_ty(tcx, ty, options))); + ty = Ty::new_tup_from_iter(tcx, tys.iter().map(|ty| transform_ty(tcx, ty, options))); } ty::Array(ty0, len) => { let len = len - .kind() .try_to_scalar() .unwrap() .to_u64() .unwrap_or_else(|_| panic!("failed to convert length to u64")); - ty = tcx.mk_array(transform_ty(tcx, *ty0, options), len); + ty = Ty::new_array(tcx, transform_ty(tcx, *ty0, options), len); } ty::Slice(ty0) => { - ty = tcx.mk_slice(transform_ty(tcx, *ty0, options)); + ty = Ty::new_slice(tcx, transform_ty(tcx, *ty0, options)); } ty::Adt(adt_def, substs) => { if ty.is_c_void(tcx) { - ty = tcx.mk_unit(); + ty = Ty::new_unit(tcx); } else if options.contains(TransformTyOptions::GENERALIZE_REPR_C) && adt_def.repr().c() { - ty = tcx.mk_adt(*adt_def, ty::List::empty()); + ty = Ty::new_adt(tcx, *adt_def, ty::List::empty()); } else if adt_def.repr().transparent() && adt_def.is_struct() { // Don't transform repr(transparent) types with an user-defined CFI encoding to // preserve the user-defined CFI encoding. @@ -863,37 +861,42 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } } else { // Transform repr(transparent) types without non-ZST field into () - ty = tcx.mk_unit(); + ty = Ty::new_unit(tcx); } } else { - ty = tcx.mk_adt(*adt_def, transform_substs(tcx, substs, options)); + ty = Ty::new_adt(tcx, *adt_def, transform_substs(tcx, substs, options)); } } ty::FnDef(def_id, substs) => { - ty = tcx.mk_fn_def(*def_id, transform_substs(tcx, substs, options)); + ty = Ty::new_fn_def(tcx, *def_id, transform_substs(tcx, substs, options)); } ty::Closure(def_id, substs) => { - ty = tcx.mk_closure(*def_id, transform_substs(tcx, substs, options)); + ty = Ty::new_closure(tcx, *def_id, transform_substs(tcx, substs, options)); } ty::Generator(def_id, substs, movability) => { - ty = tcx.mk_generator(*def_id, transform_substs(tcx, substs, options), *movability); + ty = Ty::new_generator( + tcx, + *def_id, + transform_substs(tcx, substs, options), + *movability, + ); } ty::Ref(region, ty0, ..) => { if options.contains(TransformTyOptions::GENERALIZE_POINTERS) { if ty.is_mutable_ptr() { - ty = tcx.mk_mut_ref(tcx.lifetimes.re_static, tcx.mk_unit()); + ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx)); } else { - ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_unit()); + ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx)); } } else { if ty.is_mutable_ptr() { - ty = tcx.mk_mut_ref(*region, transform_ty(tcx, *ty0, options)); + ty = Ty::new_mut_ref(tcx, *region, transform_ty(tcx, *ty0, options)); } else { - ty = tcx.mk_imm_ref(*region, transform_ty(tcx, *ty0, options)); + ty = Ty::new_imm_ref(tcx, *region, transform_ty(tcx, *ty0, options)); } } } @@ -901,22 +904,22 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio ty::RawPtr(tm) => { if options.contains(TransformTyOptions::GENERALIZE_POINTERS) { if ty.is_mutable_ptr() { - ty = tcx.mk_mut_ptr(tcx.mk_unit()); + ty = Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)); } else { - ty = tcx.mk_imm_ptr(tcx.mk_unit()); + ty = Ty::new_imm_ptr(tcx, Ty::new_unit(tcx)); } } else { if ty.is_mutable_ptr() { - ty = tcx.mk_mut_ptr(transform_ty(tcx, tm.ty, options)); + ty = Ty::new_mut_ptr(tcx, transform_ty(tcx, tm.ty, options)); } else { - ty = tcx.mk_imm_ptr(transform_ty(tcx, tm.ty, options)); + ty = Ty::new_imm_ptr(tcx, transform_ty(tcx, tm.ty, options)); } } } ty::FnPtr(fn_sig) => { if options.contains(TransformTyOptions::GENERALIZE_POINTERS) { - ty = tcx.mk_imm_ptr(tcx.mk_unit()); + ty = Ty::new_imm_ptr(tcx, Ty::new_unit(tcx)); } else { let parameters: Vec<Ty<'tcx>> = fn_sig .skip_binder() @@ -925,21 +928,25 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio .map(|ty| transform_ty(tcx, *ty, options)) .collect(); let output = transform_ty(tcx, fn_sig.skip_binder().output(), options); - ty = tcx.mk_fn_ptr(ty::Binder::bind_with_vars( - tcx.mk_fn_sig( - parameters, - output, - fn_sig.c_variadic(), - fn_sig.unsafety(), - fn_sig.abi(), + ty = Ty::new_fn_ptr( + tcx, + ty::Binder::bind_with_vars( + tcx.mk_fn_sig( + parameters, + output, + fn_sig.c_variadic(), + fn_sig.unsafety(), + fn_sig.abi(), + ), + fn_sig.bound_vars(), ), - fn_sig.bound_vars(), - )); + ); } } ty::Dynamic(predicates, _region, kind) => { - ty = tcx.mk_dynamic( + ty = Ty::new_dynamic( + tcx, transform_predicates(tcx, predicates, options), tcx.lifetimes.re_erased, *kind, @@ -1108,14 +1115,16 @@ pub fn typeid_for_instance<'tcx>( )]); // Is the concrete self mutable? let self_ty = if fn_abi.args[0].layout.ty.is_mutable_ptr() { - tcx.mk_mut_ref( + Ty::new_mut_ref( + tcx, tcx.lifetimes.re_erased, - tcx.mk_dynamic(existential_predicates, tcx.lifetimes.re_erased, ty::Dyn), + Ty::new_dynamic(tcx, existential_predicates, tcx.lifetimes.re_erased, ty::Dyn), ) } else { - tcx.mk_imm_ref( + Ty::new_imm_ref( + tcx, tcx.lifetimes.re_erased, - tcx.mk_dynamic(existential_predicates, tcx.lifetimes.re_erased, ty::Dyn), + Ty::new_dynamic(tcx, existential_predicates, tcx.lifetimes.re_erased, ty::Dyn), ) }; diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 5dc00e31786..5e5cc6e4e4a 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -535,7 +535,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { match predicate.as_ref().skip_binder() { ty::ExistentialPredicate::Trait(trait_ref) => { // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx.mk_fresh_ty(0); + let dummy_self = Ty::new_fresh(cx.tcx, 0); let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self); cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?; } @@ -651,7 +651,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { .builtin_deref(true) .expect("tried to dereference on non-ptr type") .ty; - let dereferenced_const = self.tcx.mk_const(ct.kind(), pointee_ty); + // FIXME(const_generics): add an assert that we only do this for valtrees. + let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty); self = dereferenced_const.print(self)?; } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 2e5bb3db886..2365dfaf1af 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1325,6 +1325,7 @@ supported_targets! { ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf), ("i686-unknown-netbsd", i686_unknown_netbsd), ("powerpc-unknown-netbsd", powerpc_unknown_netbsd), + ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd), ("sparc64-unknown-netbsd", sparc64_unknown_netbsd), ("x86_64-unknown-netbsd", x86_64_unknown_netbsd), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs new file mode 100644 index 00000000000..a89bd363a47 --- /dev/null +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs @@ -0,0 +1,19 @@ +use crate::spec::{CodeModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "riscv64-unknown-netbsd".into(), + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), + arch: "riscv64".into(), + options: TargetOptions { + code_model: Some(CodeModel::Medium), + cpu: "generic-rv64".into(), + features: "+m,+a,+f,+d,+c".into(), + llvm_abiname: "lp64d".into(), + max_atomic_width: Some(64), + mcount: "__mcount".into(), + ..super::netbsd_base::opts() + }, + } +} diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index ca7fcfd8ca1..422a6ee3442 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -1,6 +1,5 @@ use super::{EvalCtxt, SolverMode}; use rustc_infer::traits::query::NoSolution; -use rustc_middle::traits::solve::inspect::CandidateKind; use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; use rustc_middle::ty; @@ -110,12 +109,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { direction: ty::AliasRelationDirection, invert: Invert, ) -> QueryResult<'tcx> { - self.probe(|r| CandidateKind::Candidate { name: "normalizes-to".into(), result: *r }).enter( - |ecx| { - ecx.normalizes_to_inner(param_env, alias, other, direction, invert)?; - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }, - ) + self.probe_candidate("normalizes-to").enter(|ecx| { + ecx.normalizes_to_inner(param_env, alias, other, direction, invert)?; + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn normalizes_to_inner( @@ -156,20 +153,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { alias_rhs: ty::AliasTy<'tcx>, direction: ty::AliasRelationDirection, ) -> QueryResult<'tcx> { - self.probe(|r| CandidateKind::Candidate { name: "substs relate".into(), result: *r }).enter( - |ecx| { - match direction { - ty::AliasRelationDirection::Equate => { - ecx.eq(param_env, alias_lhs, alias_rhs)?; - } - ty::AliasRelationDirection::Subtype => { - ecx.sub(param_env, alias_lhs, alias_rhs)?; - } + self.probe_candidate("substs relate").enter(|ecx| { + match direction { + ty::AliasRelationDirection::Equate => { + ecx.eq(param_env, alias_lhs, alias_rhs)?; + } + ty::AliasRelationDirection::Subtype => { + ecx.sub(param_env, alias_lhs, alias_rhs)?; } + } - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }, - ) + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn assemble_bidirectional_normalizes_to_candidate( @@ -179,23 +174,22 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { rhs: ty::Term<'tcx>, direction: ty::AliasRelationDirection, ) -> QueryResult<'tcx> { - self.probe(|r| CandidateKind::Candidate { name: "bidir normalizes-to".into(), result: *r }) - .enter(|ecx| { - ecx.normalizes_to_inner( - param_env, - lhs.to_alias_ty(ecx.tcx()).unwrap(), - rhs, - direction, - Invert::No, - )?; - ecx.normalizes_to_inner( - param_env, - rhs.to_alias_ty(ecx.tcx()).unwrap(), - lhs, - direction, - Invert::Yes, - )?; - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) + self.probe_candidate("bidir normalizes-to").enter(|ecx| { + ecx.normalizes_to_inner( + param_env, + lhs.to_alias_ty(ecx.tcx()).unwrap(), + rhs, + direction, + Invert::No, + )?; + ecx.normalizes_to_inner( + param_env, + rhs.to_alias_ty(ecx.tcx()).unwrap(), + lhs, + direction, + Invert::Yes, + )?; + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 15e08166a8b..28138054ae5 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -331,11 +331,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates } - /// If the self type of a goal is an alias, computing the relevant candidates is difficult. + /// If the self type of a goal is an alias we first try to normalize the self type + /// and compute the candidates for the normalized self type in case that succeeds. /// - /// To deal with this, we first try to normalize the self type and add the candidates for the normalized - /// self type to the list of candidates in case that succeeds. We also have to consider candidates with the - /// projection as a self type as well + /// These candidates are used in addition to the ones with the alias as a self type. + /// We do this to simplify both builtin candidates and for better performance. + /// + /// We generate the builtin candidates on the fly by looking at the self type, e.g. + /// add `FnPtr` candidates if the self type is a function pointer. Handling builtin + /// candidates while the self type is still an alias seems difficult. This is similar + /// to `try_structurally_resolve_type` during hir typeck (FIXME once implemented). + /// + /// Looking at all impls for some trait goal is prohibitively expensive. We therefore + /// only look at implementations with a matching self type. Because of this function, + /// we can avoid looking at all existing impls if the self type is an alias. #[instrument(level = "debug", skip_all)] fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'tcx>>( &mut self, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 9eac53c3983..3bb8cad15ab 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -28,7 +28,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( | ty::Char => Ok(vec![]), // Treat `str` like it's defined as `struct str([u8]);` - ty::Str => Ok(vec![tcx.mk_slice(tcx.types.u8)]), + ty::Str => Ok(vec![Ty::new_slice(tcx, tcx.types.u8)]), ty::Dynamic(..) | ty::Param(..) @@ -233,7 +233,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( { Ok(Some( sig.subst(tcx, substs) - .map_bound(|sig| (tcx.mk_tup(sig.inputs()), sig.output())), + .map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output())), )) } else { Err(NoSolution) @@ -242,7 +242,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnPtr(sig) => { if sig.is_fn_trait_compatible() { - Ok(Some(sig.map_bound(|sig| (tcx.mk_tup(sig.inputs()), sig.output())))) + Ok(Some(sig.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output())))) } else { Err(NoSolution) } diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 05248cb9d17..255620489ff 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -283,7 +283,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { // any equated inference vars correctly! let root_vid = self.infcx.root_var(vid); if root_vid != vid { - t = self.infcx.tcx.mk_ty_var(root_vid); + t = Ty::new_var(self.infcx.tcx, root_vid); vid = root_vid; } @@ -366,7 +366,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { }), ); let bt = ty::BoundTy { var, kind: BoundTyKind::Anon }; - self.interner().mk_bound(self.binder_index, bt) + Ty::new_bound(self.infcx.tcx, self.binder_index, bt) } fn fold_const(&mut self, mut c: ty::Const<'tcx>) -> ty::Const<'tcx> { @@ -377,7 +377,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { // any equated inference vars correctly! let root_vid = self.infcx.root_const_var(vid); if root_vid != vid { - c = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), c.ty()); + c = ty::Const::new_var(self.infcx.tcx, root_vid, c.ty()); vid = root_vid; } @@ -426,6 +426,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { var }), ); - self.interner().mk_const(ty::ConstKind::Bound(self.binder_index, var), c.ty()) + ty::Const::new_bound(self.infcx.tcx, self.binder_index, var, c.ty()) } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 6b7be73b631..74dfbdddbab 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -9,7 +9,7 @@ use rustc_infer::infer::{ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; -use rustc_middle::traits::solve::inspect::{self, CandidateKind}; +use rustc_middle::traits::solve::inspect; use rustc_middle::traits::solve::{ CanonicalInput, CanonicalResponse, Certainty, IsNormalizesToHack, MaybeCause, PredefinedOpaques, PredefinedOpaquesData, QueryResult, @@ -19,7 +19,9 @@ use rustc_middle::ty::{ self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use rustc_session::config::DumpSolverProofTree; use rustc_span::DUMMY_SP; +use std::io::Write; use std::ops::ControlFlow; use crate::traits::specialization_graph; @@ -113,9 +115,23 @@ impl NestedGoals<'_> { #[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] pub enum GenerateProofTree { + Yes(UseGlobalCache), + No, +} + +#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] +pub enum UseGlobalCache { Yes, No, } +impl UseGlobalCache { + pub fn from_bool(use_cache: bool) -> Self { + match use_cache { + true => UseGlobalCache::Yes, + false => UseGlobalCache::No, + } + } +} pub trait InferCtxtEvalExt<'tcx> { /// Evaluates a goal from **outside** of the trait solver. @@ -177,17 +193,17 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { var_values: CanonicalVarValues::dummy(), nested_goals: NestedGoals::new(), tainted: Ok(()), - inspect: (infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree - || matches!(generate_proof_tree, GenerateProofTree::Yes)) - .then(ProofTreeBuilder::new_root) - .unwrap_or_else(ProofTreeBuilder::new_noop), + inspect: ProofTreeBuilder::new_maybe_root(infcx.tcx, generate_proof_tree), }; let result = f(&mut ecx); let tree = ecx.inspect.finalize(); - if let Some(tree) = &tree { - // module to allow more granular RUSTC_LOG filtering to just proof tree output - super::inspect::dump::print_tree(tree); + if let (Some(tree), DumpSolverProofTree::Always) = + (&tree, infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree) + { + let mut lock = std::io::stdout().lock(); + let _ = lock.write_fmt(format_args!("{tree:?}")); + let _ = lock.flush(); } assert!( @@ -425,12 +441,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { self.compute_well_formed_goal(Goal { param_env, predicate: arg }) } - ty::PredicateKind::Ambiguous => { - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } - // FIXME: implement this predicate :) - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(_)) => { - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { + self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct }) } ty::PredicateKind::ConstEquate(_, _) => { bug!("ConstEquate should not be emitted when `-Ztrait-solver=next` is active") @@ -440,6 +452,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { param_env, predicate: (lhs, rhs, direction), }), + ty::PredicateKind::Ambiguous => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } } } else { let kind = self.infcx.instantiate_binder_with_placeholders(kind); @@ -822,7 +837,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - pub(super) fn can_define_opaque_ty(&mut self, def_id: LocalDefId) -> bool { + pub(super) fn can_define_opaque_ty(&self, def_id: LocalDefId) -> bool { self.infcx.opaque_type_origin(def_id).is_some() } @@ -880,25 +895,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if candidate_key.def_id != key.def_id { continue; } - values.extend( - self.probe(|r| CandidateKind::Candidate { - name: "opaque type storage".into(), - result: *r, - }) - .enter(|ecx| { - for (a, b) in std::iter::zip(candidate_key.substs, key.substs) { - ecx.eq(param_env, a, b)?; - } - ecx.eq(param_env, candidate_ty, ty)?; - ecx.add_item_bounds_for_hidden_type( - candidate_key.def_id.to_def_id(), - candidate_key.substs, - param_env, - candidate_ty, - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }), - ); + values.extend(self.probe_candidate("opaque type storage").enter(|ecx| { + for (a, b) in std::iter::zip(candidate_key.substs, key.substs) { + ecx.eq(param_env, a, b)?; + } + ecx.eq(param_env, candidate_ty, ty)?; + ecx.add_item_bounds_for_hidden_type( + candidate_key.def_id.to_def_id(), + candidate_key.substs, + param_env, + candidate_ty, + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + })); } values } @@ -915,7 +924,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { use rustc_middle::mir::interpret::ErrorHandled; match self.infcx.try_const_eval_resolve(param_env, unevaluated, ty, None) { Ok(ct) => Some(ct), - Err(ErrorHandled::Reported(e)) => Some(self.tcx().const_error(ty, e.into())), + Err(ErrorHandled::Reported(e)) => Some(ty::Const::new_error(self.tcx(), e.into(), ty)), Err(ErrorHandled::TooGeneric) => None, } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs index 5d912fc039d..4477ea7d501 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs @@ -1,5 +1,5 @@ use super::EvalCtxt; -use rustc_middle::traits::solve::inspect; +use rustc_middle::traits::solve::{inspect, QueryResult}; use std::marker::PhantomData; pub(in crate::solve) struct ProbeCtxt<'me, 'a, 'tcx, F, T> { @@ -44,4 +44,24 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { { ProbeCtxt { ecx: self, probe_kind, _result: PhantomData } } + + pub(in crate::solve) fn probe_candidate( + &mut self, + name: &'static str, + ) -> ProbeCtxt< + '_, + 'a, + 'tcx, + impl FnOnce(&QueryResult<'tcx>) -> inspect::CandidateKind<'tcx>, + QueryResult<'tcx>, + > { + ProbeCtxt { + ecx: self, + probe_kind: move |result: &QueryResult<'tcx>| inspect::CandidateKind::Candidate { + name: name.to_string(), + result: *result, + }, + _result: PhantomData, + } + } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 466a03e2163..bf6cbef8c3b 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::traits::util::supertraits; use rustc_infer::traits::{ - Obligation, PredicateObligation, Selection, SelectionResult, TraitObligation, + Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult, }; use rustc_middle::traits::solve::{CanonicalInput, Certainty, Goal}; use rustc_middle::traits::{ @@ -23,14 +23,14 @@ use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, V pub trait InferCtxtSelectExt<'tcx> { fn select_in_new_trait_solver( &self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>>; } impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { fn select_in_new_trait_solver( &self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { assert!(self.next_trait_solver()); @@ -52,7 +52,11 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { let mut i = 0; while i < candidates.len() { let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { - candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j]) + candidate_should_be_dropped_in_favor_of( + ecx.tcx(), + &candidates[i], + &candidates[j], + ) }); if should_drop_i { candidates.swap_remove(i); @@ -160,12 +164,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } fn candidate_should_be_dropped_in_favor_of<'tcx>( + tcx: TyCtxt<'tcx>, victim: &Candidate<'tcx>, other: &Candidate<'tcx>, ) -> bool { match (victim.source, other.source) { - (CandidateSource::ParamEnv(i), CandidateSource::ParamEnv(j)) => i >= j, + (CandidateSource::ParamEnv(victim_idx), CandidateSource::ParamEnv(other_idx)) => { + victim_idx >= other_idx + } (_, CandidateSource::ParamEnv(_)) => true, + + ( + CandidateSource::BuiltinImpl(BuiltinImplSource::Object), + CandidateSource::BuiltinImpl(BuiltinImplSource::Object), + ) => false, + (_, CandidateSource::BuiltinImpl(BuiltinImplSource::Object)) => true, + + (CandidateSource::Impl(victim_def_id), CandidateSource::Impl(other_def_id)) => { + tcx.specializes((other_def_id, victim_def_id)) + && other.result.value.certainty == Certainty::Yes + } + _ => false, } } @@ -202,15 +221,16 @@ fn rematch_object<'tcx>( mut nested: Vec<PredicateObligation<'tcx>>, ) -> SelectionResult<'tcx, Selection<'tcx>> { let self_ty = goal.predicate.self_ty(); - let source_trait_ref = if let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind() { - data.principal().unwrap().with_self_ty(infcx.tcx, self_ty) - } else { + let ty::Dynamic(data, _, source_kind) = *self_ty.kind() + else { bug!() }; + let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, self_ty); let (is_upcasting, target_trait_ref_unnormalized) = if Some(goal.predicate.def_id()) == infcx.tcx.lang_items().unsize_trait() { + assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*"); if let ty::Dynamic(data, _, ty::Dyn) = goal.predicate.trait_ref.substs.type_at(1).kind() { (true, data.principal().unwrap().with_self_ty(infcx.tcx, self_ty)) } else { @@ -277,7 +297,8 @@ fn rematch_object<'tcx>( bug!(); }; - // If we're upcasting, get the offset of the vtable pointer, which is + // If we're upcasting, get the offset of the vtable pointer, otherwise get + // the base of the vtable. Ok(Some(if is_upcasting { ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested }) } else { diff --git a/compiler/rustc_trait_selection/src/solve/inspect.rs b/compiler/rustc_trait_selection/src/solve/inspect.rs index 6d7804a8fad..2d6717fdad9 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect.rs @@ -3,9 +3,11 @@ use rustc_middle::traits::solve::inspect::{self, CacheHit, CandidateKind}; use rustc_middle::traits::solve::{ CanonicalInput, Certainty, Goal, IsNormalizesToHack, QueryInput, QueryResult, }; -use rustc_middle::ty; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_session::config::DumpSolverProofTree; -pub mod dump; +use super::eval_ctxt::UseGlobalCache; +use super::GenerateProofTree; #[derive(Eq, PartialEq, Debug, Hash, HashStable)] pub struct WipGoalEvaluation<'tcx> { @@ -144,20 +146,42 @@ impl<'tcx> From<WipGoalCandidate<'tcx>> for DebugSolver<'tcx> { } pub struct ProofTreeBuilder<'tcx> { - state: Option<Box<DebugSolver<'tcx>>>, + state: Option<Box<BuilderData<'tcx>>>, +} + +struct BuilderData<'tcx> { + tree: DebugSolver<'tcx>, + use_global_cache: UseGlobalCache, } impl<'tcx> ProofTreeBuilder<'tcx> { - fn new(state: impl Into<DebugSolver<'tcx>>) -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder { state: Some(Box::new(state.into())) } + fn new( + state: impl Into<DebugSolver<'tcx>>, + use_global_cache: UseGlobalCache, + ) -> ProofTreeBuilder<'tcx> { + ProofTreeBuilder { + state: Some(Box::new(BuilderData { tree: state.into(), use_global_cache })), + } + } + + fn nested(&self, state: impl Into<DebugSolver<'tcx>>) -> Self { + match &self.state { + Some(prev_state) => Self { + state: Some(Box::new(BuilderData { + tree: state.into(), + use_global_cache: prev_state.use_global_cache, + })), + }, + None => Self { state: None }, + } } fn as_mut(&mut self) -> Option<&mut DebugSolver<'tcx>> { - self.state.as_mut().map(|boxed| &mut **boxed) + self.state.as_mut().map(|boxed| &mut boxed.tree) } pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> { - match *(self.state?) { + match self.state?.tree { DebugSolver::GoalEvaluation(wip_goal_evaluation) => { Some(wip_goal_evaluation.finalize()) } @@ -165,8 +189,46 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn new_root() -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder::new(DebugSolver::Root) + pub fn use_global_cache(&self) -> bool { + self.state + .as_ref() + .map(|state| matches!(state.use_global_cache, UseGlobalCache::Yes)) + .unwrap_or(true) + } + + pub fn new_maybe_root( + tcx: TyCtxt<'tcx>, + generate_proof_tree: GenerateProofTree, + ) -> ProofTreeBuilder<'tcx> { + let generate_proof_tree = match ( + tcx.sess.opts.unstable_opts.dump_solver_proof_tree, + tcx.sess.opts.unstable_opts.dump_solver_proof_tree_use_cache, + generate_proof_tree, + ) { + (_, Some(use_cache), GenerateProofTree::Yes(_)) => { + GenerateProofTree::Yes(UseGlobalCache::from_bool(use_cache)) + } + + (DumpSolverProofTree::Always, use_cache, GenerateProofTree::No) => { + let use_cache = use_cache.unwrap_or(true); + GenerateProofTree::Yes(UseGlobalCache::from_bool(use_cache)) + } + + (_, None, GenerateProofTree::Yes(_)) => generate_proof_tree, + (DumpSolverProofTree::Never, _, _) => generate_proof_tree, + (DumpSolverProofTree::OnError, _, _) => generate_proof_tree, + }; + + match generate_proof_tree { + GenerateProofTree::No => ProofTreeBuilder::new_noop(), + GenerateProofTree::Yes(global_cache_disabled) => { + ProofTreeBuilder::new_root(global_cache_disabled) + } + } + } + + pub fn new_root(use_global_cache: UseGlobalCache) -> ProofTreeBuilder<'tcx> { + ProofTreeBuilder::new(DebugSolver::Root, use_global_cache) } pub fn new_noop() -> ProofTreeBuilder<'tcx> { @@ -186,7 +248,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { return ProofTreeBuilder { state: None }; } - ProofTreeBuilder::new(WipGoalEvaluation { + self.nested(WipGoalEvaluation { uncanonicalized_goal: goal, canonicalized_goal: None, evaluation_steps: vec![], @@ -232,7 +294,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, *goal_evaluation.state.unwrap()) { + match (this, goal_evaluation.state.unwrap().tree) { ( DebugSolver::AddedGoalsEvaluation(WipAddedGoalsEvaluation { evaluations, .. @@ -253,7 +315,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { return ProofTreeBuilder { state: None }; } - ProofTreeBuilder::new(WipGoalEvaluationStep { + self.nested(WipGoalEvaluationStep { instantiated_goal, nested_goal_evaluations: vec![], candidates: vec![], @@ -262,7 +324,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } pub fn goal_evaluation_step(&mut self, goal_eval_step: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, *goal_eval_step.state.unwrap()) { + match (this, goal_eval_step.state.unwrap().tree) { (DebugSolver::GoalEvaluation(goal_eval), DebugSolver::GoalEvaluationStep(step)) => { goal_eval.evaluation_steps.push(step); } @@ -276,7 +338,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { return ProofTreeBuilder { state: None }; } - ProofTreeBuilder::new(WipGoalCandidate { + self.nested(WipGoalCandidate { nested_goal_evaluations: vec![], candidates: vec![], kind: None, @@ -296,7 +358,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn goal_candidate(&mut self, candidate: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, *candidate.state.unwrap()) { + match (this, candidate.state.unwrap().tree) { ( DebugSolver::GoalCandidate(WipGoalCandidate { candidates, .. }) | DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { candidates, .. }), @@ -312,7 +374,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { return ProofTreeBuilder { state: None }; } - ProofTreeBuilder::new(WipAddedGoalsEvaluation { evaluations: vec![], result: None }) + self.nested(WipAddedGoalsEvaluation { evaluations: vec![], result: None }) } pub fn evaluate_added_goals_loop_start(&mut self) { @@ -339,7 +401,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn added_goals_evaluation(&mut self, goals_evaluation: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, *goals_evaluation.state.unwrap()) { + match (this, goals_evaluation.state.unwrap().tree) { ( DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { nested_goal_evaluations, diff --git a/compiler/rustc_trait_selection/src/solve/inspect/dump.rs b/compiler/rustc_trait_selection/src/solve/inspect/dump.rs deleted file mode 100644 index b755ee86215..00000000000 --- a/compiler/rustc_trait_selection/src/solve/inspect/dump.rs +++ /dev/null @@ -1,5 +0,0 @@ -use rustc_middle::traits::solve::inspect::GoalEvaluation; - -pub fn print_tree(tree: &GoalEvaluation<'_>) { - debug!(?tree); -} diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index f3f78cdf09d..77809d8d2ba 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -33,7 +33,9 @@ mod search_graph; mod trait_goals; mod weak_types; -pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt, InferCtxtSelectExt}; +pub use eval_ctxt::{ + EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, UseGlobalCache, +}; pub use fulfill::FulfillmentCtxt; pub(crate) use normalize::deeply_normalize; @@ -159,6 +161,43 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] + fn compute_const_evaluatable_goal( + &mut self, + Goal { param_env, predicate: ct }: Goal<'tcx, ty::Const<'tcx>>, + ) -> QueryResult<'tcx> { + match ct.kind() { + ty::ConstKind::Unevaluated(uv) => { + // We never return `NoSolution` here as `try_const_eval_resolve` emits an + // error itself when failing to evaluate, so emitting an additional fulfillment + // error in that case is unnecessary noise. This may change in the future once + // evaluation failures are allowed to impact selection, e.g. generic const + // expressions in impl headers or `where`-clauses. + + // FIXME(generic_const_exprs): Implement handling for generic + // const expressions here. + if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv, ct.ty()) { + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } else { + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + } + ty::ConstKind::Infer(_) => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + // We can freely ICE here as: + // - `Param` gets replaced with a placeholder during canonicalization + // - `Bound` cannot exist as we don't have a binder around the self Type + // - `Expr` is part of `feature(generic_const_exprs)` and is not implemented yet + ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Expr(_) => { + bug!("unexpect const kind: {:?}", ct) + } + } + } + #[instrument(level = "debug", skip(self), ret)] fn compute_const_arg_has_type_goal( &mut self, diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index d2eed10950f..c388850d831 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -96,7 +96,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { let recursion_limit = tcx.recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.at.infcx.err_ctxt().report_overflow_error( - &tcx.mk_const(uv, ty), + &ty::Const::new_unevaluated(tcx, uv, ty), self.at.cause.span, true, |_| {}, @@ -131,7 +131,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { let ct = infcx.resolve_vars_if_possible(new_infer_ct); ct.try_fold_with(self)? } else { - tcx.mk_const(uv, ty).try_super_fold_with(self)? + ty::Const::new_unevaluated(tcx, uv, ty).try_super_fold_with(self)? }; self.depth -= 1; @@ -159,6 +159,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> { fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { let reveal = self.at.param_env.reveal(); let infcx = self.at.infcx; + debug_assert_eq!(ty, infcx.shallow_resolve(ty)); if !needs_normalization(&ty, reveal) { return Ok(ty); } @@ -166,9 +167,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> { // We don't normalize opaque types unless we have // `Reveal::All`, even if we're in the defining scope. let data = match *ty.kind() { - ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::UserFacing => { - alias_ty - } + ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::All => alias_ty, _ => return ty.try_super_fold_with(self), }; @@ -192,6 +191,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> { fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> { let reveal = self.at.param_env.reveal(); let infcx = self.at.infcx; + debug_assert_eq!(ct, infcx.shallow_resolve(ct)); if !needs_normalization(&ct, reveal) { return Ok(ct); } diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index cbea8009f02..e53b784a756 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -112,23 +112,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ) -> QueryResult<'tcx> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.projection_def_id() == goal.predicate.def_id() { - ecx.probe(|r| CandidateKind::Candidate { name: "assumption".into(), result: *r }) - .enter(|ecx| { - let assumption_projection_pred = - ecx.instantiate_binder_with_infer(projection_pred); - ecx.eq( - goal.param_env, - goal.predicate.projection_ty, - assumption_projection_pred.projection_ty, - )?; - ecx.eq( - goal.param_env, - goal.predicate.term, - assumption_projection_pred.term, - ) + ecx.probe_candidate("assumption").enter(|ecx| { + let assumption_projection_pred = + ecx.instantiate_binder_with_infer(projection_pred); + ecx.eq( + goal.param_env, + goal.predicate.projection_ty, + assumption_projection_pred.projection_ty, + )?; + ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term) .expect("expected goal term to be fully unconstrained"); - then(ecx) - }) + then(ecx) + }) } else { Err(NoSolution) } @@ -186,14 +181,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { "missing value for assoc item in impl", ); let error_term = match assoc_def.item.kind { - ty::AssocKind::Const => tcx - .const_error( - tcx.type_of(goal.predicate.def_id()) - .subst(tcx, goal.predicate.projection_ty.substs), - guar, + ty::AssocKind::Const => ty::Const::new_error(tcx, + guar, + tcx.type_of(goal.predicate.def_id()) + .subst(tcx, goal.predicate.projection_ty.substs), ) .into(), - ty::AssocKind::Type => tcx.ty_error(guar).into(), + ty::AssocKind::Type => Ty::new_error(tcx,guar).into(), ty::AssocKind::Fn => unreachable!(), }; ecx.eq(goal.param_env, goal.predicate.term, error_term) @@ -329,69 +323,53 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let tcx = ecx.tcx(); - ecx.probe(|r| CandidateKind::Candidate { name: "builtin pointee".into(), result: *r }) - .enter(|ecx| { - let metadata_ty = match goal.predicate.self_ty().kind() { - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Array(..) - | ty::RawPtr(..) - | ty::Ref(..) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::Closure(..) - | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) - | ty::Generator(..) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) - | ty::Never - | ty::Foreign(..) => tcx.types.unit, - - ty::Error(e) => tcx.ty_error(*e), - - ty::Str | ty::Slice(_) => tcx.types.usize, - - ty::Dynamic(_, _, _) => { - let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); - tcx.type_of(dyn_metadata) - .subst(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())]) - } - - ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { - // FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints. - let sized_predicate = ty::TraitRef::from_lang_item( - tcx, - LangItem::Sized, - DUMMY_SP, - [ty::GenericArg::from(goal.predicate.self_ty())], - ); - ecx.add_goal(goal.with(tcx, sized_predicate)); - tcx.types.unit - } + ecx.probe_candidate("builtin pointee").enter(|ecx| { + let metadata_ty = match goal.predicate.self_ty().kind() { + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Array(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Closure(..) + | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::GeneratorWitnessMIR(..) + | ty::Never + | ty::Foreign(..) => tcx.types.unit, + + ty::Error(e) => Ty::new_error(tcx, *e), + + ty::Str | ty::Slice(_) => tcx.types.usize, + + ty::Dynamic(_, _, _) => { + let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); + tcx.type_of(dyn_metadata) + .subst(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())]) + } - ty::Adt(def, substs) if def.is_struct() => { - match def.non_enum_variant().fields.raw.last() { - None => tcx.types.unit, - Some(field_def) => { - let self_ty = field_def.ty(tcx, substs); - ecx.add_goal(goal.with( - tcx, - ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)), - )); - return ecx.evaluate_added_goals_and_make_canonical_response( - Certainty::Yes, - ); - } - } - } - ty::Adt(_, _) => tcx.types.unit, + ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { + // FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints. + let sized_predicate = ty::TraitRef::from_lang_item( + tcx, + LangItem::Sized, + DUMMY_SP, + [ty::GenericArg::from(goal.predicate.self_ty())], + ); + ecx.add_goal(goal.with(tcx, sized_predicate)); + tcx.types.unit + } - ty::Tuple(elements) => match elements.last() { + ty::Adt(def, substs) if def.is_struct() => { + match def.non_enum_variant().tail_opt() { None => tcx.types.unit, - Some(&self_ty) => { + Some(field_def) => { + let self_ty = field_def.ty(tcx, substs); ecx.add_goal(goal.with( tcx, ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)), @@ -399,21 +377,35 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { return ecx .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); } - }, - - ty::Infer( - ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_), - ) - | ty::Bound(..) => bug!( - "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`", - goal.predicate.self_ty() - ), - }; + } + } + ty::Adt(_, _) => tcx.types.unit, - ecx.eq(goal.param_env, goal.predicate.term, metadata_ty.into()) - .expect("expected goal term to be fully unconstrained"); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) + ty::Tuple(elements) => match elements.last() { + None => tcx.types.unit, + Some(&self_ty) => { + ecx.add_goal(goal.with( + tcx, + ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)), + )); + return ecx + .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + } + }, + + ty::Infer( + ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_), + ) + | ty::Bound(..) => bug!( + "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`", + goal.predicate.self_ty() + ), + }; + + ecx.eq(goal.param_env, goal.predicate.term, metadata_ty.into()) + .expect("expected goal term to be fully unconstrained"); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_builtin_future_candidate( @@ -548,11 +540,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ), }; - ecx.probe(|r| CandidateKind::Candidate { - name: "builtin discriminant kind".into(), - result: *r, - }) - .enter(|ecx| { + ecx.probe_candidate("builtin discriminant kind").enter(|ecx| { ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into()) .expect("expected goal term to be fully unconstrained"); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index d167ee46b39..f00456e26df 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -213,7 +213,7 @@ impl<'tcx> SearchGraph<'tcx> { inspect: &mut ProofTreeBuilder<'tcx>, mut loop_body: impl FnMut(&mut Self, &mut ProofTreeBuilder<'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx> { - if self.should_use_global_cache() { + if self.should_use_global_cache() && inspect.use_global_cache() { if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_input, tcx) { debug!(?canonical_input, ?result, "cache hit"); inspect.cache_hit(CacheHit::Global); diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 18fec6d9c89..ef5f25b1f7f 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -6,8 +6,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::{LangItem, Movability}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::supertraits; -use rustc_middle::traits::solve::inspect::CandidateKind; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult}; +use rustc_middle::traits::Reveal; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; @@ -62,7 +62,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }, }; - ecx.probe(|r| CandidateKind::Candidate { name: "impl".into(), result: *r }).enter(|ecx| { + ecx.probe_candidate("impl").enter(|ecx| { let impl_substs = ecx.fresh_substs_for_item(impl_def_id); let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs); @@ -90,16 +90,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { && trait_clause.polarity() == goal.predicate.polarity { // FIXME: Constness - ecx.probe(|r| CandidateKind::Candidate { name: "assumption".into(), result: *r }) - .enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); - ecx.eq( - goal.param_env, - goal.predicate.trait_ref, - assumption_trait_pred.trait_ref, - )?; - then(ecx) - }) + ecx.probe_candidate("assumption").enter(|ecx| { + let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); + ecx.eq( + goal.param_env, + goal.predicate.trait_ref, + assumption_trait_pred.trait_ref, + )?; + then(ecx) + }) } else { Err(NoSolution) } @@ -120,6 +119,32 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return result; } + // Don't call `type_of` on a local TAIT that's in the defining scope, + // since that may require calling `typeck` on the same item we're + // currently type checking, which will result in a fatal cycle that + // ideally we want to avoid, since we can make progress on this goal + // via an alias bound or a locally-inferred hidden type instead. + // + // Also, don't call `type_of` on a TAIT in `Reveal::All` mode, since + // we already normalize the self type in + // `assemble_candidates_after_normalizing_self_ty`, and we'd + // just be registering an identical candidate here. + // + // Returning `Err(NoSolution)` here is ok in `SolverMode::Coherence` + // since we'll always be registering an ambiguous candidate in + // `assemble_candidates_after_normalizing_self_ty` due to normalizing + // the TAIT. + if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { + if matches!(goal.param_env.reveal(), Reveal::All) + || opaque_ty + .def_id + .as_local() + .is_some_and(|def_id| ecx.can_define_opaque_ty(def_id)) + { + return Err(NoSolution); + } + } + ecx.probe_and_evaluate_goal_for_constituent_tys( goal, structural_traits::instantiate_constituent_tys_for_auto_trait, @@ -136,15 +161,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let tcx = ecx.tcx(); - ecx.probe(|r| CandidateKind::Candidate { name: "trait alias".into(), result: *r }).enter( - |ecx| { - let nested_obligations = tcx - .predicates_of(goal.predicate.def_id()) - .instantiate(tcx, goal.predicate.trait_ref.substs); - ecx.add_goals(nested_obligations.predicates.into_iter().map(|p| goal.with(tcx, p))); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }, - ) + ecx.probe_candidate("trait alias").enter(|ecx| { + let nested_obligations = tcx + .predicates_of(goal.predicate.def_id()) + .instantiate(tcx, goal.predicate.trait_ref.substs); + ecx.add_goals(nested_obligations.predicates.into_iter().map(|p| goal.with(tcx, p))); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_builtin_sized_candidate( @@ -350,115 +373,104 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { if b_ty.is_ty_var() { return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); } - ecx.probe(|r| CandidateKind::Candidate { name: "builtin unsize".into(), result: *r }).enter( - |ecx| { - match (a_ty.kind(), b_ty.kind()) { - // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b` - (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => { - // Dyn upcasting is handled separately, since due to upcasting, - // when there are two supertraits that differ by substs, we - // may return more than one query response. - Err(NoSolution) + ecx.probe_candidate("builtin unsize").enter(|ecx| { + match (a_ty.kind(), b_ty.kind()) { + // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b` + (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => { + // Dyn upcasting is handled separately, since due to upcasting, + // when there are two supertraits that differ by substs, we + // may return more than one query response. + Err(NoSolution) + } + // `T` -> `dyn Trait` unsizing + (_, &ty::Dynamic(data, region, ty::Dyn)) => { + // Can only unsize to an object-safe type + if data + .principal_def_id() + .is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) + { + return Err(NoSolution); } - // `T` -> `dyn Trait` unsizing - (_, &ty::Dynamic(data, region, ty::Dyn)) => { - // Can only unsize to an object-safe type - if data - .principal_def_id() - .is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) - { - return Err(NoSolution); - } - - let Some(sized_def_id) = tcx.lang_items().sized_trait() else { + + let Some(sized_def_id) = tcx.lang_items().sized_trait() else { return Err(NoSolution); }; - // Check that the type implements all of the predicates of the def-id. - // (i.e. the principal, all of the associated types match, and any auto traits) - ecx.add_goals( - data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), - ); - // The type must be Sized to be unsized. - ecx.add_goal(goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty]))); - // The type must outlive the lifetime of the `dyn` we're unsizing into. - ecx.add_goal( - goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region))), - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } - // `[T; n]` -> `[T]` unsizing - (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { - // We just require that the element type stays the same - ecx.eq(goal.param_env, a_elem_ty, b_elem_ty)?; - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } - // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>` - (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) - if a_def.is_struct() && a_def.did() == b_def.did() => - { - let unsizing_params = tcx.unsizing_params_for_adt(a_def.did()); - // We must be unsizing some type parameters. This also implies - // that the struct has a tail field. - if unsizing_params.is_empty() { - return Err(NoSolution); - } - - let tail_field = a_def - .non_enum_variant() - .fields - .raw - .last() - .expect("expected unsized ADT to have a tail field"); - let tail_field_ty = tcx.type_of(tail_field.did); - - let a_tail_ty = tail_field_ty.subst(tcx, a_substs); - let b_tail_ty = tail_field_ty.subst(tcx, b_substs); - - // Substitute just the unsizing params from B into A. The type after - // this substitution must be equal to B. This is so we don't unsize - // unrelated type parameters. - let new_a_substs = - tcx.mk_substs_from_iter(a_substs.iter().enumerate().map(|(i, a)| { - if unsizing_params.contains(i as u32) { b_substs[i] } else { a } - })); - let unsized_a_ty = tcx.mk_adt(a_def, new_a_substs); - - // Finally, we require that `TailA: Unsize<TailB>` for the tail field - // types. - ecx.eq(goal.param_env, unsized_a_ty, b_ty)?; - ecx.add_goal(goal.with( - tcx, - ty::TraitRef::new(tcx, goal.predicate.def_id(), [a_tail_ty, b_tail_ty]), - )); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } - // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>` - (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) - if a_tys.len() == b_tys.len() && !a_tys.is_empty() => - { - let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); - let b_last_ty = b_tys.last().unwrap(); - - // Substitute just the tail field of B., and require that they're equal. - let unsized_a_ty = - tcx.mk_tup_from_iter(a_rest_tys.iter().chain([b_last_ty]).copied()); - ecx.eq(goal.param_env, unsized_a_ty, b_ty)?; - - // Similar to ADTs, require that the rest of the fields are equal. - ecx.add_goal(goal.with( - tcx, - ty::TraitRef::new( - tcx, - goal.predicate.def_id(), - [*a_last_ty, *b_last_ty], - ), - )); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + // Check that the type implements all of the predicates of the def-id. + // (i.e. the principal, all of the associated types match, and any auto traits) + ecx.add_goals( + data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), + ); + // The type must be Sized to be unsized. + ecx.add_goal(goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty]))); + // The type must outlive the lifetime of the `dyn` we're unsizing into. + ecx.add_goal( + goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region))), + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + // `[T; n]` -> `[T]` unsizing + (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { + // We just require that the element type stays the same + ecx.eq(goal.param_env, a_elem_ty, b_elem_ty)?; + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>` + (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) + if a_def.is_struct() && a_def.did() == b_def.did() => + { + let unsizing_params = tcx.unsizing_params_for_adt(a_def.did()); + // We must be unsizing some type parameters. This also implies + // that the struct has a tail field. + if unsizing_params.is_empty() { + return Err(NoSolution); } - _ => Err(NoSolution), + + let tail_field = a_def.non_enum_variant().tail(); + let tail_field_ty = tcx.type_of(tail_field.did); + + let a_tail_ty = tail_field_ty.subst(tcx, a_substs); + let b_tail_ty = tail_field_ty.subst(tcx, b_substs); + + // Substitute just the unsizing params from B into A. The type after + // this substitution must be equal to B. This is so we don't unsize + // unrelated type parameters. + let new_a_substs = + tcx.mk_substs_from_iter(a_substs.iter().enumerate().map(|(i, a)| { + if unsizing_params.contains(i as u32) { b_substs[i] } else { a } + })); + let unsized_a_ty = Ty::new_adt(tcx, a_def, new_a_substs); + + // Finally, we require that `TailA: Unsize<TailB>` for the tail field + // types. + ecx.eq(goal.param_env, unsized_a_ty, b_ty)?; + ecx.add_goal(goal.with( + tcx, + ty::TraitRef::new(tcx, goal.predicate.def_id(), [a_tail_ty, b_tail_ty]), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - }, - ) + // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>` + (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) + if a_tys.len() == b_tys.len() && !a_tys.is_empty() => + { + let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); + let b_last_ty = b_tys.last().unwrap(); + + // Substitute just the tail field of B., and require that they're equal. + let unsized_a_ty = + Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied()); + ecx.eq(goal.param_env, unsized_a_ty, b_ty)?; + + // Similar to ADTs, require that the rest of the fields are equal. + ecx.add_goal(goal.with( + tcx, + ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + _ => Err(NoSolution), + } + }) } fn consider_builtin_dyn_upcast_candidates( @@ -488,11 +500,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } let mut unsize_dyn_to_principal = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| { - ecx.probe(|r| CandidateKind::Candidate { - name: "upcast dyn to principle".into(), - result: *r, - }) - .enter(|ecx| -> Result<_, NoSolution> { + ecx.probe_candidate("upcast dyn to principle").enter(|ecx| -> Result<_, NoSolution> { // Require that all of the trait predicates from A match B, except for // the auto traits. We do this by constructing a new A type with B's // auto traits, and equating these types. @@ -509,7 +517,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { .map(ty::Binder::dummy), ); let new_a_data = tcx.mk_poly_existential_predicates_from_iter(new_a_data); - let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn); + let new_a_ty = Ty::new_dynamic(tcx, new_a_data, b_region, ty::Dyn); // We also require that A's lifetime outlives B's lifetime. ecx.eq(goal.param_env, new_a_ty, b_ty)?; @@ -714,21 +722,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, TraitPredicate<'tcx>>, constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>, ) -> QueryResult<'tcx> { - self.probe(|r| CandidateKind::Candidate { name: "constituent tys".into(), result: *r }) - .enter(|ecx| { - ecx.add_goals( - constituent_tys(ecx, goal.predicate.self_ty())? - .into_iter() - .map(|ty| { - goal.with( - ecx.tcx(), - ty::Binder::dummy(goal.predicate.with_self_ty(ecx.tcx(), ty)), - ) - }) - .collect::<Vec<_>>(), - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) + self.probe_candidate("constituent tys").enter(|ecx| { + ecx.add_goals( + constituent_tys(ecx, goal.predicate.self_ty())? + .into_iter() + .map(|ty| { + goal.with( + ecx.tcx(), + ty::Binder::dummy(goal.predicate.with_self_ty(ecx.tcx(), ty)), + ) + }) + .collect::<Vec<_>>(), + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index cb42281152d..cb38d0ac847 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -95,7 +95,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { tcx, ObligationCause::dummy(), orig_env, - ty::Binder::dummy(ty::TraitPredicate { + ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst, polarity: if polarity { @@ -103,7 +103,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } else { ImplPolarity::Negative }, - }), + }, )); if let Ok(Some(ImplSource::UserDefined(_))) = result { debug!( @@ -292,7 +292,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { new_env, pred, )); - let result = select.select(&obligation); + let result = select.poly_select(&obligation); match result { Ok(Some(ref impl_source)) => { @@ -794,7 +794,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { unevaluated, Some(obligation.cause.span), ) { - Ok(Some(valtree)) => Ok(selcx.tcx().mk_const(valtree, c.ty())), + Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, c.ty())), Ok(None) => { let tcx = self.tcx; let reported = diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 4cfe2bfcb12..1b1285e1b46 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -30,6 +30,7 @@ use std::fmt::Debug; use std::iter; use std::ops::ControlFlow; +use super::query::evaluate_obligation::InferCtxtExt; use super::NormalizeExt; /// Whether we do the orphan check relative to this crate or @@ -290,6 +291,20 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( ) -> bool { let infcx = selcx.infcx; + let obligation_guaranteed_to_fail = move |obligation: &PredicateObligation<'tcx>| { + if infcx.next_trait_solver() { + infcx.evaluate_obligation(obligation).map_or(false, |result| !result.may_apply()) + } else { + // We use `evaluate_root_obligation` to correctly track + // intercrate ambiguity clauses. We do not need this in the + // new solver. + selcx.evaluate_root_obligation(obligation).map_or( + false, // Overflow has occurred, and treat the obligation as possibly holding. + |result| !result.may_apply(), + ) + } + }; + let opt_failing_obligation = [&impl1_header.predicates, &impl2_header.predicates] .into_iter() .flatten() @@ -297,12 +312,7 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate) }) .chain(obligations) - .find(|o| { - selcx.evaluate_root_obligation(o).map_or( - false, // Overflow has occurred, and treat the obligation as possibly holding. - |result| !result.may_apply(), - ) - }); + .find(obligation_guaranteed_to_fail); if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 7b5d4f456ff..f785c4eaf9d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -1,7 +1,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; use rustc_infer::traits::util::elaborate; -use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation}; +use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation}; use rustc_middle::ty; use rustc_span::{Span, DUMMY_SP}; @@ -14,7 +14,7 @@ pub enum Ambiguity { pub fn recompute_applicable_impls<'tcx>( infcx: &InferCtxt<'tcx>, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Vec<Ambiguity> { let tcx = infcx.tcx; let param_env = obligation.param_env; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 5fff645dd22..f342180590f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -10,8 +10,8 @@ use super::{ use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt}; +use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache}; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::query::normalize::QueryNormalizeExt as _; use crate::traits::specialize::to_pretty_impl_header; use crate::traits::NormalizeExt; use on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _}; @@ -28,22 +28,24 @@ use rustc_hir::{GenericParam, Item, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; -use rustc_middle::traits::SelectionOutputTypeParameterMismatch; +use rustc_middle::traits::solve::Goal; +use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch}; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print}; use rustc_middle::ty::{ self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, }; -use rustc_session::config::TraitSolver; +use rustc_session::config::{DumpSolverProofTree, TraitSolver}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::sym; use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::borrow::Cow; use std::fmt; +use std::io::Write; use std::iter; use std::ops::ControlFlow; use suggestions::TypeErrCtxtExt as _; @@ -60,7 +62,7 @@ pub enum CandidateSimilarity { Fuzzy { ignoring_lifetimes: bool }, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ImplCandidate<'tcx> { pub trait_ref: ty::TraitRef<'tcx>, pub similarity: CandidateSimilarity, @@ -630,6 +632,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { error: &SelectionError<'tcx>, ) { let tcx = self.tcx; + + if tcx.sess.opts.unstable_opts.dump_solver_proof_tree == DumpSolverProofTree::OnError { + dump_proof_tree(root_obligation, self.infcx); + } + let mut span = obligation.cause.span; // FIXME: statically guarantee this by tainting after the diagnostic is emitted self.set_tainted_by_errors( @@ -966,7 +973,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && self.fallback_has_occurred { let predicate = trait_predicate.map_bound(|trait_pred| { - trait_pred.with_self_ty(self.tcx, self.tcx.mk_unit()) + trait_pred.with_self_ty(self.tcx, Ty::new_unit(self.tcx)) }); let unit_obligation = obligation.with(tcx, predicate); if self.predicate_may_hold(&unit_obligation) { @@ -1144,6 +1151,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => self.report_opaque_type_auto_trait_leakage( + &obligation, + def_id, + ), + TraitNotObjectSafe(did) => { let violations = self.tcx.object_safety_violations(did); report_object_safety_error(self.tcx, span, did, violations) @@ -1162,16 +1174,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } // Already reported in the query. - SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) => { - // FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token. - self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error"); - return; - } + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) | // Already reported. - Overflow(OverflowError::Error(_)) => { - self.tcx.sess.delay_span_bug(span, "`OverflowError` has been reported"); - return; - } + Overflow(OverflowError::Error(_)) => return, + Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); } @@ -1463,6 +1469,12 @@ trait InferCtxtPrivExt<'tcx> { terr: TypeError<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + fn report_opaque_type_auto_trait_leakage( + &self, + obligation: &PredicateObligation<'tcx>, + def_id: DefId, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + fn report_type_parameter_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, @@ -1522,6 +1534,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { + if self.tcx.sess.opts.unstable_opts.dump_solver_proof_tree == DumpSolverProofTree::OnError { + dump_proof_tree(&error.root_obligation, self.infcx); + } + match error.code { FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { self.report_selection_error( @@ -1608,20 +1624,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { bound_predicate.rebind(data), ); let unnormalized_term = match data.term.unpack() { - ty::TermKind::Ty(_) => self - .tcx - .mk_projection(data.projection_ty.def_id, data.projection_ty.substs) - .into(), - ty::TermKind::Const(ct) => self - .tcx - .mk_const( - ty::UnevaluatedConst { - def: data.projection_ty.def_id, - substs: data.projection_ty.substs, - }, - ct.ty(), - ) - .into(), + ty::TermKind::Ty(_) => Ty::new_projection( + self.tcx, + data.projection_ty.def_id, + data.projection_ty.substs, + ) + .into(), + ty::TermKind::Const(ct) => ty::Const::new_unevaluated( + self.tcx, + ty::UnevaluatedConst { + def: data.projection_ty.def_id, + substs: data.projection_ty.substs, + }, + ct.ty(), + ) + .into(), }; let normalized_term = ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term); @@ -1923,10 +1940,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { other: bool, ) -> bool { let other = if other { "other " } else { "" }; - let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| { - candidates.sort(); - candidates.dedup(); - let len = candidates.len(); + let report = |candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| { if candidates.is_empty() { return false; } @@ -1955,11 +1969,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect(); traits.sort(); traits.dedup(); + // FIXME: this could use a better heuristic, like just checking + // that substs[1..] is the same. + let all_traits_equal = traits.len() == 1; - let mut candidates: Vec<String> = candidates + let candidates: Vec<String> = candidates .into_iter() .map(|c| { - if traits.len() == 1 { + if all_traits_equal { format!("\n {}", c.self_ty()) } else { format!("\n {}", c) @@ -1967,14 +1984,16 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }) .collect(); - candidates.sort(); - candidates.dedup(); let end = if candidates.len() <= 9 { candidates.len() } else { 8 }; err.help(format!( "the following {other}types implement trait `{}`:{}{}", trait_ref.print_only_trait_path(), candidates[..end].join(""), - if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } + if candidates.len() > 9 { + format!("\nand {} others", candidates.len() - 8) + } else { + String::new() + } )); true }; @@ -1988,7 +2007,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Mentioning implementers of `Copy`, `Debug` and friends is not useful. return false; } - let normalized_impl_candidates: Vec<_> = self + let mut impl_candidates: Vec<_> = self .tcx .all_impls(def_id) // Ignore automatically derived impls and `!Trait` impls. @@ -2015,7 +2034,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } }) .collect(); - return report(normalized_impl_candidates, err); + + impl_candidates.sort(); + impl_candidates.dedup(); + return report(impl_candidates, err); } // Sort impl candidates so that ordering is consistent for UI tests. @@ -2024,27 +2046,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // // Prefer more similar candidates first, then sort lexicographically // by their normalized string representation. - let mut normalized_impl_candidates_and_similarities = impl_candidates + let mut impl_candidates: Vec<_> = impl_candidates .iter() - .copied() - .map(|ImplCandidate { trait_ref, similarity }| { - // FIXME(compiler-errors): This should be using `NormalizeExt::normalize` - let normalized = self - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .query_normalize(trait_ref) - .map_or(trait_ref, |normalized| normalized.value); - (similarity, normalized) + .cloned() + .map(|mut cand| { + // Fold the consts so that they shows up as, e.g., `10` + // instead of `core::::array::{impl#30}::{constant#0}`. + cand.trait_ref = cand.trait_ref.fold_with(&mut BottomUpFolder { + tcx: self.tcx, + ty_op: |ty| ty, + lt_op: |lt| lt, + ct_op: |ct| ct.eval(self.tcx, ty::ParamEnv::empty()), + }); + cand }) - .collect::<Vec<_>>(); - normalized_impl_candidates_and_similarities.sort(); - normalized_impl_candidates_and_similarities.dedup(); - - let normalized_impl_candidates = normalized_impl_candidates_and_similarities - .into_iter() - .map(|(_, normalized)| normalized) - .collect::<Vec<_>>(); + .collect(); + impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref)); + impl_candidates.dedup(); - report(normalized_impl_candidates, err) + report(impl_candidates.into_iter().map(|cand| cand.trait_ref).collect(), err) } fn report_similar_impl_candidates_for_root_obligation( @@ -2635,11 +2655,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() { + if let ty::Param(_) = *ty.kind() { let infcx = self.infcx; *self.var_map.entry(ty).or_insert_with(|| { infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeParameterDefinition(name, None), + kind: TypeVariableOriginKind::MiscVariable, span: DUMMY_SP, }) }) @@ -3181,6 +3201,39 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) } + fn report_opaque_type_auto_trait_leakage( + &self, + obligation: &PredicateObligation<'tcx>, + def_id: DefId, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + let name = match self.tcx.opaque_type_origin(def_id.expect_local()) { + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => { + format!("opaque type") + } + hir::OpaqueTyOrigin::TyAlias { .. } => { + format!("`{}`", self.tcx.def_path_debug_str(def_id)) + } + }; + let mut err = self.tcx.sess.struct_span_err( + obligation.cause.span, + format!("cannot check whether the hidden type of {name} satisfies auto traits"), + ); + err.span_note(self.tcx.def_span(def_id), "opaque type is declared here"); + match self.defining_use_anchor { + DefiningAnchor::Bubble | DefiningAnchor::Error => {} + DefiningAnchor::Bind(bind) => { + err.span_note( + self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)), + "this item depends on auto traits of the hidden type, \ + but may also be registering the hidden type. \ + This is not supported right now. \ + You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(), + ); + } + }; + err + } + fn report_type_parameter_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, @@ -3492,3 +3545,16 @@ pub enum DefIdOrName { DefId(DefId), Name(&'static str), } + +pub fn dump_proof_tree<'tcx>(o: &Obligation<'tcx, ty::Predicate<'tcx>>, infcx: &InferCtxt<'tcx>) { + infcx.probe(|_| { + let goal = Goal { predicate: o.predicate, param_env: o.param_env }; + let tree = infcx + .evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No)) + .1 + .expect("proof tree should have been generated"); + let mut lock = std::io::stdout().lock(); + let _ = lock.write_fmt(format_args!("{tree:?}")); + let _ = lock.flush(); + }); +} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 10bd027b684..b16d2eb5fc1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -41,7 +41,6 @@ pub trait TypeErrCtxtExt<'tcx> { static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ kw::SelfUpper, sym::ItemContext, - sym::from_method, sym::from_desugaring, sym::direct, sym::cause, @@ -172,23 +171,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - if let ObligationCauseCode::ItemObligation(item) - | ObligationCauseCode::BindingObligation(item, _) - | ObligationCauseCode::ExprItemObligation(item, ..) - | ObligationCauseCode::ExprBindingObligation(item, ..) = *obligation.cause.code() - { - // FIXME: maybe also have some way of handling methods - // from other traits? That would require name resolution, - // which we might want to be some sort of hygienic. - // - // Currently I'm leaving it for what I need for `try`. - if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { - let method = self.tcx.item_name(item); - flags.push((sym::from_method, None)); - flags.push((sym::from_method, Some(method.to_string()))); - } - } - if let Some(k) = obligation.cause.span.desugaring_kind() { flags.push((sym::from_desugaring, None)); flags.push((sym::from_desugaring, Some(format!("{:?}", k)))); @@ -278,7 +260,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]` if let ty::Array(aty, len) = self_ty.kind() { flags.push((sym::_Self, Some("[]".to_string()))); - let len = len.kind().try_to_value().and_then(|v| v.try_to_target_usize(self.tcx)); + let len = len.try_to_value().and_then(|v| v.try_to_target_usize(self.tcx)); flags.push((sym::_Self, Some(format!("[{}; _]", aty)))); if let Some(n) = len { flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n)))); @@ -672,7 +654,7 @@ impl<'tcx> OnUnimplementedFormatString { None => { if let Some(val) = options.get(&s) { val - } else if s == sym::from_desugaring || s == sym::from_method { + } else if s == sym::from_desugaring { // don't break messages using these two arguments incorrectly &empty_string } else if s == sym::ItemContext { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 619a099fcb5..9ac1ba0275c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -786,7 +786,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(steps) = autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| { // Re-add the `&` - let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); + let ty = Ty::new_ref(self.tcx, region, TypeAndMut { ty, mutbl }); // Remapping bound vars here let real_trait_pred_and_ty = @@ -1298,13 +1298,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| { ( trait_pred, - self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()), + Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, trait_pred.self_ty()), ) }); let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| { ( trait_pred, - self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()), + Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, trait_pred.self_ty()), ) }); @@ -1465,7 +1465,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) { let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; }; let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; }; - let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty); + let self_ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, self_ty); for predicate in predicates.iter() { if !self.predicate_must_hold_modulo_regions( @@ -1706,8 +1706,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let ty::Ref(region, t_type, mutability) = *trait_pred.skip_binder().self_ty().kind() { let suggested_ty = match mutability { - hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type), - hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type), + hir::Mutability::Mut => Ty::new_imm_ref(self.tcx, region, t_type), + hir::Mutability::Not => Ty::new_mut_ref(self.tcx, region, t_type), }; // Remapping bound vars here @@ -1951,7 +1951,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ), }; - infcx.tcx.mk_fn_ptr(trait_ref.rebind(sig)) + Ty::new_fn_ptr(infcx.tcx, trait_ref.rebind(sig)) } let argument_kind = match expected.skip_binder().self_ty().kind() { @@ -3347,7 +3347,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; // `<T as Future>::Output` let projection_ty = trait_pred.map_bound(|trait_pred| { - self.tcx.mk_projection( + Ty::new_projection( + self.tcx, item_def_id, // Future::Output has no substs [trait_pred.self_ty()], @@ -3501,7 +3502,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr { let expr = expr.peel_blocks(); - let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()); + let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx,)); let span = expr.span; if Some(span) != err.span.primary_span() { err.span_label( @@ -3555,7 +3556,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { type_diffs = vec![ Sorts(ty::error::ExpectedFound { - expected: self.tcx.mk_alias(ty::Projection, where_pred.skip_binder().projection_ty), + expected: Ty::new_alias(self.tcx,ty::Projection, where_pred.skip_binder().projection_ty), found, }), ]; @@ -3646,7 +3647,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Extract `<U as Deref>::Target` assoc type and check that it is `T` && let Some(deref_target_did) = tcx.lang_items().deref_target() - && let projection = tcx.mk_projection(deref_target_did, tcx.mk_substs(&[ty::GenericArg::from(found_ty)])) + && let projection = Ty::new_projection(tcx,deref_target_did, tcx.mk_substs(&[ty::GenericArg::from(found_ty)])) && let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(projection) && obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation)) && infcx.can_eq(param_env, deref_target, target_ty) @@ -3693,7 +3694,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut assocs = vec![]; let mut expr = expr; let mut prev_ty = self.resolve_vars_if_possible( - typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()), + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), ); while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind { // Point at every method call in the chain with the resulting type. @@ -3704,7 +3705,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env); assocs.push(assocs_in_this_method); prev_ty = self.resolve_vars_if_possible( - typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()), + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), ); if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind @@ -3722,7 +3723,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::Node::Param(param) = parent { // ...and it is a an fn argument. let prev_ty = self.resolve_vars_if_possible( - typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error_misc()), + typeck_results.node_type_opt(param.hir_id).unwrap_or(Ty::new_misc_error(tcx,)), ); let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env); if assocs_in_this_method.iter().any(|a| a.is_some()) { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3d96c422256..cf9d9315f60 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -4,7 +4,7 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome} use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ProjectionCacheKey; -use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation}; +use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -528,7 +528,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2); use rustc_hir::def::DefKind; - use ty::ConstKind::Unevaluated; + use ty::Unevaluated; match (c1.kind(), c2.kind()) { (Unevaluated(a), Unevaluated(b)) if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst => @@ -667,7 +667,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { fn process_trait_obligation( &mut self, obligation: &PredicateObligation<'tcx>, - trait_obligation: TraitObligation<'tcx>, + trait_obligation: PolyTraitObligation<'tcx>, stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>, ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> { let infcx = self.selcx.infcx; @@ -683,7 +683,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { } } - match self.selcx.select(&trait_obligation) { + match self.selcx.poly_select(&trait_obligation) { Ok(Some(impl_source)) => { debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth); ProcessResult::Changed(mk_pending(impl_source.nested_obligations())) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index e2ee347b639..1af8323b6e9 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -11,7 +11,7 @@ mod fulfill; pub mod misc; mod object_safety; pub mod outlives_bounds; -mod project; +pub mod project; pub mod query; #[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))] mod select; diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 08be60c65d4..c31944c162e 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -101,7 +101,7 @@ pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::A debug_assert!(tcx.generics_of(trait_def_id).has_self); debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); // Any method that has a `Self: Sized` bound cannot be called. - if generics_require_sized_self(tcx, method.def_id) { + if tcx.generics_require_sized_self(method.def_id) { return false; } @@ -331,7 +331,7 @@ fn super_predicates_have_non_lifetime_binders( } fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { - generics_require_sized_self(tcx, trait_def_id) + tcx.generics_require_sized_self(trait_def_id) } fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { @@ -364,7 +364,7 @@ fn object_safety_violation_for_assoc_item( ) -> Option<ObjectSafetyViolation> { // Any item that has a `Self : Sized` requisite is otherwise // exempt from the regulations. - if generics_require_sized_self(tcx, item.def_id) { + if tcx.generics_require_sized_self(item.def_id) { return None; } @@ -509,7 +509,7 @@ fn virtual_call_violation_for_method<'tcx>( // e.g., `Rc<()>` let unit_receiver_ty = - receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id); + receiver_for_self_ty(tcx, receiver_ty, Ty::new_unit(tcx), method.def_id); match abi_of_ty(unit_receiver_ty) { Some(Abi::Scalar(..)) => (), @@ -664,7 +664,7 @@ fn object_ty_for_trait<'tcx>( ); debug!(?existential_predicates); - tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn) + Ty::new_dynamic(tcx, existential_predicates, lifetime, ty::Dyn) } /// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a @@ -732,7 +732,7 @@ fn receiver_is_dispatchable<'tcx>( // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = - tcx.mk_ty_param(u32::MAX, Symbol::intern("RustaceansAreAwesome")); + Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome")); // `Receiver[Self => U]` let unsized_receiver_ty = @@ -922,5 +922,10 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>( } pub fn provide(providers: &mut Providers) { - *providers = Providers { object_safety_violations, check_is_object_safe, ..*providers }; + *providers = Providers { + object_safety_violations, + check_is_object_safe, + generics_require_sized_self, + ..*providers + }; } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 162e51d1fd6..a10bca31ff1 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -447,6 +447,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { depth: usize, obligations: &'a mut Vec<PredicateObligation<'tcx>>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { + debug_assert!(!selcx.infcx.next_trait_solver()); AssocTypeNormalizer { selcx, param_env, @@ -905,7 +906,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> { let universe = self.universe_for(debruijn); let p = ty::PlaceholderType { universe, bound: bound_ty }; self.mapped_types.insert(p, bound_ty); - self.infcx.tcx.mk_placeholder(p) + Ty::new_placeholder(self.infcx.tcx, p) } _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self), _ => t, @@ -924,7 +925,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> { let universe = self.universe_for(debruijn); let p = ty::PlaceholderConst { universe, bound: bound_const }; self.mapped_consts.insert(p, bound_const); - self.infcx.tcx.mk_const(p, ct.ty()) + ty::Const::new_placeholder(self.infcx.tcx, p, ct.ty()) } _ => ct.super_fold_with(self), } @@ -1035,7 +1036,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - self.interner().mk_bound(db, *replace_var) + Ty::new_bound(self.infcx.tcx, db, *replace_var) } None => ty, } @@ -1059,7 +1060,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - self.interner().mk_const(ty::ConstKind::Bound(db, *replace_var), ct.ty()) + ty::Const::new_bound(self.infcx.tcx, db, *replace_var, ct.ty()) } None => ct, } @@ -1122,6 +1123,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> Result<Option<Term<'tcx>>, InProgress> { let infcx = selcx.infcx; + debug_assert!(!selcx.infcx.next_trait_solver()); // Don't use the projection cache in intercrate mode - // the `infcx` may be re-used between intercrate in non-intercrate // mode, which could lead to using incorrect cache results. @@ -1438,7 +1440,7 @@ struct Progress<'tcx> { impl<'tcx> Progress<'tcx> { fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { - Progress { term: tcx.ty_error(guar).into(), obligations: vec![] } + Progress { term: Ty::new_error(tcx, guar).into(), obligations: vec![] } } fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self { @@ -1497,19 +1499,22 @@ fn project<'cx, 'tcx>( ProjectionCandidateSet::None => { let tcx = selcx.tcx(); let term = match tcx.def_kind(obligation.predicate.def_id) { - DefKind::AssocTy | DefKind::ImplTraitPlaceholder => tcx - .mk_projection(obligation.predicate.def_id, obligation.predicate.substs) - .into(), - DefKind::AssocConst => tcx - .mk_const( - ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new( - obligation.predicate.def_id, - obligation.predicate.substs, - )), - tcx.type_of(obligation.predicate.def_id) - .subst(tcx, obligation.predicate.substs), - ) - .into(), + DefKind::AssocTy | DefKind::ImplTraitPlaceholder => Ty::new_projection( + tcx, + obligation.predicate.def_id, + obligation.predicate.substs, + ) + .into(), + DefKind::AssocConst => ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst::new( + obligation.predicate.def_id, + obligation.predicate.substs, + ), + tcx.type_of(obligation.predicate.def_id) + .subst(tcx, obligation.predicate.substs), + ) + .into(), kind => { bug!("unknown projection def-id: {}", kind.descr(obligation.predicate.def_id)) } @@ -1540,7 +1545,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( let trait_def_id = tcx.parent(trait_fn_def_id); let trait_substs = obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id)); - // FIXME(named-returns): Binders let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs); let _ = selcx.infcx.commit_if_ok(|_| { @@ -1742,8 +1746,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // If we are resolving `<T as TraitRef<...>>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: - let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx())); - let trait_obligation = obligation.with(selcx.tcx(), poly_trait_ref); + let trait_ref = obligation.predicate.trait_ref(selcx.tcx()); + let trait_obligation = obligation.with(selcx.tcx(), trait_ref); let _ = selcx.infcx.commit_if_ok(|_| { let impl_source = match selcx.select(&trait_obligation) { Ok(Some(impl_source)) => impl_source, @@ -1797,7 +1801,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( if obligation.param_env.reveal() == Reveal::All { // NOTE(eddyb) inference variables can resolve to parameters, so // assume `poly_trait_ref` isn't monomorphic, if it contains any. - let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(poly_trait_ref); + let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(trait_ref); !poly_trait_ref.still_further_specializable() } else { debug!( @@ -1816,11 +1820,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let lang_items = selcx.tcx().lang_items(); - if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(poly_trait_ref.def_id())) - || selcx.tcx().fn_trait_kind_from_def_id(poly_trait_ref.def_id()).is_some() + if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(trait_ref.def_id)) + || selcx.tcx().fn_trait_kind_from_def_id(trait_ref.def_id).is_some() { true - } else if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) { + } else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) { match self_ty.kind() { ty::Bool | ty::Char @@ -1855,7 +1859,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Infer(..) | ty::Error(_) => false, } - } else if lang_items.pointee_trait() == Some(poly_trait_ref.def_id()) { + } else if lang_items.pointee_trait() == Some(trait_ref.def_id) { let tail = selcx.tcx().struct_tail_with_normalize( self_ty, |ty| { @@ -1930,7 +1934,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( } } } else { - bug!("unexpected builtin trait with associated type: {poly_trait_ref:?}") + bug!("unexpected builtin trait with associated type: {trait_ref:?}") } } super::ImplSource::Param(..) => { @@ -2349,7 +2353,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( obligation, poly_cache_entry, e, ); debug!("confirm_param_env_candidate: {}", msg); - let err = infcx.tcx.ty_error_with_message(obligation.cause.span, msg); + let err = Ty::new_error_with_message(infcx.tcx, obligation.cause.span, msg); Progress { term: err.into(), obligations: vec![] } } } @@ -2381,7 +2385,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( "confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.name, obligation.predicate ); - return Progress { term: tcx.ty_error_misc().into(), obligations: nested }; + return Progress { term: Ty::new_misc_error(tcx).into(), obligations: nested }; } // If we're trying to normalize `<Vec<u32> as X>::A<S>` using //`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then: @@ -2397,13 +2401,14 @@ fn confirm_impl_candidate<'cx, 'tcx>( let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const { let did = assoc_ty.item.def_id; let identity_substs = crate::traits::InternalSubsts::identity_for_item(tcx, did); - let kind = ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs)); - ty.map_bound(|ty| tcx.mk_const(kind, ty).into()) + let uv = ty::UnevaluatedConst::new(did, identity_substs); + ty.map_bound(|ty| ty::Const::new_unevaluated(tcx, uv, ty).into()) } else { ty.map_bound(|ty| ty.into()) }; if !check_substs_compatible(tcx, assoc_ty.item, substs) { - let err = tcx.ty_error_with_message( + let err = Ty::new_error_with_message( + tcx, obligation.cause.span, "impl item and trait item have different parameters", ); @@ -2430,13 +2435,14 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( // We don't support specialization for RPITITs anyways... yet. // Also don't try to project to an RPITIT that has no value if !leaf_def.is_final() || !leaf_def.item.defaultness(tcx).has_value() { - return Progress { term: tcx.ty_error_misc().into(), obligations }; + return Progress { term: Ty::new_misc_error(tcx).into(), obligations }; } // Use the default `impl Trait` for the trait, e.g., for a default trait body if leaf_def.item.container == ty::AssocItemContainer::TraitContainer { return Progress { - term: tcx.mk_opaque(obligation.predicate.def_id, obligation.predicate.substs).into(), + term: Ty::new_opaque(tcx, obligation.predicate.def_id, obligation.predicate.substs) + .into(), obligations, }; } @@ -2454,7 +2460,8 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( ); if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) { - let err = tcx.ty_error_with_message( + let err = Ty::new_error_with_message( + tcx, obligation.cause.span, "impl method and trait method have different parameters", ); @@ -2500,7 +2507,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( cause.clone(), obligation.recursion_depth + 1, tcx.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else( - |guar| tcx.ty_error(guar), + |guar| Ty::new_error(tcx, guar), |tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs), ), &mut obligations, diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index e29e1b25919..a50644bb709 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -97,6 +97,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } }) } else { + assert!(!self.intercrate); let c_pred = self.canonicalize_query_keep_static( param_env.and(obligation.predicate), &mut _orig_values, 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 42c2c37eca2..979498fb6e6 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,3 +1,4 @@ +use crate::solve; use crate::traits::query::NoSolution; use crate::traits::wf; use crate::traits::ObligationCtxt; @@ -6,6 +7,7 @@ use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; use rustc_infer::traits::query::OutlivesBound; use rustc_middle::infer::canonical::CanonicalQueryResponse; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::DUMMY_SP; @@ -164,19 +166,29 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( // We lazily compute the outlives components as // `select_all_or_error` constrains inference variables. - let implied_bounds = outlives_bounds - .into_iter() - .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() { - ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)], + let mut implied_bounds = Vec::new(); + for ty::OutlivesPredicate(a, r_b) in outlives_bounds { + match a.unpack() { + ty::GenericArgKind::Lifetime(r_a) => { + implied_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a)) + } ty::GenericArgKind::Type(ty_a) => { - let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a); + let mut ty_a = ocx.infcx.resolve_vars_if_possible(ty_a); + // Need to manually normalize in the new solver as `wf::obligations` does not. + if ocx.infcx.next_trait_solver() { + ty_a = solve::deeply_normalize( + ocx.infcx.at(&ObligationCause::dummy(), param_env), + ty_a, + ) + .map_err(|_errs| NoSolution)?; + } let mut components = smallvec![]; push_outlives_components(tcx, ty_a, &mut components); - implied_bounds_from_components(r_b, components) + implied_bounds.extend(implied_bounds_from_components(r_b, components)) } ty::GenericArgKind::Const(_) => unreachable!(), - }) - .collect(); + } + } Ok(implied_bounds) } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 412b601c966..d5f6aaa7fe9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -10,7 +10,7 @@ use hir::def_id::DefId; use hir::LangItem; use rustc_hir as hir; use rustc_infer::traits::ObligationCause; -use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; +use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -137,7 +137,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(level = "debug", skip(self, candidates))] fn assemble_candidates_from_projected_tys( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // Before we go into the whole placeholder thing, just @@ -206,7 +206,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn assemble_generator_candidates( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // Okay to skip binder because the substs on generator types never @@ -231,7 +231,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn assemble_future_candidates( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { let self_ty = obligation.self_ty().skip_binder(); @@ -254,7 +254,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// unified during the confirmation step. fn assemble_closure_candidates( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else { @@ -292,7 +292,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Implements one of the `Fn()` family for a fn pointer. fn assemble_fn_pointer_candidates( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // We provide impl of all fn traits for fn pointers. @@ -334,7 +334,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(level = "debug", skip(self, candidates))] fn assemble_candidates_from_impls( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // Essentially any user-written impl will match with an error type, @@ -388,9 +388,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// `FnPtr`, when we wanted to report that it doesn't implement `Trait`. #[instrument(level = "trace", skip(self), ret)] fn reject_fn_ptr_impls( - &self, + &mut self, impl_def_id: DefId, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, impl_self_ty: Ty<'tcx>, ) -> bool { // Let `impl<T: FnPtr> Trait for Vec<T>` go through the normal rejection path. @@ -464,7 +464,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) })), ); - if let Ok(r) = self.infcx.evaluate_obligation(&obligation) { + if let Ok(r) = self.evaluate_root_obligation(&obligation) { if !r.may_apply() { return true; } @@ -475,7 +475,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn assemble_candidates_from_auto_impls( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // Okay to skip binder here because the tests we do below do not involve bound regions. @@ -544,7 +544,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Searches for impls that might apply to `obligation`. fn assemble_candidates_from_object_ty( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { debug!( @@ -668,7 +668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Searches for unsizing that might apply to `obligation`. fn assemble_candidates_for_unsizing( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // We currently never consider higher-ranked obligations e.g. @@ -782,7 +782,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(level = "debug", skip(self, obligation, candidates))] fn assemble_candidates_for_transmutability( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { if obligation.predicate.has_non_region_param() { @@ -800,7 +800,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(level = "debug", skip(self, obligation, candidates))] fn assemble_candidates_for_trait_alias( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // Okay to skip binder here because the tests we do below do not involve bound regions. @@ -837,7 +837,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn assemble_const_destruct_candidates( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // If the predicate is `~const Destruct` in a non-const environment, we don't actually need @@ -924,7 +924,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn assemble_candidate_for_tuple( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); @@ -966,7 +966,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn assemble_candidate_for_pointer_like( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // The regions of a type don't affect the size of the type @@ -991,7 +991,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn assemble_candidates_for_fn_ptr_trait( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index f45d348fa96..7adc29bbba4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -27,8 +27,8 @@ use crate::traits::vtable::{ use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, - Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, - SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, + Obligation, ObligationCause, OutputTypeParameterMismatch, PolyTraitObligation, + PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, Unimplemented, }; use super::BuiltinImplConditions; @@ -42,7 +42,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(level = "debug", skip(self))] pub(super) fn confirm_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, candidate: SelectionCandidate<'tcx>, ) -> Result<Selection<'tcx>, SelectionError<'tcx>> { let mut impl_src = match candidate { @@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } AutoImplCandidate => { - let data = self.confirm_auto_impl_candidate(obligation); + let data = self.confirm_auto_impl_candidate(obligation)?; ImplSource::Builtin(data) } @@ -148,7 +148,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_projection_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, idx: usize, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { let tcx = self.tcx(); @@ -215,7 +215,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_param_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, param: ty::PolyTraitRef<'tcx>, ) -> Vec<PredicateObligation<'tcx>> { debug!(?obligation, ?param, "confirm_param_candidate"); @@ -238,7 +238,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_builtin_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, has_nested: bool, ) -> Vec<PredicateObligation<'tcx>> { debug!(?obligation, ?has_nested, "confirm_builtin_candidate"); @@ -279,13 +279,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(level = "debug", skip(self))] fn confirm_transmutability_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { use rustc_transmute::{Answer, Condition}; #[instrument(level = "debug", skip(tcx, obligation, predicate))] fn flatten_answer_tree<'tcx>( tcx: TyCtxt<'tcx>, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, predicate: TraitPredicate<'tcx>, cond: Condition<rustc_transmute::layout::rustc::Ref<'tcx>>, ) -> Vec<PredicateObligation<'tcx>> { @@ -375,19 +375,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds. fn confirm_auto_impl_candidate( &mut self, - obligation: &TraitObligation<'tcx>, - ) -> Vec<PredicateObligation<'tcx>> { + obligation: &PolyTraitObligation<'tcx>, + ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { debug!(?obligation, "confirm_auto_impl_candidate"); let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty()); - let types = self.constituent_types_for_ty(self_ty); - self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types) + let types = self.constituent_types_for_ty(self_ty)?; + Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)) } /// See `confirm_auto_impl_candidate`. fn vtable_auto_impl( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, trait_def_id: DefId, nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>, ) -> Vec<PredicateObligation<'tcx>> { @@ -426,7 +426,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_impl_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, impl_def_id: DefId, ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> { debug!(?obligation, ?impl_def_id, "confirm_impl_candidate"); @@ -481,7 +481,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_object_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, index: usize, ) -> Result<ImplSourceObjectData<PredicateObligation<'tcx>>, SelectionError<'tcx>> { let tcx = self.tcx(); @@ -587,7 +587,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let kind = ty::BoundTyKind::Param(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Ty(kind); bound_vars.push(bound_var); - tcx.mk_bound( + Ty::new_bound( + tcx, ty::INNERMOST, ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), @@ -613,11 +614,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { GenericParamDefKind::Const { .. } => { let bound_var = ty::BoundVariableKind::Const; bound_vars.push(bound_var); - tcx.mk_const( - ty::ConstKind::Bound( - ty::INNERMOST, - ty::BoundVar::from_usize(bound_vars.len() - 1), - ), + ty::Const::new_bound( + tcx, + ty::INNERMOST, + ty::BoundVar::from_usize(bound_vars.len() - 1), tcx.type_of(param.def_id) .no_bound_vars() .expect("const parameter types cannot be generic"), @@ -655,7 +655,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_fn_pointer_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, is_const: bool, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); @@ -714,7 +714,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_trait_alias_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Vec<PredicateObligation<'tcx>> { debug!(?obligation, "confirm_trait_alias_candidate"); @@ -739,7 +739,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_generator_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope @@ -778,7 +778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_future_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope @@ -809,7 +809,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(skip(self), level = "debug")] fn confirm_closure_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { let kind = self .tcx() @@ -865,7 +865,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(skip(self), level = "trace")] fn confirm_poly_trait_refs( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, self_ty_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { let obligation_trait_ref = obligation.predicate.to_poly_trait_ref(); @@ -900,7 +900,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_trait_upcasting_unsize_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, idx: usize, ) -> Result<ImplSourceTraitUpcastingData<PredicateObligation<'tcx>>, SelectionError<'tcx>> { let tcx = self.tcx(); @@ -947,7 +947,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map(ty::Binder::dummy), ); let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter); - let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_a); + let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, repr_a); // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. @@ -1004,7 +1004,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_builtin_unsize_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { let tcx = self.tcx(); @@ -1040,7 +1040,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map(ty::Binder::dummy), ); let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter); - let source_trait = tcx.mk_dynamic(existential_predicates, r_b, dyn_a); + let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a); // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. @@ -1125,12 +1125,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(Unimplemented); } - let tail_field = def - .non_enum_variant() - .fields - .raw - .last() - .expect("expected unsized ADT to have a tail field"); + let tail_field = def.non_enum_variant().tail(); let tail_field_ty = tcx.type_of(tail_field.did); // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`, @@ -1158,7 +1153,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let substs = tcx.mk_substs_from_iter(substs_a.iter().enumerate().map(|(i, k)| { if unsizing_params.contains(i as u32) { substs_b[i] } else { k } })); - let new_struct = tcx.mk_adt(def, substs); + let new_struct = Ty::new_adt(tcx, def, substs); let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) @@ -1189,7 +1184,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check that the source tuple with the target's // last element is equal to the target. let new_tuple = - tcx.mk_tup_from_iter(a_mid.iter().copied().chain(iter::once(b_last))); + Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last))); let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) @@ -1213,7 +1208,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_const_destruct_candidate( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, impl_def_id: Option<DefId>, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop` diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index eb11163de42..7f31ab75119 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -15,8 +15,8 @@ use super::util::closure_trait_ref_and_return_type; use super::wf; use super::{ ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, - ObligationCause, ObligationCauseCode, Overflow, PredicateObligation, Selection, SelectionError, - SelectionResult, TraitObligation, TraitQueryMode, + ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, + Selection, SelectionError, SelectionResult, TraitQueryMode, }; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; @@ -34,8 +34,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::LateBoundRegionConversionTime; -use rustc_infer::traits::TraitEngine; -use rustc_infer::traits::TraitEngineExt; +use rustc_infer::traits::TraitObligation; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::abstract_const::NotConstEvaluatable; @@ -124,7 +123,7 @@ pub struct SelectionContext<'cx, 'tcx> { // A stack that walks back up the stack frame. struct TraitObligationStack<'prev, 'tcx> { - obligation: &'prev TraitObligation<'tcx>, + obligation: &'prev PolyTraitObligation<'tcx>, /// The trait predicate from `obligation` but "freshened" with the /// selection-context's freshener. Used to check for recursion. @@ -261,9 +260,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Attempts to satisfy the obligation. If successful, this will affect the surrounding /// type environment by performing unification. #[instrument(level = "debug", skip(self), ret)] - pub fn select( + pub fn poly_select( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { if self.infcx.next_trait_solver() { return self.infcx.select_in_new_trait_solver(obligation); @@ -295,9 +294,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn select_from_obligation( + pub fn select( &mut self, obligation: &TraitObligation<'tcx>, + ) -> SelectionResult<'tcx, Selection<'tcx>> { + self.poly_select(&Obligation { + cause: obligation.cause.clone(), + param_env: obligation.param_env, + predicate: ty::Binder::dummy(obligation.predicate), + recursion_depth: obligation.recursion_depth, + }) + } + + fn select_from_obligation( + &mut self, + obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { debug_assert!(!obligation.predicate.has_escaping_bound_vars()); @@ -312,6 +323,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { + debug_assert!(!self.infcx.next_trait_solver()); // Watch out for overflow. This intentionally bypasses (and does // not update) the cache. self.check_recursion_limit(&stack.obligation, &stack.obligation)?; @@ -526,21 +538,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Evaluates whether the obligation `obligation` can be satisfied /// and returns an `EvaluationResult`. This is meant for the /// *initial* call. + /// + /// Do not use this directly, use `infcx.evaluate_obligation` instead. pub fn evaluate_root_obligation( &mut self, obligation: &PredicateObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { + debug_assert!(!self.infcx.next_trait_solver()); self.evaluation_probe(|this| { let goal = this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); - let mut result = if this.infcx.next_trait_solver() { - this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])? - } else { - this.evaluate_predicate_recursively( - TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), - obligation.clone(), - )? - }; + let mut result = this.evaluate_predicate_recursively( + TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), + obligation.clone(), + )?; // If the predicate has done any inference, then downgrade the // result to ambiguous. if this.infcx.shallow_resolve(goal) != goal { @@ -587,42 +598,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { where I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug, { - if self.infcx.next_trait_solver() { - self.evaluate_predicates_recursively_in_new_solver(predicates) - } else { - let mut result = EvaluatedToOk; - for mut obligation in predicates { - obligation.set_depth_from_parent(stack.depth()); - let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; - if let EvaluatedToErr = eval { - // fast-path - EvaluatedToErr is the top of the lattice, - // so we don't need to look on the other predicates. - return Ok(EvaluatedToErr); - } else { - result = cmp::max(result, eval); - } + let mut result = EvaluatedToOk; + for mut obligation in predicates { + obligation.set_depth_from_parent(stack.depth()); + let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; + if let EvaluatedToErr = eval { + // fast-path - EvaluatedToErr is the top of the lattice, + // so we don't need to look on the other predicates. + return Ok(EvaluatedToErr); + } else { + result = cmp::max(result, eval); } - Ok(result) - } - } - - /// Evaluates the predicates using the new solver when `-Ztrait-solver=next` is enabled - fn evaluate_predicates_recursively_in_new_solver( - &mut self, - predicates: impl IntoIterator<Item = PredicateObligation<'tcx>>, - ) -> Result<EvaluationResult, OverflowError> { - let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self.infcx); - fulfill_cx.register_predicate_obligations(self.infcx, predicates); - // True errors - // FIXME(-Ztrait-solver=next): Overflows are reported as ambig here, is that OK? - if !fulfill_cx.select_where_possible(self.infcx).is_empty() { - return Ok(EvaluatedToErr); - } - if !fulfill_cx.select_all_or_error(self.infcx).is_empty() { - return Ok(EvaluatedToAmbig); } - // Regions and opaques are handled in the `evaluation_probe` by looking at the snapshot - Ok(EvaluatedToOk) + Ok(result) } #[instrument( @@ -636,7 +624,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: PredicateObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - // `previous_stack` stores a `TraitObligation`, while `obligation` is + debug_assert!(!self.infcx.next_trait_solver()); + // `previous_stack` stores a `PolyTraitObligation`, while `obligation` is // a `PredicateObligation`. These are distinct types, so we can't // use any `Option` combinator method that would force them to be // the same. @@ -897,7 +886,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); use rustc_hir::def::DefKind; - use ty::ConstKind::Unevaluated; + use ty::Unevaluated; match (c1.kind(), c2.kind()) { (Unevaluated(a), Unevaluated(b)) if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst => @@ -997,7 +986,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn evaluate_trait_predicate_recursively<'o>( &mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, - mut obligation: TraitObligation<'tcx>, + mut obligation: PolyTraitObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { if !self.is_intercrate() && obligation.is_global() @@ -1179,6 +1168,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, ) -> Result<EvaluationResult, OverflowError> { + debug_assert!(!self.infcx.next_trait_solver()); // In intercrate mode, whenever any of the generics are unbound, // there can always be an impl. Even if there are no impls in // this crate, perhaps the type would be unified with @@ -1402,7 +1392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn filter_impls( &mut self, candidates: Vec<SelectionCandidate<'tcx>>, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Vec<SelectionCandidate<'tcx>> { trace!("{candidates:#?}"); let tcx = self.tcx(); @@ -1465,7 +1455,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn filter_reservation_impls( &mut self, candidate: SelectionCandidate<'tcx>, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { let tcx = self.tcx(); // Treat reservation impls as ambiguity. @@ -1637,7 +1627,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(level = "debug", skip(self), ret)] fn match_projection_obligation_against_definition_bounds( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = @@ -1700,7 +1690,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// variables or placeholders, the normalized bound is returned. fn match_normalize_trait_ref( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, ) -> Result<Option<ty::PolyTraitRef<'tcx>>, ()> { @@ -2101,7 +2091,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { impl<'tcx> SelectionContext<'_, 'tcx> { fn sized_conditions( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> BuiltinImplConditions<'tcx> { use self::BuiltinImplConditions::{Ambiguous, None, Where}; @@ -2161,7 +2151,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn copy_clone_conditions( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> BuiltinImplConditions<'tcx> { // NOTE: binder moved to (*) let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); @@ -2294,8 +2284,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn constituent_types_for_ty( &self, t: ty::Binder<'tcx, Ty<'tcx>>, - ) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> { - match *t.skip_binder().kind() { + ) -> Result<ty::Binder<'tcx, Vec<Ty<'tcx>>>, SelectionError<'tcx>> { + Ok(match *t.skip_binder().kind() { ty::Uint(_) | ty::Int(_) | ty::Bool @@ -2308,7 +2298,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Char => ty::Binder::dummy(Vec::new()), // Treat this like `struct str([u8]);` - ty::Str => ty::Binder::dummy(vec![self.tcx().mk_slice(self.tcx().types.u8)]), + ty::Str => ty::Binder::dummy(vec![Ty::new_slice(self.tcx(), self.tcx().types.u8)]), ty::Placeholder(..) | ty::Dynamic(..) @@ -2359,12 +2349,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { + let ty = self.tcx().type_of(def_id); + if ty.skip_binder().references_error() { + return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id)); + } // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. - t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)]) + t.rebind(vec![ty.subst(self.tcx(), substs)]) } - } + }) } fn collect_predicates_for_types( @@ -2433,7 +2427,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn rematch_impl( &mut self, impl_def_id: DefId, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Normalized<'tcx, SubstsRef<'tcx>> { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); match self.match_impl(impl_def_id, impl_trait_ref, obligation) { @@ -2454,7 +2448,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ), ); let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id); - let err = self.tcx().ty_error(guar); + let err = Ty::new_error(self.tcx(), guar); let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx(), ty_op: |_| err, @@ -2471,7 +2465,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { &mut self, impl_def_id: DefId, impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> { let placeholder_obligation = self.infcx.instantiate_binder_with_placeholders(obligation.predicate); @@ -2529,7 +2523,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { /// result from the normalization. fn match_where_clause_trait_ref( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, ()> { self.match_poly_trait_ref(obligation, where_clause_trait_ref) @@ -2540,7 +2534,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn match_poly_trait_ref( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, ()> { self.infcx @@ -2566,7 +2560,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn push_stack<'o>( &mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, - obligation: &'o TraitObligation<'tcx>, + obligation: &'o PolyTraitObligation<'tcx>, ) -> TraitObligationStack<'o, 'tcx> { let fresh_trait_pred = obligation.predicate.fold_with(&mut self.freshener); @@ -2585,7 +2579,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn closure_trait_ref_unnormalized( &mut self, - obligation: &TraitObligation<'tcx>, + obligation: &PolyTraitObligation<'tcx>, substs: SubstsRef<'tcx>, ) -> ty::PolyTraitRef<'tcx> { let closure_sig = substs.as_closure().sig(); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index b6c64c0196a..302b6cacf2c 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -265,7 +265,7 @@ pub fn closure_trait_ref_and_return_type<'tcx>( assert!(!self_ty.has_escaping_bound_vars()); let arguments_tuple = match tuple_arguments { TupleArgumentsFlag::No => sig.skip_binder().inputs()[0], - TupleArgumentsFlag::Yes => tcx.mk_tup(sig.skip_binder().inputs()), + TupleArgumentsFlag::Yes => Ty::new_tup(tcx, sig.skip_binder().inputs()), }; let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, arguments_tuple]); sig.map_bound(|sig| (trait_ref, sig.output())) diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index c05d557b774..1f83f1f44bc 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -362,7 +362,7 @@ pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( let trait_ref = ty::TraitRef::new(tcx, unsize_trait_did, [source, target]); - match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) { + match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) { Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => { implsrc_traitcasting.vtable_vptr_slot } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 86c7fc45ff7..d81722ce22a 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -302,6 +302,16 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec<traits::PredicateObligation<'tcx>> { + // Do not normalize `wf` obligations with the new solver. + // + // The current deep normalization routine with the new solver does not + // handle ambiguity and the new solver correctly deals with unnnormalized goals. + // If the user relies on normalized types, e.g. for `fn implied_outlives_bounds`, + // it is their responsibility to normalize while avoiding ambiguity. + if infcx.next_trait_solver() { + return self.out; + } + let cause = self.cause(traits::WellFormed(None)); let param_env = self.param_env; let mut obligations = Vec::with_capacity(self.out.len()); @@ -942,7 +952,7 @@ pub fn object_region_bounds<'tcx>( // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically // a placeholder type. - let open_ty = tcx.mk_fresh_ty(0); + let open_ty = Ty::new_fresh(tcx, 0); let predicates = existential_predicates.iter().filter_map(|predicate| { if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() { diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index ef50fa23caf..2cd1c3b502a 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -22,7 +22,7 @@ use rustc_trait_selection::traits::{ /// This also expects that `trait_ref` is fully normalized. pub fn codegen_select_candidate<'tcx>( tcx: TyCtxt<'tcx>, - (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), + (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>), ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { // We expect the input to be fully normalized. debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref)); diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 8e2a79dd4d4..55484f5c72e 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -64,7 +64,7 @@ fn fn_sig_for_fn_abi<'tcx>( // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. sig = sig.map_bound(|mut sig| { let mut inputs_and_output = sig.inputs_and_output.to_vec(); - inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); + inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]); sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); sig }); @@ -106,12 +106,13 @@ fn fn_sig_for_fn_abi<'tcx>( var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; - let env_ty = tcx.mk_mut_ref(ty::Region::new_late_bound(tcx, ty::INNERMOST, br), ty); + let env_ty = + Ty::new_mut_ref(tcx, ty::Region::new_late_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); let pin_adt_ref = tcx.adt_def(pin_did); let pin_substs = tcx.mk_substs(&[env_ty.into()]); - let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); + let env_ty = Ty::new_adt(tcx, pin_adt_ref, pin_substs); let sig = sig.skip_binder(); // The `FnSig` and the `ret_ty` here is for a generators main @@ -123,7 +124,7 @@ fn fn_sig_for_fn_abi<'tcx>( let poll_did = tcx.require_lang_item(LangItem::Poll, None); let poll_adt_ref = tcx.adt_def(poll_did); let poll_substs = tcx.mk_substs(&[sig.return_ty.into()]); - let ret_ty = tcx.mk_adt(poll_adt_ref, poll_substs); + let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_substs); // We have to replace the `ResumeTy` that is used for type and borrow checking // with `&mut Context<'_>` which is used in codegen. @@ -137,7 +138,7 @@ fn fn_sig_for_fn_abi<'tcx>( panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty); }; } - let context_mut_ref = tcx.mk_task_context(); + let context_mut_ref = Ty::new_task_context(tcx); (context_mut_ref, ret_ty) } else { @@ -145,7 +146,7 @@ fn fn_sig_for_fn_abi<'tcx>( let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); let state_adt_ref = tcx.adt_def(state_did); let state_substs = tcx.mk_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_substs); (sig.resume_ty, ret_ty) }; @@ -566,7 +567,7 @@ fn make_thin_self_ptr<'tcx>( let fat_pointer_ty = if layout.is_unsized() { // unsized `self` is passed as a pointer to `self` // FIXME (mikeyhew) change this to use &own if it is ever added to the language - tcx.mk_mut_ptr(layout.ty) + Ty::new_mut_ptr(tcx, layout.ty) } else { match layout.abi { Abi::ScalarPair(..) | Abi::Scalar(..) => (), @@ -600,7 +601,7 @@ fn make_thin_self_ptr<'tcx>( // we now have a type like `*mut RcBox<dyn Trait>` // change its layout to that of `*mut ()`, a thin pointer, but keep the same type // this is understood as a special case elsewhere in the compiler - let unit_ptr_ty = tcx.mk_mut_ptr(tcx.mk_unit()); + let unit_ptr_ty = Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)); TyAndLayout { ty: fat_pointer_ty, diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index b59458bbf35..897e7aad48b 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::definitions::DefPathData; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt}; +use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, Ty, TyCtxt}; use rustc_span::symbol::kw; pub fn provide(providers: &mut Providers) { @@ -301,7 +301,8 @@ fn associated_type_for_impl_trait_in_trait( trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id)); // Copy type_of of the opaque. - trait_assoc_ty.type_of(ty::EarlyBinder::bind(tcx.mk_opaque( + trait_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_opaque( + tcx, opaque_ty_def_id.to_def_id(), InternalSubsts::identity_for_item(tcx, opaque_ty_def_id), ))); @@ -337,6 +338,7 @@ fn associated_type_for_impl_trait_in_trait( param_def_id_to_index, has_self: opaque_ty_generics.has_self, has_late_bound_regions: opaque_ty_generics.has_late_bound_regions, + host_effect_index: parent_generics.host_effect_index, } }); @@ -415,6 +417,7 @@ fn associated_type_for_impl_trait_in_impl( param_def_id_to_index, has_self: false, has_late_bound_regions: trait_assoc_generics.has_late_bound_regions, + host_effect_index: parent_generics.host_effect_index, } }); diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index d79ed220570..426c98012b3 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -33,8 +33,10 @@ pub(crate) fn destructure_const<'tcx>( let (fields, variant) = match const_.ty().kind() { ty::Array(inner_ty, _) | ty::Slice(inner_ty) => { // construct the consts for the elements of the array/slice - let field_consts = - branches.iter().map(|b| tcx.mk_const(*b, *inner_ty)).collect::<Vec<_>>(); + let field_consts = branches + .iter() + .map(|b| ty::Const::new_value(tcx, *b, *inner_ty)) + .collect::<Vec<_>>(); debug!(?field_consts); (field_consts, None) @@ -52,7 +54,7 @@ pub(crate) fn destructure_const<'tcx>( for (field, field_valtree) in iter::zip(fields, branches) { let field_ty = field.ty(tcx, substs); - let field_const = tcx.mk_const(*field_valtree, field_ty); + let field_const = ty::Const::new_value(tcx, *field_valtree, field_ty); field_consts.push(field_const); } debug!(?field_consts); @@ -61,7 +63,7 @@ pub(crate) fn destructure_const<'tcx>( } ty::Tuple(elem_tys) => { let fields = iter::zip(*elem_tys, branches) - .map(|(elem_ty, elem_valtree)| tcx.mk_const(*elem_valtree, elem_ty)) + .map(|(elem_ty, elem_valtree)| ty::Const::new_value(tcx, *elem_valtree, elem_ty)) .collect::<Vec<_>>(); (fields, None) @@ -117,7 +119,7 @@ fn recurse_build<'tcx>( let sp = node.span; match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) { Ok(c) => c, - Err(LitToConstError::Reported(guar)) => tcx.const_error(node.ty, guar), + Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar, node.ty), Err(LitToConstError::TypeError) => { bug!("encountered type error in lit_to_const") } @@ -125,17 +127,17 @@ fn recurse_build<'tcx>( } &ExprKind::NonHirLiteral { lit, user_ty: _ } => { let val = ty::ValTree::from_scalar_int(lit); - tcx.mk_const(val, node.ty) + ty::Const::new_value(tcx, val, node.ty) } &ExprKind::ZstLiteral { user_ty: _ } => { let val = ty::ValTree::zst(); - tcx.mk_const(val, node.ty) + ty::Const::new_value(tcx, val, node.ty) } &ExprKind::NamedConst { def_id, substs, user_ty: _ } => { let uneval = ty::UnevaluatedConst::new(def_id, substs); - tcx.mk_const(uneval, node.ty) + ty::Const::new_unevaluated(tcx, uneval, node.ty) } - ExprKind::ConstParam { param, .. } => tcx.mk_const(*param, node.ty), + ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param, node.ty), ExprKind::Call { fun, args, .. } => { let fun = recurse_build(tcx, body, *fun, root_span)?; @@ -145,16 +147,16 @@ fn recurse_build<'tcx>( new_args.push(recurse_build(tcx, body, id, root_span)?); } let new_args = tcx.mk_const_list(&new_args); - tcx.mk_const(Expr::FunctionCall(fun, new_args), node.ty) + ty::Const::new_expr(tcx, Expr::FunctionCall(fun, new_args), node.ty) } &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => { let lhs = recurse_build(tcx, body, lhs, root_span)?; let rhs = recurse_build(tcx, body, rhs, root_span)?; - tcx.mk_const(Expr::Binop(op, lhs, rhs), node.ty) + ty::Const::new_expr(tcx, Expr::Binop(op, lhs, rhs), node.ty) } &ExprKind::Unary { op, arg } if check_unop(op) => { let arg = recurse_build(tcx, body, arg, root_span)?; - tcx.mk_const(Expr::UnOp(op, arg), node.ty) + ty::Const::new_expr(tcx, Expr::UnOp(op, arg), node.ty) } // This is necessary so that the following compiles: // @@ -175,11 +177,11 @@ fn recurse_build<'tcx>( // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested) &ExprKind::Use { source } => { let arg = recurse_build(tcx, body, source, root_span)?; - tcx.mk_const(Expr::Cast(CastKind::Use, arg, node.ty), node.ty) + ty::Const::new_expr(tcx, Expr::Cast(CastKind::Use, arg, node.ty), node.ty) } &ExprKind::Cast { source } => { let arg = recurse_build(tcx, body, source, root_span)?; - tcx.mk_const(Expr::Cast(CastKind::As, arg, node.ty), node.ty) + ty::Const::new_expr(tcx, Expr::Cast(CastKind::As, arg, node.ty), node.ty) } ExprKind::Borrow { arg, .. } => { let arg_node = &body.exprs[*arg]; @@ -219,7 +221,7 @@ fn recurse_build<'tcx>( maybe_supported_error(GenericConstantTooComplexSub::AdtNotSupported(node.span))? } // dont know if this is correct - ExprKind::Pointer { .. } => { + ExprKind::PointerCoercion { .. } => { error(GenericConstantTooComplexSub::PointerNotSupported(node.span))? } ExprKind::Yield { .. } => { @@ -322,7 +324,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { | thir::ExprKind::Cast { .. } | thir::ExprKind::Use { .. } | thir::ExprKind::NeverToAny { .. } - | thir::ExprKind::Pointer { .. } + | thir::ExprKind::PointerCoercion { .. } | thir::ExprKind::Loop { .. } | thir::ExprKind::Let { .. } | thir::ExprKind::Match { .. } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 2d75862014d..1d93a79e591 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -80,7 +80,7 @@ fn resolve_associated_item<'tcx>( let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = match tcx.codegen_select_candidate((param_env, ty::Binder::dummy(trait_ref))) { + let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) { Ok(vtbl) => vtbl, Err(CodegenObligationError::Ambiguity) => { let reported = tcx.sess.delay_span_bug( diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index ac015ddcb49..b67cd96a734 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -159,7 +159,7 @@ fn layout_of_uncached<'tcx>( // fall back to structurally deducing metadata. && !pointee.references_error() { - let pointee_metadata = tcx.mk_projection(metadata_def_id, [pointee]); + let pointee_metadata = Ty::new_projection(tcx,metadata_def_id, [pointee]); let metadata_ty = match tcx.try_normalize_erasing_regions( param_env, pointee_metadata, @@ -463,38 +463,85 @@ fn layout_of_uncached<'tcx>( )); } - tcx.mk_layout( - cx.layout_of_struct_or_enum( + let get_discriminant_type = + |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max); + + let discriminants_iter = || { + def.is_enum() + .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128))) + .into_iter() + .flatten() + }; + + let dont_niche_optimize_enum = def.repr().inhibit_enum_layout_opt() + || def + .variants() + .iter_enumerated() + .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32())); + + let maybe_unsized = def.is_struct() + && def.non_enum_variant().tail_opt().is_some_and(|last_field| { + let param_env = tcx.param_env(def.did()); + !tcx.type_of(last_field.did).subst_identity().is_sized(tcx, param_env) + }); + + let Some(layout) = cx.layout_of_struct_or_enum( + &def.repr(), + &variants, + def.is_enum(), + def.is_unsafe_cell(), + tcx.layout_scalar_valid_range(def.did()), + get_discriminant_type, + discriminants_iter(), + dont_niche_optimize_enum, + !maybe_unsized, + ) else { + return Err(error(cx, LayoutError::SizeOverflow(ty))); + }; + + // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around. + if cfg!(debug_assertions) + && maybe_unsized + && def.non_enum_variant().tail().ty(tcx, substs).is_sized(tcx, cx.param_env) + { + let mut variants = variants; + let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap(); + *variants[FIRST_VARIANT].raw.last_mut().unwrap() = tail_replacement.layout; + + let Some(unsized_layout) = cx.layout_of_struct_or_enum( &def.repr(), &variants, def.is_enum(), def.is_unsafe_cell(), tcx.layout_scalar_valid_range(def.did()), - |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max), - def.is_enum() - .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128))) - .into_iter() - .flatten(), - def.repr().inhibit_enum_layout_opt() - || def - .variants() - .iter_enumerated() - .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32())), - { - let param_env = tcx.param_env(def.did()); - def.is_struct() - && match def.variants().iter().next().and_then(|x| x.fields.raw.last()) - { - Some(last_field) => tcx - .type_of(last_field.did) - .subst_identity() - .is_sized(tcx, param_env), - None => false, - } - }, - ) - .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?, - ) + get_discriminant_type, + discriminants_iter(), + dont_niche_optimize_enum, + !maybe_unsized, + ) else { + bug!("failed to compute unsized layout of {ty:?}"); + }; + + let FieldsShape::Arbitrary { offsets: sized_offsets, .. } = &layout.fields else { + bug!("unexpected FieldsShape for sized layout of {ty:?}: {:?}", layout.fields); + }; + let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } = &unsized_layout.fields else { + bug!("unexpected FieldsShape for unsized layout of {ty:?}: {:?}", unsized_layout.fields); + }; + + let (sized_tail, sized_fields) = sized_offsets.raw.split_last().unwrap(); + let (unsized_tail, unsized_fields) = unsized_offsets.raw.split_last().unwrap(); + + if sized_fields != unsized_fields { + bug!("unsizing {ty:?} changed field order!\n{layout:?}\n{unsized_layout:?}"); + } + + if sized_tail < unsized_tail { + bug!("unsizing {ty:?} moved tail backwards!\n{layout:?}\n{unsized_layout:?}"); + } + } + + tcx.mk_layout(layout) } // Types with no meaningful known layout. @@ -672,7 +719,7 @@ fn generator_layout<'tcx>( let promoted_layouts = ineligible_locals .iter() .map(|local| subst_field(info.field_tys[local].ty)) - .map(|ty| tcx.mk_maybe_uninit(ty)) + .map(|ty| Ty::new_maybe_uninit(tcx, ty)) .map(|ty| Ok(cx.layout_of(ty)?.layout)); let prefix_layouts = substs .as_generator() diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 29de8bf0e53..570c3b245cd 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -1,5 +1,7 @@ use rustc_data_structures::fx::FxHashSet; +use rustc_hir::intravisit::Visitor; use rustc_hir::{def::DefKind, def_id::LocalDefId}; +use rustc_hir::{intravisit, CRATE_HIR_ID}; use rustc_middle::query::Providers; use rustc_middle::ty::util::{CheckRegions, NotUniqueParam}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -51,7 +53,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { fn parent(&self) -> Option<LocalDefId> { match self.tcx.def_kind(self.item) { - DefKind::Fn => None, + DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias => None, DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { Some(self.tcx.local_parent(self.item)) } @@ -61,6 +63,73 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { ), } } + + /// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `self.item`. + /// + /// Example: + /// ```ignore UNSOLVED (is this a bug?) + /// # #![feature(type_alias_impl_trait)] + /// pub mod foo { + /// pub mod bar { + /// pub trait Bar { /* ... */ } + /// pub type Baz = impl Bar; + /// + /// # impl Bar for () {} + /// fn f1() -> Baz { /* ... */ } + /// } + /// fn f2() -> bar::Baz { /* ... */ } + /// } + /// ``` + /// + /// and `opaque_def_id` is the `DefId` of the definition of the opaque type `Baz`. + /// For the above example, this function returns `true` for `f1` and `false` for `f2`. + #[instrument(level = "trace", skip(self), ret)] + fn check_tait_defining_scope(&self, opaque_def_id: LocalDefId) -> bool { + let mut hir_id = self.tcx.hir().local_def_id_to_hir_id(self.item); + let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(opaque_def_id); + + // Named opaque types can be defined by any siblings or children of siblings. + let scope = self.tcx.hir().get_defining_scope(opaque_hir_id); + // We walk up the node tree until we hit the root or the scope of the opaque type. + while hir_id != scope && hir_id != CRATE_HIR_ID { + hir_id = self.tcx.hir().get_parent_item(hir_id).into(); + } + // Syntactically, we are allowed to define the concrete type if: + hir_id == scope + } + + fn collect_body_and_predicate_taits(&mut self) { + // Look at all where bounds. + self.tcx.predicates_of(self.item).instantiate_identity(self.tcx).visit_with(self); + // An item is allowed to constrain opaques declared within its own body (but not nested within + // nested functions). + self.collect_taits_declared_in_body(); + } + + #[instrument(level = "trace", skip(self))] + fn collect_taits_declared_in_body(&mut self) { + let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(self.item)).value; + struct TaitInBodyFinder<'a, 'tcx> { + collector: &'a mut OpaqueTypeCollector<'tcx>, + } + impl<'v> intravisit::Visitor<'v> for TaitInBodyFinder<'_, '_> { + #[instrument(level = "trace", skip(self))] + fn visit_nested_item(&mut self, id: rustc_hir::ItemId) { + let id = id.owner_id.def_id; + if let DefKind::TyAlias = self.collector.tcx.def_kind(id) { + let items = self.collector.tcx.opaque_types_defined_by(id); + self.collector.opaques.extend(items); + } + } + #[instrument(level = "trace", skip(self))] + // Recurse into these, as they are type checked with their parent + fn visit_nested_body(&mut self, id: rustc_hir::BodyId) { + let body = self.collector.tcx.hir().body(id); + self.visit_body(body); + } + } + TaitInBodyFinder { collector: self }.visit_expr(body); + } } impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { @@ -73,6 +142,21 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { return ControlFlow::Continue(()); } + // TAITs outside their defining scopes are ignored. + let origin = self.tcx.opaque_type_origin(alias_ty.def_id.expect_local()); + trace!(?origin); + match origin { + rustc_hir::OpaqueTyOrigin::FnReturn(_) + | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {} + rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => { + if !in_assoc_ty { + if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) { + return ControlFlow::Continue(()); + } + } + } + } + self.opaques.push(alias_ty.def_id.expect_local()); match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) { @@ -188,33 +272,36 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [LocalDefId] { let kind = tcx.def_kind(item); trace!(?kind); - // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT and impl trait in assoc types. + let mut collector = OpaqueTypeCollector::new(tcx, item); match kind { + // Walk over the signature of the function-like to find the opaques. + DefKind::AssocFn | DefKind::Fn => { + let ty_sig = tcx.fn_sig(item).subst_identity(); + let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap(); + // Walk over the inputs and outputs manually in order to get good spans for them. + collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output()); + for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) { + collector.visit_spanned(hir.span, ty.map_bound(|x| *x)); + } + collector.collect_body_and_predicate_taits(); + } + // Walk over the type of the item to find opaques. + DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { + let span = match tcx.hir().get_by_def_id(item).ty() { + Some(ty) => ty.span, + _ => tcx.def_span(item), + }; + collector.visit_spanned(span, tcx.type_of(item).subst_identity()); + collector.collect_body_and_predicate_taits(); + } // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds` - DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { - let mut collector = OpaqueTypeCollector::new(tcx, item); - match kind { - // Walk over the signature of the function-like to find the opaques. - DefKind::AssocFn | DefKind::Fn => { - let ty_sig = tcx.fn_sig(item).subst_identity(); - let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap(); - // Walk over the inputs and outputs manually in order to get good spans for them. - collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output()); - for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) { - collector.visit_spanned(hir.span, ty.map_bound(|x| *x)); - } - } - // Walk over the type of the item to find opaques. - DefKind::AssocTy | DefKind::AssocConst => { - let span = match tcx.hir().get_by_def_id(item).ty() { - Some(ty) => ty.span, - _ => tcx.def_span(item), - }; - collector.visit_spanned(span, tcx.type_of(item).subst_identity()); - } - _ => unreachable!(), + DefKind::TyAlias | DefKind::AssocTy => { + tcx.type_of(item).subst_identity().visit_with(&mut collector); + } + DefKind::OpaqueTy => { + for (pred, span) in tcx.explicit_item_bounds(item).subst_identity_iter_copied() { + collector.visit_spanned(span, pred); } - tcx.arena.alloc_from_iter(collector.opaques) } DefKind::Mod | DefKind::Struct @@ -222,31 +309,26 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::TyParam - | DefKind::Const | DefKind::ConstParam - | DefKind::Static(_) | DefKind::Ctor(_, _) | DefKind::Macro(_) | DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Impl { .. } - | DefKind::Closure - | DefKind::Generator => { - span_bug!(tcx.def_span(item), "{kind:?} is type checked as part of its parent") + | DefKind::Impl { .. } => {} + // Closures and generators are type checked with their parent, so there is no difference here. + DefKind::Closure | DefKind::Generator | DefKind::InlineConst => { + return tcx.opaque_types_defined_by(tcx.local_parent(item)); } } + tcx.arena.alloc_from_iter(collector.opaques) } pub(super) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 620db143582..6e5c50492c6 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -95,7 +95,7 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { if let Some(def_id) = def_id.as_local() { if matches!(tcx.representability(def_id), ty::Representability::Infinite) { - return tcx.mk_type_list(&[tcx.ty_error_misc()]); + return tcx.mk_type_list(&[Ty::new_misc_error(tcx)]); } } let def = tcx.adt_def(def_id); @@ -103,7 +103,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { let result = tcx.mk_type_list_from_iter( def.variants() .iter() - .filter_map(|v| v.fields.raw.last()) + .filter_map(|v| v.tail_opt()) .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())), ); @@ -285,7 +285,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() { self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs) } else { - self.tcx.mk_alias(ty::Opaque, shifted_alias_ty) + Ty::new_alias(self.tcx,ty::Opaque, shifted_alias_ty) }; self.predicates.push( diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index ae16fbb162e..878a6b784ed 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -57,11 +57,19 @@ pub trait Interner: Sized { type ParamTy: Clone + Debug + Hash + Ord; type BoundTy: Clone + Debug + Hash + Ord; type PlaceholderType: Clone + Debug + Hash + Ord; - type InferTy: Clone + Debug + Hash + Ord; type ErrorGuaranteed: Clone + Debug + Hash + Ord; type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; type AllocId: Clone + Debug + Hash + Ord; + type InferConst: Clone + Debug + Hash + Ord; + type AliasConst: Clone + Debug + Hash + Ord; + type PlaceholderConst: Clone + Debug + Hash + Ord; + type ParamConst: Clone + Debug + Hash + Ord; + type BoundConst: Clone + Debug + Hash + Ord; + type InferTy: Clone + Debug + Hash + Ord; + type ValueConst: Clone + Debug + Hash + Ord; + type ExprConst: Clone + Debug + Hash + Ord; + type EarlyBoundRegion: Clone + Debug + Hash + Ord; type BoundRegion: Clone + Debug + Hash + Ord; type FreeRegion: Clone + Debug + Hash + Ord; diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 553d7f31b2d..1e42175f6e3 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -4,7 +4,7 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; -use crate::{FloatTy, IntTy, Interner, UintTy}; +use crate::{ConstKind, FloatTy, IntTy, Interner, UintTy}; use rustc_data_structures::functor::IdFunctor; use rustc_data_structures::sync::Lrc; use rustc_index::{Idx, IndexVec}; @@ -182,3 +182,21 @@ impl fmt::Debug for FloatTy { write!(f, "{}", self.name_str()) } } + +impl<I: Interner> fmt::Debug for ConstKind<I> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use ConstKind::*; + match self { + Param(param) => write!(f, "{param:?}"), + Infer(var) => write!(f, "{var:?}"), + Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()), + Placeholder(placeholder) => write!(f, "{placeholder:?}"), + Unevaluated(uv) => { + write!(f, "{uv:?}") + } + Value(valtree) => write!(f, "{valtree:?}"), + Error(_) => write!(f, "{{const error}}"), + Expr(expr) => write!(f, "{expr:?}"), + } + } +} diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index f621673f1d6..b696f9b9b59 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -876,6 +876,224 @@ where } } +/// Represents a constant in Rust. +// #[derive(derive_more::From)] +pub enum ConstKind<I: Interner> { + /// A const generic parameter. + Param(I::ParamConst), + + /// Infer the value of the const. + Infer(I::InferConst), + + /// Bound const variable, used only when preparing a trait query. + Bound(DebruijnIndex, I::BoundConst), + + /// A placeholder const - universally quantified higher-ranked const. + Placeholder(I::PlaceholderConst), + + /// An unnormalized const item such as an anon const or assoc const or free const item. + /// Right now anything other than anon consts does not actually work properly but this + /// should + Unevaluated(I::AliasConst), + + /// Used to hold computed value. + Value(I::ValueConst), + + /// A placeholder for a const which could not be computed; this is + /// propagated to avoid useless error messages. + Error(I::ErrorGuaranteed), + + /// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent + /// const arguments such as `N + 1` or `foo(N)` + Expr(I::ExprConst), +} + +const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize { + match value { + ConstKind::Param(_) => 0, + ConstKind::Infer(_) => 1, + ConstKind::Bound(_, _) => 2, + ConstKind::Placeholder(_) => 3, + ConstKind::Unevaluated(_) => 4, + ConstKind::Value(_) => 5, + ConstKind::Error(_) => 6, + ConstKind::Expr(_) => 7, + } +} + +impl<I: Interner> hash::Hash for ConstKind<I> { + fn hash<H: hash::Hasher>(&self, state: &mut H) { + const_kind_discriminant(self).hash(state); + match self { + ConstKind::Param(p) => p.hash(state), + ConstKind::Infer(i) => i.hash(state), + ConstKind::Bound(d, b) => { + d.hash(state); + b.hash(state); + } + ConstKind::Placeholder(p) => p.hash(state), + ConstKind::Unevaluated(u) => u.hash(state), + ConstKind::Value(v) => v.hash(state), + ConstKind::Error(e) => e.hash(state), + ConstKind::Expr(e) => e.hash(state), + } + } +} + +impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I> +where + I::ParamConst: HashStable<CTX>, + I::InferConst: HashStable<CTX>, + I::BoundConst: HashStable<CTX>, + I::PlaceholderConst: HashStable<CTX>, + I::AliasConst: HashStable<CTX>, + I::ValueConst: HashStable<CTX>, + I::ErrorGuaranteed: HashStable<CTX>, + I::ExprConst: HashStable<CTX>, +{ + fn hash_stable( + &self, + hcx: &mut CTX, + hasher: &mut rustc_data_structures::stable_hasher::StableHasher, + ) { + const_kind_discriminant(self).hash_stable(hcx, hasher); + match self { + ConstKind::Param(p) => p.hash_stable(hcx, hasher), + ConstKind::Infer(i) => i.hash_stable(hcx, hasher), + ConstKind::Bound(d, b) => { + d.hash_stable(hcx, hasher); + b.hash_stable(hcx, hasher); + } + ConstKind::Placeholder(p) => p.hash_stable(hcx, hasher), + ConstKind::Unevaluated(u) => u.hash_stable(hcx, hasher), + ConstKind::Value(v) => v.hash_stable(hcx, hasher), + ConstKind::Error(e) => e.hash_stable(hcx, hasher), + ConstKind::Expr(e) => e.hash_stable(hcx, hasher), + } + } +} + +impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I> +where + I::ParamConst: Decodable<D>, + I::InferConst: Decodable<D>, + I::BoundConst: Decodable<D>, + I::PlaceholderConst: Decodable<D>, + I::AliasConst: Decodable<D>, + I::ValueConst: Decodable<D>, + I::ErrorGuaranteed: Decodable<D>, + I::ExprConst: Decodable<D>, +{ + fn decode(d: &mut D) -> Self { + match Decoder::read_usize(d) { + 0 => ConstKind::Param(Decodable::decode(d)), + 1 => ConstKind::Infer(Decodable::decode(d)), + 2 => ConstKind::Bound(Decodable::decode(d), Decodable::decode(d)), + 3 => ConstKind::Placeholder(Decodable::decode(d)), + 4 => ConstKind::Unevaluated(Decodable::decode(d)), + 5 => ConstKind::Value(Decodable::decode(d)), + 6 => ConstKind::Error(Decodable::decode(d)), + 7 => ConstKind::Expr(Decodable::decode(d)), + _ => panic!( + "{}", + format!( + "invalid enum variant tag while decoding `{}`, expected 0..{}", + "ConstKind", 8, + ) + ), + } + } +} + +impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I> +where + I::ParamConst: Encodable<E>, + I::InferConst: Encodable<E>, + I::BoundConst: Encodable<E>, + I::PlaceholderConst: Encodable<E>, + I::AliasConst: Encodable<E>, + I::ValueConst: Encodable<E>, + I::ErrorGuaranteed: Encodable<E>, + I::ExprConst: Encodable<E>, +{ + fn encode(&self, e: &mut E) { + let disc = const_kind_discriminant(self); + match self { + ConstKind::Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)), + ConstKind::Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)), + ConstKind::Bound(d, b) => e.emit_enum_variant(disc, |e| { + d.encode(e); + b.encode(e); + }), + ConstKind::Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)), + ConstKind::Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)), + ConstKind::Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)), + ConstKind::Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)), + ConstKind::Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)), + } + } +} + +impl<I: Interner> PartialOrd for ConstKind<I> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl<I: Interner> Ord for ConstKind<I> { + fn cmp(&self, other: &Self) -> Ordering { + const_kind_discriminant(self) + .cmp(&const_kind_discriminant(other)) + .then_with(|| match (self, other) { + (ConstKind::Param(p1), ConstKind::Param(p2)) => p1.cmp(p2), + (ConstKind::Infer(i1), ConstKind::Infer(i2)) => i1.cmp(i2), + (ConstKind::Bound(d1, b1), ConstKind::Bound(d2, b2)) => d1.cmp(d2).then_with(|| b1.cmp(b2)), + (ConstKind::Placeholder(p1), ConstKind::Placeholder(p2)) => p1.cmp(p2), + (ConstKind::Unevaluated(u1), ConstKind::Unevaluated(u2)) => u1.cmp(u2), + (ConstKind::Value(v1), ConstKind::Value(v2)) => v1.cmp(v2), + (ConstKind::Error(e1), ConstKind::Error(e2)) => e1.cmp(e2), + (ConstKind::Expr(e1), ConstKind::Expr(e2)) => e1.cmp(e2), + _ => { + debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"); + Ordering::Equal + } + }) + } +} + +impl<I: Interner> PartialEq for ConstKind<I> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Param(l0), Self::Param(r0)) => l0 == r0, + (Self::Infer(l0), Self::Infer(r0)) => l0 == r0, + (Self::Bound(l0, l1), Self::Bound(r0, r1)) => l0 == r0 && l1 == r1, + (Self::Placeholder(l0), Self::Placeholder(r0)) => l0 == r0, + (Self::Unevaluated(l0), Self::Unevaluated(r0)) => l0 == r0, + (Self::Value(l0), Self::Value(r0)) => l0 == r0, + (Self::Error(l0), Self::Error(r0)) => l0 == r0, + (Self::Expr(l0), Self::Expr(r0)) => l0 == r0, + _ => false, + } + } +} + +impl<I: Interner> Eq for ConstKind<I> {} + +impl<I: Interner> Clone for ConstKind<I> { + fn clone(&self) -> Self { + match self { + Self::Param(arg0) => Self::Param(arg0.clone()), + Self::Infer(arg0) => Self::Infer(arg0.clone()), + Self::Bound(arg0, arg1) => Self::Bound(arg0.clone(), arg1.clone()), + Self::Placeholder(arg0) => Self::Placeholder(arg0.clone()), + Self::Unevaluated(arg0) => Self::Unevaluated(arg0.clone()), + Self::Value(arg0) => Self::Value(arg0.clone()), + Self::Error(arg0) => Self::Error(arg0.clone()), + Self::Expr(arg0) => Self::Expr(arg0.clone()), + } + } +} + /// Representation of regions. Note that the NLL checker uses a distinct /// representation of regions. For this reason, it internally replaces all the /// regions with inference variables -- the index of the variable is then used diff --git a/config.example.toml b/config.example.toml index 0c65b25fe13..367f95b156f 100644 --- a/config.example.toml +++ b/config.example.toml @@ -400,10 +400,20 @@ changelog-seen = 2 # ============================================================================= [rust] -# Whether or not to optimize the compiler and standard library. +# Whether or not to optimize when compiling the compiler and standard library, +# and what level of optimization to use. # WARNING: Building with optimize = false is NOT SUPPORTED. Due to bootstrapping, # building without optimizations takes much longer than optimizing. Further, some platforms # fail to build without this optimization (c.f. #65352). +# The valid options are: +# true - Enable optimizations. +# false - Disable optimizations. +# 0 - Disable optimizations. +# 1 - Basic optimizations. +# 2 - Some optimizations. +# 3 - All optimizations. +# "s" - Optimize for binary size. +# "z" - Optimize for binary size, but also turn off loop vectorization. #optimize = true # Indicates that the build should be configured for debugging Rust. A @@ -757,7 +767,7 @@ changelog-seen = 2 # This option will override the same option under [build] section. #profiler = build.profiler (bool) -# This option supports enable `rpath` in each target independently, +# This option supports enable `rpath` in each target independently, # and will override the same option under [rust] section. It only works on Unix platforms #rpath = rust.rpath (bool) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index fa23367593d..8ef2bac9282 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1319,56 +1319,39 @@ impl Clone for Box<str> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T, A1, A2> PartialEq<Box<T, A2>> for Box<T, A1> -where - T: ?Sized + PartialEq, - A1: Allocator, - A2: Allocator, -{ +impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for Box<T, A> { #[inline] - fn eq(&self, other: &Box<T, A2>) -> bool { + fn eq(&self, other: &Self) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &Box<T, A2>) -> bool { + fn ne(&self, other: &Self) -> bool { PartialEq::ne(&**self, &**other) } } - #[stable(feature = "rust1", since = "1.0.0")] -impl<T, A1, A2> PartialOrd<Box<T, A2>> for Box<T, A1> -where - T: ?Sized + PartialOrd, - A1: Allocator, - A2: Allocator, -{ +impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for Box<T, A> { #[inline] - fn partial_cmp(&self, other: &Box<T, A2>) -> Option<Ordering> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { PartialOrd::partial_cmp(&**self, &**other) } - #[inline] - fn lt(&self, other: &Box<T, A2>) -> bool { + fn lt(&self, other: &Self) -> bool { PartialOrd::lt(&**self, &**other) } - #[inline] - fn le(&self, other: &Box<T, A2>) -> bool { + fn le(&self, other: &Self) -> bool { PartialOrd::le(&**self, &**other) } - #[inline] - fn ge(&self, other: &Box<T, A2>) -> bool { + fn ge(&self, other: &Self) -> bool { PartialOrd::ge(&**self, &**other) } - #[inline] - fn gt(&self, other: &Box<T, A2>) -> bool { + fn gt(&self, other: &Self) -> bool { PartialOrd::gt(&**self, &**other) } } - #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized + Ord, A: Allocator> Ord for Box<T, A> { #[inline] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 21824c8a17c..ddd93e9a436 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1906,6 +1906,7 @@ fn test_stable_pointers() { assert_eq!(*v0, 13); // Smoke test that would fire even outside Miri if an actual relocation happened. + // Also ensures the pointer is still writeable after all this. *v0 -= 13; assert_eq!(v[0], 0); } diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 1f7be85d38a..5242e97eb9a 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -133,51 +133,6 @@ pub trait Default: Sized { fn default() -> Self; } -/// Return the default value of a type according to the `Default` trait. -/// -/// The type to return is inferred from context; this is equivalent to -/// `Default::default()` but shorter to type. -/// -/// For example: -/// ``` -/// #![feature(default_free_fn)] -/// -/// use std::default::default; -/// -/// #[derive(Default)] -/// struct AppConfig { -/// foo: FooConfig, -/// bar: BarConfig, -/// } -/// -/// #[derive(Default)] -/// struct FooConfig { -/// foo: i32, -/// } -/// -/// #[derive(Default)] -/// struct BarConfig { -/// bar: f32, -/// baz: u8, -/// } -/// -/// fn main() { -/// let options = AppConfig { -/// foo: default(), -/// bar: BarConfig { -/// bar: 10.1, -/// ..default() -/// }, -/// }; -/// } -/// ``` -#[unstable(feature = "default_free_fn", issue = "73014")] -#[must_use] -#[inline] -pub fn default<T: Default>() -> T { - Default::default() -} - /// Derive macro generating an impl of the trait `Default`. #[rustc_builtin_macro(Default, attributes(default))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 7437722fd06..0488c807604 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -132,7 +132,12 @@ mod c_char_definition { ), all( target_os = "netbsd", - any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc") + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "riscv64" + ) ), all( target_os = "vxworks", diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5d6e7dcfcee..e2a2428fbc2 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -851,6 +851,8 @@ impl<T> [T] { /// Swaps two elements in the slice. /// + /// If `a` equals to `b`, it's guaranteed that elements won't change value. + /// /// # Arguments /// /// * a - The index of the first element diff --git a/library/core/tests/future.rs b/library/core/tests/future.rs index 74b6f74e401..db417256dd0 100644 --- a/library/core/tests/future.rs +++ b/library/core/tests/future.rs @@ -30,7 +30,6 @@ fn poll_n(val: usize, num: usize) -> PollN { } #[test] -#[cfg_attr(miri, ignore)] // self-referential generators do not work with Miri's aliasing checks fn test_join() { block_on(async move { let x = join!(async { 0 }).await; diff --git a/library/portable-simd/.github/workflows/ci.yml b/library/portable-simd/.github/workflows/ci.yml index acd47a3da72..1ff377fce34 100644 --- a/library/portable-simd/.github/workflows/ci.yml +++ b/library/portable-simd/.github/workflows/ci.yml @@ -38,8 +38,9 @@ jobs: - i586-unknown-linux-gnu - aarch64-unknown-linux-gnu - armv7-unknown-linux-gnueabihf - - mips-unknown-linux-gnu - - mips64-unknown-linux-gnuabi64 + # non-nightly since https://github.com/rust-lang/rust/pull/113274 + # - mips-unknown-linux-gnu + # - mips64-unknown-linux-gnuabi64 - powerpc-unknown-linux-gnu - powerpc64-unknown-linux-gnu - riscv64gc-unknown-linux-gnu @@ -191,8 +192,8 @@ jobs: # Note: The issue above means neither of these mips targets will use # MSA (mips simd) but MIPS uses a nonstandard binary representation # for NaNs which makes it worth testing on despite that. - - mips-unknown-linux-gnu - - mips64-unknown-linux-gnuabi64 + # - mips-unknown-linux-gnu + # - mips64-unknown-linux-gnuabi64 - riscv64gc-unknown-linux-gnu # TODO this test works, but it appears to time out # - powerpc-unknown-linux-gnu diff --git a/library/portable-simd/crates/core_simd/src/cast.rs b/library/portable-simd/crates/core_simd/src/cast.rs index 65a3f845ffc..1c3592f8075 100644 --- a/library/portable-simd/crates/core_simd/src/cast.rs +++ b/library/portable-simd/crates/core_simd/src/cast.rs @@ -1,55 +1,51 @@ use crate::simd::SimdElement; +mod sealed { + /// Cast vector elements to other types. + /// + /// # Safety + /// Implementing this trait asserts that the type is a valid vector element for the `simd_cast` + /// or `simd_as` intrinsics. + pub unsafe trait Sealed {} +} +use sealed::Sealed; + /// Supporting trait for `Simd::cast`. Typically doesn't need to be used directly. -/// -/// # Safety -/// Implementing this trait asserts that the type is a valid vector element for the `simd_cast` or -/// `simd_as` intrinsics. -pub unsafe trait SimdCast: SimdElement {} +pub trait SimdCast: Sealed + SimdElement {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for i8 {} +unsafe impl Sealed for i8 {} +impl SimdCast for i8 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for i16 {} +unsafe impl Sealed for i16 {} +impl SimdCast for i16 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for i32 {} +unsafe impl Sealed for i32 {} +impl SimdCast for i32 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for i64 {} +unsafe impl Sealed for i64 {} +impl SimdCast for i64 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for isize {} +unsafe impl Sealed for isize {} +impl SimdCast for isize {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for u8 {} +unsafe impl Sealed for u8 {} +impl SimdCast for u8 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for u16 {} +unsafe impl Sealed for u16 {} +impl SimdCast for u16 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for u32 {} +unsafe impl Sealed for u32 {} +impl SimdCast for u32 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for u64 {} +unsafe impl Sealed for u64 {} +impl SimdCast for u64 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for usize {} +unsafe impl Sealed for usize {} +impl SimdCast for usize {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for f32 {} +unsafe impl Sealed for f32 {} +impl SimdCast for f32 {} // Safety: primitive number types can be cast to other primitive number types -unsafe impl SimdCast for f64 {} - -/// Supporting trait for `Simd::cast_ptr`. Typically doesn't need to be used directly. -/// -/// # Safety -/// Implementing this trait asserts that the type is a valid vector element for the `simd_cast_ptr` -/// intrinsic. -pub unsafe trait SimdCastPtr<T> {} - -// Safety: pointers can be cast to other pointer types -unsafe impl<T, U> SimdCastPtr<T> for *const U -where - U: core::ptr::Pointee, - T: core::ptr::Pointee<Metadata = U::Metadata>, -{ -} -// Safety: pointers can be cast to other pointer types -unsafe impl<T, U> SimdCastPtr<T> for *mut U -where - U: core::ptr::Pointee, - T: core::ptr::Pointee<Metadata = U::Metadata>, -{ -} +unsafe impl Sealed for f64 {} +impl SimdCast for f64 {} diff --git a/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs b/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs index 0ef9802b5e2..f215f9a61d0 100644 --- a/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SupportedLaneCount}; +use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SimdUint, SupportedLaneCount}; /// Operations on SIMD vectors of constant pointers. pub trait SimdConstPtr: Copy + Sealed { @@ -9,6 +9,9 @@ pub trait SimdConstPtr: Copy + Sealed { /// Vector of `isize` with the same number of lanes. type Isize; + /// Vector of const pointers with the same number of lanes. + type CastPtr<T>; + /// Vector of mutable pointers to the same type. type MutPtr; @@ -18,6 +21,11 @@ pub trait SimdConstPtr: Copy + Sealed { /// Returns `true` for each lane that is null. fn is_null(self) -> Self::Mask; + /// Casts to a pointer of another type. + /// + /// Equivalent to calling [`pointer::cast`] on each lane. + fn cast<T>(self) -> Self::CastPtr<T>; + /// Changes constness without changing the type. /// /// Equivalent to calling [`pointer::cast_mut`] on each lane. @@ -78,6 +86,7 @@ where { type Usize = Simd<usize, LANES>; type Isize = Simd<isize, LANES>; + type CastPtr<U> = Simd<*const U, LANES>; type MutPtr = Simd<*mut T, LANES>; type Mask = Mask<isize, LANES>; @@ -87,8 +96,21 @@ where } #[inline] + fn cast<U>(self) -> Self::CastPtr<U> { + // SimdElement currently requires zero-sized metadata, so this should never fail. + // If this ever changes, `simd_cast_ptr` should produce a post-mono error. + use core::{mem::size_of, ptr::Pointee}; + assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0); + assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0); + + // Safety: pointers can be cast + unsafe { intrinsics::simd_cast_ptr(self) } + } + + #[inline] fn cast_mut(self) -> Self::MutPtr { - self.cast_ptr() + // Safety: pointers can be cast + unsafe { intrinsics::simd_cast_ptr(self) } } #[inline] @@ -106,9 +128,9 @@ where // In the mean-time, this operation is defined to be "as if" it was // a wrapping_offset, so we can emulate it as such. This should properly // restore pointer provenance even under today's compiler. - self.cast_ptr::<*const u8>() + self.cast::<u8>() .wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>()) - .cast_ptr() + .cast() } #[inline] diff --git a/library/portable-simd/crates/core_simd/src/elements/float.rs b/library/portable-simd/crates/core_simd/src/elements/float.rs index d6022327055..501c1c5ddd3 100644 --- a/library/portable-simd/crates/core_simd/src/elements/float.rs +++ b/library/portable-simd/crates/core_simd/src/elements/float.rs @@ -1,6 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - intrinsics, LaneCount, Mask, Simd, SimdElement, SimdPartialEq, SimdPartialOrd, + intrinsics, LaneCount, Mask, Simd, SimdCast, SimdElement, SimdPartialEq, SimdPartialOrd, SupportedLaneCount, }; @@ -15,6 +15,53 @@ pub trait SimdFloat: Copy + Sealed { /// Bit representation of this SIMD vector type. type Bits; + /// A SIMD vector with a different element type. + type Cast<T: SimdElement>; + + /// Performs elementwise conversion of this vector's elements to another SIMD-valid type. + /// + /// This follows the semantics of Rust's `as` conversion for floats (truncating or saturating + /// at the limits) for each element. + /// + /// # Example + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::{SimdFloat, SimdInt, Simd}; + /// let floats: Simd<f32, 4> = Simd::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]); + /// let ints = floats.cast::<i32>(); + /// assert_eq!(ints, Simd::from_array([1, -4, i32::MAX, 0])); + /// + /// // Formally equivalent, but `Simd::cast` can optimize better. + /// assert_eq!(ints, Simd::from_array(floats.to_array().map(|x| x as i32))); + /// + /// // The float conversion does not round-trip. + /// let floats_again = ints.cast(); + /// assert_ne!(floats, floats_again); + /// assert_eq!(floats_again, Simd::from_array([1.0, -4.0, 2147483647.0, 0.0])); + /// ``` + #[must_use] + fn cast<T: SimdCast>(self) -> Self::Cast<T>; + + /// Rounds toward zero and converts to the same-width integer type, assuming that + /// the value is finite and fits in that type. + /// + /// # Safety + /// The value must: + /// + /// * Not be NaN + /// * Not be infinite + /// * Be representable in the return type, after truncating off its fractional part + /// + /// If these requirements are infeasible or costly, consider using the safe function [cast], + /// which saturates on conversion. + /// + /// [cast]: Simd::cast + unsafe fn to_int_unchecked<I: SimdCast>(self) -> Self::Cast<I> + where + Self::Scalar: core::convert::FloatToInt<I>; + /// Raw transmutation to an unsigned integer vector type with the /// same size and number of lanes. #[must_use = "method returns a new vector and does not mutate the original value"] @@ -206,6 +253,24 @@ macro_rules! impl_trait { type Mask = Mask<<$mask_ty as SimdElement>::Mask, LANES>; type Scalar = $ty; type Bits = Simd<$bits_ty, LANES>; + type Cast<T: SimdElement> = Simd<T, LANES>; + + #[inline] + fn cast<T: SimdCast>(self) -> Self::Cast<T> + { + // Safety: supported types are guaranteed by SimdCast + unsafe { intrinsics::simd_as(self) } + } + + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn to_int_unchecked<I: SimdCast>(self) -> Self::Cast<I> + where + Self::Scalar: core::convert::FloatToInt<I>, + { + // Safety: supported types are guaranteed by SimdCast, the caller is responsible for the extra invariants + unsafe { intrinsics::simd_cast(self) } + } #[inline] fn to_bits(self) -> Simd<$bits_ty, LANES> { diff --git a/library/portable-simd/crates/core_simd/src/elements/int.rs b/library/portable-simd/crates/core_simd/src/elements/int.rs index 9b8c37ed466..6db89ff9a65 100644 --- a/library/portable-simd/crates/core_simd/src/elements/int.rs +++ b/library/portable-simd/crates/core_simd/src/elements/int.rs @@ -1,6 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - intrinsics, LaneCount, Mask, Simd, SimdElement, SimdPartialOrd, SupportedLaneCount, + intrinsics, LaneCount, Mask, Simd, SimdCast, SimdElement, SimdPartialOrd, SupportedLaneCount, }; /// Operations on SIMD vectors of signed integers. @@ -11,6 +11,16 @@ pub trait SimdInt: Copy + Sealed { /// Scalar type contained by this SIMD vector type. type Scalar; + /// A SIMD vector with a different element type. + type Cast<T: SimdElement>; + + /// Performs elementwise conversion of this vector's elements to another SIMD-valid type. + /// + /// This follows the semantics of Rust's `as` conversion for casting integers (wrapping to + /// other integer types, and saturating to float types). + #[must_use] + fn cast<T: SimdCast>(self) -> Self::Cast<T>; + /// Lanewise saturating add. /// /// # Examples @@ -198,6 +208,13 @@ macro_rules! impl_trait { { type Mask = Mask<<$ty as SimdElement>::Mask, LANES>; type Scalar = $ty; + type Cast<T: SimdElement> = Simd<T, LANES>; + + #[inline] + fn cast<T: SimdCast>(self) -> Self::Cast<T> { + // Safety: supported types are guaranteed by SimdCast + unsafe { intrinsics::simd_as(self) } + } #[inline] fn saturating_add(self, second: Self) -> Self { diff --git a/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs index d87986b4a09..4bdc6a14ce4 100644 --- a/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SupportedLaneCount}; +use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SimdUint, SupportedLaneCount}; /// Operations on SIMD vectors of mutable pointers. pub trait SimdMutPtr: Copy + Sealed { @@ -9,6 +9,9 @@ pub trait SimdMutPtr: Copy + Sealed { /// Vector of `isize` with the same number of lanes. type Isize; + /// Vector of const pointers with the same number of lanes. + type CastPtr<T>; + /// Vector of constant pointers to the same type. type ConstPtr; @@ -18,6 +21,11 @@ pub trait SimdMutPtr: Copy + Sealed { /// Returns `true` for each lane that is null. fn is_null(self) -> Self::Mask; + /// Casts to a pointer of another type. + /// + /// Equivalent to calling [`pointer::cast`] on each lane. + fn cast<T>(self) -> Self::CastPtr<T>; + /// Changes constness without changing the type. /// /// Equivalent to calling [`pointer::cast_const`] on each lane. @@ -73,6 +81,7 @@ where { type Usize = Simd<usize, LANES>; type Isize = Simd<isize, LANES>; + type CastPtr<U> = Simd<*mut U, LANES>; type ConstPtr = Simd<*const T, LANES>; type Mask = Mask<isize, LANES>; @@ -82,8 +91,21 @@ where } #[inline] + fn cast<U>(self) -> Self::CastPtr<U> { + // SimdElement currently requires zero-sized metadata, so this should never fail. + // If this ever changes, `simd_cast_ptr` should produce a post-mono error. + use core::{mem::size_of, ptr::Pointee}; + assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0); + assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0); + + // Safety: pointers can be cast + unsafe { intrinsics::simd_cast_ptr(self) } + } + + #[inline] fn cast_const(self) -> Self::ConstPtr { - self.cast_ptr() + // Safety: pointers can be cast + unsafe { intrinsics::simd_cast_ptr(self) } } #[inline] @@ -101,9 +123,9 @@ where // In the mean-time, this operation is defined to be "as if" it was // a wrapping_offset, so we can emulate it as such. This should properly // restore pointer provenance even under today's compiler. - self.cast_ptr::<*mut u8>() + self.cast::<u8>() .wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>()) - .cast_ptr() + .cast() } #[inline] diff --git a/library/portable-simd/crates/core_simd/src/elements/uint.rs b/library/portable-simd/crates/core_simd/src/elements/uint.rs index 21e7e76eb3d..3926c395ec9 100644 --- a/library/portable-simd/crates/core_simd/src/elements/uint.rs +++ b/library/portable-simd/crates/core_simd/src/elements/uint.rs @@ -1,11 +1,21 @@ use super::sealed::Sealed; -use crate::simd::{intrinsics, LaneCount, Simd, SupportedLaneCount}; +use crate::simd::{intrinsics, LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount}; /// Operations on SIMD vectors of unsigned integers. pub trait SimdUint: Copy + Sealed { /// Scalar type contained by this SIMD vector type. type Scalar; + /// A SIMD vector with a different element type. + type Cast<T: SimdElement>; + + /// Performs elementwise conversion of this vector's elements to another SIMD-valid type. + /// + /// This follows the semantics of Rust's `as` conversion for casting integers (wrapping to + /// other integer types, and saturating to float types). + #[must_use] + fn cast<T: SimdCast>(self) -> Self::Cast<T>; + /// Lanewise saturating add. /// /// # Examples @@ -77,6 +87,13 @@ macro_rules! impl_trait { LaneCount<LANES>: SupportedLaneCount, { type Scalar = $ty; + type Cast<T: SimdElement> = Simd<T, LANES>; + + #[inline] + fn cast<T: SimdCast>(self) -> Self::Cast<T> { + // Safety: supported types are guaranteed by SimdCast + unsafe { intrinsics::simd_as(self) } + } #[inline] fn saturating_add(self, second: Self) -> Self { diff --git a/library/portable-simd/crates/core_simd/src/iter.rs b/library/portable-simd/crates/core_simd/src/iter.rs index 3275b4db8e4..328c995b81d 100644 --- a/library/portable-simd/crates/core_simd/src/iter.rs +++ b/library/portable-simd/crates/core_simd/src/iter.rs @@ -10,6 +10,7 @@ macro_rules! impl_traits { where LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold(Simd::splat(0 as $type), Add::add) } @@ -19,6 +20,7 @@ macro_rules! impl_traits { where LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn product<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold(Simd::splat(1 as $type), Mul::mul) } @@ -28,6 +30,7 @@ macro_rules! impl_traits { where LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self { iter.fold(Simd::splat(0 as $type), Add::add) } @@ -37,6 +40,7 @@ macro_rules! impl_traits { where LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self { iter.fold(Simd::splat(1 as $type), Mul::mul) } diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs index e5307de2155..fde406bda70 100644 --- a/library/portable-simd/crates/core_simd/src/lib.rs +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -16,7 +16,7 @@ )] #![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))] #![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))] -#![warn(missing_docs)] +#![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really #![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)] #![unstable(feature = "portable_simd", issue = "86656")] //! Portable SIMD module. diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs index e0f3c7beef6..fea687bdc1a 100644 --- a/library/portable-simd/crates/core_simd/src/masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks.rs @@ -179,6 +179,7 @@ where /// Panics if any lane is not 0 or -1. #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] + #[track_caller] pub fn from_int(value: Simd<T, LANES>) -> Self { assert!(T::valid(value), "all values must be either 0 or -1",); // Safety: the validity has been checked @@ -217,6 +218,7 @@ where /// Panics if `lane` is greater than or equal to the number of lanes in the vector. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] + #[track_caller] pub fn test(&self, lane: usize) -> bool { assert!(lane < LANES, "lane index out of range"); // Safety: the lane index has been checked @@ -240,6 +242,7 @@ where /// # Panics /// Panics if `lane` is greater than or equal to the number of lanes in the vector. #[inline] + #[track_caller] pub fn set(&mut self, lane: usize, value: bool) { assert!(lane < LANES, "lane index out of range"); // Safety: the lane index has been checked @@ -327,6 +330,7 @@ where T: MaskElement + fmt::Debug, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() .entries((0..LANES).map(|lane| self.test(lane))) diff --git a/library/portable-simd/crates/core_simd/src/mod.rs b/library/portable-simd/crates/core_simd/src/mod.rs index 35c659b7a42..f9891a3b7c1 100644 --- a/library/portable-simd/crates/core_simd/src/mod.rs +++ b/library/portable-simd/crates/core_simd/src/mod.rs @@ -23,6 +23,8 @@ mod vendor; #[doc = include_str!("core_simd_docs.md")] pub mod simd { + pub mod prelude; + pub(crate) use crate::core_simd::intrinsics; pub use crate::core_simd::alias::*; diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs index fc1e0bc426d..b007456cf2c 100644 --- a/library/portable-simd/crates/core_simd/src/ops.rs +++ b/library/portable-simd/crates/core_simd/src/ops.rs @@ -15,6 +15,7 @@ where I: core::slice::SliceIndex<[T]>, { type Output = I::Output; + #[inline] fn index(&self, index: I) -> &Self::Output { &self.as_array()[index] } @@ -26,6 +27,7 @@ where LaneCount<LANES>: SupportedLaneCount, I: core::slice::SliceIndex<[T]>, { + #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { &mut self.as_mut_array()[index] } @@ -118,10 +120,14 @@ macro_rules! for_base_types { #[inline] #[must_use = "operator returns a new vector without mutating the inputs"] + // TODO: only useful for int Div::div, but we hope that this + // will essentially always always get inlined anyway. + #[track_caller] fn $call(self, rhs: Self) -> Self::Output { $macro_impl!(self, rhs, $inner, $scalar) } - })* + } + )* } } diff --git a/library/portable-simd/crates/core_simd/src/ord.rs b/library/portable-simd/crates/core_simd/src/ord.rs index 1ae9cd061fb..b2455190e82 100644 --- a/library/portable-simd/crates/core_simd/src/ord.rs +++ b/library/portable-simd/crates/core_simd/src/ord.rs @@ -94,6 +94,7 @@ macro_rules! impl_integer { } #[inline] + #[track_caller] fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), @@ -200,6 +201,7 @@ macro_rules! impl_mask { } #[inline] + #[track_caller] fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), @@ -254,6 +256,7 @@ where } #[inline] + #[track_caller] fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), @@ -303,6 +306,7 @@ where } #[inline] + #[track_caller] fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), diff --git a/library/portable-simd/crates/core_simd/src/simd/prelude.rs b/library/portable-simd/crates/core_simd/src/simd/prelude.rs new file mode 100644 index 00000000000..e8fdc932d49 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/simd/prelude.rs @@ -0,0 +1,80 @@ +//! The portable SIMD prelude. +//! +//! Includes important traits and types to be imported with a glob: +//! ```ignore +//! use std::simd::prelude::*; +//! ``` + +#[doc(no_inline)] +pub use super::{ + simd_swizzle, Mask, Simd, SimdConstPtr, SimdFloat, SimdInt, SimdMutPtr, SimdOrd, SimdPartialEq, + SimdPartialOrd, SimdUint, +}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{f32x1, f32x2, f32x4, f32x8, f32x16, f32x32, f32x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{f64x1, f64x2, f64x4, f64x8, f64x16, f64x32, f64x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{i8x1, i8x2, i8x4, i8x8, i8x16, i8x32, i8x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{i16x1, i16x2, i16x4, i16x8, i16x16, i16x32, i16x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{i32x1, i32x2, i32x4, i32x8, i32x16, i32x32, i32x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{i64x1, i64x2, i64x4, i64x8, i64x16, i64x32, i64x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{isizex1, isizex2, isizex4, isizex8, isizex16, isizex32, isizex64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{u8x1, u8x2, u8x4, u8x8, u8x16, u8x32, u8x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{u16x1, u16x2, u16x4, u16x8, u16x16, u16x32, u16x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{u32x1, u32x2, u32x4, u32x8, u32x16, u32x32, u32x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{u64x1, u64x2, u64x4, u64x8, u64x16, u64x32, u64x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{usizex1, usizex2, usizex4, usizex8, usizex16, usizex32, usizex64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{mask8x1, mask8x2, mask8x4, mask8x8, mask8x16, mask8x32, mask8x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{mask16x1, mask16x2, mask16x4, mask16x8, mask16x16, mask16x32, mask16x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{mask32x1, mask32x2, mask32x4, mask32x8, mask32x16, mask32x32, mask32x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{mask64x1, mask64x2, mask64x4, mask64x8, mask64x16, mask64x32, mask64x64}; + +#[rustfmt::skip] +#[doc(no_inline)] +pub use super::{masksizex1, masksizex2, masksizex4, masksizex8, masksizex16, masksizex32, masksizex64}; diff --git a/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs b/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs index 6065d645937..ce621792534 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs @@ -16,9 +16,14 @@ where #[inline] pub fn swizzle_dyn(self, idxs: Simd<u8, N>) -> Self { #![allow(unused_imports, unused_unsafe)] - #[cfg(target_arch = "aarch64")] + #[cfg(all(target_arch = "aarch64", target_endian = "little"))] use core::arch::aarch64::{uint8x8_t, vqtbl1q_u8, vtbl1_u8}; - #[cfg(all(target_arch = "arm", target_feature = "v7", target_feature = "neon"))] + #[cfg(all( + target_arch = "arm", + target_feature = "v7", + target_feature = "neon", + target_endian = "little" + ))] use core::arch::arm::{uint8x8_t, vtbl1_u8}; #[cfg(target_arch = "wasm32")] use core::arch::wasm32 as wasm; @@ -29,13 +34,24 @@ where // SAFETY: Intrinsics covered by cfg unsafe { match N { - #[cfg(target_feature = "neon")] + #[cfg(all( + any( + target_arch = "aarch64", + all(target_arch = "arm", target_feature = "v7") + ), + target_feature = "neon", + target_endian = "little" + ))] 8 => transize(vtbl1_u8, self, idxs), #[cfg(target_feature = "ssse3")] 16 => transize(x86::_mm_shuffle_epi8, self, idxs), #[cfg(target_feature = "simd128")] 16 => transize(wasm::i8x16_swizzle, self, idxs), - #[cfg(all(target_arch = "aarch64", target_feature = "neon"))] + #[cfg(all( + target_arch = "aarch64", + target_feature = "neon", + target_endian = "little" + ))] 16 => transize(vqtbl1q_u8, self, idxs), #[cfg(all(target_feature = "avx2", not(target_feature = "avx512vbmi")))] 32 => transize_raw(avx2_pshufb, self, idxs), diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs index 3809cc96151..9aa7bacfce9 100644 --- a/library/portable-simd/crates/core_simd/src/vector.rs +++ b/library/portable-simd/crates/core_simd/src/vector.rs @@ -1,6 +1,6 @@ use crate::simd::{ - intrinsics, LaneCount, Mask, MaskElement, SimdCast, SimdCastPtr, SimdConstPtr, SimdMutPtr, - SimdPartialOrd, SupportedLaneCount, Swizzle, + intrinsics, LaneCount, Mask, MaskElement, SimdConstPtr, SimdMutPtr, SimdPartialOrd, + SupportedLaneCount, Swizzle, }; use core::convert::{TryFrom, TryInto}; @@ -122,6 +122,7 @@ where /// let v = u32x4::splat(0); /// assert_eq!(v.lanes(), 4); /// ``` + #[inline] pub const fn lanes(&self) -> usize { Self::LANES } @@ -136,6 +137,7 @@ where /// let v = u32x4::splat(8); /// assert_eq!(v.as_array(), &[8, 8, 8, 8]); /// ``` + #[inline] pub fn splat(value: T) -> Self { // This is preferred over `[value; N]`, since it's explicitly a splat: // https://github.com/rust-lang/rust/issues/97804 @@ -156,6 +158,7 @@ where /// let v: u64x4 = Simd::from_array([0, 1, 2, 3]); /// assert_eq!(v.as_array(), &[0, 1, 2, 3]); /// ``` + #[inline] pub const fn as_array(&self) -> &[T; N] { // SAFETY: `Simd<T, N>` is just an overaligned `[T; N]` with // potential padding at the end, so pointer casting to a @@ -167,6 +170,7 @@ where } /// Returns a mutable array reference containing the entire SIMD vector. + #[inline] pub fn as_mut_array(&mut self) -> &mut [T; N] { // SAFETY: `Simd<T, N>` is just an overaligned `[T; N]` with // potential padding at the end, so pointer casting to a @@ -184,6 +188,7 @@ where /// /// # Safety /// Reading `ptr` must be safe, as if by `<*const [T; N]>::read_unaligned`. + #[inline] const unsafe fn load(ptr: *const [T; N]) -> Self { // There are potentially simpler ways to write this function, but this should result in // LLVM `load <N x T>` @@ -204,6 +209,7 @@ where /// /// # Safety /// Writing to `ptr` must be safe, as if by `<*mut [T; N]>::write_unaligned`. + #[inline] const unsafe fn store(self, ptr: *mut [T; N]) { // There are potentially simpler ways to write this function, but this should result in // LLVM `store <N x T>` @@ -216,6 +222,7 @@ where } /// Converts an array to a SIMD vector. + #[inline] pub const fn from_array(array: [T; N]) -> Self { // SAFETY: `&array` is safe to read. // @@ -228,6 +235,7 @@ where } /// Converts a SIMD vector to an array. + #[inline] pub const fn to_array(self) -> [T; N] { let mut tmp = core::mem::MaybeUninit::uninit(); // SAFETY: writing to `tmp` is safe and initializes it. @@ -259,6 +267,8 @@ where /// assert_eq!(v.as_array(), &[1, 2, 3, 4]); /// ``` #[must_use] + #[inline] + #[track_caller] pub const fn from_slice(slice: &[T]) -> Self { assert!( slice.len() >= Self::LANES, @@ -287,6 +297,8 @@ where /// v.copy_to_slice(&mut dest); /// assert_eq!(&dest, &[1, 2, 3, 4, 0, 0]); /// ``` + #[inline] + #[track_caller] pub fn copy_to_slice(self, slice: &mut [T]) { assert!( slice.len() >= Self::LANES, @@ -297,76 +309,6 @@ where unsafe { self.store(slice.as_mut_ptr().cast()) } } - /// Performs elementwise conversion of a SIMD vector's elements to another SIMD-valid type. - /// - /// This follows the semantics of Rust's `as` conversion for casting integers between - /// signed and unsigned (interpreting integers as 2s complement, so `-1` to `U::MAX` and - /// `1 << (U::BITS -1)` becoming `I::MIN` ), and from floats to integers (truncating, - /// or saturating at the limits) for each element. - /// - /// # Examples - /// ``` - /// # #![feature(portable_simd)] - /// # use core::simd::Simd; - /// let floats: Simd<f32, 4> = Simd::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]); - /// let ints = floats.cast::<i32>(); - /// assert_eq!(ints, Simd::from_array([1, -4, i32::MAX, 0])); - /// - /// // Formally equivalent, but `Simd::cast` can optimize better. - /// assert_eq!(ints, Simd::from_array(floats.to_array().map(|x| x as i32))); - /// - /// // The float conversion does not round-trip. - /// let floats_again = ints.cast(); - /// assert_ne!(floats, floats_again); - /// assert_eq!(floats_again, Simd::from_array([1.0, -4.0, 2147483647.0, 0.0])); - /// ``` - #[must_use] - #[inline] - pub fn cast<U: SimdCast>(self) -> Simd<U, N> - where - T: SimdCast, - { - // Safety: supported types are guaranteed by SimdCast - unsafe { intrinsics::simd_as(self) } - } - - /// Casts a vector of pointers to another pointer type. - #[must_use] - #[inline] - pub fn cast_ptr<U>(self) -> Simd<U, N> - where - T: SimdCastPtr<U>, - U: SimdElement, - { - // Safety: supported types are guaranteed by SimdCastPtr - unsafe { intrinsics::simd_cast_ptr(self) } - } - - /// Rounds toward zero and converts to the same-width integer type, assuming that - /// the value is finite and fits in that type. - /// - /// # Safety - /// The value must: - /// - /// * Not be NaN - /// * Not be infinite - /// * Be representable in the return type, after truncating off its fractional part - /// - /// If these requirements are infeasible or costly, consider using the safe function [cast], - /// which saturates on conversion. - /// - /// [cast]: Simd::cast - #[inline] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub unsafe fn to_int_unchecked<I>(self) -> Simd<I, N> - where - T: core::convert::FloatToInt<I> + SimdCast, - I: SimdCast, - { - // Safety: supported types are guaranteed by SimdCast, the caller is responsible for the extra invariants - unsafe { intrinsics::simd_cast(self) } - } - /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. /// If an index is out-of-bounds, the element is instead selected from the `or` vector. /// @@ -717,6 +659,7 @@ where LaneCount<N>: SupportedLaneCount, T: SimdElement, { + #[inline] fn clone(&self) -> Self { *self } @@ -861,6 +804,7 @@ where LaneCount<N>: SupportedLaneCount, T: SimdElement, { + #[inline] fn from(array: [T; N]) -> Self { Self::from_array(array) } @@ -871,6 +815,7 @@ where LaneCount<N>: SupportedLaneCount, T: SimdElement, { + #[inline] fn from(vector: Simd<T, N>) -> Self { vector.to_array() } @@ -883,6 +828,7 @@ where { type Error = core::array::TryFromSliceError; + #[inline] fn try_from(slice: &[T]) -> Result<Self, core::array::TryFromSliceError> { Ok(Self::from_array(slice.try_into()?)) } @@ -895,6 +841,7 @@ where { type Error = core::array::TryFromSliceError; + #[inline] fn try_from(slice: &mut [T]) -> Result<Self, core::array::TryFromSliceError> { Ok(Self::from_array(slice.try_into()?)) } diff --git a/library/portable-simd/crates/core_simd/tests/cast.rs b/library/portable-simd/crates/core_simd/tests/cast.rs index ab5650f0713..00545936ea2 100644 --- a/library/portable-simd/crates/core_simd/tests/cast.rs +++ b/library/portable-simd/crates/core_simd/tests/cast.rs @@ -2,7 +2,8 @@ macro_rules! cast_types { ($start:ident, $($target:ident),*) => { mod $start { - use core_simd::simd::Simd; + #[allow(unused)] + use core_simd::simd::{Simd, SimdInt, SimdUint, SimdFloat}; type Vector<const N: usize> = Simd<$start, N>; $( mod $target { diff --git a/library/portable-simd/crates/core_simd/tests/round.rs b/library/portable-simd/crates/core_simd/tests/round.rs index 8b9638ad466..aacf7bd3bcc 100644 --- a/library/portable-simd/crates/core_simd/tests/round.rs +++ b/library/portable-simd/crates/core_simd/tests/round.rs @@ -53,6 +53,7 @@ macro_rules! float_rounding_test { test_helpers::test_lanes! { fn to_int_unchecked<const LANES: usize>() { + use core_simd::simd::SimdFloat; // The maximum integer that can be represented by the equivalently sized float has // all of the mantissa digits set to 1, pushed up to the MSB. const ALL_MANTISSA_BITS: IntScalar = ((1 << <Scalar>::MANTISSA_DIGITS) - 1); diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 77b657fd868..eb4815d0cdf 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,8 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'], public = true } -# FIXME(Nilstrieb): https://github.com/rust-lang/compiler-builtins/pull/532/files#r1249354225 -compiler_builtins = { version = "=0.1.93" } +compiler_builtins = { version = "0.1.95" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] } diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index bed90418be1..bc532990e94 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -500,10 +500,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f32 { - #[cfg(target_os = "android")] - return crate::sys::android::log2f32(self); - #[cfg(not(target_os = "android"))] - return unsafe { intrinsics::log2f32(self) }; + crate::sys::log2f32(self) } /// Returns the base 10 logarithm of the number. diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index e72de05ca41..5af9f8bcb23 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -456,7 +456,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f64 { - self.log_wrapper(|n| unsafe { intrinsics::logf64(n) }) + crate::sys::log_wrapper(self, |n| unsafe { intrinsics::logf64(n) }) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -500,12 +500,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f64 { - self.log_wrapper(|n| { - #[cfg(target_os = "android")] - return crate::sys::android::log2f64(n); - #[cfg(not(target_os = "android"))] - return unsafe { intrinsics::log2f64(n) }; - }) + crate::sys::log_wrapper(self, crate::sys::log2f64) } /// Returns the base 10 logarithm of the number. @@ -525,7 +520,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f64 { - self.log_wrapper(|n| unsafe { intrinsics::log10f64(n) }) + crate::sys::log_wrapper(self, |n| unsafe { intrinsics::log10f64(n) }) } /// The positive difference of two numbers. @@ -962,28 +957,4 @@ impl f64 { pub fn atanh(self) -> f64 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } - - // Solaris/Illumos requires a wrapper around log, log2, and log10 functions - // because of their non-standard behavior (e.g., log(-n) returns -Inf instead - // of expected NaN). - #[rustc_allow_incoherent_impl] - fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 { - if !cfg!(any(target_os = "solaris", target_os = "illumos")) { - log_fn(self) - } else if self.is_finite() { - if self > 0.0 { - log_fn(self) - } else if self == 0.0 { - Self::NEG_INFINITY // log(0) = -Inf - } else { - Self::NAN // log(-n) = NaN - } - } else if self.is_nan() { - self // log(NaN) = NaN - } else if self > 0.0 { - self // log(Inf) = Inf - } else { - Self::NAN // log(-Inf) = NaN - } - } } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index a66e6ccf673..7097dfef88d 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -53,7 +53,7 @@ pub struct BufReader<R: ?Sized> { } impl<R: Read> BufReader<R> { - /// Creates a new `BufReader<R>` with a default buffer capacity. The default is currently 8 KB, + /// Creates a new `BufReader<R>` with a default buffer capacity. The default is currently 8 KiB, /// but may change in the future. /// /// # Examples diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 0e2450655e5..0f04f291117 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -81,7 +81,7 @@ pub struct BufWriter<W: ?Sized + Write> { } impl<W: Write> BufWriter<W> { - /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB, + /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KiB, /// but may change in the future. /// /// # Examples diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index ef1f4031ef2..3322940d245 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,4 +1,8 @@ use super::{BorrowedBuf, BufReader, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE}; +use crate::alloc::Allocator; +use crate::cmp; +use crate::collections::VecDeque; +use crate::io::IoSlice; use crate::mem::MaybeUninit; #[cfg(test)] @@ -86,7 +90,7 @@ where /// Specialization of the read-write loop that reuses the internal /// buffer of a BufReader. If there's no buffer then the writer side -/// should be used intead. +/// should be used instead. trait BufferedReaderSpec { fn buffer_size(&self) -> usize; @@ -104,7 +108,39 @@ where } default fn copy_to(&mut self, _to: &mut (impl Write + ?Sized)) -> Result<u64> { - unimplemented!("only called from specializations"); + unreachable!("only called from specializations") + } +} + +impl BufferedReaderSpec for &[u8] { + fn buffer_size(&self) -> usize { + // prefer this specialization since the source "buffer" is all we'll ever need, + // even if it's small + usize::MAX + } + + fn copy_to(&mut self, to: &mut (impl Write + ?Sized)) -> Result<u64> { + let len = self.len(); + to.write_all(self)?; + *self = &self[len..]; + Ok(len as u64) + } +} + +impl<A: Allocator> BufferedReaderSpec for VecDeque<u8, A> { + fn buffer_size(&self) -> usize { + // prefer this specialization since the source "buffer" is all we'll ever need, + // even if it's small + usize::MAX + } + + fn copy_to(&mut self, to: &mut (impl Write + ?Sized)) -> Result<u64> { + let len = self.len(); + let (front, back) = self.as_slices(); + let bufs = &mut [IoSlice::new(front), IoSlice::new(back)]; + to.write_all_vectored(bufs)?; + self.clear(); + Ok(len as u64) } } @@ -218,6 +254,47 @@ impl<I: Write + ?Sized> BufferedWriterSpec for BufWriter<I> { } } +impl<A: Allocator> BufferedWriterSpec for Vec<u8, A> { + fn buffer_size(&self) -> usize { + cmp::max(DEFAULT_BUF_SIZE, self.capacity() - self.len()) + } + + fn copy_from<R: Read + ?Sized>(&mut self, reader: &mut R) -> Result<u64> { + let mut bytes = 0; + + // avoid allocating before we have determined that there's anything to read + if self.capacity() == 0 { + bytes = stack_buffer_copy(&mut reader.take(DEFAULT_BUF_SIZE as u64), self)?; + if bytes == 0 { + return Ok(0); + } + } + + loop { + self.reserve(DEFAULT_BUF_SIZE); + let mut buf: BorrowedBuf<'_> = self.spare_capacity_mut().into(); + match reader.read_buf(buf.unfilled()) { + Ok(()) => {} + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + }; + + let read = buf.filled().len(); + if read == 0 { + break; + } + + // SAFETY: BorrowedBuf guarantees all of its filled bytes are init + // and the number of read bytes can't exceed the spare capacity since + // that's what the buffer is borrowing from. + unsafe { self.set_len(self.len() + read) }; + bytes += read as u64; + } + + Ok(bytes) + } +} + fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>( reader: &mut R, writer: &mut W, diff --git a/library/std/src/io/copy/tests.rs b/library/std/src/io/copy/tests.rs index 8c816af15b8..af137eaf856 100644 --- a/library/std/src/io/copy/tests.rs +++ b/library/std/src/io/copy/tests.rs @@ -1,4 +1,6 @@ use crate::cmp::{max, min}; +use crate::collections::VecDeque; +use crate::io; use crate::io::*; #[test] @@ -19,7 +21,7 @@ struct ShortReader { impl Read for ShortReader { fn read(&mut self, buf: &mut [u8]) -> Result<usize> { - let bytes = min(self.cap, self.read_size); + let bytes = min(self.cap, self.read_size).min(buf.len()); self.cap -= bytes; self.observed_buffer = max(self.observed_buffer, buf.len()); Ok(bytes) @@ -78,6 +80,40 @@ fn copy_specializes_bufreader() { ); } +#[test] +fn copy_specializes_to_vec() { + let cap = 123456; + let mut source = ShortReader { cap, observed_buffer: 0, read_size: 1337 }; + let mut sink = Vec::new(); + assert_eq!(cap as u64, io::copy(&mut source, &mut sink).unwrap()); + assert!( + source.observed_buffer > DEFAULT_BUF_SIZE, + "expected a large buffer to be provided to the reader" + ); +} + +#[test] +fn copy_specializes_from_vecdeque() { + let mut source = VecDeque::with_capacity(100 * 1024); + for _ in 0..20 * 1024 { + source.push_front(0); + } + for _ in 0..20 * 1024 { + source.push_back(0); + } + let mut sink = WriteObserver { observed_buffer: 0 }; + assert_eq!(40 * 1024u64, io::copy(&mut source, &mut sink).unwrap()); + assert_eq!(20 * 1024, sink.observed_buffer); +} + +#[test] +fn copy_specializes_from_slice() { + let mut source = [1; 60 * 1024].as_slice(); + let mut sink = WriteObserver { observed_buffer: 0 }; + assert_eq!(60 * 1024u64, io::copy(&mut source, &mut sink).unwrap()); + assert_eq!(60 * 1024, sink.observed_buffer); +} + #[cfg(unix)] mod io_benches { use crate::fs::File; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index da08c018d0e..d287397aab3 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -241,7 +241,6 @@ #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(c_str_literals)] #![feature(c_unwind)] #![feature(cfg_target_thread_local)] #![feature(concat_idents)] @@ -604,7 +603,6 @@ pub mod alloc; // Private support modules mod panicking; -mod personality; #[path = "../../backtrace/src/lib.rs"] #[allow(dead_code, unused_attributes, fuzzy_provenance_casts)] diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 9da74a5ddb5..8f3201b0091 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1904,8 +1904,8 @@ impl FromInner<imp::ExitCode> for ExitCode { } impl Child { - /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`] - /// error is returned. + /// Forces the child process to exit. If the child has already exited, `Ok(())` + /// is returned. /// /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function. /// @@ -1920,7 +1920,7 @@ impl Child { /// /// let mut command = Command::new("yes"); /// if let Ok(mut child) = command.spawn() { - /// child.kill().expect("command wasn't running"); + /// child.kill().expect("command couldn't be killed"); /// } else { /// println!("yes command didn't start"); /// } diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index d7f4d335de3..366b591466c 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -582,3 +582,18 @@ fn run_canonical_bat_script() { assert!(output.status.success()); assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, fellow Rustaceans!"); } + +#[test] +fn terminate_exited_process() { + let mut cmd = if cfg!(target_os = "android") { + let mut p = shell_cmd(); + p.args(&["-c", "true"]); + p + } else { + known_command() + }; + let mut p = cmd.stdout(Stdio::null()).spawn().unwrap(); + p.wait().unwrap(); + assert!(p.kill().is_ok()); + assert!(p.kill().is_ok()); +} diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index c72be13804d..beea3f23c2d 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -23,6 +23,7 @@ #![allow(missing_debug_implementations)] pub mod common; +mod personality; cfg_if::cfg_if! { if #[cfg(unix)] { @@ -60,3 +61,52 @@ cfg_if::cfg_if! { pub const FULL_BACKTRACE_DEFAULT: bool = false; } } + +#[cfg(not(test))] +cfg_if::cfg_if! { + if #[cfg(target_os = "android")] { + pub use self::android::log2f32; + pub use self::android::log2f64; + } else { + #[inline] + pub fn log2f32(n: f32) -> f32 { + unsafe { crate::intrinsics::log2f32(n) } + } + + #[inline] + pub fn log2f64(n: f64) -> f64 { + unsafe { crate::intrinsics::log2f64(n) } + } + } +} + +// Solaris/Illumos requires a wrapper around log, log2, and log10 functions +// because of their non-standard behavior (e.g., log(-n) returns -Inf instead +// of expected NaN). +#[cfg(not(test))] +#[cfg(any(target_os = "solaris", target_os = "illumos"))] +#[inline] +pub fn log_wrapper<F: Fn(f64) -> f64>(n: f64, log_fn: F) -> f64 { + if n.is_finite() { + if n > 0.0 { + log_fn(n) + } else if n == 0.0 { + f64::NEG_INFINITY // log(0) = -Inf + } else { + f64::NAN // log(-n) = NaN + } + } else if n.is_nan() { + n // log(NaN) = NaN + } else if n > 0.0 { + n // log(Inf) = Inf + } else { + f64::NAN // log(-Inf) = NaN + } +} + +#[cfg(not(test))] +#[cfg(not(any(target_os = "solaris", target_os = "illumos")))] +#[inline] +pub fn log_wrapper<F: Fn(f64) -> f64>(n: f64, log_fn: F) -> f64 { + log_fn(n) +} diff --git a/library/std/src/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs index 79624703a4c..79624703a4c 100644 --- a/library/std/src/personality/dwarf/eh.rs +++ b/library/std/src/sys/personality/dwarf/eh.rs diff --git a/library/std/src/personality/dwarf/mod.rs b/library/std/src/sys/personality/dwarf/mod.rs index 652fbe95a14..652fbe95a14 100644 --- a/library/std/src/personality/dwarf/mod.rs +++ b/library/std/src/sys/personality/dwarf/mod.rs diff --git a/library/std/src/personality/dwarf/tests.rs b/library/std/src/sys/personality/dwarf/tests.rs index 1644f37083a..1644f37083a 100644 --- a/library/std/src/personality/dwarf/tests.rs +++ b/library/std/src/sys/personality/dwarf/tests.rs diff --git a/library/std/src/personality/emcc.rs b/library/std/src/sys/personality/emcc.rs index cb52ae89b19..cb52ae89b19 100644 --- a/library/std/src/personality/emcc.rs +++ b/library/std/src/sys/personality/emcc.rs diff --git a/library/std/src/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index 6552d96ca69..6552d96ca69 100644 --- a/library/std/src/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs diff --git a/library/std/src/personality.rs b/library/std/src/sys/personality/mod.rs index 386a399f532..386a399f532 100644 --- a/library/std/src/personality.rs +++ b/library/std/src/sys/personality/mod.rs diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index f8fa81e6ef1..eafd6821f54 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -242,15 +242,13 @@ mod imp { let mut res = Vec::new(); unsafe { - let process_info_sel = - sel_registerName(c"processInfo".as_ptr() as *const libc::c_uchar); - let arguments_sel = sel_registerName(c"arguments".as_ptr() as *const libc::c_uchar); - let utf8_sel = sel_registerName(c"UTF8String".as_ptr() as *const libc::c_uchar); - let count_sel = sel_registerName(c"count".as_ptr() as *const libc::c_uchar); - let object_at_sel = - sel_registerName(c"objectAtIndex:".as_ptr() as *const libc::c_uchar); - - let klass = objc_getClass(c"NSProcessInfo".as_ptr() as *const libc::c_uchar); + let process_info_sel = sel_registerName("processInfo\0".as_ptr()); + let arguments_sel = sel_registerName("arguments\0".as_ptr()); + let utf8_sel = sel_registerName("UTF8String\0".as_ptr()); + let count_sel = sel_registerName("count\0".as_ptr()); + let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr()); + + let klass = objc_getClass("NSProcessInfo\0".as_ptr()); let info = objc_msgSend(klass, process_info_sel); let args = objc_msgSend(info, arguments_sel); diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 9cf5cfcc8d5..fbc7f04ce9a 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1097,7 +1097,7 @@ impl File { cfg_has_statx! { if let Some(ret) = unsafe { try_statx( fd, - c"".as_ptr() as *const c_char, + b"\0" as *const _ as *const c_char, libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT, libc::STATX_ALL, ) } { diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 1b72e21a832..326f1481e19 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -1,5 +1,6 @@ #![allow(missing_docs, nonstandard_style)] +use crate::ffi::CStr; use crate::io::ErrorKind; pub use self::rand::hashmap_random_keys; @@ -74,7 +75,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { // thread-id for the main thread and so renaming the main thread will rename the // process and we only want to enable this on platforms we've tested. if cfg!(target_os = "macos") { - thread::Thread::set_name(&c"main"); + thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0")); } unsafe fn sanitize_standard_fds() { @@ -121,7 +122,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { if pfd.revents & libc::POLLNVAL == 0 { continue; } - if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { // If the stream is closed but we failed to reopen it, abort the // process. Otherwise we wouldn't preserve the safety of // operations on the corresponding Rust object Stdin, Stdout, or @@ -151,7 +152,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { use libc::open64; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { - if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { // If the stream is closed but we failed to reopen it, abort the // process. Otherwise we wouldn't preserve the safety of // operations on the corresponding Rust object Stdin, Stdout, or diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 5f316b12b62..640648e8707 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -24,11 +24,11 @@ cfg_if::cfg_if! { if #[cfg(target_os = "fuchsia")] { // fuchsia doesn't have /dev/null } else if #[cfg(target_os = "redox")] { - const DEV_NULL: &CStr = c"null:"; + const DEV_NULL: &str = "null:\0"; } else if #[cfg(target_os = "vxworks")] { - const DEV_NULL: &CStr = c"/null"; + const DEV_NULL: &str = "/null\0"; } else { - const DEV_NULL: &CStr = c"/dev/null"; + const DEV_NULL: &str = "/dev/null\0"; } } @@ -474,7 +474,8 @@ impl Stdio { let mut opts = OpenOptions::new(); opts.read(readable); opts.write(!readable); - let fd = File::open_c(DEV_NULL, &opts)?; + let path = unsafe { CStr::from_ptr(DEV_NULL.as_ptr() as *const _) }; + let fd = File::open_c(&path, &opts)?; Ok((ChildStdio::Owned(fd.into_inner()), None)) } diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 129e7643661..0ce93af66ac 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -762,12 +762,9 @@ impl Process { pub fn kill(&mut self) -> io::Result<()> { // If we've already waited on this process then the pid can be recycled // and used for another process, and we probably shouldn't be killing - // random processes, so just return an error. + // random processes, so return Ok because the process has exited already. if self.status.is_some() { - Err(io::const_io_error!( - ErrorKind::InvalidInput, - "invalid argument: can't kill an exited process", - )) + Ok(()) } else { cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) } diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs index c40e7ada03c..f70d3cb396b 100644 --- a/library/std/src/sys/unix/process/process_vxworks.rs +++ b/library/std/src/sys/unix/process/process_vxworks.rs @@ -144,12 +144,9 @@ impl Process { pub fn kill(&mut self) -> io::Result<()> { // If we've already waited on this process then the pid can be recycled // and used for another process, and we probably shouldn't be killing - // random processes, so just return an error. + // random processes, so return Ok because the process has exited already. if self.status.is_some() { - Err(io::const_io_error!( - ErrorKind::InvalidInput, - "invalid argument: can't kill an exited process", - )) + Ok(()) } else { cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 893f8b8df3f..4f2d9cf3655 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -163,9 +163,10 @@ impl Thread { #[cfg(target_os = "netbsd")] pub fn set_name(name: &CStr) { unsafe { + let cname = CStr::from_bytes_with_nul_unchecked(b"%s\0".as_slice()); let res = libc::pthread_setname_np( libc::pthread_self(), - c"%s".as_ptr(), + cname.as_ptr(), name.as_ptr() as *mut libc::c_void, ); debug_assert_eq!(res, 0); diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index b1b9e84fce9..d9ccba0e9da 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -321,7 +321,7 @@ pub unsafe fn NtWriteFile( // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. compat_fn_with_fallback! { - pub static KERNEL32: &CStr = c"kernel32"; + pub static KERNEL32: &CStr = ansi_str!("kernel32"); // >= Win10 1607 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription @@ -354,7 +354,7 @@ compat_fn_optional! { } compat_fn_with_fallback! { - pub static NTDLL: &CStr = c"ntdll"; + pub static NTDLL: &CStr = ansi_str!("ntdll"); pub fn NtCreateKeyedEvent( KeyedEventHandle: LPHANDLE, diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs index 649cc4bfdbf..4fe95d41116 100644 --- a/library/std/src/sys/windows/compat.rs +++ b/library/std/src/sys/windows/compat.rs @@ -228,9 +228,9 @@ macro_rules! compat_fn_optional { /// Load all needed functions from "api-ms-win-core-synch-l1-2-0". pub(super) fn load_synch_functions() { fn try_load() -> Option<()> { - const MODULE_NAME: &CStr = c"api-ms-win-core-synch-l1-2-0"; - const WAIT_ON_ADDRESS: &CStr = c"WaitOnAddress"; - const WAKE_BY_ADDRESS_SINGLE: &CStr = c"WakeByAddressSingle"; + const MODULE_NAME: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0"); + const WAIT_ON_ADDRESS: &CStr = ansi_str!("WaitOnAddress"); + const WAKE_BY_ADDRESS_SINGLE: &CStr = ansi_str!("WakeByAddressSingle"); // Try loading the library and all the required functions. // If any step fails, then they all fail. diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index b11c8962203..bcc172b0fae 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -1,6 +1,6 @@ #![allow(missing_docs, nonstandard_style)] -use crate::ffi::{OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString}; use crate::io::ErrorKind; use crate::mem::MaybeUninit; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; @@ -51,7 +51,7 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) { // Normally, `thread::spawn` will call `Thread::set_name` but since this thread already // exists, we have to call it ourselves. - thread::Thread::set_name(&c"main"); + thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0")); } // SAFETY: must be called only once during runtime cleanup. diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index a573a05c39c..e3493cbb850 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -595,7 +595,16 @@ pub struct Process { impl Process { pub fn kill(&mut self) -> io::Result<()> { - cvt(unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) })?; + let result = unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) }; + if result == c::FALSE { + let error = unsafe { c::GetLastError() }; + // TerminateProcess returns ERROR_ACCESS_DENIED if the process has already been + // terminated (by us, or for any other reason). So check if the process was actually + // terminated, and if so, do not return an error. + if error != c::ERROR_ACCESS_DENIED || self.try_wait().is_err() { + return Err(crate::io::Error::from_raw_os_error(error as i32)); + } + } Ok(()) } diff --git a/rustfmt.toml b/rustfmt.toml index 597ef5b9052..88700779e87 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -16,6 +16,8 @@ ignore = [ "tests", # do not format submodules + # FIXME: sync submodule list with tidy/bootstrap/etc + # tidy/src/walk.rs:filter_dirs "library/backtrace", "library/portable-simd", "library/stdarch", @@ -31,10 +33,8 @@ ignore = [ "src/tools/cargo", "src/tools/clippy", "src/tools/miri", - "src/tools/rls", "src/tools/rust-analyzer", "src/tools/rustfmt", - "src/tools/rust-installer", # these are ignored by a standard cargo fmt run "compiler/rustc_codegen_cranelift/y.rs", # running rustfmt breaks this file diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 2b2e9e9f988..66d97a2a0d0 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -85,6 +85,10 @@ dependencies = [ [[package]] name = "build_helper" version = "0.1.0" +dependencies = [ + "serde", + "serde_derive", +] [[package]] name = "cc" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 05b66f94727..c9bd329d430 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -665,6 +665,7 @@ impl<'a> Builder<'a> { llvm::Lld, llvm::CrtBeginEnd, tool::RustdocGUITest, + tool::OptimizedDist ), Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 14c3ef79a78..efe621bdb7d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -508,6 +508,49 @@ impl Step for StdLink { }; add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); + + // Special case for stage0, to make `rustup toolchain link` and `x dist --stage 0` + // work for stage0-sysroot. We only do this if the stage0 compiler comes from beta, + // and is not set to a custom path. + if compiler.stage == 0 + && builder + .build + .config + .initial_rustc + .starts_with(builder.out.join(&compiler.host.triple).join("stage0/bin")) + { + // Copy bin files from stage0/bin to stage0-sysroot/bin + let sysroot = builder.out.join(&compiler.host.triple).join("stage0-sysroot"); + + let host = compiler.host.triple; + let stage0_bin_dir = builder.out.join(&host).join("stage0/bin"); + let sysroot_bin_dir = sysroot.join("bin"); + t!(fs::create_dir_all(&sysroot_bin_dir)); + builder.cp_r(&stage0_bin_dir, &sysroot_bin_dir); + + // Copy all *.so files from stage0/lib to stage0-sysroot/lib + let stage0_lib_dir = builder.out.join(&host).join("stage0/lib"); + if let Ok(files) = fs::read_dir(&stage0_lib_dir) { + for file in files { + let file = t!(file); + let path = file.path(); + if path.is_file() && is_dylib(&file.file_name().into_string().unwrap()) { + builder.copy(&path, &sysroot.join("lib").join(path.file_name().unwrap())); + } + } + } + + // Copy codegen-backends from stage0 + let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler); + t!(fs::create_dir_all(&sysroot_codegen_backends)); + let stage0_codegen_backends = builder + .out + .join(&host) + .join("stage0/lib/rustlib") + .join(&host) + .join("codegen-backends"); + builder.cp_r(&stage0_codegen_backends, &sysroot_codegen_backends); + } } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5f5f7ea25fb..28ae46efefe 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -875,11 +875,10 @@ impl Default for StringOrBool { } } -#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] -#[serde(untagged)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum RustOptimize { - #[serde(deserialize_with = "deserialize_and_validate_opt_level")] String(String), + Int(u8), Bool(bool), } @@ -889,26 +888,74 @@ impl Default for RustOptimize { } } -fn deserialize_and_validate_opt_level<'de, D>(d: D) -> Result<String, D::Error> -where - D: serde::de::Deserializer<'de>, -{ - let v = String::deserialize(d)?; - if ["0", "1", "2", "3", "s", "z"].iter().find(|x| **x == v).is_some() { - Ok(v) - } else { - Err(format!(r#"unrecognized option for rust optimize: "{}", expected one of "0", "1", "2", "3", "s", "z""#, v)).map_err(serde::de::Error::custom) +impl<'de> Deserialize<'de> for RustOptimize { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_any(OptimizeVisitor) + } +} + +struct OptimizeVisitor; + +impl<'de> serde::de::Visitor<'de> for OptimizeVisitor { + type Value = RustOptimize; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str(r#"one of: 0, 1, 2, 3, "s", "z", true, false"#) + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + if ["s", "z"].iter().find(|x| **x == value).is_some() { + Ok(RustOptimize::String(value.to_string())) + } else { + Err(format_optimize_error_msg(value)).map_err(serde::de::Error::custom) + } + } + + fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + if matches!(value, 0..=3) { + Ok(RustOptimize::Int(value as u8)) + } else { + Err(format_optimize_error_msg(value)).map_err(serde::de::Error::custom) + } + } + + fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + Ok(RustOptimize::Bool(value)) } } +fn format_optimize_error_msg(v: impl std::fmt::Display) -> String { + format!( + r#"unrecognized option for rust optimize: "{}", expected one of 0, 1, 2, 3, "s", "z", true, false"#, + v + ) +} + impl RustOptimize { pub(crate) fn is_release(&self) -> bool { - if let RustOptimize::Bool(true) | RustOptimize::String(_) = &self { true } else { false } + match &self { + RustOptimize::Bool(true) | RustOptimize::String(_) => true, + RustOptimize::Int(i) => *i > 0, + RustOptimize::Bool(false) => false, + } } pub(crate) fn get_opt_level(&self) -> Option<String> { match &self { RustOptimize::String(s) => Some(s.clone()), + RustOptimize::Int(i) => Some(i.to_string()), RustOptimize::Bool(_) => None, } } diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs index 732df54cdac..c340bb2982a 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/config/tests.rs @@ -184,7 +184,10 @@ fn rust_optimize() { assert_eq!(parse("").rust_optimize.is_release(), true); assert_eq!(parse("rust.optimize = false").rust_optimize.is_release(), false); assert_eq!(parse("rust.optimize = true").rust_optimize.is_release(), true); - assert_eq!(parse("rust.optimize = \"1\"").rust_optimize.get_opt_level(), Some("1".to_string())); + assert_eq!(parse("rust.optimize = 0").rust_optimize.is_release(), false); + assert_eq!(parse("rust.optimize = 1").rust_optimize.is_release(), true); + assert_eq!(parse("rust.optimize = 1").rust_optimize.get_opt_level(), Some("1".to_string())); + assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.is_release(), true); assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.get_opt_level(), Some("s".to_string())); } diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 4111b7cc0d3..120b3c9c4d2 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/96971 +Last change is for: https://github.com/rust-lang/rust/pull/112931 diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 6a51450a777..0a7aff62257 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -599,6 +599,9 @@ impl Build { let mut git = self.config.git(); if let Some(branch) = current_branch { + // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name. + // This syntax isn't accepted by `branch.{branch}`. Strip it. + let branch = branch.strip_prefix("heads/").unwrap_or(&branch); git.arg("-c").arg(format!("branch.{branch}.remote=origin")); } git.args(&["submodule", "update", "--init", "--recursive", "--depth=1"]); diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 4752b1f7ea1..7e27960f3e9 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -352,7 +352,7 @@ impl Step for Llvm { // Disable zstd to avoid a dependency on libzstd.so. cfg.define("LLVM_ENABLE_ZSTD", "OFF"); - if target != "aarch64-apple-darwin" && !target.contains("windows") { + if !target.contains("windows") { cfg.define("LLVM_ENABLE_ZLIB", "ON"); } else { cfg.define("LLVM_ENABLE_ZLIB", "OFF"); @@ -380,7 +380,10 @@ impl Step for Llvm { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } - if target.starts_with("riscv") && !target.contains("freebsd") && !target.contains("openbsd") + if target.starts_with("riscv") + && !target.contains("freebsd") + && !target.contains("openbsd") + && !target.contains("netbsd") { // RISC-V GCC erroneously requires linking against // `libatomic` when using 1-byte and 2-byte C++ diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs index 5990f33b9bc..b73df7fe822 100644 --- a/src/bootstrap/metrics.rs +++ b/src/bootstrap/metrics.rs @@ -7,7 +7,10 @@ use crate::builder::{Builder, Step}; use crate::util::t; use crate::Build; -use serde_derive::{Deserialize, Serialize}; +use build_helper::metrics::{ + JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test, + TestOutcome, TestSuite, TestSuiteMetadata, +}; use std::cell::RefCell; use std::fs::File; use std::io::BufWriter; @@ -241,98 +244,7 @@ struct StepMetrics { test_suites: Vec<TestSuite>, } -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -struct JsonRoot { - #[serde(default)] // For version 0 the field was not present. - format_version: usize, - system_stats: JsonInvocationSystemStats, - invocations: Vec<JsonInvocation>, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -struct JsonInvocation { - // Unix timestamp in seconds - // - // This is necessary to easily correlate this invocation with logs or other data. - start_time: u64, - duration_including_children_sec: f64, - children: Vec<JsonNode>, -} - -#[derive(Serialize, Deserialize)] -#[serde(tag = "kind", rename_all = "snake_case")] -enum JsonNode { - RustbuildStep { - #[serde(rename = "type")] - type_: String, - debug_repr: String, - - duration_excluding_children_sec: f64, - system_stats: JsonStepSystemStats, - - children: Vec<JsonNode>, - }, - TestSuite(TestSuite), -} - -#[derive(Serialize, Deserialize)] -struct TestSuite { - metadata: TestSuiteMetadata, - tests: Vec<Test>, -} - -#[derive(Serialize, Deserialize)] -#[serde(tag = "kind", rename_all = "snake_case")] -pub(crate) enum TestSuiteMetadata { - CargoPackage { - crates: Vec<String>, - target: String, - host: String, - stage: u32, - }, - Compiletest { - suite: String, - mode: String, - compare_mode: Option<String>, - target: String, - host: String, - stage: u32, - }, -} - -#[derive(Serialize, Deserialize)] -pub(crate) struct Test { - name: String, - #[serde(flatten)] - outcome: TestOutcome, -} - -#[derive(Serialize, Deserialize)] -#[serde(tag = "outcome", rename_all = "snake_case")] -pub(crate) enum TestOutcome { - Passed, - Failed, - Ignored { ignore_reason: Option<String> }, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -struct JsonInvocationSystemStats { - cpu_threads_count: usize, - cpu_model: String, - - memory_total_bytes: u64, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -struct JsonStepSystemStats { - cpu_utilization_percent: f64, -} - -#[derive(Deserialize)] +#[derive(serde_derive::Deserialize)] struct OnlyFormatVersion { #[serde(default)] // For version 0 the field was not present. format_version: usize, diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs index 98a468c883d..ccd067053ef 100644 --- a/src/bootstrap/render_tests.rs +++ b/src/bootstrap/render_tests.rs @@ -141,9 +141,9 @@ impl<'a> Renderer<'a> { self.builder.metrics.record_test( &test.name, match outcome { - Outcome::Ok | Outcome::BenchOk => crate::metrics::TestOutcome::Passed, - Outcome::Failed => crate::metrics::TestOutcome::Failed, - Outcome::Ignored { reason } => crate::metrics::TestOutcome::Ignored { + Outcome::Ok | Outcome::BenchOk => build_helper::metrics::TestOutcome::Passed, + Outcome::Failed => build_helper::metrics::TestOutcome::Failed, + Outcome::Ignored { reason } => build_helper::metrics::TestOutcome::Ignored { ignore_reason: reason.map(|s| s.to_string()), }, }, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 75e7bd6aa24..0907291b54d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -340,7 +340,7 @@ impl Step for Cargo { #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( - crate::metrics::TestSuiteMetadata::CargoPackage { + build_helper::metrics::TestSuiteMetadata::CargoPackage { crates: vec!["cargo".into()], target: self.host.triple.to_string(), host: self.host.triple.to_string(), @@ -799,6 +799,10 @@ impl Step for Clippy { // The tests succeeded; nothing to do. return; } + + if !builder.config.cmd.bless() { + crate::detail_exit_macro!(1); + } } } @@ -1823,7 +1827,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( - crate::metrics::TestSuiteMetadata::Compiletest { + build_helper::metrics::TestSuiteMetadata::Compiletest { suite: suite.into(), mode: mode.into(), compare_mode: None, @@ -1848,7 +1852,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( - crate::metrics::TestSuiteMetadata::Compiletest { + build_helper::metrics::TestSuiteMetadata::Compiletest { suite: suite.into(), mode: mode.into(), compare_mode: Some(compare_mode.into()), @@ -2196,7 +2200,7 @@ fn run_cargo_test( #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( - crate::metrics::TestSuiteMetadata::CargoPackage { + build_helper::metrics::TestSuiteMetadata::CargoPackage { crates: crates.iter().map(|c| c.to_string()).collect(), target: target.triple.to_string(), host: compiler.host.triple.to_string(), @@ -2219,6 +2223,11 @@ fn prepare_cargo_test( ) -> Command { let mut cargo = cargo.into(); + // If bless is passed, give downstream crates a way to use it + if builder.config.cmd.bless() { + cargo.env("RUSTC_BLESS", "1"); + } + // Pass in some standard flags then iterate over the graph we've discovered // in `cargo metadata` with the maps above and figure out what `-p` // arguments need to get passed. diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 126f0b1eb31..915dceae389 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -289,7 +289,7 @@ bootstrap_tool!( Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test"; BuildManifest, "src/tools/build-manifest", "build-manifest"; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; - RustInstaller, "src/tools/rust-installer", "rust-installer", is_external_tool = true; + RustInstaller, "src/tools/rust-installer", "rust-installer"; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes"; ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; LintDocs, "src/tools/lint-docs", "lint-docs"; @@ -303,6 +303,7 @@ bootstrap_tool!( SuggestTests, "src/tools/suggest-tests", "suggest-tests"; GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys"; RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test"; + OptimizedDist, "src/tools/opt-dist", "opt-dist"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index c2fd2e3a91a..1fcb99f6d5f 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -54,7 +54,8 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ -# rustc-perf version from 2023-03-15 +# rustc-perf version from 2023-05-30 +# Should also be changed in the opt-dist tool for other environments. ENV PERF_COMMIT 8b2ac3042e1ff2c0074455a0a3618adef97156b1 RUN curl -LS -o perf.zip https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \ unzip perf.zip && \ @@ -81,7 +82,9 @@ ENV RUST_CONFIGURE_ARGS \ --set rust.jemalloc \ --set rust.use-lld=true \ --set rust.lto=thin -ENV SCRIPT python3 ../src/ci/stage-build.py python3 ../x.py dist \ + +ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \ + ./build/$HOSTS/stage0-tools-bin/opt-dist python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ build-manifest bootstrap diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index 1dc7b798724..a1d06ab1844 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -24,7 +24,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins qemu-system-x86 \ && rm -rf /var/lib/apt/lists/* -RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \ +RUN curl -sL https://nodejs.org/dist/v18.12.0/node-v18.12.0-linux-x64.tar.xz | \ tar -xJ # Install 32-bit OVMF files for the i686-unknown-uefi test. This package @@ -42,7 +42,7 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ - --set build.nodejs=/node-v15.14.0-linux-x64/bin/node \ + --set build.nodejs=/node-v18.12.0-linux-x64/bin/node \ --set rust.lld # Some run-make tests have assertions about code size, and enabling debug @@ -58,6 +58,8 @@ ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_T tests/ui \ tests/mir-opt \ tests/codegen-units \ + tests/codegen \ + tests/assembly \ library/core ENV NVPTX_TARGETS=nvptx64-nvidia-cuda diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile deleted file mode 100644 index d45ef0a7d07..00000000000 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -FROM ubuntu:22.04 - -ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - gcc-multilib \ - make \ - ninja-build \ - file \ - curl \ - ca-certificates \ - python3 \ - git \ - cmake \ - sudo \ - gdb \ - llvm-14-tools \ - llvm-14-dev \ - libedit-dev \ - libssl-dev \ - pkg-config \ - zlib1g-dev \ - xz-utils \ - nodejs \ - mingw-w64 \ - && rm -rf /var/lib/apt/lists/* - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -# We are disabling CI LLVM since this builder is intentionally using a host -# LLVM, rather than the typical src/llvm-project LLVM. -ENV NO_DOWNLOAD_CI_LLVM 1 - -# This is not the latest LLVM version, so some components required by tests may -# be missing. -ENV IS_NOT_LATEST_LLVM 1 - -# Using llvm-link-shared due to libffi issues -- see #34486 -ENV RUST_CONFIGURE_ARGS \ - --build=x86_64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-14 \ - --enable-llvm-link-shared \ - --set rust.thin-lto-import-instr-limit=10 - -ENV SCRIPT ../x.py --stage 1 test --exclude src/tools/tidy && \ - # Run the `mir-opt` tests again but this time for a 32-bit target. - # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have - # both 32-bit and 64-bit outputs updated by the PR author, before - # the PR is approved and tested for merging. - # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`, - # despite having different output on 32-bit vs 64-bit targets. - ../x.py --stage 1 test tests/mir-opt \ - --host='' --target=i686-unknown-linux-gnu diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile index 1f28b939778..93d18bcf1b1 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile @@ -49,20 +49,6 @@ ENV RUST_CONFIGURE_ARGS \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 -# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux. -ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \ - # Run the `mir-opt` tests again but this time for a 32-bit target. - # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have - # both 32-bit and 64-bit outputs updated by the PR author, before - # the PR is approved and tested for merging. - # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`, - # despite having different output on 32-bit vs 64-bit targets. - ../x --stage 2 test tests/mir-opt \ - --host='' --target=i686-unknown-linux-gnu && \ - # Run the UI test suite again, but in `--pass=check` mode - # - # This is intended to make sure that both `--pass=check` continues to - # work. - # - ../x.ps1 --stage 2 test tests/ui --pass=check \ - --host='' --target=i686-unknown-linux-gnu +COPY host-x86_64/x86_64-gnu-llvm-14/script.sh /tmp/ + +ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/script.sh b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/script.sh new file mode 100755 index 00000000000..0120fd98298 --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/script.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -ex + +# Only run the stage 1 tests on merges, not on PR CI jobs. +if [[ -z "${PR_CI_JOB}" ]]; then +../x.py --stage 1 test --exclude src/tools/tidy && \ + # Run the `mir-opt` tests again but this time for a 32-bit target. + # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have + # both 32-bit and 64-bit outputs updated by the PR author, before + # the PR is approved and tested for merging. + # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`, + # despite having different output on 32-bit vs 64-bit targets. + ../x.py --stage 1 test tests/mir-opt \ + --host='' --target=i686-unknown-linux-gnu +fi + +# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux. +../x.py --stage 2 test --exclude src/tools/tidy && \ + # Run the `mir-opt` tests again but this time for a 32-bit target. + # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have + # both 32-bit and 64-bit outputs updated by the PR author, before + # the PR is approved and tested for merging. + # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`, + # despite having different output on 32-bit vs 64-bit targets. + ../x --stage 2 test tests/mir-opt \ + --host='' --target=i686-unknown-linux-gnu && \ + # Run the UI test suite again, but in `--pass=check` mode + # + # This is intended to make sure that both `--pass=check` continues to + # work. + # + ../x.ps1 --stage 2 test tests/ui --pass=check \ + --host='' --target=i686-unknown-linux-gnu diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 0a098467d94..4b218d57727 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -263,6 +263,7 @@ docker \ --env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \ --env BASE_COMMIT="$BASE_COMMIT" \ --env DIST_TRY_BUILD \ + --env PR_CI_JOB \ --init \ --rm \ rust-ci \ diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index cb12042c117..b5b478e60f4 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -302,7 +302,7 @@ concurrency: # For a given workflow, if we push to the same branch, cancel all previous builds on that branch. # We add an exception for try builds (try branch) and unrolled rollup builds (try-perf), which # are all triggered on the same branch, but which should be able to run concurrently. - group: ${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }} + group: ${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }} cancel-in-progress: true jobs: @@ -311,6 +311,7 @@ jobs: name: PR - ${{ matrix.name }} env: <<: [*shared-ci-variables, *public-variables] + PR_CI_JOB: 1 if: github.event_name == 'pull_request' continue-on-error: ${{ matrix.name == 'mingw-check-tidy' }} strategy: @@ -374,18 +375,6 @@ jobs: - name: dist-loongarch64-linux <<: *job-linux-8c - - name: dist-mips-linux - <<: *job-linux-8c - - - name: dist-mips64-linux - <<: *job-linux-8c - - - name: dist-mips64el-linux - <<: *job-linux-8c - - - name: dist-mipsel-linux - <<: *job-linux-8c - - name: dist-powerpc-linux <<: *job-linux-8c @@ -485,11 +474,6 @@ jobs: RUST_BACKTRACE: 1 <<: *job-linux-8c - - name: x86_64-gnu-llvm-14-stage1 - env: - RUST_BACKTRACE: 1 - <<: *job-linux-8c - - name: x86_64-gnu-nopt <<: *job-linux-4c @@ -606,16 +590,10 @@ jobs: SCRIPT: make ci-msvc <<: *job-windows-8c - - name: x86_64-msvc-cargo - env: - SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld - <<: *job-windows-8c - - - name: x86_64-msvc-tools + - name: x86_64-msvc-ext env: - SCRIPT: src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json + SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json DEPLOY_TOOLSTATES_JSON: toolstates-windows.json <<: *job-windows-8c @@ -665,7 +643,7 @@ jobs: --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: PGO_HOST=x86_64-pc-windows-msvc python src/ci/stage-build.py python x.py dist bootstrap --include-default-paths + SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c diff --git a/src/ci/run.sh b/src/ci/run.sh index 5363086f68b..48fb40d6a6d 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -188,6 +188,7 @@ else fi if [ ! -z "$SCRIPT" ]; then + echo "Executing ${SCRIPT}" sh -x -c "$SCRIPT" else do_make() { diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py deleted file mode 100755 index 3f30b69e8f4..00000000000 --- a/src/ci/stage-build.py +++ /dev/null @@ -1,1030 +0,0 @@ -#!/usr/bin/env python3 -# ignore-tidy-linelength - -# Compatible with Python 3.6+ - -import contextlib -import getpass -import glob -import json -import logging -import os -import pprint -import shutil -import subprocess -import sys -import time -import traceback -import urllib.request -from io import StringIO -from pathlib import Path -from typing import Callable, ContextManager, Dict, Iterable, Iterator, List, Optional, \ - Tuple, Union - -PGO_HOST = os.environ["PGO_HOST"] - -LOGGER = logging.getLogger("stage-build") - -LLVM_PGO_CRATES = [ - "syn-1.0.89", - "cargo-0.60.0", - "serde-1.0.136", - "ripgrep-13.0.0", - "regex-1.5.5", - "clap-3.1.6", - "hyper-0.14.18" -] - -RUSTC_PGO_CRATES = [ - "externs", - "ctfe-stress-5", - "cargo-0.60.0", - "token-stream-stress", - "match-stress", - "tuple-stress", - "diesel-1.4.8", - "bitmaps-3.1.0" -] - -LLVM_BOLT_CRATES = LLVM_PGO_CRATES - - -def is_try_build() -> bool: - return os.environ.get("DIST_TRY_BUILD", "0") != "0" - - -class Pipeline: - # Paths - def checkout_path(self) -> Path: - """ - The root checkout, where the source is located. - """ - raise NotImplementedError - - def downloaded_llvm_dir(self) -> Path: - """ - Directory where the host LLVM is located. - """ - raise NotImplementedError - - def build_root(self) -> Path: - """ - The main directory where the build occurs. - """ - raise NotImplementedError - - def build_artifacts(self) -> Path: - return self.build_root() / "build" / PGO_HOST - - def rustc_stage_0(self) -> Path: - return self.build_artifacts() / "stage0" / "bin" / "rustc" - - def cargo_stage_0(self) -> Path: - return self.build_artifacts() / "stage0" / "bin" / "cargo" - - def rustc_stage_2(self) -> Path: - return self.build_artifacts() / "stage2" / "bin" / "rustc" - - def opt_artifacts(self) -> Path: - raise NotImplementedError - - def llvm_profile_dir_root(self) -> Path: - return self.opt_artifacts() / "llvm-pgo" - - def llvm_profile_merged_file(self) -> Path: - return self.opt_artifacts() / "llvm-pgo.profdata" - - def rustc_perf_dir(self) -> Path: - return self.opt_artifacts() / "rustc-perf" - - def build_rustc_perf(self): - raise NotImplementedError() - - def rustc_profile_dir_root(self) -> Path: - return self.opt_artifacts() / "rustc-pgo" - - def rustc_profile_merged_file(self) -> Path: - return self.opt_artifacts() / "rustc-pgo.profdata" - - def rustc_profile_template_path(self) -> Path: - """ - The profile data is written into a single filepath that is being repeatedly merged when each - rustc invocation ends. Empirically, this can result in some profiling data being lost. That's - why we override the profile path to include the PID. This will produce many more profiling - files, but the resulting profile will produce a slightly faster rustc binary. - """ - return self.rustc_profile_dir_root() / "default_%m_%p.profraw" - - def supports_bolt(self) -> bool: - raise NotImplementedError - - def llvm_bolt_profile_merged_file(self) -> Path: - return self.opt_artifacts() / "bolt.profdata" - - def metrics_path(self) -> Path: - return self.build_root() / "build" / "metrics.json" - - def executable_extension(self) -> str: - raise NotImplementedError - - def skipped_tests(self) -> Iterable[str]: - return () - - -class LinuxPipeline(Pipeline): - def checkout_path(self) -> Path: - return Path("/checkout") - - def downloaded_llvm_dir(self) -> Path: - return Path("/rustroot") - - def build_root(self) -> Path: - return self.checkout_path() / "obj" - - def opt_artifacts(self) -> Path: - return Path("/tmp/tmp-multistage/opt-artifacts") - - def build_rustc_perf(self): - # /tmp/rustc-perf comes from the Dockerfile - shutil.copytree("/tmp/rustc-perf", self.rustc_perf_dir()) - cmd(["chown", "-R", f"{getpass.getuser()}:", self.rustc_perf_dir()]) - - with change_cwd(self.rustc_perf_dir()): - cmd([self.cargo_stage_0(), "build", "-p", "collector"], env=dict( - RUSTC=str(self.rustc_stage_0()), - RUSTC_BOOTSTRAP="1" - )) - - def supports_bolt(self) -> bool: - return True - - def executable_extension(self) -> str: - return "" - - def skipped_tests(self) -> Iterable[str]: - # This test fails because of linker errors, as of June 2023. - yield "tests/ui/process/nofile-limit.rs" - - -class WindowsPipeline(Pipeline): - def __init__(self): - self.checkout_dir = Path(os.getcwd()) - - def checkout_path(self) -> Path: - return self.checkout_dir - - def downloaded_llvm_dir(self) -> Path: - return self.checkout_path() / "citools" / "clang-rust" - - def build_root(self) -> Path: - return self.checkout_path() - - def opt_artifacts(self) -> Path: - return self.checkout_path() / "opt-artifacts" - - def rustc_stage_0(self) -> Path: - return super().rustc_stage_0().with_suffix(".exe") - - def cargo_stage_0(self) -> Path: - return super().cargo_stage_0().with_suffix(".exe") - - def rustc_stage_2(self) -> Path: - return super().rustc_stage_2().with_suffix(".exe") - - def build_rustc_perf(self): - # rustc-perf version from 2023-03-15 - perf_commit = "8b2ac3042e1ff2c0074455a0a3618adef97156b1" - rustc_perf_zip_path = self.opt_artifacts() / "perf.zip" - - def download_rustc_perf(): - download_file( - f"https://github.com/rust-lang/rustc-perf/archive/{perf_commit}.zip", - rustc_perf_zip_path - ) - with change_cwd(self.opt_artifacts()): - unpack_archive(rustc_perf_zip_path) - move_path(Path(f"rustc-perf-{perf_commit}"), self.rustc_perf_dir()) - delete_file(rustc_perf_zip_path) - - retry_action(download_rustc_perf, "Download rustc-perf") - - with change_cwd(self.rustc_perf_dir()): - cmd([self.cargo_stage_0(), "build", "-p", "collector"], env=dict( - RUSTC=str(self.rustc_stage_0()), - RUSTC_BOOTSTRAP="1" - )) - - def rustc_profile_template_path(self) -> Path: - """ - On Windows, we don't have enough space to use separate files for each rustc invocation. - Therefore, we use a single file for the generated profiles. - """ - return self.rustc_profile_dir_root() / "default_%m.profraw" - - def supports_bolt(self) -> bool: - return False - - def executable_extension(self) -> str: - return ".exe" - - def skipped_tests(self) -> Iterable[str]: - # This test fails as of June 2023 - yield "tests\\codegen\\vec-shrink-panik.rs" - - -def get_timestamp() -> float: - return time.time() - - -Duration = float - - -def iterate_timers(timer: "Timer", name: str, level: int = 0) -> Iterator[ - Tuple[int, str, Duration]]: - """ - Hierarchically iterate the children of a timer, in a depth-first order. - """ - yield (level, name, timer.total_duration()) - for (child_name, child_timer) in timer.children: - yield from iterate_timers(child_timer, child_name, level=level + 1) - - -class Timer: - def __init__(self, parent_names: Tuple[str, ...] = ()): - self.children: List[Tuple[str, Timer]] = [] - self.section_active = False - self.parent_names = parent_names - self.duration_excluding_children: Duration = 0 - - @contextlib.contextmanager - def section(self, name: str) -> ContextManager["Timer"]: - assert not self.section_active - self.section_active = True - - start = get_timestamp() - exc = None - - child_timer = Timer(parent_names=self.parent_names + (name,)) - full_name = " > ".join(child_timer.parent_names) - try: - LOGGER.info(f"Section `{full_name}` starts") - yield child_timer - except BaseException as exception: - exc = exception - raise - finally: - end = get_timestamp() - duration = end - start - - child_timer.duration_excluding_children = duration - child_timer.total_duration() - self.add_child(name, child_timer) - if exc is None: - LOGGER.info(f"Section `{full_name}` ended: OK ({duration:.2f}s)") - else: - LOGGER.info(f"Section `{full_name}` ended: FAIL ({duration:.2f}s)") - self.section_active = False - - def total_duration(self) -> Duration: - return self.duration_excluding_children + sum( - c.total_duration() for (_, c) in self.children) - - def has_children(self) -> bool: - return len(self.children) > 0 - - def print_stats(self): - rows = [] - for (child_name, child_timer) in self.children: - for (level, name, duration) in iterate_timers(child_timer, child_name, level=0): - label = f"{' ' * level}{name}:" - rows.append((label, duration)) - - # Empty row - rows.append(("", "")) - - total_duration_label = "Total duration:" - total_duration = self.total_duration() - rows.append((total_duration_label, humantime(total_duration))) - - space_after_label = 2 - max_label_length = max(16, max(len(label) for (label, _) in rows)) + space_after_label - - table_width = max_label_length + 23 - divider = "-" * table_width - - with StringIO() as output: - print(divider, file=output) - for (label, duration) in rows: - if isinstance(duration, Duration): - pct = (duration / total_duration) * 100 - value = f"{duration:>12.2f}s ({pct:>5.2f}%)" - else: - value = f"{duration:>{len(total_duration_label) + 7}}" - print(f"{label:<{max_label_length}} {value}", file=output) - print(divider, file=output, end="") - LOGGER.info(f"Timer results\n{output.getvalue()}") - - def add_child(self, name: str, timer: "Timer"): - self.children.append((name, timer)) - - def add_duration(self, name: str, duration: Duration): - timer = Timer(parent_names=self.parent_names + (name,)) - timer.duration_excluding_children = duration - self.add_child(name, timer) - - -class BuildStep: - def __init__(self, type: str, children: List["BuildStep"], duration: float): - self.type = type - self.children = children - self.duration = duration - - def find_all_by_type(self, type: str) -> Iterator["BuildStep"]: - if type == self.type: - yield self - for child in self.children: - yield from child.find_all_by_type(type) - - def __repr__(self): - return f"BuildStep(type={self.type}, duration={self.duration}, children={len(self.children)})" - - -def load_last_metrics(path: Path) -> BuildStep: - """ - Loads the metrics of the most recent bootstrap execution from a metrics.json file. - """ - with open(path, "r") as f: - metrics = json.load(f) - invocation = metrics["invocations"][-1] - - def parse(entry) -> Optional[BuildStep]: - if "kind" not in entry or entry["kind"] != "rustbuild_step": - return None - type = entry.get("type", "") - duration = entry.get("duration_excluding_children_sec", 0) - children = [] - - for child in entry.get("children", ()): - step = parse(child) - if step is not None: - children.append(step) - duration += step.duration - return BuildStep(type=type, children=children, duration=duration) - - children = [parse(child) for child in invocation.get("children", ())] - return BuildStep( - type="root", - children=children, - duration=invocation.get("duration_including_children_sec", 0) - ) - - -@contextlib.contextmanager -def change_cwd(dir: Path): - """ - Temporarily change working directory to `dir`. - """ - cwd = os.getcwd() - LOGGER.debug(f"Changing working dir from `{cwd}` to `{dir}`") - os.chdir(dir) - try: - yield - finally: - LOGGER.debug(f"Reverting working dir to `{cwd}`") - os.chdir(cwd) - - -def humantime(time_s: float) -> str: - hours = time_s // 3600 - time_s = time_s % 3600 - minutes = time_s // 60 - seconds = time_s % 60 - - result = "" - if hours > 0: - result += f"{int(hours)}h " - if minutes > 0: - result += f"{int(minutes)}m " - result += f"{round(seconds)}s" - return result - - -def move_path(src: Path, dst: Path): - LOGGER.info(f"Moving `{src}` to `{dst}`") - shutil.move(src, dst) - - -def delete_file(path: Path): - LOGGER.info(f"Deleting file `{path}`") - os.unlink(path) - - -def delete_directory(path: Path): - LOGGER.info(f"Deleting directory `{path}`") - shutil.rmtree(path) - - -def unpack_archive(archive: Path, target_dir: Optional[Path] = None): - LOGGER.info(f"Unpacking archive `{archive}`") - shutil.unpack_archive(str(archive), extract_dir=str(target_dir) if target_dir is not None else None) - - -def download_file(src: str, target: Path): - LOGGER.info(f"Downloading `{src}` into `{target}`") - urllib.request.urlretrieve(src, str(target)) - - -def retry_action(action, name: str, max_fails: int = 5): - LOGGER.info(f"Attempting to perform action `{name}` with retry") - for iteration in range(max_fails): - LOGGER.info(f"Attempt {iteration + 1}/{max_fails}") - try: - action() - return - except BaseException: # also catch ctrl+c/sysexit - LOGGER.error(f"Action `{name}` has failed\n{traceback.format_exc()}") - - raise Exception(f"Action `{name}` has failed after {max_fails} attempts") - - -def cmd( - args: List[Union[str, Path]], - env: Optional[Dict[str, str]] = None, - output_path: Optional[Path] = None -): - args = [str(arg) for arg in args] - - environment = os.environ.copy() - - cmd_str = "" - if env is not None: - environment.update(env) - cmd_str += " ".join(f"{k}={v}" for (k, v) in (env or {}).items()) - cmd_str += " " - cmd_str += " ".join(args) - if output_path is not None: - cmd_str += f" > {output_path}" - LOGGER.info(f"Executing `{cmd_str}`") - - if output_path is not None: - with open(output_path, "w") as f: - return subprocess.run( - args, - env=environment, - check=True, - stdout=f - ) - return subprocess.run(args, env=environment, check=True) - - -class BenchmarkRunner: - def run_rustc(self, pipeline: Pipeline): - raise NotImplementedError - - def run_llvm(self, pipeline: Pipeline): - raise NotImplementedError - - def run_bolt(self, pipeline: Pipeline): - raise NotImplementedError - - -class DefaultBenchmarkRunner(BenchmarkRunner): - def run_rustc(self, pipeline: Pipeline): - # Here we're profiling the `rustc` frontend, so we also include `Check`. - # The benchmark set includes various stress tests that put the frontend under pressure. - run_compiler_benchmarks( - pipeline, - profiles=["Check", "Debug", "Opt"], - scenarios=["All"], - crates=RUSTC_PGO_CRATES, - env=dict( - LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path()) - ) - ) - - def run_llvm(self, pipeline: Pipeline): - run_compiler_benchmarks( - pipeline, - profiles=["Debug", "Opt"], - scenarios=["Full"], - crates=LLVM_PGO_CRATES - ) - - def run_bolt(self, pipeline: Pipeline): - run_compiler_benchmarks( - pipeline, - profiles=["Check", "Debug", "Opt"], - scenarios=["Full"], - crates=LLVM_BOLT_CRATES - ) - - -def run_compiler_benchmarks( - pipeline: Pipeline, - profiles: List[str], - scenarios: List[str], - crates: List[str], - env: Optional[Dict[str, str]] = None -): - env = env if env is not None else {} - - # Compile libcore, both in opt-level=0 and opt-level=3 - with change_cwd(pipeline.build_root()): - cmd([ - pipeline.rustc_stage_2(), - "--edition", "2021", - "--crate-type", "lib", - str(pipeline.checkout_path() / "library/core/src/lib.rs"), - "--out-dir", pipeline.opt_artifacts() - ], env=dict(RUSTC_BOOTSTRAP="1", **env)) - - cmd([ - pipeline.rustc_stage_2(), - "--edition", "2021", - "--crate-type", "lib", - "-Copt-level=3", - str(pipeline.checkout_path() / "library/core/src/lib.rs"), - "--out-dir", pipeline.opt_artifacts() - ], env=dict(RUSTC_BOOTSTRAP="1", **env)) - - # Run rustc-perf benchmarks - # Benchmark using profile_local with eprintln, which essentially just means - # don't actually benchmark -- just make sure we run rustc a bunch of times. - with change_cwd(pipeline.rustc_perf_dir()): - cmd([ - pipeline.cargo_stage_0(), - "run", - "-p", "collector", "--bin", "collector", "--", - "profile_local", "eprintln", - pipeline.rustc_stage_2(), - "--id", "Test", - "--cargo", pipeline.cargo_stage_0(), - "--profiles", ",".join(profiles), - "--scenarios", ",".join(scenarios), - "--include", ",".join(crates) - ], env=dict( - RUST_LOG="collector=debug", - RUSTC=str(pipeline.rustc_stage_0()), - RUSTC_BOOTSTRAP="1", - **env - )) - - -# https://stackoverflow.com/a/31631711/1107768 -def format_bytes(size: int) -> str: - """Return the given bytes as a human friendly KiB, MiB or GiB string.""" - KB = 1024 - MB = KB ** 2 # 1,048,576 - GB = KB ** 3 # 1,073,741,824 - TB = KB ** 4 # 1,099,511,627,776 - - if size < KB: - return f"{size} B" - elif KB <= size < MB: - return f"{size / KB:.2f} KiB" - elif MB <= size < GB: - return f"{size / MB:.2f} MiB" - elif GB <= size < TB: - return f"{size / GB:.2f} GiB" - else: - return str(size) - - -# https://stackoverflow.com/a/63307131/1107768 -def count_files(path: Path) -> int: - return sum(1 for p in path.rglob("*") if p.is_file()) - - -def count_files_with_prefix(path: Path) -> int: - return sum(1 for p in glob.glob(f"{path}*") if Path(p).is_file()) - - -# https://stackoverflow.com/a/55659577/1107768 -def get_path_size(path: Path) -> int: - if path.is_dir(): - return sum(p.stat().st_size for p in path.rglob("*")) - return path.stat().st_size - - -def get_path_prefix_size(path: Path) -> int: - """ - Get size of all files beginning with the prefix `path`. - Alternative to shell `du -sh <path>*`. - """ - return sum(Path(p).stat().st_size for p in glob.glob(f"{path}*")) - - -def get_files(directory: Path, filter: Optional[Callable[[Path], bool]] = None) -> Iterable[Path]: - for file in os.listdir(directory): - path = directory / file - if filter is None or filter(path): - yield path - - -def bootstrap_build( - pipeline: Pipeline, - args: List[str], - env: Optional[Dict[str, str]] = None, - targets: Iterable[str] = ("library/std", ) -): - if env is None: - env = {} - else: - env = dict(env) - env["RUST_BACKTRACE"] = "1" - arguments = [ - sys.executable, - pipeline.checkout_path() / "x.py", - "build", - "--target", PGO_HOST, - "--host", PGO_HOST, - "--stage", "2", - ] + list(targets) + args - cmd(arguments, env=env) - - -def create_pipeline() -> Pipeline: - if sys.platform == "linux": - return LinuxPipeline() - elif sys.platform in ("cygwin", "win32"): - return WindowsPipeline() - else: - raise Exception(f"Optimized build is not supported for platform {sys.platform}") - - -def gather_llvm_profiles(pipeline: Pipeline, runner: BenchmarkRunner): - LOGGER.info("Running benchmarks with PGO instrumented LLVM") - - runner.run_llvm(pipeline) - - profile_path = pipeline.llvm_profile_merged_file() - LOGGER.info(f"Merging LLVM PGO profiles to {profile_path}") - cmd([ - pipeline.downloaded_llvm_dir() / "bin" / "llvm-profdata", - "merge", - "-o", profile_path, - pipeline.llvm_profile_dir_root() - ]) - - LOGGER.info("LLVM PGO statistics") - LOGGER.info(f"{profile_path}: {format_bytes(get_path_size(profile_path))}") - LOGGER.info( - f"{pipeline.llvm_profile_dir_root()}: {format_bytes(get_path_size(pipeline.llvm_profile_dir_root()))}") - LOGGER.info(f"Profile file count: {count_files(pipeline.llvm_profile_dir_root())}") - - # We don't need the individual .profraw files now that they have been merged - # into a final .profdata - delete_directory(pipeline.llvm_profile_dir_root()) - - -def gather_rustc_profiles(pipeline: Pipeline, runner: BenchmarkRunner): - LOGGER.info("Running benchmarks with PGO instrumented rustc") - - runner.run_rustc(pipeline) - - profile_path = pipeline.rustc_profile_merged_file() - LOGGER.info(f"Merging Rustc PGO profiles to {profile_path}") - cmd([ - pipeline.build_artifacts() / "llvm" / "bin" / "llvm-profdata", - "merge", - "-o", profile_path, - pipeline.rustc_profile_dir_root() - ]) - - LOGGER.info("Rustc PGO statistics") - LOGGER.info(f"{profile_path}: {format_bytes(get_path_size(profile_path))}") - LOGGER.info( - f"{pipeline.rustc_profile_dir_root()}: {format_bytes(get_path_size(pipeline.rustc_profile_dir_root()))}") - LOGGER.info(f"Profile file count: {count_files(pipeline.rustc_profile_dir_root())}") - - # We don't need the individual .profraw files now that they have been merged - # into a final .profdata - delete_directory(pipeline.rustc_profile_dir_root()) - - -def gather_llvm_bolt_profiles(pipeline: Pipeline, runner: BenchmarkRunner): - LOGGER.info("Running benchmarks with BOLT instrumented LLVM") - - runner.run_bolt(pipeline) - - merged_profile_path = pipeline.llvm_bolt_profile_merged_file() - profile_files_path = Path("/tmp/prof.fdata") - LOGGER.info(f"Merging LLVM BOLT profiles to {merged_profile_path}") - - profile_files = sorted(glob.glob(f"{profile_files_path}*")) - cmd([ - "merge-fdata", - *profile_files, - ], output_path=merged_profile_path) - - LOGGER.info("LLVM BOLT statistics") - LOGGER.info(f"{merged_profile_path}: {format_bytes(get_path_size(merged_profile_path))}") - LOGGER.info( - f"{profile_files_path}: {format_bytes(get_path_prefix_size(profile_files_path))}") - LOGGER.info(f"Profile file count: {count_files_with_prefix(profile_files_path)}") - - -def clear_llvm_files(pipeline: Pipeline): - """ - Rustbuild currently doesn't support rebuilding LLVM when PGO options - change (or any other llvm-related options); so just clear out the relevant - directories ourselves. - """ - LOGGER.info("Clearing LLVM build files") - delete_directory(pipeline.build_artifacts() / "llvm") - delete_directory(pipeline.build_artifacts() / "lld") - - -def print_binary_sizes(pipeline: Pipeline): - bin_dir = pipeline.build_artifacts() / "stage2" / "bin" - binaries = get_files(bin_dir) - - lib_dir = pipeline.build_artifacts() / "stage2" / "lib" - libraries = get_files(lib_dir, lambda p: p.suffix == ".so") - - paths = sorted(binaries) + sorted(libraries) - with StringIO() as output: - for path in paths: - path_str = f"{path.name}:" - print(f"{path_str:<50}{format_bytes(path.stat().st_size):>14}", file=output) - LOGGER.info(f"Rustc binary size\n{output.getvalue()}") - - -def print_free_disk_space(pipeline: Pipeline): - usage = shutil.disk_usage(pipeline.opt_artifacts()) - total = usage.total - used = usage.used - free = usage.free - - logging.info( - f"Free disk space: {format_bytes(free)} out of total {format_bytes(total)} ({(used / total) * 100:.2f}% used)") - - -def log_metrics(step: BuildStep): - substeps: List[Tuple[int, BuildStep]] = [] - - def visit(step: BuildStep, level: int): - substeps.append((level, step)) - for child in step.children: - visit(child, level=level + 1) - - visit(step, 0) - - output = StringIO() - for (level, step) in substeps: - label = f"{'.' * level}{step.type}" - print(f"{label:<65}{step.duration:>8.2f}s", file=output) - logging.info(f"Build step durations\n{output.getvalue()}") - - -def record_metrics(pipeline: Pipeline, timer: Timer): - metrics = load_last_metrics(pipeline.metrics_path()) - if metrics is None: - return - llvm_steps = tuple(metrics.find_all_by_type("bootstrap::llvm::Llvm")) - llvm_duration = sum(step.duration for step in llvm_steps) - - rustc_steps = tuple(metrics.find_all_by_type("bootstrap::compile::Rustc")) - rustc_duration = sum(step.duration for step in rustc_steps) - - # The LLVM step is part of the Rustc step - rustc_duration = max(0, rustc_duration - llvm_duration) - - if llvm_duration > 0: - timer.add_duration("LLVM", llvm_duration) - if rustc_duration > 0: - timer.add_duration("Rustc", rustc_duration) - - log_metrics(metrics) - - -def run_tests(pipeline: Pipeline): - """ - After `dist` is executed, we extract its archived components into a sysroot directory, - and then use that extracted rustc as a stage0 compiler. - Then we run a subset of tests using that compiler, to have a basic smoke test which checks - whether the optimization pipeline hasn't broken something. - """ - build_dir = pipeline.build_root() / "build" - dist_dir = build_dir / "dist" - - def extract_dist_dir(name: str) -> Path: - target_dir = build_dir / "optimized-dist" - target_dir.mkdir(parents=True, exist_ok=True) - unpack_archive(dist_dir / f"{name}.tar.xz", target_dir=target_dir) - extracted_path = target_dir / name - assert extracted_path.is_dir() - return extracted_path - - # Extract rustc, libstd, cargo and src archives to create the optimized sysroot - rustc_dir = extract_dist_dir(f"rustc-nightly-{PGO_HOST}") / "rustc" - libstd_dir = extract_dist_dir(f"rust-std-nightly-{PGO_HOST}") / f"rust-std-{PGO_HOST}" - cargo_dir = extract_dist_dir(f"cargo-nightly-{PGO_HOST}") / "cargo" - extracted_src_dir = extract_dist_dir("rust-src-nightly") / "rust-src" - - # We need to manually copy libstd to the extracted rustc sysroot - shutil.copytree( - libstd_dir / "lib" / "rustlib" / PGO_HOST / "lib", - rustc_dir / "lib" / "rustlib" / PGO_HOST / "lib" - ) - - # Extract sources - they aren't in the `rustc-nightly-{host}` tarball, so we need to manually copy libstd - # sources to the extracted sysroot. We need sources available so that `-Zsimulate-remapped-rust-src-base` - # works correctly. - shutil.copytree( - extracted_src_dir / "lib" / "rustlib" / "src", - rustc_dir / "lib" / "rustlib" / "src" - ) - - rustc_path = rustc_dir / "bin" / f"rustc{pipeline.executable_extension()}" - assert rustc_path.is_file() - cargo_path = cargo_dir / "bin" / f"cargo{pipeline.executable_extension()}" - assert cargo_path.is_file() - - config_content = f"""profile = "user" -changelog-seen = 2 - -[build] -rustc = "{rustc_path.as_posix()}" -cargo = "{cargo_path.as_posix()}" - -[llvm] -download-ci-llvm = true -""" - logging.info(f"Using following `config.toml` for running tests:\n{config_content}") - - # Simulate a stage 0 compiler with the extracted optimized dist artifacts. - with open("config.toml", "w") as f: - f.write(config_content) - - args = [ - sys.executable, - pipeline.checkout_path() / "x.py", - "test", - "--stage", "0", - "tests/assembly", - "tests/codegen", - "tests/codegen-units", - "tests/incremental", - "tests/mir-opt", - "tests/pretty", - "tests/run-pass-valgrind", - "tests/ui", - ] - for test_path in pipeline.skipped_tests(): - args.extend(["--exclude", test_path]) - cmd(args=args, env=dict( - COMPILETEST_FORCE_STAGE0="1" - )) - - -def execute_build_pipeline(timer: Timer, pipeline: Pipeline, runner: BenchmarkRunner, dist_build_args: List[str]): - # Clear and prepare tmp directory - shutil.rmtree(pipeline.opt_artifacts(), ignore_errors=True) - os.makedirs(pipeline.opt_artifacts(), exist_ok=True) - - pipeline.build_rustc_perf() - - """ - Stage 1: Build PGO instrumented rustc - - We use a normal build of LLVM, because gathering PGO profiles for LLVM and `rustc` at the same time - can cause issues. - """ - with timer.section("Stage 1 (rustc PGO)") as stage1: - with stage1.section("Build PGO instrumented rustc and LLVM") as rustc_pgo_instrument: - bootstrap_build(pipeline, args=[ - "--rust-profile-generate", - pipeline.rustc_profile_dir_root() - ]) - record_metrics(pipeline, rustc_pgo_instrument) - - with stage1.section("Gather profiles"): - gather_rustc_profiles(pipeline, runner) - print_free_disk_space(pipeline) - - with stage1.section("Build PGO optimized rustc") as rustc_pgo_use: - bootstrap_build(pipeline, args=[ - "--rust-profile-use", - pipeline.rustc_profile_merged_file() - ]) - record_metrics(pipeline, rustc_pgo_use) - dist_build_args += [ - "--rust-profile-use", - pipeline.rustc_profile_merged_file() - ] - - """ - Stage 2: Gather LLVM PGO profiles - """ - with timer.section("Stage 2 (LLVM PGO)") as stage2: - # Clear normal LLVM artifacts - clear_llvm_files(pipeline) - - with stage2.section("Build PGO instrumented LLVM") as llvm_pgo_instrument: - bootstrap_build(pipeline, args=[ - "--llvm-profile-generate", - # We want to keep the already built PGO-optimized `rustc`. - "--keep-stage", "0", - "--keep-stage", "1" - ], env=dict( - LLVM_PROFILE_DIR=str(pipeline.llvm_profile_dir_root() / "prof-%p") - )) - record_metrics(pipeline, llvm_pgo_instrument) - - with stage2.section("Gather profiles"): - gather_llvm_profiles(pipeline, runner) - - dist_build_args += [ - "--llvm-profile-use", - pipeline.llvm_profile_merged_file(), - ] - print_free_disk_space(pipeline) - - # Clear PGO-instrumented LLVM artifacts - clear_llvm_files(pipeline) - - """ - Stage 3: Build BOLT instrumented LLVM - - We build a PGO optimized LLVM in this step, then instrument it with BOLT and gather BOLT profiles. - Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build. - BOLT instrumentation is performed "on-the-fly" when the LLVM library is copied to the sysroot of rustc, - therefore the LLVM artifacts on disk are not "tainted" with BOLT instrumentation and they can be reused. - """ - if pipeline.supports_bolt(): - with timer.section("Stage 3 (LLVM BOLT)") as stage3: - with stage3.section("Build BOLT instrumented LLVM") as llvm_bolt_instrument: - bootstrap_build(pipeline, args=[ - "--llvm-profile-use", - pipeline.llvm_profile_merged_file(), - "--llvm-bolt-profile-generate", - # We want to keep the already built PGO-optimized `rustc`. - "--keep-stage", "0", - "--keep-stage", "1" - ]) - record_metrics(pipeline, llvm_bolt_instrument) - - with stage3.section("Gather profiles"): - gather_llvm_bolt_profiles(pipeline, runner) - - dist_build_args += [ - "--llvm-bolt-profile-use", - pipeline.llvm_bolt_profile_merged_file() - ] - print_free_disk_space(pipeline) - - # We want to keep the already built PGO-optimized `rustc`. - dist_build_args += [ - "--keep-stage", "0", - "--keep-stage", "1" - ] - - """ - Final stage: Build PGO optimized rustc + PGO/BOLT optimized LLVM - """ - with timer.section("Final stage (dist build)") as final_stage: - cmd(dist_build_args) - record_metrics(pipeline, final_stage) - - # Try builds can be in various broken states, so we don't want to gatekeep them with tests - if not is_try_build(): - with timer.section("Run tests"): - run_tests(pipeline) - - -def run(runner: BenchmarkRunner): - logging.basicConfig( - level=logging.DEBUG, - format="%(name)s %(levelname)-4s: %(message)s", - ) - - LOGGER.info(f"Running multi-stage build using Python {sys.version}") - LOGGER.info(f"Environment values\n{pprint.pformat(dict(os.environ), indent=2)}") - - build_args = sys.argv[1:] - - # Skip components that are not needed for try builds to speed them up - if is_try_build(): - LOGGER.info("Skipping building of unimportant components for a try build") - for target in ("rust-docs", "rustc-docs", "rust-docs-json", "rust-analyzer", - "rustc-src", "clippy", "miri", "rustfmt"): - build_args.extend(["--exclude", target]) - - timer = Timer() - pipeline = create_pipeline() - - try: - execute_build_pipeline(timer, pipeline, runner, build_args) - except BaseException as e: - LOGGER.error("The multi-stage build has failed") - raise e - finally: - timer.print_stats() - print_free_disk_space(pipeline) - - print_binary_sizes(pipeline) - - -if __name__ == "__main__": - runner = DefaultBenchmarkRunner() - run(runner) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 6d1729e57b1..d2a25e612ec 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -87,7 +87,7 @@ target | notes `aarch64-unknown-linux-musl` | ARM64 Linux with MUSL `arm-unknown-linux-gnueabi` | ARMv6 Linux (kernel 3.2, glibc 2.17) `arm-unknown-linux-gnueabihf` | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17) -`armv7-unknown-linux-gnueabihf` | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17) +`armv7-unknown-linux-gnueabihf` | ARMv7-A Linux, hardfloat (kernel 3.2, glibc 2.17) [`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36) `mips-unknown-linux-gnu` | MIPS Linux (kernel 4.4, glibc 2.23) `mips64-unknown-linux-gnuabi64` | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23) @@ -133,17 +133,17 @@ target | std | notes `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat `aarch64-unknown-none` | * | Bare ARM64, hardfloat [`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | ARM64 UEFI -[`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android +[`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv6 Android `arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL `arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat `armebv7r-none-eabi` | * | Bare ARMv7-R, Big Endian `armebv7r-none-eabihf` | * | Bare ARMv7-R, Big Endian, hardfloat `armv5te-unknown-linux-gnueabi` | ✓ | ARMv5TE Linux (kernel 4.4, glibc 2.23) `armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with MUSL -[`armv7-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7a Android -`armv7-unknown-linux-gnueabi` | ✓ |ARMv7 Linux (kernel 4.15, glibc 2.27) -`armv7-unknown-linux-musleabi` | ✓ |ARMv7 Linux with MUSL -`armv7-unknown-linux-musleabihf` | ✓ | ARMv7 Linux with MUSL, hardfloat +[`armv7-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7-A Android +`armv7-unknown-linux-gnueabi` | ✓ | ARMv7-A Linux (kernel 4.15, glibc 2.27) +`armv7-unknown-linux-musleabi` | ✓ | ARMv7-A Linux with MUSL +`armv7-unknown-linux-musleabihf` | ✓ | ARMv7-A Linux with MUSL, hardfloat `armv7a-none-eabi` | * | Bare ARMv7-A `armv7r-none-eabi` | * | Bare ARMv7-R `armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat @@ -167,15 +167,15 @@ target | std | notes `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA) `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23) `sparcv9-sun-solaris` | ✓ | SPARC Solaris 10/11, illumos -`thumbv6m-none-eabi` | * | Bare Cortex-M0, M0+, M1 -`thumbv7em-none-eabi` | * | Bare Cortex-M4, M7 -`thumbv7em-none-eabihf` | * | Bare Cortex-M4F, M7F, FPU, hardfloat -`thumbv7m-none-eabi` | * | Bare Cortex-M3 -[`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode ARMv7a Android with NEON -`thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode ARMv7a Linux with NEON (kernel 4.4, glibc 2.23) -`thumbv8m.base-none-eabi` | * | ARMv8-M Baseline -`thumbv8m.main-none-eabi` | * | ARMv8-M Mainline -`thumbv8m.main-none-eabihf` | * | ARMv8-M Mainline, hardfloat +`thumbv6m-none-eabi` | * | Bare ARMv6-M +`thumbv7em-none-eabi` | * | Bare ARMv7E-M +`thumbv7em-none-eabihf` | * | Bare ARMV7E-M, hardfloat +`thumbv7m-none-eabi` | * | Bare ARMv7-M +[`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode ARMv7-A Android with NEON +`thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode ARMv7-A Linux with NEON (kernel 4.4, glibc 2.23) +`thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline +`thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline +`thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI @@ -234,26 +234,26 @@ target | std | host | notes [`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian) [`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers [`armeb-unknown-linux-gnueabi`](platform-support/armeb-unknown-linux-gnueabi.md) | ✓ | ? | ARM BE8 the default ARM big-endian architecture since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). -`armv4t-none-eabi` | * | | ARMv4T A32 -`armv4t-unknown-linux-gnueabi` | ? | | -[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE A32 +`armv4t-none-eabi` | * | | Bare ARMv4T +`armv4t-unknown-linux-gnueabi` | ? | | ARMv4T Linux +[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare ARMv5TE `armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD [`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) -`armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8 -[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARM Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) -[`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARMv7 OpenHarmony | -[`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7 Linux with uClibc, softfloat -[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux with uClibc, hardfloat -`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD -[`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv7 NetBSD w/hard-float -`armv7-wrs-vxworks-eabihf` | ? | | +`armv7-apple-ios` | ✓ | | ARMv7-A Cortex-A8 iOS +[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) +[`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARMv7-A OpenHarmony | +[`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7-A Linux with uClibc, softfloat +[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7-A Linux with uClibc, hardfloat +`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7-A FreeBSD +[`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv7-A NetBSD w/hard-float +`armv7-wrs-vxworks-eabihf` | ? | | ARMv7-A for VxWorks [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat -`armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat -[`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS -`armv7s-apple-ios` | ✓ | | +`armv7a-none-eabihf` | * | | Bare ARMv7-A, hardfloat +[`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARMv7-A Apple WatchOS +`armv7s-apple-ios` | ✓ | | ARMv7-A Apple-A6 Apple iOS `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) @@ -305,16 +305,17 @@ target | std | host | notes `riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia `riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0) +[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ? | RISC-V NetBSD [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 -`thumbv4t-none-eabi` | * | | ARMv4T T32 -[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE T32 +`thumbv4t-none-eabi` | * | | Thumb-mode Bare ARMv4T +[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare ARMv5TE `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | -`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL +`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md index a1969524a20..23f4488de6e 100644 --- a/src/doc/rustc/src/platform-support/netbsd.md +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -22,6 +22,7 @@ are currently defined running NetBSD: | `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) | | `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) | | `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) | +| `riscv64gc-unknown-netbsd` | [64-bit RISC-V](https://wiki.netbsd.org/ports/riscv/) | `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) | All use the "native" `stdc++` library which goes along with the natively diff --git a/src/doc/style-guide/src/SUMMARY.md b/src/doc/style-guide/src/SUMMARY.md index 59fe9fdc669..606485bfb6c 100644 --- a/src/doc/style-guide/src/SUMMARY.md +++ b/src/doc/style-guide/src/SUMMARY.md @@ -9,3 +9,4 @@ - [Other style advice](advice.md) - [`Cargo.toml` conventions](cargo.md) - [Guiding principles and rationale](principles.md) +- [Nightly-only syntax](nightly.md) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index f5e37b6c46f..143161da6cf 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -295,8 +295,9 @@ Use parentheses liberally, do not necessarily elide them due to precedence. Tools should not automatically insert or remove parentheses. Do not use spaces to indicate precedence. -If line-breaking, put the operator on a new line and block indent. Put each -sub-expression on its own line. E.g., +If line-breaking, block-indent each subsequent line. For assignment operators, +break after the operator; for all other operators, put the operator on the +subsequent line. Put each sub-expression on its own line: ```rust foo_bar @@ -752,9 +753,9 @@ not put the `if` clause on a newline. E.g., } ``` -If every clause in a pattern is *small*, but does not fit on one line, then the -pattern may be formatted across multiple lines with as many clauses per line as -possible. Again break before a `|`: +If every clause in a pattern is *small*, but the whole pattern does not fit on +one line, then the pattern may be formatted across multiple lines with as many +clauses per line as possible. Again break before a `|`: ```rust foo | bar | baz @@ -763,17 +764,18 @@ possible. Again break before a `|`: } ``` -We define a pattern clause to be *small* if it matches the following grammar: +We define a pattern clause to be *small* if it fits on a single line and +matches "small" in the following grammar: ``` -[small, ntp]: - - single token - - `&[single-line, ntp]` +small: + - small_no_tuple + - unary tuple constructor: `(` small_no_tuple `,` `)` + - `&` small -[small]: - - `[small, ntp]` - - unary tuple constructor `([small, ntp])` - - `&[small]` +small_no_tuple: + - single token + - `&` small_no_tuple ``` E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not. diff --git a/src/doc/style-guide/src/nightly.md b/src/doc/style-guide/src/nightly.md new file mode 100644 index 00000000000..031811b0e6f --- /dev/null +++ b/src/doc/style-guide/src/nightly.md @@ -0,0 +1,5 @@ +This chapter documents style and formatting for nightly-only syntax. The rest of the style guide documents style for stable Rust syntax; nightly syntax only appears in this chapter. Each section here includes the name of the feature gate, so that searches (e.g. `git grep`) for a nightly feature in the Rust repository also turn up the style guide section. + +Style and formatting for nightly-only syntax should be removed from this chapter and integrated into the appropriate sections of the style guide at the time of stabilization. + +There is no guarantee of the stability of this chapter in contrast to the rest of the style guide. Refer to the style team policy for nightly formatting procedure regarding breaking changes to this chapter. diff --git a/src/doc/unstable-book/src/library-features/default-free-fn.md b/src/doc/unstable-book/src/library-features/default-free-fn.md deleted file mode 100644 index bafc9ac4d0d..00000000000 --- a/src/doc/unstable-book/src/library-features/default-free-fn.md +++ /dev/null @@ -1,47 +0,0 @@ -# `default_free_fn` - -The tracking issue for this feature is: [#73014] - -[#73014]: https://github.com/rust-lang/rust/issues/73014 - ------------------------- - -Adds a free `default()` function to the `std::default` module. This function -just forwards to [`Default::default()`], but may remove repetition of the word -"default" from the call site. - -[`Default::default()`]: ../../std/default/trait.Default.html#tymethod.default - -Here is an example: - -```rust -#![feature(default_free_fn)] -use std::default::default; - -#[derive(Default)] -struct AppConfig { - foo: FooConfig, - bar: BarConfig, -} - -#[derive(Default)] -struct FooConfig { - foo: i32, -} - -#[derive(Default)] -struct BarConfig { - bar: f32, - baz: u8, -} - -fn main() { - let options = AppConfig { - foo: default(), - bar: BarConfig { - bar: 10.1, - ..default() - }, - }; -} -``` diff --git a/src/llvm-project b/src/llvm-project -Subproject 22897bce7bfedc9cd3953a33419b34693626350 +Subproject 06248fa7f35136f66114b2f82c29abcefd5f1e9 diff --git a/src/tools/build_helper/Cargo.toml b/src/tools/build_helper/Cargo.toml index 99f6fea2ecf..66894e1abc4 100644 --- a/src/tools/build_helper/Cargo.toml +++ b/src/tools/build_helper/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +serde = "1" +serde_derive = "1" diff --git a/src/tools/build_helper/src/lib.rs b/src/tools/build_helper/src/lib.rs index 3fa970373b3..575f3677155 100644 --- a/src/tools/build_helper/src/lib.rs +++ b/src/tools/build_helper/src/lib.rs @@ -1,3 +1,4 @@ pub mod ci; pub mod git; +pub mod metrics; pub mod util; diff --git a/src/tools/build_helper/src/metrics.rs b/src/tools/build_helper/src/metrics.rs new file mode 100644 index 00000000000..2d0c66a8f33 --- /dev/null +++ b/src/tools/build_helper/src/metrics.rs @@ -0,0 +1,92 @@ +use serde_derive::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub struct JsonRoot { + #[serde(default)] // For version 0 the field was not present. + pub format_version: usize, + pub system_stats: JsonInvocationSystemStats, + pub invocations: Vec<JsonInvocation>, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub struct JsonInvocation { + // Unix timestamp in seconds + // + // This is necessary to easily correlate this invocation with logs or other data. + pub start_time: u64, + pub duration_including_children_sec: f64, + pub children: Vec<JsonNode>, +} + +#[derive(Serialize, Deserialize)] +#[serde(tag = "kind", rename_all = "snake_case")] +pub enum JsonNode { + RustbuildStep { + #[serde(rename = "type")] + type_: String, + debug_repr: String, + + duration_excluding_children_sec: f64, + system_stats: JsonStepSystemStats, + + children: Vec<JsonNode>, + }, + TestSuite(TestSuite), +} + +#[derive(Serialize, Deserialize)] +pub struct TestSuite { + pub metadata: TestSuiteMetadata, + pub tests: Vec<Test>, +} + +#[derive(Serialize, Deserialize)] +#[serde(tag = "kind", rename_all = "snake_case")] +pub enum TestSuiteMetadata { + CargoPackage { + crates: Vec<String>, + target: String, + host: String, + stage: u32, + }, + Compiletest { + suite: String, + mode: String, + compare_mode: Option<String>, + target: String, + host: String, + stage: u32, + }, +} + +#[derive(Serialize, Deserialize)] +pub struct Test { + pub name: String, + #[serde(flatten)] + pub outcome: TestOutcome, +} + +#[derive(Serialize, Deserialize)] +#[serde(tag = "outcome", rename_all = "snake_case")] +pub enum TestOutcome { + Passed, + Failed, + Ignored { ignore_reason: Option<String> }, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub struct JsonInvocationSystemStats { + pub cpu_threads_count: usize, + pub cpu_model: String, + + pub memory_total_bytes: u64, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub struct JsonStepSystemStats { + pub cpu_utilization_percent: f64, +} diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 5b377cece0e0dd0af686cf53ce4637d5d85c2a1 +Subproject 45782b6b8afd1da042d45c2daeec9c0744f72cc diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index 8c3ad24eeed..e8775b08144 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -61,7 +61,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - ) }) .map_or(false, |assoc_item| { - let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, [])); + let proj = Ty::new_projection(cx.tcx,assoc_item.def_id, cx.tcx.mk_substs_trait(ty, [])); let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj); nty.is_bool() diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index ec0ca50cfec..020ffe7f8fa 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -9,7 +9,7 @@ use rustc_hir::{ Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::adjustment::{Adjust, PointerCast}; +use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::{self, Adt, AdtDef, SubstsRef, Ty, TypeckResults}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::sym; @@ -116,7 +116,7 @@ fn check_struct<'tcx>( let is_default_without_adjusts = |expr| { is_default_equivalent(cx, expr) && typeck_results.expr_adjustments(expr).iter().all(|adj| { - !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize) + !matches!(adj.kind, Adjust::Pointer(PointerCoercion::Unsize) if contains_trait_object(adj.target)) }) }; diff --git a/src/tools/clippy/clippy_lints/src/incorrect_impls.rs b/src/tools/clippy/clippy_lints/src/incorrect_impls.rs index 13cc0b23ba3..7b95116ee4e 100644 --- a/src/tools/clippy/clippy_lints/src/incorrect_impls.rs +++ b/src/tools/clippy/clippy_lints/src/incorrect_impls.rs @@ -82,7 +82,7 @@ impl LateLintPass<'_> for IncorrectImpls { cx, hir_ty_to_ty(cx.tcx, imp.self_ty), copy_def_id, - trait_impl.substs, + &[], ) { if impl_item.ident.name == sym::clone { diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index f3347e33077..5c5a4cfce88 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -149,7 +149,7 @@ fn is_ref_iterable<'tcx>( let self_ty = if mutbl.is_mut() { self_ty } else { - cx.tcx.mk_ref(region, TypeAndMut { ty, mutbl }) + Ty::new_ref(cx.tcx,region, TypeAndMut { ty, mutbl }) }; if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = @@ -164,7 +164,7 @@ fn is_ref_iterable<'tcx>( && !self_ty.is_ref() { // Attempt to borrow - let self_ty = cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, TypeAndMut { + let self_ty = Ty::new_ref(cx.tcx,cx.tcx.lifetimes.re_erased, TypeAndMut { ty: self_ty, mutbl, }); diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index ac209d01406..8ca7af8107f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -215,7 +215,7 @@ fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty]) && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions( cx.param_env, - cx.tcx.mk_projection(into_iter_item_proj.def_id, into_iter_item_proj.substs) + Ty::new_projection(cx.tcx,into_iter_item_proj.def_id, into_iter_item_proj.substs) ) { iter_item_ty == into_iter_item_ty @@ -238,7 +238,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - .associated_items(iter_trait) .find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait) && let substs = cx.tcx.mk_substs(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))]) - && let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs) + && let proj_ty = Ty::new_projection(cx.tcx,iter_item.def_id, substs) && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty) { item_ty == EarlyBinder::bind(search_ty).subst(cx.tcx, cx.typeck_results().node_substs(call_id)) diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 16ef24bd4e3..6bd5e9e88c8 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -270,7 +270,7 @@ fn check_other_call_arg<'tcx>( if let Some((n_refs, receiver_ty)) = if n_refs > 0 || is_copy(cx, receiver_ty) { Some((n_refs, receiver_ty)) } else if trait_predicate.def_id() != deref_trait_id { - Some((1, cx.tcx.mk_ref( + Some((1, Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, ty::TypeAndMut { ty: receiver_ty, diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index ece10474715..f11d5773d04 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -17,7 +17,7 @@ use rustc_hir_typeck::expr_use_visitor as euv; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::{self, TypeVisitableExt}; +use rustc_middle::ty::{self, TypeVisitableExt, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::kw; @@ -168,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { ( preds.iter().any(|t| cx.tcx.is_diagnostic_item(sym::Borrow, t.def_id())), !preds.is_empty() && { - let ty_empty_region = cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_erased, ty); + let ty_empty_region = Ty::new_imm_ref(cx.tcx,cx.tcx.lifetimes.re_erased, ty); preds.iter().all(|t| { let ty_params = t.trait_ref.substs.iter().skip(1).collect::<Vec<_>>(); implements_trait(cx, ty_empty_region, t.def_id(), &ty_params) diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 0d78c3048ba..eab725de17f 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -14,7 +14,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingAnnotation, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::adjustment::{Adjust, PointerCast}; +use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, RegionKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -195,7 +195,7 @@ impl<'tcx> PassByRefOrValue { .adjustments() .items() .flat_map(|(_, a)| a) - .any(|a| matches!(a.kind, Adjust::Pointer(PointerCast::UnsafeFnPointer))) + .any(|a| matches!(a.kind, Adjust::Pointer(PointerCoercion::UnsafeFnPointer))) { continue; } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 866a04466c9..32213718b27 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -389,11 +389,11 @@ impl<'tcx> DerefTy<'tcx> { fn ty(&self, cx: &LateContext<'tcx>) -> Ty<'tcx> { match *self { Self::Str => cx.tcx.types.str_, - Self::Path => cx.tcx.mk_adt( + Self::Path => Ty::new_adt(cx.tcx, cx.tcx.adt_def(cx.tcx.get_diagnostic_item(sym::Path).unwrap()), List::empty(), ), - Self::Slice(_, ty) => cx.tcx.mk_slice(ty), + Self::Slice(_, ty) => Ty::new_slice(cx.tcx,ty), } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index 2fdd775ad48..c70ce83a9c4 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -7,6 +7,7 @@ use rustc_ast::util::parser::PREC_PREFIX; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; use rustc_lint::{LateContext, LateLintPass, Lint}; +use rustc_middle::ty::Ty; use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::subst::GenericArg; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -134,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( cx.param_env, - cx.tcx.mk_projection(target_id, cx.tcx.mk_substs(&[GenericArg::from(indexed_ty)])), + Ty::new_projection(cx.tcx,target_id, cx.tcx.mk_substs(&[GenericArg::from(indexed_ty)])), ) { if deref_ty == expr_ty { let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 31a9b69ca15..857d2ad8258 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>( "transmute from a pointer to a pointer", |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - let sugg = arg.as_ty(cx.tcx.mk_ptr(*to_ty)); + let sugg = arg.as_ty(Ty::new_ptr(cx.tcx,*to_ty)); diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); } }, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 426c7253806..ea9ad99618a 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -64,8 +64,8 @@ pub(super) fn check<'tcx>( }; let ty_to_and_mut = ty::TypeAndMut { ty: *ty_to, mutbl: *to_mutbl }; let sugg_paren = arg - .as_ty(cx.tcx.mk_ptr(ty_from_and_mut)) - .as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); + .as_ty(Ty::new_ptr(cx.tcx,ty_from_and_mut)) + .as_ty(Ty::new_ptr(cx.tcx,ty_to_and_mut)); let sugg = if *to_mutbl == Mutability::Mut { sugg_paren.mut_addr_deref() } else { diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs index 56207fe767c..b6615410e25 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs @@ -43,7 +43,7 @@ pub(super) fn check<'tcx>( let sugg = if *ptr_ty == rty_and_mut { arg.as_ty(to_ty) } else { - arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) + arg.as_ty(Ty::new_ptr(cx.tcx,rty_and_mut)).as_ty(to_ty) }; diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index dd3cda8ec52..d1cfdc49658 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -689,7 +689,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), ty::Array(sub_type, len) => match sub_type.kind() { - ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(lcx.tcx) { + ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap())) @@ -700,7 +700,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t .map(Constant::Vec), _ => None, }, - ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(lcx.tcx) { + ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap())) @@ -725,13 +725,14 @@ fn field_of_struct<'tcx>( result: mir::ConstantKind<'tcx>, field: &Ident, ) -> Option<mir::ConstantKind<'tcx>> { - if let Some(dc) = lcx.tcx.try_destructure_mir_constant(lcx.param_env.and(result)) + if let mir::ConstantKind::Val(result, ty) = result + && let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics((result, ty)) && let Some(dc_variant) = dc.variant && let Some(variant) = adt_def.variants().get(dc_variant) && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name) - && let Some(dc_field) = dc.fields.get(field_idx) + && let Some(&(val, ty)) = dc.fields.get(field_idx) { - Some(*dc_field) + Some(mir::ConstantKind::Val(val, ty)) } else { None diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index c9938caefb0..fbf4ab2722e 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::{ImplSource, ObligationCause}; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; +use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; use rustc_middle::ty::{BoundConstness, TraitRef}; use rustc_semver::RustcVersion; use rustc_span::symbol::sym; @@ -119,18 +119,18 @@ fn check_rvalue<'tcx>( | CastKind::FloatToFloat | CastKind::FnPtrToPtr | CastKind::PtrToPtr - | CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), + | CastKind::PointerCoercion(PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer), operand, _, ) => check_operand(tcx, operand, span, body), Rvalue::Cast( - CastKind::Pointer( - PointerCast::UnsafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer, + CastKind::PointerCoercion( + PointerCoercion::UnsafeFnPointer | PointerCoercion::ClosureFnPointer(_) | PointerCoercion::ReifyFnPointer, ), _, _, ) => Err((span, "function pointer casts are not allowed in const fn".into())), - Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), op, cast_ty) => { + Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), op, cast_ty) => { let pointee_ty = if let Some(deref_ty) = cast_ty.builtin_deref(true) { deref_ty.ty } else { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 9c39d22c61b..d650cbe0b13 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -1124,7 +1124,7 @@ pub fn make_normalized_projection<'tcx>( ); return None; } - match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.def_id, ty.substs)) { + match tcx.try_normalize_erasing_regions(param_env, Ty::new_projection(tcx,ty.def_id, ty.substs)) { Ok(ty) => Some(ty), Err(e) => { debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}"); @@ -1207,7 +1207,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( .infer_ctxt() .build() .at(&cause, param_env) - .query_normalize(tcx.mk_projection(ty.def_id, ty.substs)) + .query_normalize(Ty::new_projection(tcx,ty.def_id, ty.substs)) { Ok(ty) => Some(ty.value), Err(e) => { diff --git a/src/tools/clippy/tests/ui/needless_raw_string.fixed b/src/tools/clippy/tests/ui/needless_raw_string.fixed index 6438e46977b..b36912efbb2 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.fixed +++ b/src/tools/clippy/tests/ui/needless_raw_string.fixed @@ -10,7 +10,8 @@ fn main() { b"aaa"; br#""aaa""#; br#"\s"#; - c"aaa"; - cr#""aaa""#; - cr#"\s"#; + // currently disabled: https://github.com/rust-lang/rust/issues/113333 + // cr#"aaa"#; + // cr#""aaa""#; + // cr#"\s"#; } diff --git a/src/tools/clippy/tests/ui/needless_raw_string.rs b/src/tools/clippy/tests/ui/needless_raw_string.rs index f7ddc68265e..8f48e7dab2a 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.rs +++ b/src/tools/clippy/tests/ui/needless_raw_string.rs @@ -10,7 +10,8 @@ fn main() { br#"aaa"#; br#""aaa""#; br#"\s"#; - cr#"aaa"#; - cr#""aaa""#; - cr#"\s"#; + // currently disabled: https://github.com/rust-lang/rust/issues/113333 + // cr#"aaa"#; + // cr#""aaa""#; + // cr#"\s"#; } diff --git a/src/tools/clippy/tests/ui/needless_raw_string.stderr b/src/tools/clippy/tests/ui/needless_raw_string.stderr index 0179978b7b0..cfb07b647d7 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.stderr +++ b/src/tools/clippy/tests/ui/needless_raw_string.stderr @@ -12,11 +12,5 @@ error: unnecessary raw string literal LL | br#"aaa"#; | ^^^^^^^^^ help: try: `b"aaa"` -error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:13:5 - | -LL | cr#"aaa"#; - | ^^^^^^^^^ help: try: `c"aaa"` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed index e4d7d8fb017..c8507c72715 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed @@ -12,8 +12,9 @@ fn main() { br#"Hello "world"!"#; br####" "### "## "# "####; br###" "aa" "# "## "###; - cr#"aaa"#; - cr#"Hello "world"!"#; - cr####" "### "## "# "####; - cr###" "aa" "# "## "###; + // currently disabled: https://github.com/rust-lang/rust/issues/113333 + // cr#"aaa"#; + // cr##"Hello "world"!"##; + // cr######" "### "## "# "######; + // cr######" "aa" "# "## "######; } diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs index e2d85c52e78..912fbde1679 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs @@ -12,8 +12,9 @@ fn main() { br##"Hello "world"!"##; br######" "### "## "# "######; br######" "aa" "# "## "######; - cr#"aaa"#; - cr##"Hello "world"!"##; - cr######" "### "## "# "######; - cr######" "aa" "# "## "######; + // currently disabled: https://github.com/rust-lang/rust/issues/113333 + // cr#"aaa"#; + // cr##"Hello "world"!"##; + // cr######" "### "## "# "######; + // cr######" "aa" "# "## "######; } diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr index dff47a2d042..30e6783a38e 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr @@ -36,23 +36,5 @@ error: unnecessary hashes around raw string literal LL | br######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br###" "aa" "# "## "###` -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:16:5 - | -LL | cr##"Hello "world"!"##; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr#"Hello "world"!"#` - -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:17:5 - | -LL | cr######" "### "## "# "######; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr####" "### "## "# "####` - -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:18:5 - | -LL | cr######" "aa" "# "## "######; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr###" "aa" "# "## "###` - -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.rs b/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.rs deleted file mode 100644 index 67115f7c5a7..00000000000 --- a/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@run-rustfix -//@compile-flags: -C incremental=target/debug/test/incr - -// see https://github.com/rust-lang/rust-clippy/issues/10969 - -fn main() { - let s = "Hello, world!"; - println!("{}", s.to_string()); -} diff --git a/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.stderr b/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.stderr deleted file mode 100644 index a992c542914..00000000000 --- a/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/to_string_in_format_args_incremental.rs:8:21 - | -LL | println!("{}", s.to_string()); - | ^^^^^^^^^^^^ help: remove this - | - = note: `-D clippy::to-string-in-format-args` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c835962ad12..ad10c3e07ce 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -588,21 +588,22 @@ impl TestProps { } } +/// Extract a `(Option<line_config>, directive)` directive from a line if comment is present. pub fn line_directive<'line>( comment: &str, ln: &'line str, ) -> Option<(Option<&'line str>, &'line str)> { + let ln = ln.trim_start(); if ln.starts_with(comment) { let ln = ln[comment.len()..].trim_start(); if ln.starts_with('[') { // A comment like `//[foo]` is specific to revision `foo` - if let Some(close_brace) = ln.find(']') { - let lncfg = &ln[1..close_brace]; + let Some(close_brace) = ln.find(']') else { + panic!("malformed condition directive: expected `{}[foo]`, found `{}`", comment, ln); + }; - Some((Some(lncfg), ln[(close_brace + 1)..].trim_start())) - } else { - panic!("malformed condition directive: expected `{}[foo]`, found `{}`", comment, ln) - } + let lncfg = &ln[1..close_brace]; + Some((Some(lncfg), ln[(close_brace + 1)..].trim_start())) } else { Some((None, ln)) } diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs index 725f7a1515c..a455a1badc0 100644 --- a/src/tools/compiletest/src/read2.rs +++ b/src/tools/compiletest/src/read2.rs @@ -83,7 +83,7 @@ impl ProcOutput { } let new_len = bytes.len(); - if *filtered_len <= HEAD_LEN + TAIL_LEN { + if (*filtered_len).min(new_len) <= HEAD_LEN + TAIL_LEN { return; } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e8d0ebd40b0..ac19fe078f0 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -41,7 +41,7 @@ use crate::extract_gdb_version; use crate::is_android_gdb_target; mod debugger; -use debugger::{check_debugger_output, DebuggerCommands}; +use debugger::DebuggerCommands; #[cfg(test)] mod tests; @@ -997,16 +997,13 @@ impl<'test> TestCx<'test> { }; // Parse debugger commands etc from test files - let DebuggerCommands { commands, check_lines, breakpoint_lines, .. } = - match DebuggerCommands::parse_from( - &self.testpaths.file, - self.config, - prefixes, - self.revision, - ) { - Ok(cmds) => cmds, - Err(e) => self.fatal(&e), - }; + let dbg_cmds = DebuggerCommands::parse_from( + &self.testpaths.file, + self.config, + prefixes, + self.revision, + ) + .unwrap_or_else(|e| self.fatal(&e)); // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands let mut script_str = String::with_capacity(2048); @@ -1023,12 +1020,12 @@ impl<'test> TestCx<'test> { // Set breakpoints on every line that contains the string "#break" let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); - for line in &breakpoint_lines { + for line in &dbg_cmds.breakpoint_lines { script_str.push_str(&format!("bp `{}:{}`\n", source_file_name, line)); } // Append the other `cdb-command:`s - for line in &commands { + for line in &dbg_cmds.commands { script_str.push_str(line); script_str.push_str("\n"); } @@ -1058,7 +1055,7 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("Error while running CDB", &debugger_run_result); } - if let Err(e) = check_debugger_output(&debugger_run_result, &check_lines) { + if let Err(e) = dbg_cmds.check_output(&debugger_run_result) { self.fatal_proc_rec(&e, &debugger_run_result); } } @@ -1088,17 +1085,14 @@ impl<'test> TestCx<'test> { PREFIXES }; - let DebuggerCommands { commands, check_lines, breakpoint_lines } = - match DebuggerCommands::parse_from( - &self.testpaths.file, - self.config, - prefixes, - self.revision, - ) { - Ok(cmds) => cmds, - Err(e) => self.fatal(&e), - }; - let mut cmds = commands.join("\n"); + let dbg_cmds = DebuggerCommands::parse_from( + &self.testpaths.file, + self.config, + prefixes, + self.revision, + ) + .unwrap_or_else(|e| self.fatal(&e)); + let mut cmds = dbg_cmds.commands.join("\n"); // compile test file (it should have 'compile-flags:-g' in the header) let should_run = self.run_if_enabled(); @@ -1132,13 +1126,14 @@ impl<'test> TestCx<'test> { ./{}/stage2/lib/rustlib/{}/lib/\n", self.config.host, self.config.target )); - for line in &breakpoint_lines { + for line in &dbg_cmds.breakpoint_lines { script_str.push_str( - &format!( + format!( "break {:?}:{}\n", self.testpaths.file.file_name().unwrap().to_string_lossy(), *line - )[..], + ) + .as_str(), ); } script_str.push_str(&cmds); @@ -1279,7 +1274,7 @@ impl<'test> TestCx<'test> { } // Add line breakpoints - for line in &breakpoint_lines { + for line in &dbg_cmds.breakpoint_lines { script_str.push_str(&format!( "break '{}':{}\n", self.testpaths.file.file_name().unwrap().to_string_lossy(), @@ -1315,7 +1310,7 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("gdb failed to execute", &debugger_run_result); } - if let Err(e) = check_debugger_output(&debugger_run_result, &check_lines) { + if let Err(e) = dbg_cmds.check_output(&debugger_run_result) { self.fatal_proc_rec(&e, &debugger_run_result); } } @@ -1372,16 +1367,13 @@ impl<'test> TestCx<'test> { }; // Parse debugger commands etc from test files - let DebuggerCommands { commands, check_lines, breakpoint_lines, .. } = - match DebuggerCommands::parse_from( - &self.testpaths.file, - self.config, - prefixes, - self.revision, - ) { - Ok(cmds) => cmds, - Err(e) => self.fatal(&e), - }; + let dbg_cmds = DebuggerCommands::parse_from( + &self.testpaths.file, + self.config, + prefixes, + self.revision, + ) + .unwrap_or_else(|e| self.fatal(&e)); // Write debugger script: // We don't want to hang when calling `quit` while the process is still running @@ -1430,7 +1422,7 @@ impl<'test> TestCx<'test> { // Set breakpoints on every line that contains the string "#break" let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); - for line in &breakpoint_lines { + for line in &dbg_cmds.breakpoint_lines { script_str.push_str(&format!( "breakpoint set --file '{}' --line {}\n", source_file_name, line @@ -1438,7 +1430,7 @@ impl<'test> TestCx<'test> { } // Append the other commands - for line in &commands { + for line in &dbg_cmds.commands { script_str.push_str(line); script_str.push_str("\n"); } @@ -1458,7 +1450,7 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("Error while running LLDB", &debugger_run_result); } - if let Err(e) = check_debugger_output(&debugger_run_result, &check_lines) { + if let Err(e) = dbg_cmds.check_output(&debugger_run_result) { self.fatal_proc_rec(&e, &debugger_run_result); } } @@ -4022,8 +4014,11 @@ impl<'test> TestCx<'test> { } fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { + let rflags = self.props.run_flags.as_ref(); let cflags = self.props.compile_flags.join(" "); - let json = cflags.contains("--error-format json") + let json = rflags + .map_or(false, |s| s.contains("--format json") || s.contains("--format=json")) + || cflags.contains("--error-format json") || cflags.contains("--error-format pretty-json") || cflags.contains("--error-format=json") || cflags.contains("--error-format=pretty-json") diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs index 379ff0bab40..eebe5f3580b 100644 --- a/src/tools/compiletest/src/runtest/debugger.rs +++ b/src/tools/compiletest/src/runtest/debugger.rs @@ -2,18 +2,25 @@ use crate::common::Config; use crate::header::line_directive; use crate::runtest::ProcRes; +use std::fmt::Write; use std::fs::File; use std::io::{BufRead, BufReader}; -use std::path::Path; +use std::path::{Path, PathBuf}; +/// Representation of information to invoke a debugger and check its output pub(super) struct DebuggerCommands { + /// Commands for the debuuger pub commands: Vec<String>, - pub check_lines: Vec<String>, + /// Lines to insert breakpoints at pub breakpoint_lines: Vec<usize>, + /// Contains the source line number to check and the line itself + check_lines: Vec<(usize, String)>, + /// Source file name + file: PathBuf, } impl DebuggerCommands { - pub(super) fn parse_from( + pub fn parse_from( file: &Path, config: &Config, debugger_prefixes: &[&str], @@ -21,7 +28,7 @@ impl DebuggerCommands { ) -> Result<Self, String> { let directives = debugger_prefixes .iter() - .map(|prefix| (format!("{}-command", prefix), format!("{}-check", prefix))) + .map(|prefix| (format!("{prefix}-command"), format!("{prefix}-check"))) .collect::<Vec<_>>(); let mut breakpoint_lines = vec![]; @@ -29,63 +36,88 @@ impl DebuggerCommands { let mut check_lines = vec![]; let mut counter = 0; let reader = BufReader::new(File::open(file).unwrap()); - for line in reader.lines() { + for (line_no, line) in reader.lines().enumerate() { counter += 1; - match line { - Ok(line) => { - let (lnrev, line) = line_directive("//", &line).unwrap_or((None, &line)); - - // Skip any revision specific directive that doesn't match the current - // revision being tested - if lnrev.is_some() && lnrev != rev { - continue; - } - - if line.contains("#break") { - breakpoint_lines.push(counter); - } - - for &(ref command_directive, ref check_directive) in &directives { - config - .parse_name_value_directive(&line, command_directive) - .map(|cmd| commands.push(cmd)); - - config - .parse_name_value_directive(&line, check_directive) - .map(|cmd| check_lines.push(cmd)); - } - } - Err(e) => return Err(format!("Error while parsing debugger commands: {}", e)), + let line = line.map_err(|e| format!("Error while parsing debugger commands: {}", e))?; + let (lnrev, line) = line_directive("//", &line).unwrap_or((None, &line)); + + // Skip any revision specific directive that doesn't match the current + // revision being tested + if lnrev.is_some() && lnrev != rev { + continue; + } + + if line.contains("#break") { + breakpoint_lines.push(counter); + } + + for &(ref command_directive, ref check_directive) in &directives { + config + .parse_name_value_directive(&line, command_directive) + .map(|cmd| commands.push(cmd)); + + config + .parse_name_value_directive(&line, check_directive) + .map(|cmd| check_lines.push((line_no, cmd))); } } - Ok(Self { commands, check_lines, breakpoint_lines }) + Ok(Self { commands, breakpoint_lines, check_lines, file: file.to_owned() }) } -} -pub(super) fn check_debugger_output( - debugger_run_result: &ProcRes, - check_lines: &[String], -) -> Result<(), String> { - let num_check_lines = check_lines.len(); - - let mut check_line_index = 0; - for line in debugger_run_result.stdout.lines() { - if check_line_index >= num_check_lines { - break; + /// Given debugger output and lines to check, ensure that every line is + /// contained in the debugger output. The check lines need to be found in + /// order, but there can be extra lines between. + pub fn check_output(&self, debugger_run_result: &ProcRes) -> Result<(), String> { + // (src_lineno, ck_line) that we did find + let mut found = vec![]; + // (src_lineno, ck_line) that we couldn't find + let mut missing = vec![]; + // We can find our any current match anywhere after our last match + let mut last_idx = 0; + let dbg_lines: Vec<&str> = debugger_run_result.stdout.lines().collect(); + + for (src_lineno, ck_line) in &self.check_lines { + if let Some(offset) = dbg_lines + .iter() + .skip(last_idx) + .position(|out_line| check_single_line(out_line, &ck_line)) + { + last_idx += offset; + found.push((src_lineno, dbg_lines[last_idx])); + } else { + missing.push((src_lineno, ck_line)); + } } - if check_single_line(line, &(check_lines[check_line_index])[..]) { - check_line_index += 1; + if missing.is_empty() { + Ok(()) + } else { + let fname = self.file.file_name().unwrap().to_string_lossy(); + let mut msg = format!( + "check directive(s) from `{}` not found in debugger output. errors:", + self.file.display() + ); + + for (src_lineno, err_line) in missing { + write!(msg, "\n ({fname}:{num}) `{err_line}`", num = src_lineno + 1).unwrap(); + } + + if !found.is_empty() { + let init = "\nthe following subset of check directive(s) was found successfully:"; + msg.push_str(init); + for (src_lineno, found_line) in found { + write!(msg, "\n ({fname}:{num}) `{found_line}`", num = src_lineno + 1) + .unwrap(); + } + } + + Err(msg) } } - if check_line_index != num_check_lines && num_check_lines > 0 { - Err(format!("line not found in debugger output: {}", check_lines[check_line_index])) - } else { - Ok(()) - } } +/// Check that the pattern in `check_line` applies to `line`. Returns `true` if they do match. fn check_single_line(line: &str, check_line: &str) -> bool { // Allow check lines to leave parts unspecified (e.g., uninitialized // bits in the wrong case of an enum) with the notation "[...]". @@ -101,21 +133,19 @@ fn check_single_line(line: &str, check_line: &str) -> bool { } let (mut rest, first_fragment) = if can_start_anywhere { - match line.find(check_fragments[0]) { - Some(pos) => (&line[pos + check_fragments[0].len()..], 1), - None => return false, - } + let Some(pos) = line.find(check_fragments[0]) else { + return false; + }; + (&line[pos + check_fragments[0].len()..], 1) } else { (line, 0) }; for current_fragment in &check_fragments[first_fragment..] { - match rest.find(current_fragment) { - Some(pos) => { - rest = &rest[pos + current_fragment.len()..]; - } - None => return false, - } + let Some(pos) = rest.find(current_fragment) else { + return false; + }; + rest = &rest[pos + current_fragment.len()..]; } if !can_end_anywhere && !rest.is_empty() { false } else { true } diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 8068db1cf4f..c87b3e42323 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -15,6 +15,10 @@ on: env: CARGO_UNSTABLE_SPARSE_REGISTRY: 'true' +defaults: + run: + shell: bash + jobs: build: runs-on: ${{ matrix.os }} @@ -59,12 +63,9 @@ jobs: - name: Install rustup-toolchain-install-master if: ${{ steps.cache.outputs.cache-hit != 'true' }} - shell: bash - run: | - cargo install -f rustup-toolchain-install-master + run: cargo install -f rustup-toolchain-install-master - name: Install "master" toolchain - shell: bash run: | if [[ ${{ github.event_name }} == 'schedule' ]]; then echo "Building against latest rustc git version" @@ -79,7 +80,7 @@ jobs: cargo -V - name: Test - run: bash ./ci.sh + run: ./ci.sh style: name: style checks @@ -111,14 +112,10 @@ jobs: - name: Install rustup-toolchain-install-master if: ${{ steps.cache.outputs.cache-hit != 'true' }} - shell: bash - run: | - cargo install -f rustup-toolchain-install-master + run: cargo install -f rustup-toolchain-install-master - name: Install "master" toolchain - shell: bash - run: | - ./miri toolchain + run: ./miri toolchain - name: Show Rust version run: | @@ -138,7 +135,6 @@ jobs: # workflow is successful listening to webhooks only. # # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! - # (`fmt` is deliberately not listed, we want bors to ignore it.) end-success: name: bors build finished runs-on: ubuntu-latest @@ -166,12 +162,12 @@ jobs: - name: Install zulip-send run: pip3 install zulip - name: Send Zulip notification - shell: bash env: ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }} ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }} run: | - ~/.local/bin/zulip-send --stream miri --subject "Cron Job Failure (miri, $(date -u +%Y-%m))" \ + ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \ + --stream miri --subject "Cron Job Failure (miri, $(date -u +%Y-%m))" \ --message 'Dear @*T-miri*, It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed. @@ -183,9 +179,12 @@ jobs: Thanks in advance! Sincerely, - The Miri Cronjobs Bot' \ - --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com + The Miri Cronjobs Bot' + # Attempt to auto-sync with rustc + - uses: actions/checkout@v3 + with: + fetch-depth: 256 # get a bit more of the history - name: install josh-proxy run: cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06 - name: start josh-proxy @@ -196,16 +195,24 @@ jobs: git config --global user.email 'miri@cron.bot' - name: get changes from rustc run: ./miri rustc-pull + - name: Install rustup-toolchain-install-master + run: cargo install -f rustup-toolchain-install-master - name: format changes (if any) run: | ./miri toolchain ./miri fmt --check || (./miri fmt && git commit -am "fmt") - name: Push changes to a branch run: | - git switch -c "rustup$(date -u +%Y-%m)" - git push + BRANCH="rustup$(date -u +%Y-%m-%d)" + git switch -c $BRANCH + git push -u origin $BRANCH - name: Create Pull Request - run: gh pr create -B master --title 'Automatic sync from rustc' --body '' + run: | + PR=$(gh pr create -B master --title 'Automatic sync from rustc' --body '') + ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \ + --stream miri --subject "Cron Job Failure (miri, $(date -u +%Y-%m))" \ + --message "A PR doing a rustc-pull [has been automatically created]($PR) for your convenience." env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }} + ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }} diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index edb3ee48a4e..4232d7fda78 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -842,9 +842,9 @@ dependencies = [ [[package]] name = "ui_test" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a2e70adc9d18b9b4dd80ea57aeec447103c6fbb354a07c080adad451c645e1" +checksum = "c21899b59f53717dfad29e4f46e5b21a200a1b6888ab86532a07cfc8b48dd78c" dependencies = [ "bstr", "cargo-platform", diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 50864334fc5..a625e1696e1 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -36,7 +36,7 @@ libloading = "0.7" [dev-dependencies] colored = "2" -ui_test = "0.11.6" +ui_test = "0.11.7" rustc_version = "0.4" # Features chosen to match those required by env_logger, to avoid rebuilds regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] } diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs index 85c9cdad7df..6178670b4f0 100644 --- a/src/tools/miri/cargo-miri/src/main.rs +++ b/src/tools/miri/cargo-miri/src/main.rs @@ -80,7 +80,11 @@ fn main() { match first.as_str() { "miri" => phase_cargo_miri(args), "runner" => phase_runner(args, RunnerPhase::Cargo), - arg if arg == env::var("RUSTC").unwrap() => { + arg if arg == env::var("RUSTC").unwrap_or_else(|_| { + show_error!( + "`cargo-miri` called without RUSTC set; please only invoke this binary through `cargo miri`" + ) + }) => { // If the first arg is equal to the RUSTC env variable (which should be set at this // point), then we need to behave as rustc. This is the somewhat counter-intuitive // behavior of having both RUSTC and RUSTC_WRAPPER set diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs index 60f39cb36ab..4c19ed97fb8 100644 --- a/src/tools/miri/cargo-miri/src/util.rs +++ b/src/tools/miri/cargo-miri/src/util.rs @@ -82,7 +82,7 @@ pub enum MiriCommand { pub fn escape_for_toml(s: &str) -> String { // We want to surround this string in quotes `"`. So we first escape all quotes, // and also all backslashes (that are used to escape quotes). - let s = s.replace('\\', r#"\\"#).replace('"', r#"\""#); + let s = s.replace('\\', r"\\").replace('"', r#"\""#); format!("\"{s}\"") } @@ -130,7 +130,7 @@ pub fn exec(mut cmd: Command) -> ! { { use std::os::unix::process::CommandExt; let error = cmd.exec(); - Err(error).expect("failed to run command") + panic!("failed to run command: {error}") } } diff --git a/src/tools/miri/miri b/src/tools/miri/miri index 7cda995879c..ace3d17ae2a 100755 --- a/src/tools/miri/miri +++ b/src/tools/miri/miri @@ -124,7 +124,7 @@ rustc-pull) git commit rust-version -m "Preparing for merge from rustc" || (echo "FAILED to commit rust-version file, something went wrong"; exit 1) # Fetch given rustc commit and note down which one that was git fetch http://localhost:8000/rust-lang/rust.git@$FETCH_COMMIT$JOSH_FILTER.git || (echo "FAILED to fetch new commits, something went wrong"; exit 1) - git merge FETCH_HEAD --no-ff -m "Merge from rustc" || (echo "FAILED to merge new commits, something went wrong"; exit 1) + git merge FETCH_HEAD --no-ff -m "Merge from rustc" || (echo "FAILED to merge new commits ($(git rev-parse FETCH_HEAD)), something went wrong"; exit 1) exit 0 ;; rustc-push) @@ -325,6 +325,7 @@ run|run-dep) MIRIFLAGS="$MIRIFLAGS --target $MIRI_TEST_TARGET" fi + CARGO="$CARGO --quiet" # First build and get a sysroot. $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml find_sysroot diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 6790454bdb7..02b0dd16f91 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -75726cae37317c7262b69d3e9fd11a3496a88d04 +d4096e0412ac5de785d739a0aa2b1c1c7b9d3b7d diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 2dc33334417..1ec4cbc4de7 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -67,7 +67,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { if tcx.sess.compile_status().is_err() { tcx.sess.fatal("miri cannot be run on programs that fail compilation"); } -; + init_late_loggers(handler, tcx); if !tcx.sess.crate_types().contains(&CrateType::Executable) { tcx.sess.fatal("miri only makes sense on bin crates"); diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index c9674e0a2fe..de307a3c5f5 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -221,7 +221,10 @@ impl AllocHistory { impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { pub fn start_grant(&mut self, perm: Permission) { let Operation::Retag(op) = &mut self.operation else { - unreachable!("start_grant must only be called during a retag, this is: {:?}", self.operation) + unreachable!( + "start_grant must only be called during a retag, this is: {:?}", + self.operation + ) }; op.permission = Some(perm); @@ -286,7 +289,8 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { tag: BorTag, protector_tag: Option<BorTag>, ) -> Option<TagHistory> { - let Some(created) = self.history + let Some(created) = self + .history .creations .iter() .rev() @@ -315,22 +319,27 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { None } }) - }).or_else(|| { + }) + .or_else(|| { // If we didn't find a retag that created this tag, it might be the base tag of // this allocation. if self.history.base.0.tag() == tag { Some(( - format!("{tag:?} was created here, as the base tag for {:?}", self.history.id), - self.history.base.1.data() + format!( + "{tag:?} was created here, as the base tag for {:?}", + self.history.id + ), + self.history.base.1.data(), )) } else { None } - }) else { - // But if we don't have a creation event, this is related to a wildcard, and there - // is really nothing we can do to help. - return None; - }; + }) + else { + // But if we don't have a creation event, this is related to a wildcard, and there + // is really nothing we can do to help. + return None; + }; let invalidated = self.history.invalidations.iter().rev().find_map(|event| { if event.tag == tag { Some(event.generate_diagnostic()) } else { None } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 29881bbcfca..ca0f69450c9 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -430,12 +430,15 @@ impl<'tcx> Stack { .find_granting(AccessKind::Write, derived_from, exposed_tags) .map_err(|()| dcx.grant_error(self))?; - let (Some(granting_idx), ProvenanceExtra::Concrete(_)) = (granting_idx, derived_from) else { + let (Some(granting_idx), ProvenanceExtra::Concrete(_)) = (granting_idx, derived_from) + else { // The parent is a wildcard pointer or matched the unknown bottom. // This is approximate. Nobody knows what happened, so forget everything. // The new thing is SRW anyway, so we cannot push it "on top of the unknown part" // (for all we know, it might join an SRW group inside the unknown). - trace!("reborrow: forgetting stack entirely due to SharedReadWrite reborrow from wildcard or unknown"); + trace!( + "reborrow: forgetting stack entirely due to SharedReadWrite reborrow from wildcard or unknown" + ); self.set_unknown_bottom(global.next_ptr_tag); return Ok(()); }; @@ -1008,7 +1011,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // We have to turn the place into a pointer to use the existing code. // (The pointer type does not matter, so we use a raw pointer.) - let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?; + let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, return_place.layout.ty))?; let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout); // Reborrow it. With protection! That is part of the point. let new_perm = NewPermission::Uniform { diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs index a1e949183ad..291807c25ee 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs @@ -196,19 +196,19 @@ impl<'tcx> Stack { let ProvenanceExtra::Concrete(tag) = tag else { // Handle the wildcard case. // Go search the stack for an exposed tag. - if let Some(idx) = - self.borrows - .iter() - .enumerate() // we also need to know *where* in the stack - .rev() // search top-to-bottom - .find_map(|(idx, item)| { - // If the item fits and *might* be this wildcard, use it. - if item.perm().grants(access) && exposed_tags.contains(&item.tag()) { - Some(idx) - } else { - None - } - }) + if let Some(idx) = self + .borrows + .iter() + .enumerate() // we also need to know *where* in the stack + .rev() // search top-to-bottom + .find_map(|(idx, item)| { + // If the item fits and *might* be this wildcard, use it. + if item.perm().grants(access) && exposed_tags.contains(&item.tag()) { + Some(idx) + } else { + None + } + }) { return Ok(Some(idx)); } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index a87a4bbddad..3b2d6f9608e 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -570,9 +570,13 @@ impl DisplayRepr { extraction_aux(tree, tree.root, show_unnamed, &mut v); let Some(root) = v.pop() else { if show_unnamed { - unreachable!("This allocation contains no tags, not even a root. This should not happen."); + unreachable!( + "This allocation contains no tags, not even a root. This should not happen." + ); } - eprintln!("This allocation does not contain named tags. Use `miri_print_borrow_state(_, true)` to also print unnamed tags."); + eprintln!( + "This allocation does not contain named tags. Use `miri_print_borrow_state(_, true)` to also print unnamed tags." + ); return None; }; assert!(v.is_empty()); diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index c4fc2fea74c..e134b739888 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -256,7 +256,9 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' ptr_size.bytes() ); - let Some(new_perm) = new_perm else { return Ok(Some((alloc_id, orig_tag))); }; + let Some(new_perm) = new_perm else { + return Ok(Some((alloc_id, orig_tag))); + }; if let Some(protect) = new_perm.protector { // We register the protection in two different places. @@ -509,7 +511,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // We have to turn the place into a pointer to use the existing code. // (The pointer type does not matter, so we use a raw pointer.) - let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?; + let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, return_place.layout.ty))?; let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout); // Reborrow it. With protection! That is part of the point. // FIXME: do we truly want a 2phase borrow here? diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 91e004e0106..aba7dd5a9fe 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -8,6 +8,7 @@ use std::task::Poll; use std::thread; use log::info; +use rustc_middle::ty::Ty; use crate::borrow_tracker::RetagFields; use crate::diagnostics::report_leaks; @@ -304,7 +305,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( for arg in config.args.iter() { // Make space for `0` terminator. let size = u64::try_from(arg.len()).unwrap().checked_add(1).unwrap(); - let arg_type = tcx.mk_array(tcx.types.u8, size); + let arg_type = Ty::new_array(tcx, tcx.types.u8, size); let arg_place = ecx.allocate(ecx.layout_of(arg_type)?, MiriMemoryKind::Machine.into())?; ecx.write_os_str_to_c_str(OsStr::new(arg), arg_place.ptr, size)?; @@ -312,9 +313,11 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( argvs.push(arg_place.to_ref(&ecx)); } // Make an array with all these pointers, in the Miri memory. - let argvs_layout = ecx.layout_of( - tcx.mk_array(tcx.mk_imm_ptr(tcx.types.u8), u64::try_from(argvs.len()).unwrap()), - )?; + 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 argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Machine.into())?; for (idx, arg) in argvs.into_iter().enumerate() { let place = ecx.mplace_field(&argvs_place, idx)?; @@ -332,7 +335,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( ecx.machine.argc = Some(*argc_place); let argv_place = ecx.allocate( - ecx.layout_of(tcx.mk_imm_ptr(tcx.types.unit))?, + ecx.layout_of(Ty::new_imm_ptr(tcx, tcx.types.unit))?, MiriMemoryKind::Machine.into(), )?; ecx.write_immediate(argv, &argv_place.into())?; @@ -344,7 +347,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( // Construct a command string with all the arguments. let cmd_utf16: Vec<u16> = args_to_utf16_command_string(config.args.iter()); - let cmd_type = tcx.mk_array(tcx.types.u16, u64::try_from(cmd_utf16.len()).unwrap()); + let cmd_type = + Ty::new_array(tcx, tcx.types.u16, u64::try_from(cmd_utf16.len()).unwrap()); let cmd_place = ecx.allocate(ecx.layout_of(cmd_type)?, MiriMemoryKind::Machine.into())?; ecx.machine.cmd_line = Some(*cmd_place); @@ -365,7 +369,11 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( match entry_type { EntryFnType::Main { .. } => { - let start_id = tcx.lang_items().start_fn().unwrap(); + let start_id = tcx.lang_items().start_fn().unwrap_or_else(|| { + tcx.sess.fatal( + "could not find start function. Make sure the entry point is marked with `#[start]`." + ); + }); let main_ret_ty = tcx.fn_sig(entry_id).no_bound_vars().unwrap().output(); let main_ret_ty = main_ret_ty.no_bound_vars().unwrap(); let start_instance = ty::Instance::resolve( diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index e79bb47c78b..7e92dc7a0c7 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -9,6 +9,7 @@ #![feature(local_key_cell_methods)] #![feature(round_ties_even)] #![feature(os_str_bytes)] +#![feature(lint_reasons)] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index bbe5bbee719..ac2bad22119 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -313,10 +313,12 @@ pub struct PrimitiveLayouts<'tcx> { impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> { fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, &'tcx LayoutError<'tcx>> { let tcx = layout_cx.tcx; - let mut_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Mut }); - let const_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not }); + let mut_raw_ptr = + Ty::new_ptr(tcx, TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Mut }); + let const_raw_ptr = + Ty::new_ptr(tcx, TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not }); Ok(Self { - unit: layout_cx.layout_of(tcx.mk_unit())?, + unit: layout_cx.layout_of(Ty::new_unit(tcx))?, i8: layout_cx.layout_of(tcx.types.i8)?, i16: layout_cx.layout_of(tcx.types.i16)?, i32: layout_cx.layout_of(tcx.types.i32)?, diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 323991249d3..adf9a35d5c3 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -1,7 +1,7 @@ use crate::*; use rustc_ast::ast::Mutability; use rustc_middle::ty::layout::LayoutOf as _; -use rustc_middle::ty::{self, Instance}; +use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{BytePos, Loc, Symbol}; use rustc_target::{abi::Size, spec::abi::Abi}; @@ -71,7 +71,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let len: u64 = ptrs.len().try_into().unwrap(); let ptr_ty = this.machine.layouts.mut_raw_ptr.ty; - let array_layout = this.layout_of(tcx.mk_array(ptr_ty, len)).unwrap(); + let array_layout = this.layout_of(Ty::new_array(tcx.tcx, ptr_ty, len)).unwrap(); match flags { // storage for pointers is allocated by miri diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index f50c135435f..1dcb877a83f 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -6,6 +6,7 @@ use std::mem; use rustc_const_eval::interpret::Pointer; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::Ty; use rustc_target::abi::Size; use crate::helpers::target_os_is_unix; @@ -448,9 +449,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { vars.push(Pointer::null()); // Make an array with all these pointers inside Miri. let tcx = this.tcx; - let vars_layout = this.layout_of( - tcx.mk_array(this.machine.layouts.mut_raw_ptr.ty, u64::try_from(vars.len()).unwrap()), - )?; + let vars_layout = this.layout_of(Ty::new_array( + tcx.tcx, + this.machine.layouts.mut_raw_ptr.ty, + u64::try_from(vars.len()).unwrap(), + ))?; let vars_place = this.allocate(vars_layout, MiriMemoryKind::Runtime.into())?; for (idx, var) in vars.into_iter().enumerate() { let place = this.mplace_field(&vars_place, idx)?; diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index f4e91c30d9f..6915c396d61 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -763,6 +763,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let ptr_dest = this.read_pointer(ptr_dest)?; let ptr_src = this.read_pointer(ptr_src)?; let n = this.read_target_usize(n)?; + + // C requires that this must always be a valid pointer, even if `n` is zero, so we better check that. + // (This is more than Rust requires, so `mem_copy` is not sufficient.) + this.ptr_get_alloc_id(ptr_dest)?; + this.ptr_get_alloc_id(ptr_src)?; + this.mem_copy( ptr_src, Align::ONE, diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 1995db715e8..94f8cfbfb1c 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -483,7 +483,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // `index` is an array, not a SIMD type let ty::Array(_, index_len) = index.layout.ty.kind() else { - span_bug!(this.cur_span(), "simd_shuffle index argument has non-array type {}", index.layout.ty) + span_bug!( + this.cur_span(), + "simd_shuffle index argument has non-array type {}", + index.layout.ty + ) }; let index_len = index_len.eval_target_usize(*this.tcx, this.param_env()); @@ -622,9 +626,7 @@ fn fmax_op<'tcx>( right: &ImmTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar<Provenance>> { assert_eq!(left.layout.ty, right.layout.ty); - let ty::Float(float_ty) = left.layout.ty.kind() else { - bug!("fmax operand is not a float") - }; + let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmax operand is not a float") }; let left = left.to_scalar(); let right = right.to_scalar(); Ok(match float_ty { @@ -638,9 +640,7 @@ fn fmin_op<'tcx>( right: &ImmTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar<Provenance>> { assert_eq!(left.layout.ty, right.layout.ty); - let ty::Float(float_ty) = left.layout.ty.kind() else { - bug!("fmin operand is not a float") - }; + let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmin operand is not a float") }; let left = left.to_scalar(); let right = right.to_scalar(); Ok(match float_ty { diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs index e85ab7a48b3..f08f0aad5e7 100644 --- a/src/tools/miri/src/shims/os_str.rs +++ b/src/tools/miri/src/shims/os_str.rs @@ -8,6 +8,7 @@ use std::os::unix::ffi::{OsStrExt, OsStringExt}; use std::os::windows::ffi::{OsStrExt, OsStringExt}; use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::Ty; use crate::*; @@ -140,7 +141,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator. let this = self.eval_context_mut(); - let arg_type = this.tcx.mk_array(this.tcx.types.u8, size); + let arg_type = Ty::new_array(this.tcx.tcx, this.tcx.types.u8, size); let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?; let (written, _) = self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap(); assert!(written); @@ -156,7 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator. let this = self.eval_context_mut(); - let arg_type = this.tcx.mk_array(this.tcx.types.u16, size); + let arg_type = Ty::new_array(this.tcx.tcx, this.tcx.types.u16, size); let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?; let (written, _) = self.write_os_str_to_wide_str(os_str, arg_place.ptr, size, /*truncate*/ false).unwrap(); diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/fd.rs index dc395d39ce1..87e887000c5 100644 --- a/src/tools/miri/src/shims/unix/linux/fd.rs +++ b/src/tools/miri/src/shims/unix/linux/fd.rs @@ -181,6 +181,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics. /// /// <https://linux.die.net/man/2/eventfd> + #[expect(clippy::needless_if)] fn eventfd( &mut self, val: &OpTy<'tcx, Provenance>, diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 73671e716ef..59143550253 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -145,7 +145,8 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R // The files we're actually interested in (all `.rs` files). |path| { path.extension().is_some_and(|ext| ext == "rs") - && (filters.is_empty() || filters.iter().any(|f| path.starts_with(f))) + && (filters.is_empty() + || filters.iter().any(|f| path.display().to_string().contains(f))) }, // This could be used to overwrite the `Config` on a per-test basis. |_, _| None, @@ -274,13 +275,13 @@ fn main() -> Result<()> { fn run_dep_mode(target: String, mut args: impl Iterator<Item = OsString>) -> Result<()> { let path = args.next().expect("./miri run-dep must be followed by a file name"); let mut config = test_config(&target, "", Mode::Yolo, /* with dependencies */ true); - config.program.args.remove(0); // remove the `--error-format=json` argument - config.program.args.push("--color".into()); - config.program.args.push("always".into()); - let mut cmd = ui_test::test_command(config, Path::new(&path))?; - // Separate the arguments to the `cargo miri` invocation from - // the arguments to the interpreted prog - cmd.arg("--"); + config.program.args.clear(); // We want to give the user full control over flags + config.build_dependencies_and_link_them()?; + + let mut cmd = config.program.build(&config.out_dir); + + cmd.arg(path); + cmd.args(args); if cmd.spawn()?.wait()?.success() { Ok(()) } else { std::process::exit(1) } } diff --git a/src/tools/miri/tests/fail/overlapping_assignment.rs b/src/tools/miri/tests/fail/overlapping_assignment.rs new file mode 100644 index 00000000000..84994c179f9 --- /dev/null +++ b/src/tools/miri/tests/fail/overlapping_assignment.rs @@ -0,0 +1,23 @@ +#![feature(core_intrinsics)] +#![feature(custom_mir)] + +use std::intrinsics::mir::*; + +// It's not that easy to fool the MIR validity check +// which wants to prevent overlapping assignments... +// So we use two separate pointer arguments, and then arrange for them to alias. +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn self_copy(ptr1: *mut [i32; 4], ptr2: *mut [i32; 4]) { + mir! { + { + *ptr1 = *ptr2; //~ERROR: overlapping ranges + Return() + } + } +} + +pub fn main() { + let mut x = [0; 4]; + let ptr = std::ptr::addr_of_mut!(x); + self_copy(ptr, ptr); +} diff --git a/src/tools/miri/tests/fail/overlapping_assignment.stderr b/src/tools/miri/tests/fail/overlapping_assignment.stderr new file mode 100644 index 00000000000..42a000dfcc6 --- /dev/null +++ b/src/tools/miri/tests/fail/overlapping_assignment.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges + --> $DIR/overlapping_assignment.rs:LL:CC + | +LL | *ptr1 = *ptr2; + | ^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges + | + = 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: + = note: inside `self_copy` at $DIR/overlapping_assignment.rs:LL:CC +note: inside `main` + --> $DIR/overlapping_assignment.rs:LL:CC + | +LL | self_copy(ptr, ptr); + | ^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/shims/memchr_null.rs b/src/tools/miri/tests/fail/shims/memchr_null.rs new file mode 100644 index 00000000000..6bc7af7e6bf --- /dev/null +++ b/src/tools/miri/tests/fail/shims/memchr_null.rs @@ -0,0 +1,10 @@ +//@ignore-target-windows: No libc on Windows + +use std::ptr; + +// null is explicitly called out as UB in the C docs. +fn main() { + unsafe { + libc::memchr(ptr::null(), 0, 0); //~ERROR: dangling + } +} diff --git a/src/tools/miri/tests/fail/shims/memchr_null.stderr b/src/tools/miri/tests/fail/shims/memchr_null.stderr new file mode 100644 index 00000000000..d48606f34ad --- /dev/null +++ b/src/tools/miri/tests/fail/shims/memchr_null.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance) + --> $DIR/memchr_null.rs:LL:CC + | +LL | libc::memchr(ptr::null(), 0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance) + | + = 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: + = note: inside `main` at $DIR/memchr_null.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/shims/memcmp_null.rs b/src/tools/miri/tests/fail/shims/memcmp_null.rs new file mode 100644 index 00000000000..a4e0034c40b --- /dev/null +++ b/src/tools/miri/tests/fail/shims/memcmp_null.rs @@ -0,0 +1,10 @@ +//@ignore-target-windows: No libc on Windows + +use std::ptr; + +// null is explicitly called out as UB in the C docs. +fn main() { + unsafe { + libc::memcmp(ptr::null(), ptr::null(), 0); //~ERROR: dangling + } +} diff --git a/src/tools/miri/tests/fail/shims/memcmp_null.stderr b/src/tools/miri/tests/fail/shims/memcmp_null.stderr new file mode 100644 index 00000000000..7a09c779894 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/memcmp_null.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance) + --> $DIR/memcmp_null.rs:LL:CC + | +LL | libc::memcmp(ptr::null(), ptr::null(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance) + | + = 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: + = note: inside `main` at $DIR/memcmp_null.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/shims/memcpy_zero.rs b/src/tools/miri/tests/fail/shims/memcpy_zero.rs new file mode 100644 index 00000000000..5283fea4cb9 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/memcpy_zero.rs @@ -0,0 +1,12 @@ +//@ignore-target-windows: No libc on Windows +//@compile-flags: -Zmiri-permissive-provenance +// C's memcpy is 0 bytes is UB for some pointers that are allowed in Rust's `copy_nonoverlapping`. + +fn main() { + let from = 42 as *const u8; + let to = 23 as *mut u8; + unsafe { + to.copy_from(from, 0); // this is fine + libc::memcpy(to.cast(), from.cast(), 0); //~ERROR: dangling + } +} diff --git a/src/tools/miri/tests/fail/shims/memcpy_zero.stderr b/src/tools/miri/tests/fail/shims/memcpy_zero.stderr new file mode 100644 index 00000000000..7c1c3fe20c4 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/memcpy_zero.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: out-of-bounds pointer use: 0x17[noalloc] is a dangling pointer (it has no provenance) + --> $DIR/memcpy_zero.rs:LL:CC + | +LL | libc::memcpy(to.cast(), from.cast(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x17[noalloc] is a dangling pointer (it has no provenance) + | + = 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: + = note: inside `main` at $DIR/memcpy_zero.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/shims/memrchr_null.rs b/src/tools/miri/tests/fail/shims/memrchr_null.rs new file mode 100644 index 00000000000..b6707d558d8 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/memrchr_null.rs @@ -0,0 +1,11 @@ +//@ignore-target-windows: No libc on Windows +//@ignore-target-apple: No `memrchr` on some apple targets + +use std::ptr; + +// null is explicitly called out as UB in the C docs. +fn main() { + unsafe { + libc::memrchr(ptr::null(), 0, 0); //~ERROR: dangling + } +} diff --git a/src/tools/miri/tests/fail/shims/memrchr_null.stderr b/src/tools/miri/tests/fail/shims/memrchr_null.stderr new file mode 100644 index 00000000000..b5b7630e7fd --- /dev/null +++ b/src/tools/miri/tests/fail/shims/memrchr_null.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance) + --> $DIR/memrchr_null.rs:LL:CC + | +LL | libc::memrchr(ptr::null(), 0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance) + | + = 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: + = note: inside `main` at $DIR/memrchr_null.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/pass/portable-simd-ptrs.rs b/src/tools/miri/tests/pass/portable-simd-ptrs.rs index 303c99834f5..843bb0284cf 100644 --- a/src/tools/miri/tests/pass/portable-simd-ptrs.rs +++ b/src/tools/miri/tests/pass/portable-simd-ptrs.rs @@ -6,7 +6,7 @@ use std::simd::*; fn main() { // Pointer casts - let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast_ptr(); + let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast(); let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr(); let _ptrs = Simd::<*const i32, 4>::from_exposed_addr(addrs); } diff --git a/src/tools/miri/tests/pass/vec.rs b/src/tools/miri/tests/pass/vec.rs index 048f7d1c351..4ab2bcb7f22 100644 --- a/src/tools/miri/tests/pass/vec.rs +++ b/src/tools/miri/tests/pass/vec.rs @@ -100,7 +100,7 @@ fn vec_push_ptr_stable() { v.push(0); let v0 = unsafe { &mut *(&mut v[0] as *mut _) }; // laundering the lifetime -- we take care that `v` does not reallocate, so that's okay. v.push(1); - let _val = *v0; + *v0 = *v0; } fn vec_extend_ptr_stable() { @@ -109,23 +109,23 @@ fn vec_extend_ptr_stable() { let v0 = unsafe { &mut *(&mut v[0] as *mut _) }; // laundering the lifetime -- we take care that `v` does not reallocate, so that's okay. // `slice::Iter` (with `T: Copy`) specialization v.extend(&[1]); - let _val = *v0; + *v0 = *v0; // `vec::IntoIter` specialization v.extend(vec![2]); - let _val = *v0; + *v0 = *v0; // `TrustedLen` specialization v.extend(std::iter::once(3)); - let _val = *v0; + *v0 = *v0; // base case v.extend(std::iter::once(3).filter(|_| true)); - let _val = *v0; + *v0 = *v0; } fn vec_truncate_ptr_stable() { let mut v = vec![0; 10]; let v0 = unsafe { &mut *(&mut v[0] as *mut _) }; // laundering the lifetime -- we take care that `v` does not reallocate, so that's okay. v.truncate(5); - let _val = *v0; + *v0 = *v0; } fn push_str_ptr_stable() { diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml new file mode 100644 index 00000000000..5a1794d3336 --- /dev/null +++ b/src/tools/opt-dist/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "opt-dist" +version = "0.1.0" +edition = "2021" + +[dependencies] +build_helper = { path = "../build_helper" } +env_logger = "0.10" +log = "0.4" +anyhow = { version = "1", features = ["backtrace"] } +humantime = "2" +humansize = "2" +sysinfo = { version = "0.29", default-features = false } +fs_extra = "1" +camino = "1" +reqwest = { version = "0.11", features = ["blocking"] } +zip = { version = "0.6", default-features = false, features = ["deflate"] } +tar = "0.4" +xz = "0.1" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +glob = "0.3" diff --git a/src/tools/opt-dist/README.md b/src/tools/opt-dist/README.md new file mode 100644 index 00000000000..05a75870da1 --- /dev/null +++ b/src/tools/opt-dist/README.md @@ -0,0 +1,7 @@ +# Optimized build pipeline +This binary implements a heavily optimized build pipeline for `rustc` and `LLVM` artifacts that are used for both for +benchmarking using the perf. bot and for final distribution to users. + +It uses LTO, PGO and BOLT to optimize the compiler and LLVM as much as possible. +This logic is not part of bootstrap, because it needs to invoke bootstrap multiple times, force-rebuild various +artifacts repeatedly and sometimes go around bootstrap's cache mechanism. diff --git a/src/tools/opt-dist/src/environment/linux.rs b/src/tools/opt-dist/src/environment/linux.rs new file mode 100644 index 00000000000..d4c55c46f7c --- /dev/null +++ b/src/tools/opt-dist/src/environment/linux.rs @@ -0,0 +1,54 @@ +use crate::environment::Environment; +use crate::exec::cmd; +use crate::utils::io::copy_directory; +use camino::{Utf8Path, Utf8PathBuf}; + +pub(super) struct LinuxEnvironment; + +impl Environment for LinuxEnvironment { + fn python_binary(&self) -> &'static str { + "python3" + } + + fn checkout_path(&self) -> Utf8PathBuf { + Utf8PathBuf::from("/checkout") + } + + fn downloaded_llvm_dir(&self) -> Utf8PathBuf { + Utf8PathBuf::from("/rustroot") + } + + fn opt_artifacts(&self) -> Utf8PathBuf { + Utf8PathBuf::from("/tmp/tmp-multistage/opt-artifacts") + } + + fn build_root(&self) -> Utf8PathBuf { + self.checkout_path().join("obj") + } + + fn prepare_rustc_perf(&self) -> anyhow::Result<()> { + // /tmp/rustc-perf comes from the x64 dist Dockerfile + copy_directory(Utf8Path::new("/tmp/rustc-perf"), &self.rustc_perf_dir())?; + cmd(&[self.cargo_stage_0().as_str(), "build", "-p", "collector"]) + .workdir(&self.rustc_perf_dir()) + .env("RUSTC", &self.rustc_stage_0().into_string()) + .env("RUSTC_BOOTSTRAP", "1") + .run()?; + Ok(()) + } + + fn supports_bolt(&self) -> bool { + true + } + + fn executable_extension(&self) -> &'static str { + "" + } + + fn skipped_tests(&self) -> &'static [&'static str] { + &[ + // Fails because of linker errors, as of June 2023. + "tests/ui/process/nofile-limit.rs", + ] + } +} diff --git a/src/tools/opt-dist/src/environment/mod.rs b/src/tools/opt-dist/src/environment/mod.rs new file mode 100644 index 00000000000..f66b9ab41ea --- /dev/null +++ b/src/tools/opt-dist/src/environment/mod.rs @@ -0,0 +1,75 @@ +use camino::Utf8PathBuf; + +#[cfg(target_family = "unix")] +mod linux; +#[cfg(target_family = "windows")] +mod windows; + +pub trait Environment { + fn host_triple(&self) -> String { + std::env::var("PGO_HOST").expect("PGO_HOST environment variable missing") + } + + fn python_binary(&self) -> &'static str; + + /// The rustc checkout, where the compiler source is located. + fn checkout_path(&self) -> Utf8PathBuf; + + /// Path to the downloaded host LLVM. + fn downloaded_llvm_dir(&self) -> Utf8PathBuf; + + /// Directory where the optimization artifacts (PGO/BOLT profiles, etc.) + /// will be stored. + fn opt_artifacts(&self) -> Utf8PathBuf; + + /// The main directory where the build occurs. + fn build_root(&self) -> Utf8PathBuf; + + fn build_artifacts(&self) -> Utf8PathBuf { + self.build_root().join("build").join(self.host_triple()) + } + + fn cargo_stage_0(&self) -> Utf8PathBuf { + self.build_artifacts() + .join("stage0") + .join("bin") + .join(format!("cargo{}", self.executable_extension())) + } + + fn rustc_stage_0(&self) -> Utf8PathBuf { + self.build_artifacts() + .join("stage0") + .join("bin") + .join(format!("rustc{}", self.executable_extension())) + } + + fn rustc_stage_2(&self) -> Utf8PathBuf { + self.build_artifacts() + .join("stage2") + .join("bin") + .join(format!("rustc{}", self.executable_extension())) + } + + /// Path to the built rustc-perf benchmark suite. + fn rustc_perf_dir(&self) -> Utf8PathBuf { + self.opt_artifacts().join("rustc-perf") + } + + /// Download and/or compile rustc-perf. + fn prepare_rustc_perf(&self) -> anyhow::Result<()>; + + fn supports_bolt(&self) -> bool; + + /// What is the extension of binary executables in this environment? + fn executable_extension(&self) -> &'static str; + + /// List of test paths that should be skipped when testing the optimized artifacts. + fn skipped_tests(&self) -> &'static [&'static str]; +} + +pub fn create_environment() -> Box<dyn Environment> { + #[cfg(target_family = "unix")] + return Box::new(linux::LinuxEnvironment); + #[cfg(target_family = "windows")] + return Box::new(windows::WindowsEnvironment::new()); +} diff --git a/src/tools/opt-dist/src/environment/windows.rs b/src/tools/opt-dist/src/environment/windows.rs new file mode 100644 index 00000000000..36f4c0f29cc --- /dev/null +++ b/src/tools/opt-dist/src/environment/windows.rs @@ -0,0 +1,78 @@ +use crate::environment::Environment; +use crate::exec::cmd; +use crate::utils::io::move_directory; +use camino::Utf8PathBuf; +use std::io::Cursor; +use zip::ZipArchive; + +pub(super) struct WindowsEnvironment { + checkout_dir: Utf8PathBuf, +} + +impl WindowsEnvironment { + pub fn new() -> Self { + Self { checkout_dir: std::env::current_dir().unwrap().try_into().unwrap() } + } +} + +impl Environment for WindowsEnvironment { + fn python_binary(&self) -> &'static str { + "python" + } + + fn checkout_path(&self) -> Utf8PathBuf { + self.checkout_dir.clone() + } + + fn downloaded_llvm_dir(&self) -> Utf8PathBuf { + self.checkout_path().join("citools").join("clang-rust") + } + + fn opt_artifacts(&self) -> Utf8PathBuf { + self.checkout_path().join("opt-artifacts") + } + + fn build_root(&self) -> Utf8PathBuf { + self.checkout_path() + } + + fn prepare_rustc_perf(&self) -> anyhow::Result<()> { + // FIXME: add some mechanism for synchronization of this commit SHA with + // Linux (which builds rustc-perf in a Dockerfile) + // rustc-perf version from 2023-05-30 + const PERF_COMMIT: &str = "8b2ac3042e1ff2c0074455a0a3618adef97156b1"; + + let url = format!("https://github.com/rust-lang/rustc-perf/archive/{PERF_COMMIT}.zip"); + let response = reqwest::blocking::get(url)?.error_for_status()?.bytes()?.to_vec(); + + let mut archive = ZipArchive::new(Cursor::new(response))?; + archive.extract(self.rustc_perf_dir())?; + move_directory( + &self.rustc_perf_dir().join(format!("rustc-perf-{PERF_COMMIT}")), + &self.rustc_perf_dir(), + )?; + + cmd(&[self.cargo_stage_0().as_str(), "build", "-p", "collector"]) + .workdir(&self.rustc_perf_dir()) + .env("RUSTC", &self.rustc_stage_0().into_string()) + .env("RUSTC_BOOTSTRAP", "1") + .run()?; + + Ok(()) + } + + fn supports_bolt(&self) -> bool { + false + } + + fn executable_extension(&self) -> &'static str { + ".exe" + } + + fn skipped_tests(&self) -> &'static [&'static str] { + &[ + // Fails as of June 2023. + "tests\\codegen\\vec-shrink-panik.rs", + ] + } +} diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs new file mode 100644 index 00000000000..d05ddbd4c0e --- /dev/null +++ b/src/tools/opt-dist/src/exec.rs @@ -0,0 +1,169 @@ +use crate::environment::Environment; +use crate::metrics::{load_metrics, record_metrics}; +use crate::timer::TimerSection; +use crate::training::{LlvmBoltProfile, LlvmPGOProfile, RustcPGOProfile}; +use camino::{Utf8Path, Utf8PathBuf}; +use std::collections::BTreeMap; +use std::fs::File; +use std::process::{Command, Stdio}; + +#[derive(Default)] +pub struct CmdBuilder { + args: Vec<String>, + env: BTreeMap<String, String>, + workdir: Option<Utf8PathBuf>, + output: Option<Utf8PathBuf>, +} + +impl CmdBuilder { + pub fn arg(mut self, arg: &str) -> Self { + self.args.push(arg.to_string()); + self + } + + pub fn env(mut self, name: &str, value: &str) -> Self { + self.env.insert(name.to_string(), value.to_string()); + self + } + + pub fn workdir(mut self, path: &Utf8Path) -> Self { + self.workdir = Some(path.to_path_buf()); + self + } + + pub fn redirect_output(mut self, path: Utf8PathBuf) -> Self { + self.output = Some(path); + self + } + + pub fn run(self) -> anyhow::Result<()> { + let mut cmd_str = String::new(); + cmd_str.push_str( + &self + .env + .iter() + .map(|(key, value)| format!("{key}={value}")) + .collect::<Vec<_>>() + .join(" "), + ); + if !self.env.is_empty() { + cmd_str.push(' '); + } + cmd_str.push_str(&self.args.join(" ")); + if let Some(ref path) = self.output { + cmd_str.push_str(&format!(" > {path:?}")); + } + cmd_str.push_str(&format!( + " [at {}]", + self.workdir + .clone() + .unwrap_or_else(|| std::env::current_dir().unwrap().try_into().unwrap()) + )); + log::info!("Executing `{cmd_str}`"); + + let mut cmd = Command::new(&self.args[0]); + cmd.stdin(Stdio::null()); + cmd.args(self.args.iter().skip(1)); + for (key, value) in &self.env { + cmd.env(key, value); + } + if let Some(ref output) = self.output { + cmd.stdout(File::create(output.clone().into_std_path_buf())?); + } + if let Some(ref workdir) = self.workdir { + cmd.current_dir(workdir.clone().into_std_path_buf()); + } + let exit_status = cmd.spawn()?.wait()?; + if !exit_status.success() { + Err(anyhow::anyhow!( + "Command {cmd_str} has failed with exit code {:?}", + exit_status.code(), + )) + } else { + Ok(()) + } + } +} + +pub fn cmd(args: &[&str]) -> CmdBuilder { + assert!(!args.is_empty()); + CmdBuilder { args: args.iter().map(|s| s.to_string()).collect(), ..Default::default() } +} + +pub struct Bootstrap { + cmd: CmdBuilder, + metrics_path: Utf8PathBuf, +} + +impl Bootstrap { + pub fn build(env: &dyn Environment) -> Self { + let metrics_path = env.build_root().join("build").join("metrics.json"); + let cmd = cmd(&[ + env.python_binary(), + env.checkout_path().join("x.py").as_str(), + "build", + "--target", + &env.host_triple(), + "--host", + &env.host_triple(), + "--stage", + "2", + "library/std", + ]) + .env("RUST_BACKTRACE", "full"); + Self { cmd, metrics_path } + } + + pub fn dist(env: &dyn Environment, dist_args: &[String]) -> Self { + let metrics_path = env.build_root().join("build").join("metrics.json"); + let cmd = cmd(&dist_args.iter().map(|arg| arg.as_str()).collect::<Vec<_>>()) + .env("RUST_BACKTRACE", "full"); + Self { cmd, metrics_path } + } + + pub fn llvm_pgo_instrument(mut self, profile_dir: &Utf8Path) -> Self { + self.cmd = self + .cmd + .arg("--llvm-profile-generate") + .env("LLVM_PROFILE_DIR", profile_dir.join("prof-%p").as_str()); + self + } + + pub fn llvm_pgo_optimize(mut self, profile: &LlvmPGOProfile) -> Self { + self.cmd = self.cmd.arg("--llvm-profile-use").arg(profile.0.as_str()); + self + } + + pub fn rustc_pgo_instrument(mut self, profile_dir: &Utf8Path) -> Self { + self.cmd = self.cmd.arg("--rust-profile-generate").arg(profile_dir.as_str()); + self + } + + pub fn rustc_pgo_optimize(mut self, profile: &RustcPGOProfile) -> Self { + self.cmd = self.cmd.arg("--rust-profile-use").arg(profile.0.as_str()); + self + } + + pub fn llvm_bolt_instrument(mut self) -> Self { + self.cmd = self.cmd.arg("--llvm-bolt-profile-generate"); + self + } + + pub fn llvm_bolt_optimize(mut self, profile: &LlvmBoltProfile) -> Self { + self.cmd = self.cmd.arg("--llvm-bolt-profile-use").arg(profile.0.as_str()); + self + } + + /// Do not rebuild rustc, and use a previously built rustc sysroot instead. + pub fn avoid_rustc_rebuild(mut self) -> Self { + self.cmd = self.cmd.arg("--keep-stage").arg("0").arg("--keep-stage").arg("1"); + self + } + + pub fn run(self, timer: &mut TimerSection) -> anyhow::Result<()> { + self.cmd.run()?; + let metrics = load_metrics(&self.metrics_path)?; + record_metrics(&metrics, timer); + Ok(()) + } +} diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs new file mode 100644 index 00000000000..39fa7e1fb2a --- /dev/null +++ b/src/tools/opt-dist/src/main.rs @@ -0,0 +1,175 @@ +use anyhow::Context; +use log::LevelFilter; + +use crate::environment::{create_environment, Environment}; +use crate::exec::Bootstrap; +use crate::tests::run_tests; +use crate::timer::Timer; +use crate::training::{gather_llvm_bolt_profiles, gather_llvm_profiles, gather_rustc_profiles}; +use crate::utils::io::reset_directory; +use crate::utils::{clear_llvm_files, format_env_variables, print_free_disk_space}; + +mod environment; +mod exec; +mod metrics; +mod tests; +mod timer; +mod training; +mod utils; + +fn is_try_build() -> bool { + std::env::var("DIST_TRY_BUILD").unwrap_or_else(|_| "0".to_string()) != "0" +} + +fn execute_pipeline( + env: &dyn Environment, + timer: &mut Timer, + dist_args: Vec<String>, +) -> anyhow::Result<()> { + reset_directory(&env.opt_artifacts())?; + env.prepare_rustc_perf()?; + + // Stage 1: Build PGO instrumented rustc + // We use a normal build of LLVM, because gathering PGO profiles for LLVM and `rustc` at the + // same time can cause issues, because the host and in-tree LLVM versions can diverge. + let rustc_pgo_profile = timer.section("Stage 1 (Rustc PGO)", |stage| { + let rustc_profile_dir_root = env.opt_artifacts().join("rustc-pgo"); + + stage.section("Build PGO instrumented rustc and LLVM", |section| { + Bootstrap::build(env).rustc_pgo_instrument(&rustc_profile_dir_root).run(section) + })?; + + let profile = stage + .section("Gather profiles", |_| gather_rustc_profiles(env, &rustc_profile_dir_root))?; + print_free_disk_space()?; + + stage.section("Build PGO optimized rustc", |section| { + Bootstrap::build(env).rustc_pgo_optimize(&profile).run(section) + })?; + + Ok(profile) + })?; + + // Stage 2: Gather LLVM PGO profiles + // Here we build a PGO instrumented LLVM, reusing the previously PGO optimized rustc. + // Then we use the instrumented LLVM to gather LLVM PGO profiles. + let llvm_pgo_profile = timer.section("Stage 2 (LLVM PGO)", |stage| { + // Remove the previous, uninstrumented build of LLVM. + clear_llvm_files(env)?; + + let llvm_profile_dir_root = env.opt_artifacts().join("llvm-pgo"); + + stage.section("Build PGO instrumented LLVM", |section| { + Bootstrap::build(env) + .llvm_pgo_instrument(&llvm_profile_dir_root) + .avoid_rustc_rebuild() + .run(section) + })?; + + let profile = stage + .section("Gather profiles", |_| gather_llvm_profiles(env, &llvm_profile_dir_root))?; + + print_free_disk_space()?; + + // Proactively delete the instrumented artifacts, to avoid using them by accident in + // follow-up stages. + clear_llvm_files(env)?; + + Ok(profile) + })?; + + let llvm_bolt_profile = if env.supports_bolt() { + // Stage 3: Build BOLT instrumented LLVM + // We build a PGO optimized LLVM in this step, then instrument it with BOLT and gather BOLT profiles. + // Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build. + // BOLT instrumentation is performed "on-the-fly" when the LLVM library is copied to the sysroot of rustc, + // therefore the LLVM artifacts on disk are not "tainted" with BOLT instrumentation and they can be reused. + timer.section("Stage 3 (LLVM BOLT)", |stage| { + stage.section("Build BOLT instrumented LLVM", |stage| { + Bootstrap::build(env) + .llvm_bolt_instrument() + .llvm_pgo_optimize(&llvm_pgo_profile) + .avoid_rustc_rebuild() + .run(stage) + })?; + + let profile = stage.section("Gather profiles", |_| gather_llvm_bolt_profiles(env))?; + print_free_disk_space()?; + + // LLVM is not being cleared here, we want to reuse the previous PGO-optimized build + + Ok(Some(profile)) + })? + } else { + None + }; + + let mut dist = Bootstrap::dist(env, &dist_args) + .llvm_pgo_optimize(&llvm_pgo_profile) + .rustc_pgo_optimize(&rustc_pgo_profile) + .avoid_rustc_rebuild(); + + if let Some(llvm_bolt_profile) = llvm_bolt_profile { + dist = dist.llvm_bolt_optimize(&llvm_bolt_profile); + } + + // Final stage: Assemble the dist artifacts + // The previous PGO optimized rustc build and PGO optimized LLVM builds should be reused. + timer.section("Stage 4 (final build)", |stage| dist.run(stage))?; + + // After dist has finished, run a subset of the test suite on the optimized artifacts to discover + // possible regressions. + // The tests are not executed for try builds, which can be in various broken states, so we don't + // want to gatekeep them with tests. + if !is_try_build() { + timer.section("Run tests", |_| run_tests(env))?; + } + + Ok(()) +} + +fn main() -> anyhow::Result<()> { + // Make sure that we get backtraces for easier debugging in CI + std::env::set_var("RUST_BACKTRACE", "1"); + + env_logger::builder() + .filter_level(LevelFilter::Info) + .format_timestamp_millis() + .parse_default_env() + .init(); + + let mut build_args: Vec<String> = std::env::args().skip(1).collect(); + log::info!("Running optimized build pipeline with args `{}`", build_args.join(" ")); + log::info!("Environment values\n{}", format_env_variables()); + + if let Ok(config) = std::fs::read_to_string("config.toml") { + log::info!("Contents of `config.toml`:\n{config}"); + } + + // Skip components that are not needed for try builds to speed them up + if is_try_build() { + log::info!("Skipping building of unimportant components for a try build"); + for target in [ + "rust-docs", + "rustc-docs", + "rust-docs-json", + "rust-analyzer", + "rustc-src", + "clippy", + "miri", + "rustfmt", + ] { + build_args.extend(["--exclude".to_string(), target.to_string()]); + } + } + + let mut timer = Timer::new(); + let env = create_environment(); + + let result = execute_pipeline(env.as_ref(), &mut timer, build_args); + log::info!("Timer results\n{}", timer.format_stats()); + + print_free_disk_space()?; + + result.context("Optimized build pipeline has failed") +} diff --git a/src/tools/opt-dist/src/metrics.rs b/src/tools/opt-dist/src/metrics.rs new file mode 100644 index 00000000000..cabe07eda32 --- /dev/null +++ b/src/tools/opt-dist/src/metrics.rs @@ -0,0 +1,106 @@ +use crate::timer::TimerSection; +use build_helper::metrics::{JsonNode, JsonRoot}; +use camino::Utf8Path; +use std::time::Duration; + +#[derive(Clone, Debug)] +pub struct BuildStep { + r#type: String, + children: Vec<BuildStep>, + duration: Duration, +} + +impl BuildStep { + pub fn find_all_by_type(&self, r#type: &str) -> Vec<&BuildStep> { + let mut result = Vec::new(); + self.find_by_type(r#type, &mut result); + result + } + fn find_by_type<'a>(&'a self, r#type: &str, result: &mut Vec<&'a BuildStep>) { + if self.r#type == r#type { + result.push(self); + } + for child in &self.children { + child.find_by_type(r#type, result); + } + } +} + +/// Loads the metrics of the most recent bootstrap execution from a metrics.json file. +pub fn load_metrics(path: &Utf8Path) -> anyhow::Result<BuildStep> { + let content = std::fs::read(path.as_std_path())?; + let mut metrics = serde_json::from_slice::<JsonRoot>(&content)?; + let invocation = metrics + .invocations + .pop() + .ok_or_else(|| anyhow::anyhow!("No bootstrap invocation found in metrics file"))?; + + fn parse(node: JsonNode) -> Option<BuildStep> { + match node { + JsonNode::RustbuildStep { + type_: kind, + children, + duration_excluding_children_sec, + .. + } => { + let children: Vec<_> = children.into_iter().filter_map(parse).collect(); + let children_duration = children.iter().map(|c| c.duration).sum::<Duration>(); + Some(BuildStep { + r#type: kind.to_string(), + children, + duration: children_duration + + Duration::from_secs_f64(duration_excluding_children_sec), + }) + } + JsonNode::TestSuite(_) => None, + } + } + + let duration = Duration::from_secs_f64(invocation.duration_including_children_sec); + let children: Vec<_> = invocation.children.into_iter().filter_map(parse).collect(); + Ok(BuildStep { r#type: "root".to_string(), children, duration }) +} + +/// Logs the individual metrics in a table and add Rustc and LLVM durations to the passed +/// timer. +pub fn record_metrics(metrics: &BuildStep, timer: &mut TimerSection) { + let llvm_steps = metrics.find_all_by_type("bootstrap::llvm::Llvm"); + let llvm_duration: Duration = llvm_steps.into_iter().map(|s| s.duration).sum(); + + let rustc_steps = metrics.find_all_by_type("bootstrap::compile::Rustc"); + let rustc_duration: Duration = rustc_steps.into_iter().map(|s| s.duration).sum(); + + // The LLVM step is part of the Rustc step + let rustc_duration = rustc_duration.saturating_sub(llvm_duration); + + if !llvm_duration.is_zero() { + timer.add_duration("LLVM", llvm_duration); + } + if !rustc_duration.is_zero() { + timer.add_duration("Rustc", rustc_duration); + } + + log_metrics(metrics); +} + +fn log_metrics(metrics: &BuildStep) { + use std::fmt::Write; + + let mut substeps: Vec<(u32, &BuildStep)> = Vec::new(); + + fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) { + substeps.push((level, step)); + for child in &step.children { + visit(child, level + 1, substeps); + } + } + + visit(metrics, 0, &mut substeps); + + let mut output = String::new(); + for (level, step) in substeps { + let label = format!("{}{}", ".".repeat(level as usize), step.r#type); + writeln!(output, "{label:<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap(); + } + log::info!("Build step durations\n{output}"); +} diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs new file mode 100644 index 00000000000..6b35b13e586 --- /dev/null +++ b/src/tools/opt-dist/src/tests.rs @@ -0,0 +1,101 @@ +use crate::environment::Environment; +use crate::exec::cmd; +use crate::utils::io::{copy_directory, unpack_archive}; +use anyhow::Context; +use camino::Utf8PathBuf; + +/// Run tests on optimized dist artifacts. +pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> { + // After `dist` is executed, we extract its archived components into a sysroot directory, + // and then use that extracted rustc as a stage0 compiler. + // Then we run a subset of tests using that compiler, to have a basic smoke test which checks + // whether the optimization pipeline hasn't broken something. + let build_dir = env.build_root().join("build"); + let dist_dir = build_dir.join("dist"); + let unpacked_dist_dir = build_dir.join("unpacked-dist"); + std::fs::create_dir_all(&unpacked_dist_dir)?; + + let extract_dist_dir = |name: &str| -> anyhow::Result<Utf8PathBuf> { + unpack_archive(&dist_dir.join(format!("{name}.tar.xz")), &unpacked_dist_dir)?; + let extracted_path = unpacked_dist_dir.join(name); + assert!(extracted_path.is_dir()); + Ok(extracted_path) + }; + let host_triple = env.host_triple(); + + // Extract rustc, libstd, cargo and src archives to create the optimized sysroot + let rustc_dir = extract_dist_dir(&format!("rustc-nightly-{host_triple}"))?.join("rustc"); + let libstd_dir = extract_dist_dir(&format!("rust-std-nightly-{host_triple}"))? + .join(format!("rust-std-{host_triple}")); + let cargo_dir = extract_dist_dir(&format!("cargo-nightly-{host_triple}"))?.join("cargo"); + let extracted_src_dir = extract_dist_dir("rust-src-nightly")?.join("rust-src"); + + // We need to manually copy libstd to the extracted rustc sysroot + copy_directory( + &libstd_dir.join("lib").join("rustlib").join(&host_triple).join("lib"), + &rustc_dir.join("lib").join("rustlib").join(&host_triple).join("lib"), + )?; + + // Extract sources - they aren't in the `rustc-nightly-{host}` tarball, so we need to manually copy libstd + // sources to the extracted sysroot. We need sources available so that `-Zsimulate-remapped-rust-src-base` + // works correctly. + copy_directory( + &extracted_src_dir.join("lib").join("rustlib").join("src"), + &rustc_dir.join("lib").join("rustlib").join("src"), + )?; + + let rustc_path = rustc_dir.join("bin").join(format!("rustc{}", env.executable_extension())); + assert!(rustc_path.is_file()); + let cargo_path = cargo_dir.join("bin").join(format!("cargo{}", env.executable_extension())); + assert!(cargo_path.is_file()); + + // Specify path to a LLVM config so that LLVM is not rebuilt. + // It doesn't really matter which LLVM config we choose, because no sysroot will be compiled. + let llvm_config = env + .build_artifacts() + .join("llvm") + .join("bin") + .join(format!("llvm-config{}", env.executable_extension())); + assert!(llvm_config.is_file()); + + let config_content = format!( + r#"profile = "user" +changelog-seen = 2 + +[build] +rustc = "{rustc}" +cargo = "{cargo}" + +[target.{host_triple}] +llvm-config = "{llvm_config}" +"#, + rustc = rustc_path.to_string().replace('\\', "/"), + cargo = cargo_path.to_string().replace('\\', "/"), + llvm_config = llvm_config.to_string().replace('\\', "/") + ); + log::info!("Using following `config.toml` for running tests:\n{config_content}"); + + // Simulate a stage 0 compiler with the extracted optimized dist artifacts. + std::fs::write("config.toml", config_content)?; + + let x_py = env.checkout_path().join("x.py"); + let mut args = vec![ + env.python_binary(), + x_py.as_str(), + "test", + "--stage", + "0", + "tests/assembly", + "tests/codegen", + "tests/codegen-units", + "tests/incremental", + "tests/mir-opt", + "tests/pretty", + "tests/run-pass-valgrind", + "tests/ui", + ]; + for test_path in env.skipped_tests() { + args.extend(["--exclude", test_path]); + } + cmd(&args).env("COMPILETEST_FORCE_STAGE0", "1").run().context("Cannot execute tests") +} diff --git a/src/tools/opt-dist/src/timer.rs b/src/tools/opt-dist/src/timer.rs new file mode 100644 index 00000000000..2b29ba8d59f --- /dev/null +++ b/src/tools/opt-dist/src/timer.rs @@ -0,0 +1,167 @@ +use std::ops::{Deref, DerefMut}; +use std::time::{Duration, SystemTime}; + +pub struct Timer { + root: TimerSection, +} + +impl Timer { + pub fn new() -> Self { + Timer { root: TimerSection::new(None) } + } + + pub fn format_stats(&self) -> String { + use std::fmt::Write; + + let mut items = Vec::new(); + for (name, child) in &self.root.children { + match child { + SectionEntry::SubSection(section) => { + section.collect_levels(0, name, &mut items); + } + SectionEntry::Duration(duration) => items.push((0, name, *duration)), + } + } + + let rows: Vec<(String, Duration)> = items + .into_iter() + .map(|(level, name, duration)| (format!("{}{name}:", " ".repeat(level)), duration)) + .collect(); + + let total_duration = self.total_duration(); + let total_duration_label = "Total duration:".to_string(); + + const SPACE_AFTER_LABEL: usize = 2; + let max_label_length = 16.max(rows.iter().map(|(label, _)| label.len()).max().unwrap_or(0)) + + SPACE_AFTER_LABEL; + + let table_width = max_label_length + 23; + let divider = "-".repeat(table_width); + + let mut output = String::new(); + writeln!(output, "{divider}").unwrap(); + for (label, duration) in rows { + let pct = (duration.as_millis() as f64 / total_duration.as_millis() as f64) * 100.0; + let duration_fmt = format!("{:>12.2}s ({pct:>5.2}%)", duration.as_secs_f64()); + writeln!(output, "{label:<0$} {duration_fmt}", max_label_length).unwrap(); + } + output.push('\n'); + + let total_duration = Duration::new(total_duration.as_secs(), 0); + let total_duration = format!( + "{:>1$}", + humantime::format_duration(total_duration).to_string(), + table_width - total_duration_label.len() + ); + writeln!(output, "{total_duration_label}{total_duration}").unwrap(); + + writeln!(output, "{divider}").unwrap(); + output + } +} + +impl Deref for Timer { + type Target = TimerSection; + + fn deref(&self) -> &Self::Target { + &self.root + } +} + +impl DerefMut for Timer { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.root + } +} + +pub struct TimerSection { + name: Option<String>, + children: Vec<(String, SectionEntry)>, + duration_excluding_children: Duration, +} + +impl TimerSection { + pub fn new(name: Option<String>) -> Self { + TimerSection { + name, + children: Default::default(), + duration_excluding_children: Duration::ZERO, + } + } + + pub fn section<F: FnOnce(&mut TimerSection) -> anyhow::Result<R>, R>( + &mut self, + name: &str, + func: F, + ) -> anyhow::Result<R> { + let full_name = match &self.name { + Some(current_name) => { + format!("{current_name} > {name}") + } + None => name.to_string(), + }; + log::info!("Section `{full_name}` starts"); + let mut child = TimerSection { + name: Some(full_name.clone()), + children: Default::default(), + duration_excluding_children: Duration::ZERO, + }; + + let start = SystemTime::now(); + let result = func(&mut child); + let duration = start.elapsed().unwrap(); + + let msg = match result { + Ok(_) => "OK", + Err(_) => "FAIL", + }; + + child.duration_excluding_children = duration.saturating_sub(child.total_duration()); + + log::info!("Section `{full_name}` ended: {msg} ({:.2}s)`", duration.as_secs_f64()); + self.children.push((name.to_string(), SectionEntry::SubSection(child))); + result + } + + pub fn add_duration(&mut self, name: &str, duration: Duration) { + self.children.push((name.to_string(), SectionEntry::Duration(duration))); + } + + fn total_duration(&self) -> Duration { + self.duration_excluding_children + + self.children.iter().map(|(_, child)| child.total_duration()).sum::<Duration>() + } + + fn collect_levels<'a>( + &'a self, + level: usize, + name: &'a str, + items: &mut Vec<(usize, &'a str, Duration)>, + ) { + items.push((level, name, self.total_duration())); + for (name, child) in &self.children { + match &child { + SectionEntry::Duration(duration) => { + items.push((level + 1, name, *duration)); + } + SectionEntry::SubSection(section) => { + section.collect_levels(level + 1, name, items); + } + } + } + } +} + +enum SectionEntry { + Duration(Duration), + SubSection(TimerSection), +} + +impl SectionEntry { + fn total_duration(&self) -> Duration { + match self { + SectionEntry::Duration(duration) => *duration, + SectionEntry::SubSection(timer) => timer.total_duration(), + } + } +} diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs new file mode 100644 index 00000000000..10f4a603695 --- /dev/null +++ b/src/tools/opt-dist/src/training.rs @@ -0,0 +1,202 @@ +use crate::environment::Environment; +use crate::exec::{cmd, CmdBuilder}; +use crate::utils::io::{count_files, delete_directory}; +use anyhow::Context; +use camino::{Utf8Path, Utf8PathBuf}; +use humansize::BINARY; + +const LLVM_PGO_CRATES: &[&str] = &[ + "syn-1.0.89", + "cargo-0.60.0", + "serde-1.0.136", + "ripgrep-13.0.0", + "regex-1.5.5", + "clap-3.1.6", + "hyper-0.14.18", +]; + +const RUSTC_PGO_CRATES: &[&str] = &[ + "externs", + "ctfe-stress-5", + "cargo-0.60.0", + "token-stream-stress", + "match-stress", + "tuple-stress", + "diesel-1.4.8", + "bitmaps-3.1.0", +]; + +const LLVM_BOLT_CRATES: &[&str] = LLVM_PGO_CRATES; + +fn init_compiler_benchmarks( + env: &dyn Environment, + profiles: &[&str], + scenarios: &[&str], + crates: &[&str], +) -> CmdBuilder { + // Run rustc-perf benchmarks + // Benchmark using profile_local with eprintln, which essentially just means + // don't actually benchmark -- just make sure we run rustc a bunch of times. + cmd(&[ + env.cargo_stage_0().as_str(), + "run", + "-p", + "collector", + "--bin", + "collector", + "--", + "profile_local", + "eprintln", + env.rustc_stage_2().as_str(), + "--id", + "Test", + "--cargo", + env.cargo_stage_0().as_str(), + "--profiles", + profiles.join(",").as_str(), + "--scenarios", + scenarios.join(",").as_str(), + "--include", + crates.join(",").as_str(), + ]) + .env("RUST_LOG", "collector=debug") + .env("RUSTC", env.rustc_stage_0().as_str()) + .env("RUSTC_BOOTSTRAP", "1") + .workdir(&env.rustc_perf_dir()) +} + +fn merge_llvm_profiles( + env: &dyn Environment, + merged_path: &Utf8Path, + profile_dir: &Utf8Path, +) -> anyhow::Result<()> { + cmd(&[ + env.downloaded_llvm_dir().join("bin/llvm-profdata").as_str(), + "merge", + "-o", + merged_path.as_str(), + profile_dir.as_str(), + ]) + .run() + .context("Cannot merge LLVM profiles")?; + Ok(()) +} + +fn log_profile_stats( + name: &str, + merged_profile: &Utf8Path, + profile_root: &Utf8Path, +) -> anyhow::Result<()> { + log::info!("{name} PGO statistics"); + log::info!( + "{merged_profile}: {}", + humansize::format_size(std::fs::metadata(merged_profile.as_std_path())?.len(), BINARY) + ); + log::info!( + "{profile_root}: {}", + humansize::format_size(fs_extra::dir::get_size(profile_root.as_std_path())?, BINARY) + ); + log::info!("Profile file count: {}", count_files(profile_root)?); + Ok(()) +} + +pub struct LlvmPGOProfile(pub Utf8PathBuf); + +pub fn gather_llvm_profiles( + env: &dyn Environment, + profile_root: &Utf8Path, +) -> anyhow::Result<LlvmPGOProfile> { + log::info!("Running benchmarks with PGO instrumented LLVM"); + + init_compiler_benchmarks(env, &["Debug", "Opt"], &["Full"], LLVM_PGO_CRATES) + .run() + .context("Cannot gather LLVM PGO profiles")?; + + let merged_profile = env.opt_artifacts().join("llvm-pgo.profdata"); + log::info!("Merging LLVM PGO profiles to {merged_profile}"); + + merge_llvm_profiles(env, &merged_profile, profile_root)?; + log_profile_stats("LLVM", &merged_profile, profile_root)?; + + // We don't need the individual .profraw files now that they have been merged + // into a final .profdata + delete_directory(profile_root)?; + + Ok(LlvmPGOProfile(merged_profile)) +} + +pub struct RustcPGOProfile(pub Utf8PathBuf); + +pub fn gather_rustc_profiles( + env: &dyn Environment, + profile_root: &Utf8Path, +) -> anyhow::Result<RustcPGOProfile> { + log::info!("Running benchmarks with PGO instrumented rustc"); + + // The profile data is written into a single filepath that is being repeatedly merged when each + // rustc invocation ends. Empirically, this can result in some profiling data being lost. That's + // why we override the profile path to include the PID. This will produce many more profiling + // files, but the resulting profile will produce a slightly faster rustc binary. + let profile_template = profile_root.join("default_%m_%p.profraw"); + + // Here we're profiling the `rustc` frontend, so we also include `Check`. + // The benchmark set includes various stress tests that put the frontend under pressure. + init_compiler_benchmarks(env, &["Check", "Debug", "Opt"], &["All"], RUSTC_PGO_CRATES) + .env("LLVM_PROFILE_FILE", profile_template.as_str()) + .run() + .context("Cannot gather rustc PGO profiles")?; + + let merged_profile = env.opt_artifacts().join("rustc-pgo.profdata"); + log::info!("Merging Rustc PGO profiles to {merged_profile}"); + + merge_llvm_profiles(env, &merged_profile, profile_root)?; + log_profile_stats("Rustc", &merged_profile, profile_root)?; + + // We don't need the individual .profraw files now that they have been merged + // into a final .profdata + delete_directory(profile_root)?; + + Ok(RustcPGOProfile(merged_profile)) +} + +pub struct LlvmBoltProfile(pub Utf8PathBuf); + +pub fn gather_llvm_bolt_profiles(env: &dyn Environment) -> anyhow::Result<LlvmBoltProfile> { + log::info!("Running benchmarks with BOLT instrumented LLVM"); + + init_compiler_benchmarks(env, &["Check", "Debug", "Opt"], &["Full"], LLVM_BOLT_CRATES) + .run() + .context("Cannot gather LLVM BOLT profiles")?; + + let merged_profile = env.opt_artifacts().join("bolt.profdata"); + let profile_root = Utf8PathBuf::from("/tmp/prof.fdata"); + log::info!("Merging LLVM BOLT profiles to {merged_profile}"); + + let profiles: Vec<_> = + glob::glob(&format!("{profile_root}*"))?.into_iter().collect::<Result<Vec<_>, _>>()?; + + let mut merge_args = vec!["merge-fdata"]; + merge_args.extend(profiles.iter().map(|p| p.to_str().unwrap())); + + cmd(&merge_args) + .redirect_output(merged_profile.clone()) + .run() + .context("Cannot merge BOLT profiles")?; + + log::info!("LLVM BOLT statistics"); + log::info!( + "{merged_profile}: {}", + humansize::format_size(std::fs::metadata(merged_profile.as_std_path())?.len(), BINARY) + ); + + let size = profiles + .iter() + .map(|p| std::fs::metadata(p).map(|metadata| metadata.len())) + .collect::<Result<Vec<_>, _>>()? + .into_iter() + .sum::<u64>(); + log::info!("{profile_root}: {}", humansize::format_size(size, BINARY)); + log::info!("Profile file count: {}", profiles.len()); + + Ok(LlvmBoltProfile(merged_profile)) +} diff --git a/src/tools/opt-dist/src/utils/io.rs b/src/tools/opt-dist/src/utils/io.rs new file mode 100644 index 00000000000..43546e5fcfa --- /dev/null +++ b/src/tools/opt-dist/src/utils/io.rs @@ -0,0 +1,48 @@ +use anyhow::Context; +use camino::Utf8Path; +use fs_extra::dir::CopyOptions; +use std::fs::File; + +/// Delete and re-create the directory. +pub fn reset_directory(path: &Utf8Path) -> anyhow::Result<()> { + log::info!("Resetting directory {path}"); + let _ = std::fs::remove_dir(path); + std::fs::create_dir_all(path)?; + Ok(()) +} + +pub fn copy_directory(src: &Utf8Path, dst: &Utf8Path) -> anyhow::Result<()> { + log::info!("Copying directory {src} to {dst}"); + fs_extra::dir::copy(src, dst, &CopyOptions::default().copy_inside(true))?; + Ok(()) +} + +#[allow(unused)] +pub fn move_directory(src: &Utf8Path, dst: &Utf8Path) -> anyhow::Result<()> { + log::info!("Moving directory {src} to {dst}"); + fs_extra::dir::move_dir(src, dst, &CopyOptions::default().content_only(true))?; + Ok(()) +} + +/// Counts all children of a directory (non-recursively). +pub fn count_files(dir: &Utf8Path) -> anyhow::Result<u64> { + Ok(std::fs::read_dir(dir)?.count() as u64) +} + +pub fn delete_directory(path: &Utf8Path) -> anyhow::Result<()> { + log::info!("Deleting directory `{path}`"); + std::fs::remove_dir_all(path.as_std_path()) + .context(format!("Cannot remove directory {path}"))?; + Ok(()) +} + +pub fn unpack_archive(path: &Utf8Path, dest_dir: &Utf8Path) -> anyhow::Result<()> { + log::info!("Unpacking directory `{path}` into `{dest_dir}`"); + + assert!(path.as_str().ends_with(".tar.xz")); + let file = File::open(path.as_std_path())?; + let file = xz::read::XzDecoder::new(file); + let mut archive = tar::Archive::new(file); + archive.unpack(dest_dir.as_std_path())?; + Ok(()) +} diff --git a/src/tools/opt-dist/src/utils/mod.rs b/src/tools/opt-dist/src/utils/mod.rs new file mode 100644 index 00000000000..9305d4989aa --- /dev/null +++ b/src/tools/opt-dist/src/utils/mod.rs @@ -0,0 +1,36 @@ +pub mod io; + +use crate::environment::Environment; +use crate::utils::io::delete_directory; +use humansize::BINARY; +use sysinfo::{DiskExt, RefreshKind, System, SystemExt}; + +pub fn format_env_variables() -> String { + let vars = std::env::vars().map(|(key, value)| format!("{key}={value}")).collect::<Vec<_>>(); + vars.join("\n") +} + +pub fn print_free_disk_space() -> anyhow::Result<()> { + let sys = System::new_with_specifics(RefreshKind::default().with_disks_list().with_disks()); + let available_space: u64 = sys.disks().iter().map(|d| d.available_space()).sum(); + let total_space: u64 = sys.disks().iter().map(|d| d.total_space()).sum(); + let used_space = total_space - available_space; + + log::info!( + "Free disk space: {} out of total {} ({:.2}% used)", + humansize::format_size(available_space, BINARY), + humansize::format_size(total_space, BINARY), + (used_space as f64 / total_space as f64) * 100.0 + ); + Ok(()) +} + +pub fn clear_llvm_files(env: &dyn Environment) -> anyhow::Result<()> { + // Bootstrap currently doesn't support rebuilding LLVM when PGO options + // change (or any other llvm-related options); so just clear out the relevant + // directories ourselves. + log::info!("Clearing LLVM build files"); + delete_directory(&env.build_artifacts().join("llvm"))?; + delete_directory(&env.build_artifacts().join("lld"))?; + Ok(()) +} diff --git a/src/tools/rust-installer/install-template.sh b/src/tools/rust-installer/install-template.sh index 92a3f1f2c98..6415644e045 100644 --- a/src/tools/rust-installer/install-template.sh +++ b/src/tools/rust-installer/install-template.sh @@ -17,8 +17,8 @@ log_line() { local _line="$1" if [ -n "${LOGFILE-}" -a -e "${LOGFILE-}" ]; then - echo "$_line" >> "$LOGFILE" - # Ignore errors, which may happen e.g. after the manifest dir is deleted + echo "$_line" >> "$LOGFILE" + # Ignore errors, which may happen e.g. after the manifest dir is deleted fi } @@ -30,9 +30,9 @@ msg() { verbose_msg() { if [ -n "${CFG_VERBOSE-}" ]; then - msg "${1-}" + msg "${1-}" else - log_line "install: ${1-}" + log_line "install: ${1-}" fi } @@ -44,13 +44,13 @@ step_msg() { verbose_step_msg() { if [ -n "${CFG_VERBOSE-}" ]; then - msg - msg "$1" - msg + msg + msg "$1" + msg else - log_line "" - log_line "install: $1" - log_line "" + log_line "" + log_line "install: $1" + log_line "" fi } @@ -91,7 +91,7 @@ critical_need_ok() { want_ok() { if [ $? -ne 0 ]; then - warn "$1" + warn "$1" fi } @@ -321,40 +321,40 @@ uninstall_legacy() { # Uninstall from legacy manifests local _md for _md in $_legacy_manifest_dirs; do - # First, uninstall from the installation prefix. - # Errors are warnings - try to rm everything in the manifest even if some fail. - if [ -f "$_abs_libdir/$_md/manifest" ] - then - - # iterate through installed manifest and remove files - local _p; - while read _p; do - # the installed manifest contains absolute paths - msg "removing legacy file $_p" - if [ -f "$_p" ] - then - run rm -f "$_p" - want_ok "failed to remove $_p" - else - warn "supposedly installed file $_p does not exist!" - fi - done < "$_abs_libdir/$_md/manifest" - - # If we fail to remove $md below, then the - # installed manifest will still be full; the installed manifest - # needs to be empty before install. - msg "removing legacy manifest $_abs_libdir/$_md/manifest" - run rm -f "$_abs_libdir/$_md/manifest" - # For the above reason, this is a hard error - need_ok "failed to remove installed manifest" - - # Remove $template_rel_manifest_dir directory - msg "removing legacy manifest dir $_abs_libdir/$_md" - run rm -R "$_abs_libdir/$_md" - want_ok "failed to remove $_md" - - _uninstalled_something=true - fi + # First, uninstall from the installation prefix. + # Errors are warnings - try to rm everything in the manifest even if some fail. + if [ -f "$_abs_libdir/$_md/manifest" ] + then + + # iterate through installed manifest and remove files + local _p; + while read _p; do + # the installed manifest contains absolute paths + msg "removing legacy file $_p" + if [ -f "$_p" ] + then + run rm -f "$_p" + want_ok "failed to remove $_p" + else + warn "supposedly installed file $_p does not exist!" + fi + done < "$_abs_libdir/$_md/manifest" + + # If we fail to remove $md below, then the + # installed manifest will still be full; the installed manifest + # needs to be empty before install. + msg "removing legacy manifest $_abs_libdir/$_md/manifest" + run rm -f "$_abs_libdir/$_md/manifest" + # For the above reason, this is a hard error + need_ok "failed to remove installed manifest" + + # Remove $template_rel_manifest_dir directory + msg "removing legacy manifest dir $_abs_libdir/$_md" + run rm -R "$_abs_libdir/$_md" + want_ok "failed to remove $_md" + + _uninstalled_something=true + fi done RETVAL="$_uninstalled_something" @@ -373,133 +373,134 @@ uninstall_components() { uninstall_legacy "$_abs_libdir" assert_nz "$RETVAL", "RETVAL" if [ "$RETVAL" = true ]; then - _uninstalled_something=true; + _uninstalled_something=true; fi # Load the version of the installed installer local _installed_version= if [ -f "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" ]; then - _installed_version=`cat "$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"` + _installed_version=`cat "$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"` - # Sanity check - if [ ! -n "$_installed_version" ]; then critical_err "rust installer version is empty"; fi + # Sanity check + if [ ! -n "$_installed_version" ]; then critical_err "rust installer version is empty"; fi fi # If there's something installed, then uninstall if [ -n "$_installed_version" ]; then - # Check the version of the installed installer - case "$_installed_version" in - - # If this is a previous version, then upgrade in place to the - # current version before uninstalling. - 2 ) - # The only change between version 2 -> 3 is that components are placed - # in subdirectories of the installer tarball. There are no changes - # to the installed data format, so nothing to do. - ;; - - # This is the current version. Nothing need to be done except uninstall. - "$TEMPLATE_RUST_INSTALLER_VERSION") - ;; - - # If this is an unknown (future) version then bail. - * ) - echo "The copy of $TEMPLATE_PRODUCT_NAME at $_dest_prefix was installed using an" - echo "unknown version ($_installed_version) of rust-installer." - echo "Uninstall it first with the installer used for the original installation" - echo "before continuing." - exit 1 - ;; - esac - - local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" - local _installed_components="$(cat "$_md/components")" - - # Uninstall (our components only) before reinstalling - local _available_component - for _available_component in $_components; do - local _installed_component - for _installed_component in $_installed_components; do - if [ "$_available_component" = "$_installed_component" ]; then - msg "uninstalling component '$_available_component'" - local _component_manifest="$_md/manifest-$_installed_component" - - # Sanity check: there should be a component manifest - if [ ! -f "$_component_manifest" ]; then - critical_err "installed component '$_installed_component' has no manifest" - fi - - # Iterate through installed component manifest and remove files - local _directive - while read _directive; do - - local _command=`echo $_directive | cut -f1 -d:` - local _file=`echo $_directive | cut -f2 -d:` - - # Sanity checks - if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi - if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi - - case "$_command" in - file) - verbose_msg "removing file $_file" - if [ -f "$_file" ]; then - run rm -f "$_file" - want_ok "failed to remove $_file" - else - warn "supposedly installed file $_file does not exist!" - fi - ;; - - dir) - verbose_msg "removing directory $_file" - run rm -r "$_file" - want_ok "unable to remove directory $_file" - ;; - - *) - critical_err "unknown installation directive" - ;; - esac - - done < "$_component_manifest" - - # Remove the installed component manifest - verbose_msg "removing component manifest $_component_manifest" - run rm "$_component_manifest" - # This is a hard error because the installation is unrecoverable - critical_need_ok "failed to remove installed manifest for component '$_installed_component'" - - # Update the installed component list - local _modified_components="$(sed "/^$_installed_component\$/d" "$_md/components")" - write_to_file "$_modified_components" "$_md/components" - critical_need_ok "failed to update installed component list" - fi - done - done - - # If there are no remaining components delete the manifest directory, - # but only if we're doing an uninstall - if we're doing an install, - # then leave the manifest directory around to hang onto the logs, - # and any files not managed by the installer. - if [ -n "${CFG_UNINSTALL-}" ]; then - local _remaining_components="$(cat "$_md/components")" - if [ ! -n "$_remaining_components" ]; then - verbose_msg "removing manifest directory $_md" - run rm -r "$_md" - want_ok "failed to remove $_md" - - maybe_unconfigure_ld - fi - fi - - _uninstalled_something=true + # Check the version of the installed installer + case "$_installed_version" in + + # If this is a previous version, then upgrade in place to the + # current version before uninstalling. + 2 ) + # The only change between version 2 -> 3 is that components are placed + # in subdirectories of the installer tarball. There are no changes + # to the installed data format, so nothing to do. + ;; + + # This is the current version. Nothing need to be done except uninstall. + "$TEMPLATE_RUST_INSTALLER_VERSION") + ;; + + # If this is an unknown (future) version then bail. + * ) + echo "The copy of $TEMPLATE_PRODUCT_NAME at $_dest_prefix was installed using an" + echo "unknown version ($_installed_version) of rust-installer." + echo "Uninstall it first with the installer used for the original installation" + echo "before continuing." + exit 1 + ;; + esac + + local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" + local _installed_components="$(cat "$_md/components")" + + # Uninstall (our components only) before reinstalling + local _available_component + for _available_component in $_components; do + local _installed_component + for _installed_component in $_installed_components; do + if [ "$_available_component" = "$_installed_component" ]; then + msg "uninstalling component '$_available_component'" + local _component_manifest="$_md/manifest-$_installed_component" + + # Sanity check: there should be a component manifest + if [ ! -f "$_component_manifest" ]; then + critical_err "installed component '$_installed_component' has no manifest" + fi + + # Iterate through installed component manifest and remove files + local _directive + while read _directive; do + + local _command=`echo $_directive | cut -f1 -d:` + local _file=`echo $_directive | cut -f2 -d:` + + # Sanity checks + if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi + if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi + + case "$_command" in + file) + verbose_msg "removing file $_file" + if [ -f "$_file" ]; then + run rm -f "$_file" + want_ok "failed to remove $_file" + else + warn "supposedly installed file $_file does not exist!" + fi + ;; + + dir) + verbose_msg "removing directory $_file" + run rm -r "$_file" + want_ok "unable to remove directory $_file" + ;; + + *) + critical_err "unknown installation directive" + ;; + esac + + done < "$_component_manifest" + + # Remove the installed component manifest + verbose_msg "removing component manifest $_component_manifest" + run rm "$_component_manifest" + # This is a hard error because the installation is unrecoverable + local _err_cant_r_manifest="failed to remove installed manifest for component" + critical_need_ok "$_err_cant_r_manifest '$_installed_component'" + + # Update the installed component list + local _modified_components="$(sed "/^$_installed_component\$/d" "$_md/components")" + write_to_file "$_modified_components" "$_md/components" + critical_need_ok "failed to update installed component list" + fi + done + done + + # If there are no remaining components delete the manifest directory, + # but only if we're doing an uninstall - if we're doing an install, + # then leave the manifest directory around to hang onto the logs, + # and any files not managed by the installer. + if [ -n "${CFG_UNINSTALL-}" ]; then + local _remaining_components="$(cat "$_md/components")" + if [ ! -n "$_remaining_components" ]; then + verbose_msg "removing manifest directory $_md" + run rm -r "$_md" + want_ok "failed to remove $_md" + + maybe_unconfigure_ld + fi + fi + + _uninstalled_something=true fi # There's no installed version. If we were asked to uninstall, then that's a problem. if [ -n "${CFG_UNINSTALL-}" -a "$_uninstalled_something" = false ] then - err "unable to find installation manifest at $CFG_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR" + err "unable to find installation manifest at $CFG_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR" fi } @@ -512,73 +513,73 @@ install_components() { local _component for _component in $_components; do - msg "installing component '$_component'" + msg "installing component '$_component'" - # The file name of the manifest we're installing from - local _input_manifest="$_src_dir/$_component/manifest.in" + # The file name of the manifest we're installing from + local _input_manifest="$_src_dir/$_component/manifest.in" - # Sanity check: do we have our input manifests? - if [ ! -f "$_input_manifest" ]; then - critical_err "manifest for $_component does not exist at $_input_manifest" - fi + # Sanity check: do we have our input manifests? + if [ ! -f "$_input_manifest" ]; then + critical_err "manifest for $_component does not exist at $_input_manifest" + fi - # The installed manifest directory - local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" + # The installed manifest directory + local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" - # The file name of the manifest we're going to create during install - local _installed_manifest="$_md/manifest-$_component" + # The file name of the manifest we're going to create during install + local _installed_manifest="$_md/manifest-$_component" - # Create the installed manifest, which we will fill in with absolute file paths - touch "$_installed_manifest" - critical_need_ok "failed to create installed manifest" + # Create the installed manifest, which we will fill in with absolute file paths + touch "$_installed_manifest" + critical_need_ok "failed to create installed manifest" - # Add this component to the installed component list - append_to_file "$_component" "$_md/components" - critical_need_ok "failed to update components list for $_component" + # Add this component to the installed component list + append_to_file "$_component" "$_md/components" + critical_need_ok "failed to update components list for $_component" - # Now install, iterate through the new manifest and copy files - local _directive - while read _directive; do + # Now install, iterate through the new manifest and copy files + local _directive + while read _directive; do - local _command=`echo $_directive | cut -f1 -d:` - local _file=`echo $_directive | cut -f2 -d:` + local _command=`echo $_directive | cut -f1 -d:` + local _file=`echo $_directive | cut -f2 -d:` - # Sanity checks - if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi - if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi + # Sanity checks + if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi + if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi - # Decide the destination of the file - local _file_install_path="$_dest_prefix/$_file" + # Decide the destination of the file + local _file_install_path="$_dest_prefix/$_file" - if echo "$_file" | grep "^etc/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^etc\///')" - _file_install_path="$CFG_SYSCONFDIR/$_f" - fi + if echo "$_file" | grep "^etc/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^etc\///')" + _file_install_path="$CFG_SYSCONFDIR/$_f" + fi - if echo "$_file" | grep "^bin/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^bin\///')" - _file_install_path="$CFG_BINDIR/$_f" - fi + if echo "$_file" | grep "^bin/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^bin\///')" + _file_install_path="$CFG_BINDIR/$_f" + fi - if echo "$_file" | grep "^lib/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^lib\///')" - _file_install_path="$CFG_LIBDIR/$_f" - fi + if echo "$_file" | grep "^lib/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^lib\///')" + _file_install_path="$CFG_LIBDIR/$_f" + fi - if echo "$_file" | grep "^share" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^share\///')" - _file_install_path="$CFG_DATADIR/$_f" - fi + if echo "$_file" | grep "^share" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^share\///')" + _file_install_path="$CFG_DATADIR/$_f" + fi - if echo "$_file" | grep "^share/man/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^share\/man\///')" - _file_install_path="$CFG_MANDIR/$_f" - fi + if echo "$_file" | grep "^share/man/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^share\/man\///')" + _file_install_path="$CFG_MANDIR/$_f" + fi # HACK: Try to support overriding --docdir. Paths with the form # "share/doc/$product/" can be redirected to a single --docdir @@ -592,69 +593,69 @@ install_components() { # this problem to be a big deal in practice. if [ "$CFG_DOCDIR" != "<default>" ] then - if echo "$_file" | grep "^share/doc/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^share\/doc\/[^/]*\///')" - _file_install_path="$CFG_DOCDIR/$_f" - fi + if echo "$_file" | grep "^share/doc/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^share\/doc\/[^/]*\///')" + _file_install_path="$CFG_DOCDIR/$_f" + fi fi - # Make sure there's a directory for it - make_dir_recursive "$(dirname "$_file_install_path")" - critical_need_ok "directory creation failed" + # Make sure there's a directory for it + make_dir_recursive "$(dirname "$_file_install_path")" + critical_need_ok "directory creation failed" - # Make the path absolute so we can uninstall it later without - # starting from the installation cwd - absolutify "$_file_install_path" - _file_install_path="$RETVAL" - assert_nz "$_file_install_path" "file_install_path" + # Make the path absolute so we can uninstall it later without + # starting from the installation cwd + absolutify "$_file_install_path" + _file_install_path="$RETVAL" + assert_nz "$_file_install_path" "file_install_path" - case "$_command" in - file ) + case "$_command" in + file ) - verbose_msg "copying file $_file_install_path" + verbose_msg "copying file $_file_install_path" - maybe_backup_path "$_file_install_path" + maybe_backup_path "$_file_install_path" - if echo "$_file" | grep "^bin/" > /dev/null || test -x "$_src_dir/$_component/$_file" - then - run cp "$_src_dir/$_component/$_file" "$_file_install_path" - run chmod 755 "$_file_install_path" - else - run cp "$_src_dir/$_component/$_file" "$_file_install_path" - run chmod 644 "$_file_install_path" - fi - critical_need_ok "file creation failed" + if echo "$_file" | grep "^bin/" > /dev/null || test -x "$_src_dir/$_component/$_file" + then + run cp "$_src_dir/$_component/$_file" "$_file_install_path" + run chmod 755 "$_file_install_path" + else + run cp "$_src_dir/$_component/$_file" "$_file_install_path" + run chmod 644 "$_file_install_path" + fi + critical_need_ok "file creation failed" - # Update the manifest - append_to_file "file:$_file_install_path" "$_installed_manifest" - critical_need_ok "failed to update manifest" + # Update the manifest + append_to_file "file:$_file_install_path" "$_installed_manifest" + critical_need_ok "failed to update manifest" - ;; + ;; - dir ) + dir ) - verbose_msg "copying directory $_file_install_path" + verbose_msg "copying directory $_file_install_path" - maybe_backup_path "$_file_install_path" + maybe_backup_path "$_file_install_path" - run cp -R "$_src_dir/$_component/$_file" "$_file_install_path" - critical_need_ok "failed to copy directory" + run cp -R "$_src_dir/$_component/$_file" "$_file_install_path" + critical_need_ok "failed to copy directory" # Set permissions. 0755 for dirs, 644 for files run chmod -R u+rwX,go+rX,go-w "$_file_install_path" critical_need_ok "failed to set permissions on directory" - # Update the manifest - append_to_file "dir:$_file_install_path" "$_installed_manifest" - critical_need_ok "failed to update manifest" - ;; + # Update the manifest + append_to_file "dir:$_file_install_path" "$_installed_manifest" + critical_need_ok "failed to update manifest" + ;; - *) - critical_err "unknown installation directive" - ;; - esac - done < "$_input_manifest" + *) + critical_err "unknown installation directive" + ;; + esac + done < "$_input_manifest" done } @@ -667,33 +668,35 @@ maybe_configure_ld() { if [ "$_ostype" = "Linux" -a ! -n "${CFG_DISABLE_LDCONFIG-}" ]; then - # Fedora-based systems do not configure the dynamic linker to look - # /usr/local/lib, which is our default installation directory. To - # make things just work, try to put that directory in - # /etc/ld.so.conf.d/rust-installer-v1 so ldconfig picks it up. - # Issue #30. - # - # This will get rm'd when the last component is uninstalled in - # maybe_unconfigure_ld. - if [ "$_abs_libdir" = "/usr/local/lib" -a -d "/etc/ld.so.conf.d" ]; then - echo "$_abs_libdir" > "/etc/ld.so.conf.d/rust-installer-v1-$TEMPLATE_REL_MANIFEST_DIR.conf" - if [ $? -ne 0 ]; then - # This shouldn't happen if we've gotten this far - # installing to /usr/local - warn "failed to update /etc/ld.so.conf.d. this is unexpected" - fi - fi - - verbose_msg "running ldconfig" - if [ -n "${CFG_VERBOSE-}" ]; then - ldconfig - else - ldconfig 2> /dev/null - fi - if [ $? -ne 0 ] - then - warn "failed to run ldconfig. this may happen when not installing as root. run with --verbose to see the error" - fi + # Fedora-based systems do not configure the dynamic linker to look + # /usr/local/lib, which is our default installation directory. To + # make things just work, try to put that directory in + # /etc/ld.so.conf.d/rust-installer-v1 so ldconfig picks it up. + # Issue #30. + # + # This will get rm'd when the last component is uninstalled in + # maybe_unconfigure_ld. + if [ "$_abs_libdir" = "/usr/local/lib" -a -d "/etc/ld.so.conf.d" ]; then + echo "$_abs_libdir" > "/etc/ld.so.conf.d/rust-installer-v1-$TEMPLATE_REL_MANIFEST_DIR.conf" + if [ $? -ne 0 ]; then + # This shouldn't happen if we've gotten this far + # installing to /usr/local + warn "failed to update /etc/ld.so.conf.d. this is unexpected" + fi + fi + + verbose_msg "running ldconfig" + if [ -n "${CFG_VERBOSE-}" ]; then + ldconfig + else + ldconfig 2> /dev/null + fi + if [ $? -ne 0 ] + then + local _warn_s="failed to run ldconfig. this may happen when \ +not installing as root. run with --verbose to see the error" + warn "$_warn_s" + fi fi } @@ -702,7 +705,7 @@ maybe_unconfigure_ld() { assert_nz "$_ostype" "ostype" if [ "$_ostype" != "Linux" ]; then - return 0 + return 0 fi rm "/etc/ld.so.conf.d/rust-installer-v1-$TEMPLATE_REL_MANIFEST_DIR.conf" 2> /dev/null @@ -714,9 +717,9 @@ maybe_backup_path() { local _file_install_path="$1" if [ -e "$_file_install_path" ]; then - msg "backing up existing file at $_file_install_path" - run mv -f "$_file_install_path" "$_file_install_path.old" - critical_need_ok "failed to back up $_file_install_path" + msg "backing up existing file at $_file_install_path" + run mv -f "$_file_install_path" "$_file_install_path.old" + critical_need_ok "failed to back up $_file_install_path" fi } @@ -742,7 +745,7 @@ do_preflight_sanity_checks() { touch "$CFG_LIBDIR/rust-install-probe" > /dev/null if [ $? -ne 0 ] then - err "can't write to destination. consider \`sudo\`." + err "can't write to destination. consider \`sudo\`." fi rm "$CFG_LIBDIR/rust-install-probe" need_ok "failed to remove install probe" @@ -752,7 +755,7 @@ do_preflight_sanity_checks() { verbose_msg "verifying destination is not the same as source" local _prefix_dir="$(abs_path "$dest_prefix")" if [ "$_src_dir" = "$_dest_prefix" -a "${CFG_UNINSTALL-}" != 1 ]; then - err "cannot install to same directory as installer" + err "cannot install to same directory as installer" fi } @@ -857,8 +860,8 @@ src_basename="$(basename "$0")" # which just means 'uninstall my components'. if [ "$src_basename" = "uninstall.sh" ]; then if [ "${*:-}" != "" ]; then - # Currently don't know what to do with arguments in this mode - err "uninstall.sh does not take any arguments" + # Currently don't know what to do with arguments in this mode + err "uninstall.sh does not take any arguments" fi CFG_UNINSTALL=1 CFG_DESTDIR_PREFIX="$(abs_path "$src_dir/../../")" @@ -885,7 +888,7 @@ if [ -n "${CFG_LIST_COMPONENTS-}" ]; then echo "# Available components" echo for component in $components; do - echo "* $component" + echo "* $component" done echo exit 0 @@ -897,15 +900,15 @@ if [ -n "$CFG_COMPONENTS" ]; then # Remove commas user_components="$(echo "$CFG_COMPONENTS" | sed "s/,/ /g")" for user_component in $user_components; do - found=false - for my_component in $components; do - if [ "$user_component" = "$my_component" ]; then - found=true - fi - done - if [ "$found" = false ]; then - err "unknown component: $user_component" - fi + found=false + for my_component in $components; do + if [ "$user_component" = "$my_component" ]; then + found=true + fi + done + if [ "$found" = false ]; then + err "unknown component: $user_component" + fi done components="$user_components" fi @@ -937,9 +940,9 @@ fi if [ -z "$components" ]; then if [ -z "${CFG_UNINSTALL-}" ]; then - err "no components selected for installation" + err "no components selected for installation" else - err "no components selected for uninstallation" + err "no components selected for uninstallation" fi fi @@ -977,7 +980,9 @@ make_dir_recursive "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" need_ok "failed to create $TEMPLATE_REL_MANIFEST_DIR" # Drop the version number into the manifest dir -write_to_file "$TEMPLATE_RUST_INSTALLER_VERSION" "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" +write_to_file "$TEMPLATE_RUST_INSTALLER_VERSION" \ +"$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" + critical_need_ok "failed to write installer version" # Install the uninstaller @@ -992,5 +997,3 @@ maybe_configure_ld "$abs_libdir" echo echo " $TEMPLATE_SUCCESS_MESSAGE" echo - - diff --git a/src/tools/rust-installer/src/combiner.rs b/src/tools/rust-installer/src/combiner.rs index 19466f63fed..565d19d863f 100644 --- a/src/tools/rust-installer/src/combiner.rs +++ b/src/tools/rust-installer/src/combiner.rs @@ -71,25 +71,16 @@ impl Combiner { // Merge each installer into the work directory of the new installer. let components = create_new_file(package_dir.join("components"))?; - for input_tarball in self - .input_tarballs - .split(',') - .map(str::trim) - .filter(|s| !s.is_empty()) + for input_tarball in self.input_tarballs.split(',').map(str::trim).filter(|s| !s.is_empty()) { // Extract the input tarballs let compression = CompressionFormat::detect_from_path(input_tarball).ok_or_else(|| { anyhow::anyhow!("couldn't figure out the format of {}", input_tarball) })?; - Archive::new(compression.decode(input_tarball)?) - .unpack(&self.work_dir) - .with_context(|| { - format!( - "unable to extract '{}' into '{}'", - &input_tarball, self.work_dir - ) - })?; + Archive::new(compression.decode(input_tarball)?).unpack(&self.work_dir).with_context( + || format!("unable to extract '{}' into '{}'", &input_tarball, self.work_dir), + )?; let pkg_name = input_tarball.trim_end_matches(&format!(".tar.{}", compression.extension())); @@ -126,12 +117,8 @@ impl Combiner { // Write the installer version. let version = package_dir.join("rust-installer-version"); - writeln!( - create_new_file(version)?, - "{}", - crate::RUST_INSTALLER_VERSION - ) - .context("failed to write new installer version")?; + writeln!(create_new_file(version)?, "{}", crate::RUST_INSTALLER_VERSION) + .context("failed to write new installer version")?; // Copy the overlay. if !self.non_installed_overlay.is_empty() { diff --git a/src/tools/rust-installer/src/generator.rs b/src/tools/rust-installer/src/generator.rs index 45f8c49d03e..b101e67d8df 100644 --- a/src/tools/rust-installer/src/generator.rs +++ b/src/tools/rust-installer/src/generator.rs @@ -86,12 +86,8 @@ impl Generator { // Write the installer version (only used by combine-installers.sh) let version = package_dir.join("rust-installer-version"); - writeln!( - create_new_file(version)?, - "{}", - crate::RUST_INSTALLER_VERSION - ) - .context("failed to write new installer version")?; + writeln!(create_new_file(version)?, "{}", crate::RUST_INSTALLER_VERSION) + .context("failed to write new installer version")?; // Copy the overlay if !self.non_installed_overlay.is_empty() { @@ -128,33 +124,19 @@ impl Generator { /// Copies the `src` directory recursively to `dst`, writing `manifest.in` too. fn copy_and_manifest(src: &Path, dst: &Path, bulk_dirs: &str) -> Result<()> { let mut manifest = create_new_file(dst.join("manifest.in"))?; - let bulk_dirs: Vec<_> = bulk_dirs - .split(',') - .filter(|s| !s.is_empty()) - .map(Path::new) - .collect(); + let bulk_dirs: Vec<_> = bulk_dirs.split(',').filter(|s| !s.is_empty()).map(Path::new).collect(); let mut paths = BTreeSet::new(); copy_with_callback(src, dst, |path, file_type| { // We need paths to be compatible with both Unix and Windows. - if path - .components() - .filter_map(|c| c.as_os_str().to_str()) - .any(|s| s.contains('\\')) - { - bail!( - "rust-installer doesn't support '\\' in path components: {:?}", - path - ); + if path.components().filter_map(|c| c.as_os_str().to_str()).any(|s| s.contains('\\')) { + bail!("rust-installer doesn't support '\\' in path components: {:?}", path); } // Normalize to Unix-style path separators. let normalized_string; let mut string = path.to_str().ok_or_else(|| { - format_err!( - "rust-installer doesn't support non-Unicode paths: {:?}", - path - ) + format_err!("rust-installer doesn't support non-Unicode paths: {:?}", path) })?; if string.contains('\\') { normalized_string = string.replace('\\', "/"); diff --git a/src/tools/rust-installer/src/main.rs b/src/tools/rust-installer/src/main.rs index be8a0d68343..99acecdd43c 100644 --- a/src/tools/rust-installer/src/main.rs +++ b/src/tools/rust-installer/src/main.rs @@ -19,8 +19,12 @@ fn main() -> Result<()> { let command_line = CommandLine::parse(); match command_line.command { Subcommand::Combine(combiner) => combiner.run().context("failed to combine installers")?, - Subcommand::Generate(generator) => generator.run().context("failed to generate installer")?, - Subcommand::Script(scripter) => scripter.run().context("failed to generate installation script")?, + Subcommand::Generate(generator) => { + generator.run().context("failed to generate installer")? + } + Subcommand::Script(scripter) => { + scripter.run().context("failed to generate installation script")? + } Subcommand::Tarball(tarballer) => tarballer.run().context("failed to generate tarballs")?, } Ok(()) diff --git a/src/tools/rust-installer/src/scripter.rs b/src/tools/rust-installer/src/scripter.rs index 8180f925cb0..ff65e818b09 100644 --- a/src/tools/rust-installer/src/scripter.rs +++ b/src/tools/rust-installer/src/scripter.rs @@ -32,22 +32,19 @@ actor! { impl Scripter { /// Generates the actual installer script pub fn run(self) -> Result<()> { - // Replace dashes in the success message with spaces (our arg handling botches spaces) - // TODO: still needed? Kept for compatibility for now. + // Replace dashes in the product name with spaces (our arg handling botches spaces) + // FIXME: still needed? Kept for compatibility for now. let product_name = self.product_name.replace('-', " "); // Replace dashes in the success message with spaces (our arg handling botches spaces) - // TODO: still needed? Kept for compatibility for now. + // FIXME: still needed? Kept for compatibility for now. let success_message = self.success_message.replace('-', " "); let script = TEMPLATE .replace("%%TEMPLATE_PRODUCT_NAME%%", &sh_quote(&product_name)) .replace("%%TEMPLATE_REL_MANIFEST_DIR%%", &self.rel_manifest_dir) .replace("%%TEMPLATE_SUCCESS_MESSAGE%%", &sh_quote(&success_message)) - .replace( - "%%TEMPLATE_LEGACY_MANIFEST_DIRS%%", - &sh_quote(&self.legacy_manifest_dirs), - ) + .replace("%%TEMPLATE_LEGACY_MANIFEST_DIRS%%", &sh_quote(&self.legacy_manifest_dirs)) .replace( "%%TEMPLATE_RUST_INSTALLER_VERSION%%", &sh_quote(&crate::RUST_INSTALLER_VERSION), diff --git a/src/tools/rust-installer/src/tarballer.rs b/src/tools/rust-installer/src/tarballer.rs index c60d5f648ff..7572dc6dcf8 100644 --- a/src/tools/rust-installer/src/tarballer.rs +++ b/src/tools/rust-installer/src/tarballer.rs @@ -58,10 +58,7 @@ impl Tarballer { let buf = BufWriter::with_capacity(1024 * 1024, encoder); let mut builder = Builder::new(buf); - let pool = rayon::ThreadPoolBuilder::new() - .num_threads(2) - .build() - .unwrap(); + let pool = rayon::ThreadPoolBuilder::new().num_threads(2).build().unwrap(); pool.install(move || { for path in dirs { let src = Path::new(&self.work_dir).join(&path); @@ -122,11 +119,7 @@ where let name = name.as_ref(); if !name.is_relative() && !name.starts_with(root) { - bail!( - "input '{}' is not in work dir '{}'", - name.display(), - root.display() - ); + bail!("input '{}' is not in work dir '{}'", name.display(), root.display()); } let mut dirs = vec![]; diff --git a/src/tools/rust-installer/src/util.rs b/src/tools/rust-installer/src/util.rs index 4eb2e75fd7e..47ca0cfa3cc 100644 --- a/src/tools/rust-installer/src/util.rs +++ b/src/tools/rust-installer/src/util.rs @@ -15,8 +15,7 @@ use std::os::windows::fs::symlink_file; /// Converts a `&Path` to a UTF-8 `&str`. pub fn path_to_str(path: &Path) -> Result<&str> { - path.to_str() - .ok_or_else(|| format_err!("path is not valid UTF-8 '{}'", path.display())) + path.to_str().ok_or_else(|| format_err!("path is not valid UTF-8 '{}'", path.display())) } /// Wraps `fs::copy` with a nicer error message. @@ -27,11 +26,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<u64> { Ok(0) } else { let amt = fs::copy(&from, &to).with_context(|| { - format!( - "failed to copy '{}' to '{}'", - from.as_ref().display(), - to.as_ref().display() - ) + format!("failed to copy '{}' to '{}'", from.as_ref().display(), to.as_ref().display()) })?; Ok(amt) } @@ -123,8 +118,12 @@ where } macro_rules! actor_field_default { - () => { Default::default() }; - (= $expr:expr) => { $expr.into() } + () => { + Default::default() + }; + (= $expr:expr) => { + $expr.into() + }; } /// Creates an "actor" with default values, setters for all fields, and Clap parser support. diff --git a/src/tools/rust-installer/test.sh b/src/tools/rust-installer/test.sh index dac6f77ef14..4f69bfc63e9 100755 --- a/src/tools/rust-installer/test.sh +++ b/src/tools/rust-installer/test.sh @@ -27,7 +27,7 @@ PREFIX_DIR="$TMP_DIR/prefix" case $(uname -s) in MINGW* | MSYS*) - WINDOWS=1 + WINDOWS=1 ;; esac @@ -48,10 +48,10 @@ pre() { need_ok() { if [ $? -ne 0 ] then - echo - echo "TEST FAILED!" - echo - exit 1 + echo + echo "TEST FAILED!" + echo + exit 1 fi } @@ -69,20 +69,20 @@ try() { _cmd="$@" _output=`$@ 2>&1` if [ $? -ne 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -92,20 +92,20 @@ expect_fail() { _cmd="$@" _output=`$@ 2>&1` if [ $? -eq 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -117,30 +117,30 @@ expect_output_ok() { _cmd="$@" _output=`$@ 2>&1` if [ $? -ne 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 elif ! echo "$_output" | grep -q "$_expected"; then - echo \$ "$_cmd" - $ECHO "$_output" - echo - echo "missing expected output '$_expected'" - echo - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + $ECHO "$_output" + echo + echo "missing expected output '$_expected'" + echo + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -152,30 +152,30 @@ expect_output_fail() { _cmd="$@" _output=`$@ 2>&1` if [ $? -eq 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 elif ! echo "$_output" | grep -q "$_expected"; then - echo \$ "$_cmd" - $ECHO "$_output" - echo - echo "missing expected output '$_expected'" - echo - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + $ECHO "$_output" + echo + echo "missing expected output '$_expected'" + echo + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -187,30 +187,30 @@ expect_not_output_ok() { _cmd="$@" _output=`$@ 2>&1` if [ $? -ne 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 elif echo "$_output" | grep -q "$_expected"; then - echo \$ "$_cmd" - $ECHO "$_output" - echo - echo "unexpected output '$_expected'" - echo - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + $ECHO "$_output" + echo + echo "unexpected output '$_expected'" + echo + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -218,9 +218,9 @@ expect_not_output_ok() { runtest() { local _testname="$1" if [ -n "${TESTNAME-}" ]; then - if ! echo "$_testname" | grep -q "$TESTNAME"; then - return 0 - fi + if ! echo "$_testname" | grep -q "$TESTNAME"; then + return 0 + fi fi pre "$_testname" @@ -231,9 +231,9 @@ runtest() { basic_install() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -245,9 +245,9 @@ runtest basic_install basic_uninstall() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/package/install.sh --uninstall" --prefix="$PREFIX_DIR" try test ! -e "$PREFIX_DIR/something-to-install" @@ -263,10 +263,10 @@ not_installed_files() { mkdir -p "$WORK_DIR/overlay" touch "$WORK_DIR/overlay/not-installed" try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --non-installed-overlay="$WORK_DIR/overlay" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --non-installed-overlay="$WORK_DIR/overlay" try test -e "$WORK_DIR/package/not-installed" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test ! -e "$PREFIX_DIR/not-installed" @@ -275,10 +275,10 @@ runtest not_installed_files tarball_with_package_name() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc-nightly + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc-nightly try "$WORK_DIR/rustc-nightly/install.sh" --prefix="$PREFIX_DIR" try test -e "$OUT_DIR/rustc-nightly.tar.gz" try test -e "$OUT_DIR/rustc-nightly.tar.xz" @@ -287,9 +287,9 @@ runtest tarball_with_package_name install_overwrite_backup() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try mkdir -p "$PREFIX_DIR/bin" touch "$PREFIX_DIR/bin/program" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" @@ -300,10 +300,10 @@ runtest install_overwrite_backup bulk_directory() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -317,10 +317,10 @@ runtest bulk_directory bulk_directory_overwrite() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install try mkdir -p "$PREFIX_DIR/dir-to-install" try touch "$PREFIX_DIR/dir-to-install/overwrite" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" @@ -333,10 +333,10 @@ runtest bulk_directory_overwrite bulk_directory_overwrite_existing_backup() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install try mkdir -p "$PREFIX_DIR/dir-to-install" try touch "$PREFIX_DIR/dir-to-install/overwrite" # This time we've already got an existing backup of the overwritten directory. @@ -351,10 +351,10 @@ runtest bulk_directory_overwrite_existing_backup nested_bulk_directory() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install/qux + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install/qux try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/dir-to-install/qux/bar" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --uninstall @@ -364,10 +364,10 @@ runtest nested_bulk_directory only_bulk_directory_no_files() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image5" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install + --image-dir="$TEST_DIR/image5" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/dir-to-install/foo" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --uninstall @@ -379,10 +379,10 @@ nested_not_installed_files() { mkdir -p "$WORK_DIR/overlay" touch "$WORK_DIR/overlay/not-installed" try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --non-installed-overlay="$WORK_DIR/overlay" + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --non-installed-overlay="$WORK_DIR/overlay" try test -e "$WORK_DIR/package/not-installed" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test ! -e "$PREFIX_DIR/not-installed" @@ -391,15 +391,15 @@ runtest nested_not_installed_files multiple_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR/c1" \ - --output-dir="$OUT_DIR/c1" \ - --component-name=rustc + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR/c1" \ + --output-dir="$OUT_DIR/c1" \ + --component-name=rustc try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR/c2" \ - --output-dir="$OUT_DIR/c2" \ - --component-name=cargo + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR/c2" \ + --output-dir="$OUT_DIR/c2" \ + --component-name=cargo try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/c2/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" @@ -422,15 +422,15 @@ runtest multiple_components uninstall_from_installed_script() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR/c1" \ - --output-dir="$OUT_DIR/c1" \ - --component-name=rustc + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR/c1" \ + --output-dir="$OUT_DIR/c1" \ + --component-name=rustc try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR/c2" \ - --output-dir="$OUT_DIR/c2" \ - --component-name=cargo + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR/c2" \ + --output-dir="$OUT_DIR/c2" \ + --component-name=cargo try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/c2/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" @@ -453,12 +453,13 @@ runtest uninstall_from_installed_script uninstall_from_installed_script_with_args_fails() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR/c1" \ - --output-dir="$OUT_DIR/c1" \ - --component-name=rustc + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR/c1" \ + --output-dir="$OUT_DIR/c1" \ + --component-name=rustc try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" - expect_output_fail "uninstall.sh does not take any arguments" sh "$PREFIX_DIR/lib/packagelib/uninstall.sh" --prefix=foo + expect_output_fail "uninstall.sh does not take any arguments" \ + sh "$PREFIX_DIR/lib/packagelib/uninstall.sh" --prefix=foo } runtest uninstall_from_installed_script_with_args_fails @@ -466,22 +467,22 @@ runtest uninstall_from_installed_script_with_args_fails combine_installers() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -502,28 +503,28 @@ runtest combine_installers combine_three_installers() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -546,25 +547,25 @@ runtest combine_three_installers combine_installers_with_overlay() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo mkdir -p "$WORK_DIR/overlay" touch "$WORK_DIR/overlay/README" try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ - --non-installed-overlay="$WORK_DIR/overlay" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ + --non-installed-overlay="$WORK_DIR/overlay" try test -e "$WORK_DIR/rust/README" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test ! -e "$PREFIX_DIR/README" @@ -573,23 +574,23 @@ runtest combine_installers_with_overlay combined_with_bulk_dirs() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc \ - --bulk-dirs=dir-to-install - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc \ + --bulk-dirs=dir-to-install + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/dir-to-install/foo" try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" @@ -599,25 +600,25 @@ runtest combined_with_bulk_dirs combine_install_with_separate_uninstall() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc \ - --rel-manifest-dir=rustlib - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo \ - --rel-manifest-dir=rustlib + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc \ + --rel-manifest-dir=rustlib + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo \ + --rel-manifest-dir=rustlib try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ - --rel-manifest-dir=rustlib + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ + --rel-manifest-dir=rustlib try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -639,28 +640,28 @@ runtest combine_install_with_separate_uninstall select_components_to_install() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --components=rustc try test -e "$PREFIX_DIR/bin/program" try test ! -e "$PREFIX_DIR/bin/cargo" @@ -680,7 +681,8 @@ select_components_to_install() { try test -e "$PREFIX_DIR/bin/program" try test -e "$PREFIX_DIR/bin/cargo" try test ! -e "$PREFIX_DIR/baz" - try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --components=rustc,cargo,rust-docs + try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" \ + --components=rustc,cargo,rust-docs try test ! -e "$PREFIX_DIR/bin/program" try test ! -e "$PREFIX_DIR/bin/cargo" try test ! -e "$PREFIX_DIR/baz" @@ -690,28 +692,28 @@ runtest select_components_to_install select_components_to_uninstall() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --components=rustc try test ! -e "$PREFIX_DIR/bin/program" @@ -733,7 +735,8 @@ select_components_to_uninstall() { try test ! -e "$PREFIX_DIR/bin/cargo" try test -e "$PREFIX_DIR/baz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" - try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --components=rustc,cargo,rust-docs + try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" \ + --components=rustc,cargo,rust-docs try test ! -e "$PREFIX_DIR/bin/program" try test ! -e "$PREFIX_DIR/bin/cargo" try test ! -e "$PREFIX_DIR/baz" @@ -743,56 +746,57 @@ runtest select_components_to_uninstall invalid_component() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" - expect_output_fail "unknown component" "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --components=foo + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + expect_output_fail "unknown component" "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" \ + --components=foo } runtest invalid_component without_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --without=rust-docs try test -e "$PREFIX_DIR/bin/program" try test -e "$PREFIX_DIR/bin/cargo" @@ -815,28 +819,28 @@ runtest without_components # --without causes components to remain installed uninstall_without_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --without=rust-docs try test ! -e "$PREFIX_DIR/bin/program" @@ -857,88 +861,88 @@ runtest uninstall_without_components without_any_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" expect_output_fail "no components selected for installation" \ - "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --without=rust-docs,rustc,cargo + "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --without=rust-docs,rustc,cargo } runtest without_any_components uninstall_without_any_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" expect_output_fail "no components selected for uninstallation" \ - "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" \ - --uninstall --without=rust-docs,rustc,cargo + "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" \ + --uninstall --without=rust-docs,rustc,cargo } runtest uninstall_without_any_components list_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" expect_output_ok "rustc" "$WORK_DIR/rust/install.sh" --list-components expect_output_ok "cargo" "$WORK_DIR/rust/install.sh" --list-components expect_output_ok "rust-docs" "$WORK_DIR/rust/install.sh" --list-components @@ -947,32 +951,32 @@ runtest list_components combined_remains() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" for component in rustc cargo rust-docs; do - # rustbuild wants the original extracted package intact too - try test -d "$WORK_DIR/$component/$component" - try test -d "$WORK_DIR/rust/$component" + # rustbuild wants the original extracted package intact too + try test -d "$WORK_DIR/$component/$component" + try test -d "$WORK_DIR/rust/$component" done } runtest combined_remains @@ -982,34 +986,34 @@ runtest combined_remains cannot_write_error() { # chmod doesn't work on windows if [ ! -n "${WINDOWS-}" ]; then - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" - chmod u-w "$PREFIX_DIR" - expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" - chmod u+w "$PREFIX_DIR" + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" + chmod u-w "$PREFIX_DIR" + expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" + chmod u+w "$PREFIX_DIR" fi } runtest cannot_write_error cannot_install_to_installer() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=my-package + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=my-package expect_output_fail "cannot install to same directory as installer" \ - "$WORK_DIR/my-package/install.sh" --prefix="$WORK_DIR/my-package" + "$WORK_DIR/my-package/install.sh" --prefix="$WORK_DIR/my-package" } runtest cannot_install_to_installer upgrade_from_future_installer_error() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --rel-manifest-dir=rustlib + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --rel-manifest-dir=rustlib try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" echo 100 > "$PREFIX_DIR/lib/rustlib/rust-installer-version" expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" @@ -1018,9 +1022,9 @@ runtest upgrade_from_future_installer_error destdir() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --destdir="$PREFIX_DIR/" --prefix=prefix try test -e "$PREFIX_DIR/prefix/bin/program" } @@ -1028,9 +1032,9 @@ runtest destdir destdir_no_trailing_slash() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --destdir="$PREFIX_DIR" --prefix=prefix try test -e "$PREFIX_DIR/prefix/bin/program" } @@ -1055,7 +1059,7 @@ create_log() { try test -e "$PREFIX_DIR/lib/packagelib/install.log" local _log="$(cat "$PREFIX_DIR/lib/packagelib/install.log")" if [ -z "$_log" ]; then - fail "log is empty" + fail "log is empty" fi } runtest create_log @@ -1063,24 +1067,24 @@ runtest create_log leave_log_after_failure() { # chmod doesn't work on windows if [ ! -n "${WINDOWS-}" ]; then - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" - mkdir -p "$PREFIX_DIR/lib/packagelib" - touch "$PREFIX_DIR/lib/packagelib/components" - chmod u-w "$PREFIX_DIR/lib/packagelib/components" - expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" - chmod u+w "$PREFIX_DIR/lib/packagelib/components" - try test -e "$PREFIX_DIR/lib/packagelib/install.log" - local _log="$(cat "$PREFIX_DIR/lib/packagelib/install.log")" - if [ -z "$_log" ]; then - fail "log is empty" - fi - # script should tell user where the logs are - if ! grep -q "see logs at" "$PREFIX_DIR/lib/packagelib/install.log"; then - fail "missing log message" - fi + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" + mkdir -p "$PREFIX_DIR/lib/packagelib" + touch "$PREFIX_DIR/lib/packagelib/components" + chmod u-w "$PREFIX_DIR/lib/packagelib/components" + expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" + chmod u+w "$PREFIX_DIR/lib/packagelib/components" + try test -e "$PREFIX_DIR/lib/packagelib/install.log" + local _log="$(cat "$PREFIX_DIR/lib/packagelib/install.log")" + if [ -z "$_log" ]; then + fail "log is empty" + fi + # script should tell user where the logs are + if ! grep -q "see logs at" "$PREFIX_DIR/lib/packagelib/install.log"; then + fail "missing log message" + fi fi } runtest leave_log_after_failure @@ -1088,9 +1092,9 @@ runtest leave_log_after_failure # https://github.com/rust-lang/rust-installer/issues/22 help() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --help } runtest help @@ -1098,9 +1102,9 @@ runtest help # https://github.com/rust-lang/rust-installer/issues/31 CDPATH_does_not_destroy_things() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" cd "$WORK_DIR" || exit 1 export CDPATH="../$(basename $WORK_DIR)/foo" try sh "package/install.sh" --prefix="$PREFIX_DIR" @@ -1115,9 +1119,9 @@ runtest CDPATH_does_not_destroy_things docdir_default() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image-docdir1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image-docdir1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/share/doc/rust/README" try test -e "$PREFIX_DIR/share/doc/rust/rustdocs.txt" @@ -1126,9 +1130,9 @@ runtest docdir_default docdir() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image-docdir1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image-docdir1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try mkdir "$WORK_DIR/docdir" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --docdir="$WORK_DIR/docdir" try test -e "$WORK_DIR/docdir/README" @@ -1138,22 +1142,22 @@ runtest docdir docdir_combined() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image-docdir1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ + --image-dir="$TEST_DIR/image-docdir1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ --package-name="rustc" \ --component-name="rustc" try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image-docdir2" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ + --image-dir="$TEST_DIR/image-docdir2" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ --package-name="cargo" \ --component-name="cargo" try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" try mkdir "$WORK_DIR/docdir" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --docdir="$WORK_DIR/docdir" try test -e "$WORK_DIR/docdir/README" diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 197e9a9965f..64ba79dc185 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -95,17 +95,41 @@ mod os_impl { return true; } + // FIXME: check when rust-installer test sh files will be removed, + // and then remove them from exclude list + const RI_EXCLUSION_LIST: &[&str] = &[ + "src/tools/rust-installer/test/image1/bin/program", + "src/tools/rust-installer/test/image1/bin/program2", + "src/tools/rust-installer/test/image1/bin/bad-bin", + "src/tools/rust-installer/test/image2/bin/oldprogram", + "src/tools/rust-installer/test/image3/bin/cargo", + ]; + + fn filter_rust_installer_no_so_bins(path: &Path) -> bool { + RI_EXCLUSION_LIST.iter().any(|p| path.ends_with(p)) + } + #[cfg(unix)] pub fn check(path: &Path, bad: &mut bool) { use std::ffi::OsStr; const ALLOWED: &[&str] = &["configure", "x"]; + for p in RI_EXCLUSION_LIST { + if !path.join(Path::new(p)).exists() { + tidy_error!(bad, "rust-installer test bins missed: {p}"); + } + } + // FIXME: we don't need to look at all binaries, only files that have been modified in this branch // (e.g. using `git ls-files`). walk_no_read( &[path], - |path, _is_dir| filter_dirs(path) || path.ends_with("src/etc"), + |path, _is_dir| { + filter_dirs(path) + || path.ends_with("src/etc") + || filter_rust_installer_no_so_bins(path) + }, &mut |entry| { let file = entry.path(); let extension = file.extension(); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1f6c0b75a09..2c237c418b1 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -40,10 +40,12 @@ const EXCEPTIONS: &[(&str, &str)] = &[ ("ar_archive_writer", "Apache-2.0 WITH LLVM-exception"), // rustc ("colored", "MPL-2.0"), // rustfmt ("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps) + ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), // opt-dist ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations) ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target. FIXME: this dependency violates the documentation comment above. ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot ("mdbook", "MPL-2.0"), // mdbook + ("openssl", "Apache-2.0"), // opt-dist ("ryu", "Apache-2.0 OR BSL-1.0"), // cargo/... (because of serde) ("self_cell", "Apache-2.0"), // rustc (fluent translations) ("snap", "BSD-3-Clause"), // rustc @@ -131,6 +133,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "crossbeam-epoch", "crossbeam-utils", "crypto-common", + "cstr", "datafrog", "derive_more", "digest", @@ -141,6 +144,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "elsa", "ena", "equivalent", + "errno", + "errno-dragonfly", "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 6fd41e83362..62c070221dc 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -53,13 +53,9 @@ const EXCEPTION_PATHS: &[&str] = &[ // FIXME: platform-specific code should be moved to `sys` "library/std/src/io/copy.rs", "library/std/src/io/stdio.rs", - "library/std/src/f32.rs", - "library/std/src/f64.rs", "library/std/src/path.rs", "library/std/src/sys_common", // Should only contain abstractions over platforms "library/std/src/net/test.rs", // Utility helpers for tests - "library/std/src/personality.rs", - "library/std/src/personality/", ]; pub fn check(path: &Path, bad: &mut bool) { diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index 3539943ebef..185e1f3209b 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -4,6 +4,8 @@ use std::{ffi::OsStr, fs::File, io::Read, path::Path}; /// The default directory filter. pub fn filter_dirs(path: &Path) -> bool { + // FIXME: sync submodule exclusion list with rustfmt.toml + // bootstrap/etc let skip = [ "tidy-test-file", "compiler/rustc_codegen_cranelift", @@ -15,9 +17,7 @@ pub fn filter_dirs(path: &Path) -> bool { "src/tools/cargo", "src/tools/clippy", "src/tools/miri", - "src/tools/rls", "src/tools/rust-analyzer", - "src/tools/rust-installer", "src/tools/rustfmt", "src/doc/book", "src/doc/edition-guide", diff --git a/src/version b/src/version index 0834888f558..5e3a4256626 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.72.0 +1.73.0 diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs index 011a253c6ff..a7c9e4845c7 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -3,6 +3,7 @@ // ignore-macos slightly different policy on stack protection of arrays // ignore-windows stack check code uses different function names // ignore-nvptx64 stack protector is not supported +// ignore-wasm32-bare // [all] compile-flags: -Z stack-protector=all // [strong] compile-flags: -Z stack-protector=strong // [basic] compile-flags: -Z stack-protector=basic diff --git a/tests/assembly/wasm_exceptions.rs b/tests/assembly/wasm_exceptions.rs new file mode 100644 index 00000000000..b7d20881b62 --- /dev/null +++ b/tests/assembly/wasm_exceptions.rs @@ -0,0 +1,60 @@ +// only-wasm32-bare +// assembly-output: emit-asm +// compile-flags: -C target-feature=+exception-handling +// compile-flags: -C panic=unwind +// compile-flags: -C llvm-args=-wasm-enable-eh + +#![crate_type = "lib"] +#![feature(core_intrinsics)] +#![feature(rustc_attrs)] + +extern { + fn may_panic(); + + #[rustc_nounwind] + fn log_number(number: usize); +} + +struct LogOnDrop; + +impl Drop for LogOnDrop { + fn drop(&mut self) { + unsafe { log_number(0); } + } +} + +// CHECK-LABEL: test_cleanup: +#[no_mangle] +pub fn test_cleanup() { + let _log_on_drop = LogOnDrop; + unsafe { may_panic(); } + + // CHECK-NOT: call + // CHECK: try + // CHECK: call may_panic + // CHECK: catch_all + // CHECK: rethrow + // CHECK: end_try +} + +// CHECK-LABEL: test_rtry: +#[no_mangle] +pub fn test_rtry() { + unsafe { + core::intrinsics::r#try(|_| { + may_panic(); + }, core::ptr::null_mut(), |data, exception| { + log_number(data as usize); + log_number(exception as usize); + }); + } + + // CHECK-NOT: call + // CHECK: try + // CHECK: call may_panic + // CHECK: catch + // CHECK: call log_number + // CHECK: call log_number + // CHECK-NOT: rethrow + // CHECK: end_try +} diff --git a/tests/codegen/array-codegen.rs b/tests/codegen/array-codegen.rs index 98488eb92ee..71acd781549 100644 --- a/tests/codegen/array-codegen.rs +++ b/tests/codegen/array-codegen.rs @@ -6,10 +6,10 @@ // CHECK-LABEL: @array_load #[no_mangle] pub fn array_load(a: &[u8; 4]) -> [u8; 4] { - // CHECK: %0 = alloca [4 x i8], align 1 + // CHECK: %_0 = alloca [4 x i8], align 1 // CHECK: %[[TEMP1:.+]] = load <4 x i8>, ptr %a, align 1 - // CHECK: store <4 x i8> %[[TEMP1]], ptr %0, align 1 - // CHECK: %[[TEMP2:.+]] = load i32, ptr %0, align 1 + // CHECK: store <4 x i8> %[[TEMP1]], ptr %_0, align 1 + // CHECK: %[[TEMP2:.+]] = load i32, ptr %_0, align 1 // CHECK: ret i32 %[[TEMP2]] *a } diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index bc11e108124..83baae9e432 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -116,7 +116,7 @@ pub enum Either<T, U> { A(T), B(U) } // with the `ptr` field representing both `&i32` and `fn()` depending on the variant. // This is incorrect, because `fn()` should be `ptr addrspace(1)`, not `ptr`. -// CHECK: define{{.+}}void @should_not_combine_addrspace({{.+\*|ptr}}{{.+}}sret{{.+}}%0, {{.+\*|ptr}}{{.+}}%x) +// CHECK: define{{.+}}void @should_not_combine_addrspace({{.+\*|ptr}}{{.+}}sret{{.+}}%_0, {{.+\*|ptr}}{{.+}}%x) #[no_mangle] #[inline(never)] pub fn should_not_combine_addrspace(x: Either<&i32, fn()>) -> Either<&i32, fn()> { diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs index fc2badc417c..810da581ce9 100644 --- a/tests/codegen/consts.rs +++ b/tests/codegen/consts.rs @@ -1,4 +1,5 @@ // compile-flags: -C no-prepopulate-passes +// min-llvm-version: 15.0 (for opaque pointers) #![crate_type = "lib"] @@ -42,7 +43,7 @@ pub fn inline_enum_const() -> E<i8, i16> { #[no_mangle] pub fn low_align_const() -> E<i16, [i16; 3]> { // Check that low_align_const and high_align_const use the same constant - // CHECK: memcpy.{{.+}}({{i8\*|ptr}} align 2 %{{[0-9]+}}, {{i8\*|ptr}} align 2 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false) + // CHECK: memcpy.{{.+}}(ptr align 2 %_0, ptr align 2 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false) *&E::A(0) } @@ -50,6 +51,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> { #[no_mangle] pub fn high_align_const() -> E<i16, i32> { // Check that low_align_const and high_align_const use the same constant - // CHECK: memcpy.{{.+}}({{i8\*|ptr}} align 4 %{{[0-9]+}}, {{i8\*|ptr}} align 4 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false) + // CHECK: memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false) *&E::A(0) } diff --git a/tests/codegen/enum-match.rs b/tests/codegen/enum-match.rs index 36c6be19012..5548cd25147 100644 --- a/tests/codegen/enum-match.rs +++ b/tests/codegen/enum-match.rs @@ -15,7 +15,7 @@ pub enum Enum0 { // CHECK-NEXT: start: // CHECK-NEXT: %1 = icmp eq i8 %0, 2 // CHECK-NEXT: %2 = and i8 %0, 1 -// CHECK-NEXT: %.0 = select i1 %1, i8 13, i8 %2 +// CHECK-NEXT: %_0.0 = select i1 %1, i8 13, i8 %2 #[no_mangle] pub fn match0(e: Enum0) -> u8 { use Enum0::*; diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs index a09c795924c..df1080bff2b 100644 --- a/tests/codegen/fewer-names.rs +++ b/tests/codegen/fewer-names.rs @@ -13,8 +13,8 @@ pub fn sum(x: u32, y: u32) -> u32 { // NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y) // NO-NEXT: start: - // NO-NEXT: %0 = add i32 %y, %x - // NO-NEXT: ret i32 %0 + // NO-NEXT: %z = add i32 %y, %x + // NO-NEXT: ret i32 %z let z = x + y; z } diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs index 0c62e0d35e3..35f31eba3b1 100644 --- a/tests/codegen/function-arguments-noopt.rs +++ b/tests/codegen/function-arguments-noopt.rs @@ -42,7 +42,7 @@ pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 { f(x) } -// CHECK: void @struct_({{%S\*|ptr}} sret(%S){{( %0)?}}, {{%S\*|ptr}} %x) +// CHECK: void @struct_({{%S\*|ptr}} sret(%S){{( %_0)?}}, {{%S\*|ptr}} %x) #[no_mangle] pub fn struct_(x: S) -> S { x @@ -51,7 +51,7 @@ pub fn struct_(x: S) -> S { // CHECK-LABEL: @struct_call #[no_mangle] pub fn struct_call(x: S, f: fn(S) -> S) -> S { - // CHECK: call void %f({{%S\*|ptr}} sret(%S){{( %0)?}}, {{%S\*|ptr}} %{{.+}}) + // CHECK: call void %f({{%S\*|ptr}} sret(%S){{( %_0)?}}, {{%S\*|ptr}} %{{.+}}) f(x) } diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index d6f019016a5..ccf4a5de327 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -188,7 +188,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> { x } -// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) dereferenceable(32){{( %0)?}}) +// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) dereferenceable(32){{( %_0)?}}) #[no_mangle] pub fn struct_return() -> S { S { diff --git a/tests/codegen/intrinsics/transmute-niched.rs b/tests/codegen/intrinsics/transmute-niched.rs index 69e9b1d1206..fffc24a1181 100644 --- a/tests/codegen/intrinsics/transmute-niched.rs +++ b/tests/codegen/intrinsics/transmute-niched.rs @@ -169,16 +169,16 @@ pub unsafe fn check_bool_from_ordering(x: std::cmp::Ordering) -> bool { // CHECK-LABEL: @check_bool_to_ordering( #[no_mangle] pub unsafe fn check_bool_to_ordering(x: bool) -> std::cmp::Ordering { - // CHECK: %0 = zext i1 %x to i8 - // OPT: %1 = icmp ule i8 %0, 1 - // OPT: call void @llvm.assume(i1 %1) - // OPT: %2 = icmp uge i8 %0, -1 - // OPT: %3 = icmp ule i8 %0, 1 - // OPT: %4 = or i1 %2, %3 - // OPT: call void @llvm.assume(i1 %4) + // CHECK: %_0 = zext i1 %x to i8 + // OPT: %0 = icmp ule i8 %_0, 1 + // OPT: call void @llvm.assume(i1 %0) + // OPT: %1 = icmp uge i8 %_0, -1 + // OPT: %2 = icmp ule i8 %_0, 1 + // OPT: %3 = or i1 %1, %2 + // OPT: call void @llvm.assume(i1 %3) // DBG-NOT: icmp // DBG-NOT: assume - // CHECK: ret i8 %0 + // CHECK: ret i8 %_0 transmute(x) } diff --git a/tests/codegen/intrinsics/transmute-x64.rs b/tests/codegen/intrinsics/transmute-x64.rs index 99d258c6204..168838ef497 100644 --- a/tests/codegen/intrinsics/transmute-x64.rs +++ b/tests/codegen/intrinsics/transmute-x64.rs @@ -11,8 +11,8 @@ use std::mem::transmute; #[no_mangle] pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i { // CHECK-NOT: alloca - // CHECK: %1 = load <4 x float>, ptr %x, align 16 - // CHECK: store <4 x float> %1, ptr %0, align 16 + // CHECK: %0 = load <4 x float>, ptr %x, align 16 + // CHECK: store <4 x float> %0, ptr %_0, align 16 transmute(x) } @@ -20,8 +20,8 @@ pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i { #[no_mangle] pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i { // CHECK-NOT: alloca - // CHECK: %1 = load <4 x i64>, ptr %x, align 16 - // CHECK: store <4 x i64> %1, ptr %0, align 32 + // CHECK: %0 = load <4 x i64>, ptr %x, align 16 + // CHECK: store <4 x i64> %0, ptr %_0, align 32 transmute(x) } @@ -29,7 +29,7 @@ pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i { #[no_mangle] pub unsafe fn check_sse_pair_from_avx(x: __m256i) -> (__m128i, __m128i) { // CHECK-NOT: alloca - // CHECK: %1 = load <4 x i64>, ptr %x, align 32 - // CHECK: store <4 x i64> %1, ptr %0, align 16 + // CHECK: %0 = load <4 x i64>, ptr %x, align 32 + // CHECK: store <4 x i64> %0, ptr %_0, align 16 transmute(x) } diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index fe42494000e..f8c20960660 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -8,8 +8,8 @@ #![feature(inline_const)] #![allow(unreachable_code)] -use std::mem::MaybeUninit; use std::intrinsics::{transmute, transmute_unchecked}; +use std::mem::MaybeUninit; // Some of these need custom MIR to not get removed by MIR optimizations. use std::intrinsics::mir::*; @@ -63,7 +63,7 @@ pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] { // CHECK-NOT: trap // CHECK: call void @llvm.trap // CHECK-NOT: trap - mir!{ + mir! { { RET = CastTransmute(x); Return() @@ -78,7 +78,7 @@ pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] { // CHECK-NOT: trap // CHECK: call void @llvm.trap // CHECK-NOT: trap - mir!{ + mir! { { RET = CastTransmute(x); Return() @@ -93,7 +93,7 @@ pub unsafe fn check_to_uninhabited(x: u16) { // CHECK-NOT: trap // CHECK: call void @llvm.trap // CHECK-NOT: trap - mir!{ + mir! { let temp: BigNever; { temp = CastTransmute(x); @@ -107,7 +107,7 @@ pub unsafe fn check_to_uninhabited(x: u16) { #[custom_mir(dialect = "runtime", phase = "optimized")] pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 { // CHECK: ret i16 poison - mir!{ + mir! { { RET = CastTransmute(x); Return() @@ -122,9 +122,7 @@ pub unsafe fn check_intermediate_passthrough(x: u32) -> i32 { // CHECK: %[[TMP:.+]] = add i32 1, %x // CHECK: %[[RET:.+]] = add i32 %[[TMP]], 1 // CHECK: ret i32 %[[RET]] - unsafe { - transmute::<u32, i32>(1 + x) + 1 - } + unsafe { transmute::<u32, i32>(1 + x) + 1 } } // CHECK-LABEL: @check_nop_pair( @@ -134,9 +132,7 @@ pub unsafe fn check_nop_pair(x: (u8, i8)) -> (i8, u8) { // CHECK: %0 = insertvalue { i8, i8 } poison, i8 %x.0, 0 // CHECK: %1 = insertvalue { i8, i8 } %0, i8 %x.1, 1 // CHECK: ret { i8, i8 } %1 - unsafe { - transmute(x) - } + unsafe { transmute(x) } } // CHECK-LABEL: @check_to_newtype( @@ -168,9 +164,9 @@ pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool { // CHECK-LABEL: @check_aggregate_from_bool( #[no_mangle] pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 { - // CHECK: %0 = alloca %Aggregate8, align 1 + // CHECK: %_0 = alloca %Aggregate8, align 1 // CHECK: %[[BYTE:.+]] = zext i1 %x to i8 - // CHECK: store i8 %[[BYTE]], ptr %0, align 1 + // CHECK: store i8 %[[BYTE]], ptr %_0, align 1 transmute(x) } @@ -195,8 +191,8 @@ pub unsafe fn check_byte_from_bool(x: bool) -> u8 { // CHECK-LABEL: @check_to_pair( #[no_mangle] pub unsafe fn check_to_pair(x: u64) -> Option<i32> { - // CHECK: %0 = alloca { i32, i32 }, align 4 - // CHECK: store i64 %x, ptr %0, align 4 + // CHECK: %_0 = alloca { i32, i32 }, align 4 + // CHECK: store i64 %x, ptr %_0, align 4 transmute(x) } @@ -207,11 +203,11 @@ pub unsafe fn check_from_pair(x: Option<i32>) -> u64 { // immediates so we can write using the destination alloca's alignment. const { assert!(std::mem::align_of::<Option<i32>>() == 4) }; - // CHECK: %0 = alloca i64, align 8 - // CHECK: store i32 %x.0, ptr %1, align 8 - // CHECK: store i32 %x.1, ptr %2, align 4 - // CHECK: %3 = load i64, ptr %0, align 8 - // CHECK: ret i64 %3 + // CHECK: %_0 = alloca i64, align 8 + // CHECK: store i32 %x.0, ptr %0, align 8 + // CHECK: store i32 %x.1, ptr %1, align 4 + // CHECK: %2 = load i64, ptr %_0, align 8 + // CHECK: ret i64 %2 transmute(x) } @@ -219,8 +215,8 @@ pub unsafe fn check_from_pair(x: Option<i32>) -> u64 { #[no_mangle] pub unsafe fn check_to_float(x: u32) -> f32 { // CHECK-NOT: alloca - // CHECK: %0 = bitcast i32 %x to float - // CHECK: ret float %0 + // CHECK: %_0 = bitcast i32 %x to float + // CHECK: ret float %_0 transmute(x) } @@ -228,16 +224,16 @@ pub unsafe fn check_to_float(x: u32) -> f32 { #[no_mangle] pub unsafe fn check_from_float(x: f32) -> u32 { // CHECK-NOT: alloca - // CHECK: %0 = bitcast float %x to i32 - // CHECK: ret i32 %0 + // CHECK: %_0 = bitcast float %x to i32 + // CHECK: ret i32 %_0 transmute(x) } // CHECK-LABEL: @check_to_bytes( #[no_mangle] pub unsafe fn check_to_bytes(x: u32) -> [u8; 4] { - // CHECK: %0 = alloca [4 x i8], align 1 - // CHECK: store i32 %x, ptr %0, align 1 + // CHECK: %_0 = alloca [4 x i8], align 1 + // CHECK: store i32 %x, ptr %_0, align 1 transmute(x) } @@ -253,10 +249,10 @@ pub unsafe fn check_from_bytes(x: [u8; 4]) -> u32 { // CHECK-LABEL: @check_to_aggregate( #[no_mangle] pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 { - // CHECK: %0 = alloca %Aggregate64, align 4 - // CHECK: store i64 %x, ptr %0, align 4 - // CHECK: %1 = load i64, ptr %0, align 4 - // CHECK: ret i64 %1 + // CHECK: %_0 = alloca %Aggregate64, align 4 + // CHECK: store i64 %x, ptr %_0, align 4 + // CHECK: %0 = load i64, ptr %_0, align 4 + // CHECK: ret i64 %0 transmute(x) } @@ -273,7 +269,7 @@ pub unsafe fn check_from_aggregate(x: Aggregate64) -> u64 { #[no_mangle] pub unsafe fn check_long_array_less_aligned(x: [u64; 100]) -> [u16; 400] { // CHECK-NEXT: start - // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 %0, ptr align 8 %x, i64 800, i1 false) + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 %_0, ptr align 8 %x, i64 800, i1 false) // CHECK-NEXT: ret void transmute(x) } @@ -282,7 +278,7 @@ pub unsafe fn check_long_array_less_aligned(x: [u64; 100]) -> [u16; 400] { #[no_mangle] pub unsafe fn check_long_array_more_aligned(x: [u8; 100]) -> [u32; 25] { // CHECK-NEXT: start - // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %0, ptr align 1 %x, i64 100, i1 false) + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %_0, ptr align 1 %x, i64 100, i1 false) // CHECK-NEXT: ret void transmute(x) } @@ -301,8 +297,8 @@ pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) { pub unsafe fn check_float_to_pointer(x: f64) -> *const () { // CHECK-NOT: alloca // CHECK: %0 = bitcast double %x to i64 - // CHECK: %1 = inttoptr i64 %0 to ptr - // CHECK: ret ptr %1 + // CHECK: %_0 = inttoptr i64 %0 to ptr + // CHECK: ret ptr %_0 transmute(x) } @@ -311,8 +307,8 @@ pub unsafe fn check_float_to_pointer(x: f64) -> *const () { pub unsafe fn check_float_from_pointer(x: *const ()) -> f64 { // CHECK-NOT: alloca // CHECK: %0 = ptrtoint ptr %x to i64 - // CHECK: %1 = bitcast i64 %0 to double - // CHECK: ret double %1 + // CHECK: %_0 = bitcast i64 %0 to double + // CHECK: ret double %_0 transmute(x) } @@ -376,10 +372,10 @@ pub unsafe fn check_issue_110005(x: (usize, bool)) -> Option<Box<[u8]>> { // CHECK-LABEL: @check_pair_to_dst_ref( #[no_mangle] pub unsafe fn check_pair_to_dst_ref<'a>(x: (usize, usize)) -> &'a [u8] { - // CHECK: %0 = inttoptr i64 %x.0 to ptr - // CHECK: %1 = insertvalue { ptr, i64 } poison, ptr %0, 0 - // CHECK: %2 = insertvalue { ptr, i64 } %1, i64 %x.1, 1 - // CHECK: ret { ptr, i64 } %2 + // CHECK: %_0.0 = inttoptr i64 %x.0 to ptr + // CHECK: %0 = insertvalue { ptr, i64 } poison, ptr %_0.0, 0 + // CHECK: %1 = insertvalue { ptr, i64 } %0, i64 %x.1, 1 + // CHECK: ret { ptr, i64 } %1 transmute(x) } @@ -391,7 +387,7 @@ pub unsafe fn check_issue_109992(x: ()) -> [(); 1] { // CHECK: start // CHECK-NEXT: ret void - mir!{ + mir! { { RET = CastTransmute(x); Return() @@ -408,7 +404,7 @@ pub unsafe fn check_unit_to_never(x: ()) { // CHECK-NOT: trap // CHECK: call void @llvm.trap // CHECK-NOT: trap - mir!{ + mir! { let temp: ZstNever; { temp = CastTransmute(x); @@ -425,7 +421,7 @@ pub unsafe fn check_unit_from_never(x: ZstNever) -> () { // CHECK: start // CHECK-NEXT: ret void - mir!{ + mir! { { RET = CastTransmute(x); Return() @@ -457,10 +453,10 @@ pub struct HighAlignScalar(u8); // CHECK-LABEL: @check_to_overalign( #[no_mangle] pub unsafe fn check_to_overalign(x: u64) -> HighAlignScalar { - // CHECK: %0 = alloca %HighAlignScalar, align 8 - // CHECK: store i64 %x, ptr %0, align 8 - // CHECK: %1 = load i64, ptr %0, align 8 - // CHECK: ret i64 %1 + // CHECK: %_0 = alloca %HighAlignScalar, align 8 + // CHECK: store i64 %x, ptr %_0, align 8 + // CHECK: %0 = load i64, ptr %_0, align 8 + // CHECK: ret i64 %0 transmute(x) } diff --git a/tests/codegen/match-optimized.rs b/tests/codegen/match-optimized.rs index 520c46a0d57..59e6eeb7c5d 100644 --- a/tests/codegen/match-optimized.rs +++ b/tests/codegen/match-optimized.rs @@ -20,13 +20,13 @@ pub fn exhaustive_match(e: E) -> u8 { // CHECK-NEXT: unreachable // // CHECK: [[A]]: -// CHECK-NEXT: store i8 0, {{i8\*|ptr}} %1, align 1 +// CHECK-NEXT: store i8 0, {{i8\*|ptr}} %_0, align 1 // CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]] // CHECK: [[B]]: -// CHECK-NEXT: store i8 1, {{i8\*|ptr}} %1, align 1 +// CHECK-NEXT: store i8 1, {{i8\*|ptr}} %_0, align 1 // CHECK-NEXT: br label %[[EXIT]] // CHECK: [[C]]: -// CHECK-NEXT: store i8 2, {{i8\*|ptr}} %1, align 1 +// CHECK-NEXT: store i8 2, {{i8\*|ptr}} %_0, align 1 // CHECK-NEXT: br label %[[EXIT]] match e { E::A => 0, diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs index c6b920cf599..55c2741faaf 100644 --- a/tests/codegen/mem-replace-big-type.rs +++ b/tests/codegen/mem-replace-big-type.rs @@ -25,7 +25,7 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big { // For a large type, we expect exactly three `memcpy`s // CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big) // CHECK-NOT: call void @llvm.memcpy -// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %0, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false) +// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %result, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false) // CHECK-NOT: call void @llvm.memcpy // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %dest, {{i8\*|ptr}} align 8 %src, i{{.*}} 56, i1 false) // CHECK-NOT: call void @llvm.memcpy diff --git a/tests/codegen/mem-replace-simple-type.rs b/tests/codegen/mem-replace-simple-type.rs index 6151177de15..5c4acf813ea 100644 --- a/tests/codegen/mem-replace-simple-type.rs +++ b/tests/codegen/mem-replace-simple-type.rs @@ -38,7 +38,7 @@ pub fn replace_ref_str<'a>(r: &mut &'a str, v: &'a str) -> &'a str { pub fn replace_short_array(r: &mut [u32; 3], v: [u32; 3]) -> [u32; 3] { // CHECK-NOT: alloca // CHECK: %[[R:.+]] = load <3 x i32>, ptr %r, align 4 - // CHECK: store <3 x i32> %[[R]], ptr %0 + // CHECK: store <3 x i32> %[[R]], ptr %result // CHECK: %[[V:.+]] = load <3 x i32>, ptr %v, align 4 // CHECK: store <3 x i32> %[[V]], ptr %r std::mem::replace(r, v) diff --git a/tests/codegen/repeat-trusted-len.rs b/tests/codegen/repeat-trusted-len.rs index 87c8fe1354d..d06978f2435 100644 --- a/tests/codegen/repeat-trusted-len.rs +++ b/tests/codegen/repeat-trusted-len.rs @@ -8,13 +8,13 @@ use std::iter; // CHECK-LABEL: @repeat_take_collect #[no_mangle] pub fn repeat_take_collect() -> Vec<u8> { -// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{[0-9]+}}, i8 42, i{{[0-9]+}} 100000, i1 false) + // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{.*}}, i8 42, i{{[0-9]+}} 100000, i1 false) iter::repeat(42).take(100000).collect() } // CHECK-LABEL: @repeat_with_take_collect #[no_mangle] pub fn repeat_with_take_collect() -> Vec<u8> { -// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{[0-9]+}}, i8 13, i{{[0-9]+}} 12345, i1 false) + // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{.*}}, i8 13, i{{[0-9]+}} 12345, i1 false) iter::repeat_with(|| 13).take(12345).collect() } diff --git a/tests/codegen/repr-transparent-aggregates-1.rs b/tests/codegen/repr-transparent-aggregates-1.rs index 9c4b0e58e71..ba3ba272efb 100644 --- a/tests/codegen/repr-transparent-aggregates-1.rs +++ b/tests/codegen/repr-transparent-aggregates-1.rs @@ -11,6 +11,7 @@ // ignore-s390x // ignore-windows // ignore-loongarch64 +// ignore-wasm32-bare // See repr-transparent.rs #![feature(transparent_unions)] diff --git a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs index 045f01985a5..ec18fa9a328 100644 --- a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs +++ b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs @@ -152,7 +152,7 @@ pub extern "C" fn f_scalar_stack_1( ) { } -// CHECK: define void @f_scalar_stack_2({{%Large\*|ptr}} {{.*}}sret{{.*}} %0, i64 noundef %a, i128 %1, i128 %2, i64 noundef %d, i8 noundef zeroext %e, i8 noundef %f, i8 noundef %g) +// CHECK: define void @f_scalar_stack_2({{%Large\*|ptr}} {{.*}}sret{{.*}} %_0, i64 noundef %a, i128 %0, i128 %1, i64 noundef %d, i8 noundef zeroext %e, i8 noundef %f, i8 noundef %g) #[no_mangle] pub extern "C" fn f_scalar_stack_2( a: u64, diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs index faac7566a0c..0bcfacec6d7 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs @@ -116,150 +116,150 @@ extern "platform-intrinsic" { fn simd_saturating_sub<T>(x: T, y: T) -> T; } -// NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM) +// NOTE(eddyb) `%{{x|0}}` is used because on some targets (e.g. WASM) // SIMD vectors are passed directly, resulting in `%x` being a vector, // while on others they're passed indirectly, resulting in `%x` being -// a pointer to a vector, and `%1` a vector loaded from that pointer. +// a pointer to a vector, and `%0` a vector loaded from that pointer. // This is controlled by the target spec option `simd_types_indirect`. -// The same applies to `%{{y|2}}` as well. +// The same applies to `%{{y|1}}` as well. // CHECK-LABEL: @sadd_i8x2 #[no_mangle] pub unsafe fn sadd_i8x2(x: i8x2, y: i8x2) -> i8x2 { - // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{x|0}}, <2 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x4 #[no_mangle] pub unsafe fn sadd_i8x4(x: i8x4, y: i8x4) -> i8x4 { - // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{x|0}}, <4 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x8 #[no_mangle] pub unsafe fn sadd_i8x8(x: i8x8, y: i8x8) -> i8x8 { - // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{x|0}}, <8 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x16 #[no_mangle] pub unsafe fn sadd_i8x16(x: i8x16, y: i8x16) -> i8x16 { - // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{x|0}}, <16 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x32 #[no_mangle] pub unsafe fn sadd_i8x32(x: i8x32, y: i8x32) -> i8x32 { - // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{x|0}}, <32 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x64 #[no_mangle] pub unsafe fn sadd_i8x64(x: i8x64, y: i8x64) -> i8x64 { - // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{x|0}}, <64 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x2 #[no_mangle] pub unsafe fn sadd_i16x2(x: i16x2, y: i16x2) -> i16x2 { - // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{x|0}}, <2 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x4 #[no_mangle] pub unsafe fn sadd_i16x4(x: i16x4, y: i16x4) -> i16x4 { - // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{x|0}}, <4 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x8 #[no_mangle] pub unsafe fn sadd_i16x8(x: i16x8, y: i16x8) -> i16x8 { - // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{x|0}}, <8 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x16 #[no_mangle] pub unsafe fn sadd_i16x16(x: i16x16, y: i16x16) -> i16x16 { - // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{x|0}}, <16 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x32 #[no_mangle] pub unsafe fn sadd_i16x32(x: i16x32, y: i16x32) -> i16x32 { - // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{x|0}}, <32 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i32x2 #[no_mangle] pub unsafe fn sadd_i32x2(x: i32x2, y: i32x2) -> i32x2 { - // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{x|0}}, <2 x i32> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i32x4 #[no_mangle] pub unsafe fn sadd_i32x4(x: i32x4, y: i32x4) -> i32x4 { - // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{x|0}}, <4 x i32> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i32x8 #[no_mangle] pub unsafe fn sadd_i32x8(x: i32x8, y: i32x8) -> i32x8 { - // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{x|0}}, <8 x i32> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i32x16 #[no_mangle] pub unsafe fn sadd_i32x16(x: i32x16, y: i32x16) -> i32x16 { - // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{x|0}}, <16 x i32> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i64x2 #[no_mangle] pub unsafe fn sadd_i64x2(x: i64x2, y: i64x2) -> i64x2 { - // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{x|0}}, <2 x i64> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i64x4 #[no_mangle] pub unsafe fn sadd_i64x4(x: i64x4, y: i64x4) -> i64x4 { - // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{x|0}}, <4 x i64> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i64x8 #[no_mangle] pub unsafe fn sadd_i64x8(x: i64x8, y: i64x8) -> i64x8 { - // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{x|0}}, <8 x i64> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i128x2 #[no_mangle] pub unsafe fn sadd_i128x2(x: i128x2, y: i128x2) -> i128x2 { - // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{x|0}}, <2 x i128> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i128x4 #[no_mangle] pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 { - // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{x|0}}, <4 x i128> %{{y|1}}) simd_saturating_add(x, y) } @@ -268,140 +268,140 @@ pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 { // CHECK-LABEL: @uadd_u8x2 #[no_mangle] pub unsafe fn uadd_u8x2(x: u8x2, y: u8x2) -> u8x2 { - // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{x|0}}, <2 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x4 #[no_mangle] pub unsafe fn uadd_u8x4(x: u8x4, y: u8x4) -> u8x4 { - // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{x|0}}, <4 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x8 #[no_mangle] pub unsafe fn uadd_u8x8(x: u8x8, y: u8x8) -> u8x8 { - // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{x|0}}, <8 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x16 #[no_mangle] pub unsafe fn uadd_u8x16(x: u8x16, y: u8x16) -> u8x16 { - // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{x|0}}, <16 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x32 #[no_mangle] pub unsafe fn uadd_u8x32(x: u8x32, y: u8x32) -> u8x32 { - // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{x|0}}, <32 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x64 #[no_mangle] pub unsafe fn uadd_u8x64(x: u8x64, y: u8x64) -> u8x64 { - // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{x|0}}, <64 x i8> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x2 #[no_mangle] pub unsafe fn uadd_u16x2(x: u16x2, y: u16x2) -> u16x2 { - // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{x|0}}, <2 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x4 #[no_mangle] pub unsafe fn uadd_u16x4(x: u16x4, y: u16x4) -> u16x4 { - // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{x|0}}, <4 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x8 #[no_mangle] pub unsafe fn uadd_u16x8(x: u16x8, y: u16x8) -> u16x8 { - // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{x|0}}, <8 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x16 #[no_mangle] pub unsafe fn uadd_u16x16(x: u16x16, y: u16x16) -> u16x16 { - // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{x|0}}, <16 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x32 #[no_mangle] pub unsafe fn uadd_u16x32(x: u16x32, y: u16x32) -> u16x32 { - // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{x|0}}, <32 x i16> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u32x2 #[no_mangle] pub unsafe fn uadd_u32x2(x: u32x2, y: u32x2) -> u32x2 { - // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{x|0}}, <2 x i32> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u32x4 #[no_mangle] pub unsafe fn uadd_u32x4(x: u32x4, y: u32x4) -> u32x4 { - // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{x|0}}, <4 x i32> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u32x8 #[no_mangle] pub unsafe fn uadd_u32x8(x: u32x8, y: u32x8) -> u32x8 { - // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{x|0}}, <8 x i32> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u32x16 #[no_mangle] pub unsafe fn uadd_u32x16(x: u32x16, y: u32x16) -> u32x16 { - // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{x|0}}, <16 x i32> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u64x2 #[no_mangle] pub unsafe fn uadd_u64x2(x: u64x2, y: u64x2) -> u64x2 { - // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{x|0}}, <2 x i64> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u64x4 #[no_mangle] pub unsafe fn uadd_u64x4(x: u64x4, y: u64x4) -> u64x4 { - // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{x|0}}, <4 x i64> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u64x8 #[no_mangle] pub unsafe fn uadd_u64x8(x: u64x8, y: u64x8) -> u64x8 { - // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{x|0}}, <8 x i64> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u128x2 #[no_mangle] pub unsafe fn uadd_u128x2(x: u128x2, y: u128x2) -> u128x2 { - // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{x|0}}, <2 x i128> %{{y|1}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u128x4 #[no_mangle] pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 { - // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{x|0}}, <4 x i128> %{{y|1}}) simd_saturating_add(x, y) } @@ -412,140 +412,140 @@ pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 { // CHECK-LABEL: @ssub_i8x2 #[no_mangle] pub unsafe fn ssub_i8x2(x: i8x2, y: i8x2) -> i8x2 { - // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{x|0}}, <2 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x4 #[no_mangle] pub unsafe fn ssub_i8x4(x: i8x4, y: i8x4) -> i8x4 { - // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{x|0}}, <4 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x8 #[no_mangle] pub unsafe fn ssub_i8x8(x: i8x8, y: i8x8) -> i8x8 { - // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{x|0}}, <8 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x16 #[no_mangle] pub unsafe fn ssub_i8x16(x: i8x16, y: i8x16) -> i8x16 { - // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{x|0}}, <16 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x32 #[no_mangle] pub unsafe fn ssub_i8x32(x: i8x32, y: i8x32) -> i8x32 { - // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{x|0}}, <32 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x64 #[no_mangle] pub unsafe fn ssub_i8x64(x: i8x64, y: i8x64) -> i8x64 { - // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{x|0}}, <64 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x2 #[no_mangle] pub unsafe fn ssub_i16x2(x: i16x2, y: i16x2) -> i16x2 { - // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{x|0}}, <2 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x4 #[no_mangle] pub unsafe fn ssub_i16x4(x: i16x4, y: i16x4) -> i16x4 { - // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{x|0}}, <4 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x8 #[no_mangle] pub unsafe fn ssub_i16x8(x: i16x8, y: i16x8) -> i16x8 { - // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{x|0}}, <8 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x16 #[no_mangle] pub unsafe fn ssub_i16x16(x: i16x16, y: i16x16) -> i16x16 { - // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{x|0}}, <16 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x32 #[no_mangle] pub unsafe fn ssub_i16x32(x: i16x32, y: i16x32) -> i16x32 { - // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{x|0}}, <32 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i32x2 #[no_mangle] pub unsafe fn ssub_i32x2(x: i32x2, y: i32x2) -> i32x2 { - // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{x|0}}, <2 x i32> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i32x4 #[no_mangle] pub unsafe fn ssub_i32x4(x: i32x4, y: i32x4) -> i32x4 { - // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{x|0}}, <4 x i32> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i32x8 #[no_mangle] pub unsafe fn ssub_i32x8(x: i32x8, y: i32x8) -> i32x8 { - // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{x|0}}, <8 x i32> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i32x16 #[no_mangle] pub unsafe fn ssub_i32x16(x: i32x16, y: i32x16) -> i32x16 { - // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{x|0}}, <16 x i32> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i64x2 #[no_mangle] pub unsafe fn ssub_i64x2(x: i64x2, y: i64x2) -> i64x2 { - // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{x|0}}, <2 x i64> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i64x4 #[no_mangle] pub unsafe fn ssub_i64x4(x: i64x4, y: i64x4) -> i64x4 { - // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{x|0}}, <4 x i64> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i64x8 #[no_mangle] pub unsafe fn ssub_i64x8(x: i64x8, y: i64x8) -> i64x8 { - // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{x|0}}, <8 x i64> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i128x2 #[no_mangle] pub unsafe fn ssub_i128x2(x: i128x2, y: i128x2) -> i128x2 { - // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{x|0}}, <2 x i128> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i128x4 #[no_mangle] pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 { - // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{x|0}}, <4 x i128> %{{y|1}}) simd_saturating_sub(x, y) } @@ -554,139 +554,139 @@ pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 { // CHECK-LABEL: @usub_u8x2 #[no_mangle] pub unsafe fn usub_u8x2(x: u8x2, y: u8x2) -> u8x2 { - // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{x|0}}, <2 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x4 #[no_mangle] pub unsafe fn usub_u8x4(x: u8x4, y: u8x4) -> u8x4 { - // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{x|0}}, <4 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x8 #[no_mangle] pub unsafe fn usub_u8x8(x: u8x8, y: u8x8) -> u8x8 { - // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{x|0}}, <8 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x16 #[no_mangle] pub unsafe fn usub_u8x16(x: u8x16, y: u8x16) -> u8x16 { - // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{x|0}}, <16 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x32 #[no_mangle] pub unsafe fn usub_u8x32(x: u8x32, y: u8x32) -> u8x32 { - // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{x|0}}, <32 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x64 #[no_mangle] pub unsafe fn usub_u8x64(x: u8x64, y: u8x64) -> u8x64 { - // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{x|0}}, <64 x i8> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x2 #[no_mangle] pub unsafe fn usub_u16x2(x: u16x2, y: u16x2) -> u16x2 { - // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{x|0}}, <2 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x4 #[no_mangle] pub unsafe fn usub_u16x4(x: u16x4, y: u16x4) -> u16x4 { - // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{x|0}}, <4 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x8 #[no_mangle] pub unsafe fn usub_u16x8(x: u16x8, y: u16x8) -> u16x8 { - // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{x|0}}, <8 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x16 #[no_mangle] pub unsafe fn usub_u16x16(x: u16x16, y: u16x16) -> u16x16 { - // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{x|0}}, <16 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x32 #[no_mangle] pub unsafe fn usub_u16x32(x: u16x32, y: u16x32) -> u16x32 { - // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{x|0}}, <32 x i16> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u32x2 #[no_mangle] pub unsafe fn usub_u32x2(x: u32x2, y: u32x2) -> u32x2 { - // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{x|0}}, <2 x i32> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u32x4 #[no_mangle] pub unsafe fn usub_u32x4(x: u32x4, y: u32x4) -> u32x4 { - // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{x|0}}, <4 x i32> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u32x8 #[no_mangle] pub unsafe fn usub_u32x8(x: u32x8, y: u32x8) -> u32x8 { - // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{x|0}}, <8 x i32> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u32x16 #[no_mangle] pub unsafe fn usub_u32x16(x: u32x16, y: u32x16) -> u32x16 { - // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{x|0}}, <16 x i32> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u64x2 #[no_mangle] pub unsafe fn usub_u64x2(x: u64x2, y: u64x2) -> u64x2 { - // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{x|0}}, <2 x i64> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u64x4 #[no_mangle] pub unsafe fn usub_u64x4(x: u64x4, y: u64x4) -> u64x4 { - // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{x|0}}, <4 x i64> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u64x8 #[no_mangle] pub unsafe fn usub_u64x8(x: u64x8, y: u64x8) -> u64x8 { - // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{x|0}}, <8 x i64> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u128x2 #[no_mangle] pub unsafe fn usub_u128x2(x: u128x2, y: u128x2) -> u128x2 { - // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{x|0}}, <2 x i128> %{{y|1}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u128x4 #[no_mangle] pub unsafe fn usub_u128x4(x: u128x4, y: u128x4) -> u128x4 { - // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{x|0}}, <4 x i128> %{{y|1}}) simd_saturating_sub(x, y) } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs index 80583dec195..a5d2509d000 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs @@ -35,13 +35,13 @@ pub unsafe fn extract_s(v: S<4>, i: u32) -> f32 { // CHECK-LABEL: @insert_m #[no_mangle] pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M { - // CHECK: insertelement <4 x float> %{{v|1|2}}, float %j, i32 %i + // CHECK: insertelement <4 x float> %{{v|0|1}}, float %j, i32 %i simd_insert(v, i, j) } // CHECK-LABEL: @insert_s #[no_mangle] pub unsafe fn insert_s(v: S<4>, i: u32, j: f32) -> S<4> { - // CHECK: insertelement <4 x float> %{{v|1|2}}, float %j, i32 %i + // CHECK: insertelement <4 x float> %{{v|0|1}}, float %j, i32 %i simd_insert(v, i, j) } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index fd488a14bd3..3a0e37de2f3 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -2,7 +2,6 @@ // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] - #![allow(non_camel_case_types)] #![feature(repr_simd, platform_intrinsics)] #![feature(inline_const)] @@ -44,7 +43,7 @@ pub fn build_array_s(x: [f32; 4]) -> S<4> { #[no_mangle] pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> { // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]] + // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %_0|.+>\* %.+}}, align [[VECTOR_ALIGN]] unsafe { std::mem::transmute(x) } } @@ -59,7 +58,7 @@ pub fn build_array_t(x: [f32; 4]) -> T { #[no_mangle] pub fn build_array_transmute_t(x: [f32; 4]) -> T { // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]] + // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %_0|.+>\* %.+}}, align [[VECTOR_ALIGN]] unsafe { std::mem::transmute(x) } } @@ -78,6 +77,6 @@ pub fn build_array_u(x: [f32; 4]) -> U { #[no_mangle] pub fn build_array_transmute_u(x: [f32; 4]) -> U { // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]] + // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %_0|.+>\* %.+}}, align [[VECTOR_ALIGN]] unsafe { std::mem::transmute(x) } } diff --git a/tests/codegen/simd_arith_offset.rs b/tests/codegen/simd_arith_offset.rs index f2333777391..74d7edc70d7 100644 --- a/tests/codegen/simd_arith_offset.rs +++ b/tests/codegen/simd_arith_offset.rs @@ -21,6 +21,6 @@ pub struct Simd<T, const LANES: usize>([T; LANES]); // CHECK-LABEL: smoke #[no_mangle] pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> { - // CHECK: getelementptr i8, <8 x {{i8\*|ptr}}> %1, <8 x i64> %2 + // CHECK: getelementptr i8, <8 x {{i8\*|ptr}}> %0, <8 x i64> %1 unsafe { simd_arith_offset(ptrs, offsets) } } diff --git a/tests/codegen/slice-iter-len-eq-zero.rs b/tests/codegen/slice-iter-len-eq-zero.rs index 894b0ec3de4..69f78cea564 100644 --- a/tests/codegen/slice-iter-len-eq-zero.rs +++ b/tests/codegen/slice-iter-len-eq-zero.rs @@ -9,8 +9,8 @@ type Demo = [u8; 3]; #[no_mangle] pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool { // CHECK-NOT: sub - // CHECK: %2 = icmp eq {{i8\*|ptr}} {{%1|%0}}, {{%1|%0}} - // CHECK: ret i1 %2 + // CHECK: %_0 = icmp eq {{i8\*|ptr}} {{%1|%0}}, {{%1|%0}} + // CHECK: ret i1 %_0 y.len() == 0 } @@ -22,7 +22,7 @@ pub fn array_into_iter_len_eq_zero(y: std::array::IntoIter<Demo, 123>) -> bool { // CHECK-NOT: icmp // CHECK-NOT: sub - // CHECK: %1 = icmp eq {{i16|i32|i64}} - // CHECK: ret i1 %1 + // CHECK: %_0 = icmp eq {{i16|i32|i64}} + // CHECK: ret i1 %_0 y.len() == 0 } diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index a0894a505c7..293b0d664f6 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -11,24 +11,24 @@ // that allows us to avoid the `alloca`s entirely; see `rvalue_creates_operand`. // CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float %x) -// CHECK: %0 = bitcast float %x to i32 -// CHECK-NEXT: ret i32 %0 +// CHECK: %_0 = bitcast float %x to i32 +// CHECK-NEXT: ret i32 %_0 #[no_mangle] pub fn f32_to_bits(x: f32) -> u32 { unsafe { std::mem::transmute(x) } } // CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 zeroext %b) -// CHECK: %0 = zext i1 %b to i8 -// CHECK-NEXT: ret i8 %0 +// CHECK: %_0 = zext i1 %b to i8 +// CHECK-NEXT: ret i8 %_0 #[no_mangle] pub fn bool_to_byte(b: bool) -> u8 { unsafe { std::mem::transmute(b) } } // CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte) -// CHECK: %0 = trunc i8 %byte to i1 -// CHECK-NEXT: ret i1 %0 +// CHECK: %_0 = trunc i8 %byte to i1 +// CHECK-NEXT: ret i1 %_0 #[no_mangle] pub unsafe fn byte_to_bool(byte: u8) -> bool { std::mem::transmute(byte) @@ -42,16 +42,16 @@ pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 { } // CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr %p) -// CHECK: %0 = ptrtoint ptr %p to [[USIZE]] -// CHECK-NEXT: ret [[USIZE]] %0 +// CHECK: %_0 = ptrtoint ptr %p to [[USIZE]] +// CHECK-NEXT: ret [[USIZE]] %_0 #[no_mangle] pub fn ptr_to_int(p: *mut u16) -> usize { unsafe { std::mem::transmute(p) } } // CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] %i) -// CHECK: %0 = inttoptr [[USIZE]] %i to ptr -// CHECK-NEXT: ret ptr %0 +// CHECK: %_0 = inttoptr [[USIZE]] %i to ptr +// CHECK-NEXT: ret ptr %_0 #[no_mangle] pub fn int_to_ptr(i: usize) -> *mut u16 { unsafe { std::mem::transmute(i) } diff --git a/tests/codegen/uninit-consts.rs b/tests/codegen/uninit-consts.rs index 54e9a9e9bb8..f169988e1f5 100644 --- a/tests/codegen/uninit-consts.rs +++ b/tests/codegen/uninit-consts.rs @@ -1,4 +1,5 @@ // compile-flags: -C no-prepopulate-passes +// min-llvm-version: 15.0 (for opaque pointers) // Check that we use undef (and not zero) for uninitialized bytes in constants. @@ -8,7 +9,7 @@ use std::mem::MaybeUninit; pub struct PartiallyUninit { x: u32, - y: MaybeUninit<[u8; 10]> + y: MaybeUninit<[u8; 10]>, } // CHECK: [[FULLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [10 x i8] }> undef @@ -25,7 +26,7 @@ pub struct PartiallyUninit { #[no_mangle] pub const fn fully_uninit() -> MaybeUninit<[u8; 10]> { const M: MaybeUninit<[u8; 10]> = MaybeUninit::uninit(); - // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{[0-9]+}}, {{i8\*|ptr}} align 1 {{.*}}[[FULLY_UNINIT]]{{.*}}, i{{(32|64)}} 10, i1 false) + // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 1 %_0, ptr align 1 {{.*}}[[FULLY_UNINIT]]{{.*}}, i{{(32|64)}} 10, i1 false) M } @@ -33,7 +34,7 @@ pub const fn fully_uninit() -> MaybeUninit<[u8; 10]> { #[no_mangle] pub const fn partially_uninit() -> PartiallyUninit { const X: PartiallyUninit = PartiallyUninit { x: 0xdeadbeef, y: MaybeUninit::uninit() }; - // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 4 %{{[0-9]+}}, {{i8\*|ptr}} align 4 {{.*}}[[PARTIALLY_UNINIT]]{{.*}}, i{{(32|64)}} 16, i1 false) + // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[PARTIALLY_UNINIT]]{{.*}}, i{{(32|64)}} 16, i1 false) X } @@ -41,7 +42,7 @@ pub const fn partially_uninit() -> PartiallyUninit { #[no_mangle] pub const fn uninit_padding_huge() -> [(u32, u8); 4096] { const X: [(u32, u8); 4096] = [(123, 45); 4096]; - // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 4 %{{[0-9]+}}, {{i8\*|ptr}} align 4 {{.*}}[[UNINIT_PADDING_HUGE]]{{.*}}, i{{(32|64)}} 32768, i1 false) + // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[UNINIT_PADDING_HUGE]]{{.*}}, i{{(32|64)}} 32768, i1 false) X } @@ -49,6 +50,6 @@ pub const fn uninit_padding_huge() -> [(u32, u8); 4096] { #[no_mangle] pub const fn fully_uninit_huge() -> MaybeUninit<[u32; 4096]> { const F: MaybeUninit<[u32; 4096]> = MaybeUninit::uninit(); - // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 4 %{{[0-9]+}}, {{i8\*|ptr}} align 4 {{.*}}[[FULLY_UNINIT_HUGE]]{{.*}}, i{{(32|64)}} 16384, i1 false) + // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[FULLY_UNINIT_HUGE]]{{.*}}, i{{(32|64)}} 16384, i1 false) F } diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs index 8481ca8ccfa..653c5837daf 100644 --- a/tests/codegen/union-abi.rs +++ b/tests/codegen/union-abi.rs @@ -73,4 +73,4 @@ pub union UnionBool { b:bool } // CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b) #[no_mangle] pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b } } -// CHECK: %0 = trunc i8 %b to i1 +// CHECK: %_0 = trunc i8 %b to i1 diff --git a/tests/codegen/var-names.rs b/tests/codegen/var-names.rs index 53841df32e8..d4715efad73 100644 --- a/tests/codegen/var-names.rs +++ b/tests/codegen/var-names.rs @@ -9,7 +9,7 @@ pub fn test(a: u32, b: u32) -> u32 { // CHECK: %c = add i32 %a, %b let d = c; let e = d * a; - // CHECK-NEXT: %0 = mul i32 %c, %a + // CHECK-NEXT: %e = mul i32 %c, %a e - // CHECK-NEXT: ret i32 %0 + // CHECK-NEXT: ret i32 %e } diff --git a/tests/codegen/wasm_exceptions.rs b/tests/codegen/wasm_exceptions.rs new file mode 100644 index 00000000000..2b2359f5b6c --- /dev/null +++ b/tests/codegen/wasm_exceptions.rs @@ -0,0 +1,51 @@ +// only-wasm32-bare +// compile-flags: -C panic=unwind + +#![crate_type = "lib"] +#![feature(core_intrinsics)] +#![feature(rustc_attrs)] + +extern { + fn may_panic(); + + #[rustc_nounwind] + fn log_number(number: usize); +} + +struct LogOnDrop; + +impl Drop for LogOnDrop { + fn drop(&mut self) { + unsafe { log_number(0); } + } +} + +// CHECK-LABEL: @test_cleanup() {{.*}} @__gxx_wasm_personality_v0 +#[no_mangle] +pub fn test_cleanup() { + let _log_on_drop = LogOnDrop; + unsafe { may_panic(); } + + // CHECK-NOT: call + // CHECK: invoke void @may_panic() + // CHECK: %cleanuppad = cleanuppad within none [] +} + +// CHECK-LABEL: @test_rtry() {{.*}} @__gxx_wasm_personality_v0 +#[no_mangle] +pub fn test_rtry() { + unsafe { + core::intrinsics::r#try(|_| { + may_panic(); + }, core::ptr::null_mut(), |data, exception| { + log_number(data as usize); + log_number(exception as usize); + }); + } + + // CHECK-NOT: call + // CHECK: invoke void @may_panic() + // CHECK: {{.*}} = catchswitch within none [label {{.*}}] unwind to caller + // CHECK: {{.*}} = catchpad within {{.*}} [ptr null] + // CHECK: catchret +} diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir index 93bf2b64deb..61aa89e445f 100644 --- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -150,7 +150,7 @@ fn address_of_reborrow() -> () { StorageLive(_9); StorageLive(_10); _10 = &raw const (*_1); - _9 = move _10 as *const dyn std::marker::Send (Pointer(Unsize)); + _9 = move _10 as *const dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_10); AscribeUserType(_9, o, UserTypeProjection { base: UserType(1), projs: [] }); _8 = _9; @@ -159,13 +159,13 @@ fn address_of_reborrow() -> () { StorageLive(_11); StorageLive(_12); _12 = &raw const (*_1); - _11 = move _12 as *const [i32] (Pointer(Unsize)); + _11 = move _12 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_12); StorageDead(_11); StorageLive(_13); StorageLive(_14); _14 = &raw const (*_1); - _13 = move _14 as *const i32 (Pointer(ArrayToPointer)); + _13 = move _14 as *const i32 (PointerCoercion(ArrayToPointer)); StorageDead(_14); StorageDead(_13); StorageLive(_15); @@ -179,14 +179,14 @@ fn address_of_reborrow() -> () { StorageLive(_17); StorageLive(_18); _18 = &raw const (*_1); - _17 = move _18 as *const dyn std::marker::Send (Pointer(Unsize)); + _17 = move _18 as *const dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_18); FakeRead(ForLet(None), _17); AscribeUserType(_17, o, UserTypeProjection { base: UserType(7), projs: [] }); StorageLive(_19); StorageLive(_20); _20 = &raw const (*_1); - _19 = move _20 as *const [i32] (Pointer(Unsize)); + _19 = move _20 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_20); FakeRead(ForLet(None), _19); AscribeUserType(_19, o, UserTypeProjection { base: UserType(9), projs: [] }); @@ -204,7 +204,7 @@ fn address_of_reborrow() -> () { StorageLive(_25); StorageLive(_26); _26 = &raw const (*_3); - _25 = move _26 as *const dyn std::marker::Send (Pointer(Unsize)); + _25 = move _26 as *const dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_26); AscribeUserType(_25, o, UserTypeProjection { base: UserType(11), projs: [] }); _24 = _25; @@ -213,7 +213,7 @@ fn address_of_reborrow() -> () { StorageLive(_27); StorageLive(_28); _28 = &raw const (*_3); - _27 = move _28 as *const [i32] (Pointer(Unsize)); + _27 = move _28 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_28); StorageDead(_27); StorageLive(_29); @@ -227,14 +227,14 @@ fn address_of_reborrow() -> () { StorageLive(_31); StorageLive(_32); _32 = &raw const (*_3); - _31 = move _32 as *const dyn std::marker::Send (Pointer(Unsize)); + _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_32); FakeRead(ForLet(None), _31); AscribeUserType(_31, o, UserTypeProjection { base: UserType(17), projs: [] }); StorageLive(_33); StorageLive(_34); _34 = &raw const (*_3); - _33 = move _34 as *const [i32] (Pointer(Unsize)); + _33 = move _34 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_34); FakeRead(ForLet(None), _33); AscribeUserType(_33, o, UserTypeProjection { base: UserType(19), projs: [] }); @@ -252,7 +252,7 @@ fn address_of_reborrow() -> () { StorageLive(_39); StorageLive(_40); _40 = &raw mut (*_3); - _39 = move _40 as *mut dyn std::marker::Send (Pointer(Unsize)); + _39 = move _40 as *mut dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_40); AscribeUserType(_39, o, UserTypeProjection { base: UserType(21), projs: [] }); _38 = _39; @@ -261,7 +261,7 @@ fn address_of_reborrow() -> () { StorageLive(_41); StorageLive(_42); _42 = &raw mut (*_3); - _41 = move _42 as *mut [i32] (Pointer(Unsize)); + _41 = move _42 as *mut [i32] (PointerCoercion(Unsize)); StorageDead(_42); StorageDead(_41); StorageLive(_43); @@ -275,14 +275,14 @@ fn address_of_reborrow() -> () { StorageLive(_45); StorageLive(_46); _46 = &raw mut (*_3); - _45 = move _46 as *mut dyn std::marker::Send (Pointer(Unsize)); + _45 = move _46 as *mut dyn std::marker::Send (PointerCoercion(Unsize)); StorageDead(_46); FakeRead(ForLet(None), _45); AscribeUserType(_45, o, UserTypeProjection { base: UserType(27), projs: [] }); StorageLive(_47); StorageLive(_48); _48 = &raw mut (*_3); - _47 = move _48 as *mut [i32] (Pointer(Unsize)); + _47 = move _48 as *mut [i32] (PointerCoercion(Unsize)); StorageDead(_48); FakeRead(ForLet(None), _47); AscribeUserType(_47, o, UserTypeProjection { base: UserType(29), projs: [] }); diff --git a/tests/mir-opt/building/issue_110508.rs b/tests/mir-opt/building/issue_110508.rs new file mode 100644 index 00000000000..bcbb1c29830 --- /dev/null +++ b/tests/mir-opt/building/issue_110508.rs @@ -0,0 +1,13 @@ +// EMIT_MIR issue_110508.{impl#0}-BAR.built.after.mir +// EMIT_MIR issue_110508.{impl#0}-SELF_BAR.built.after.mir + +enum Foo { + Bar(()), +} + +impl Foo { + const BAR: Foo = Foo::Bar(()); + const SELF_BAR: Foo = Self::Bar(()); +} + +fn main() {} diff --git a/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir b/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir new file mode 100644 index 00000000000..5fc6d911af3 --- /dev/null +++ b/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir @@ -0,0 +1,14 @@ +// MIR for `<impl at $DIR/issue_110508.rs:8:1: 8:9>::BAR` after built + +const <impl at $DIR/issue_110508.rs:8:1: 8:9>::BAR: Foo = { + let mut _0: Foo; + let mut _1: (); + + bb0: { + StorageLive(_1); + _1 = (); + _0 = Foo::Bar(move _1); + StorageDead(_1); + return; + } +} diff --git a/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir b/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir new file mode 100644 index 00000000000..1a892559971 --- /dev/null +++ b/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir @@ -0,0 +1,14 @@ +// MIR for `<impl at $DIR/issue_110508.rs:8:1: 8:9>::SELF_BAR` after built + +const <impl at $DIR/issue_110508.rs:8:1: 8:9>::SELF_BAR: Foo = { + let mut _0: Foo; + let mut _1: (); + + bb0: { + StorageLive(_1); + _1 = (); + _0 = Foo::Bar(move _1); + StorageDead(_1); + return; + } +} diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir index b3db1d76ca7..fed5e68c3c9 100644 --- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir +++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir @@ -39,7 +39,7 @@ fn main() -> () { StorageLive(_3); StorageLive(_4); _4 = _1; - _3 = move _4 as *const Test (Pointer(MutToConstPointer)); + _3 = move _4 as *const Test (PointerCoercion(MutToConstPointer)); StorageDead(_4); _2 = Test::x(move _3) -> [return: bb2, unwind: bb4]; } @@ -64,7 +64,7 @@ fn main() -> () { StorageLive(_11); StorageLive(_12); _12 = (*(*(*(*_5)))); - _11 = move _12 as *const Test (Pointer(MutToConstPointer)); + _11 = move _12 as *const Test (PointerCoercion(MutToConstPointer)); StorageDead(_12); _10 = Test::x(move _11) -> [return: bb3, unwind: bb4]; } diff --git a/tests/mir-opt/building/storage_live_dead_in_statics.XXX.built.after.mir b/tests/mir-opt/building/storage_live_dead_in_statics.XXX.built.after.mir index 1d7adfde4ed..683f63065f7 100644 --- a/tests/mir-opt/building/storage_live_dead_in_statics.XXX.built.after.mir +++ b/tests/mir-opt/building/storage_live_dead_in_statics.XXX.built.after.mir @@ -187,7 +187,7 @@ static XXX: &Foo = { StorageDead(_7); _5 = &_6; _4 = &(*_5); - _3 = move _4 as &[(u32, u32)] (Pointer(Unsize)); + _3 = move _4 as &[(u32, u32)] (PointerCoercion(Unsize)); StorageDead(_4); _2 = Foo { tup: const "hi", data: move _3 }; StorageDead(_3); diff --git a/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir b/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir index aca7b12c4c6..f0c35fe9782 100644 --- a/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir +++ b/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir @@ -8,7 +8,7 @@ fn roundtrip(_1: *const u8) -> *const u8 { bb0: { StorageLive(_2); _2 = _1 as *mut u8 (PtrToPtr); - _0 = move _2 as *const u8 (Pointer(MutToConstPointer)); + _0 = move _2 as *const u8 (PointerCoercion(MutToConstPointer)); StorageDead(_2); return; } diff --git a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 0eee91469e6..14d2d7fc85c 100644 --- a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -22,7 +22,7 @@ - _2 = &_3; + _6 = const _; + _2 = &(*_6); - _1 = move _2 as &[&i32] (Pointer(Unsize)); + _1 = move _2 as &[&i32] (PointerCoercion(Unsize)); - StorageDead(_4); StorageDead(_2); _0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index 0b117f4aaa5..ffdd195eca3 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -24,7 +24,7 @@ - _2 = &_3; + _6 = const _; + _2 = &(*_6); - _1 = move _2 as &[&i32] (Pointer(Unsize)); + _1 = move _2 as &[&i32] (PointerCoercion(Unsize)); - StorageDead(_4); StorageDead(_2); _0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-abort.diff index 6d5e34f23e8..30402df47c2 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-abort.diff @@ -28,7 +28,7 @@ _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); - _1 = move _2 as *const [i32] (Pointer(Unsize)); + _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); StorageDead(_3); StorageLive(_5); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff index 2c0e4844ecc..16d62daed29 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff @@ -28,7 +28,7 @@ _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); - _1 = move _2 as *const [i32] (Pointer(Unsize)); + _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); StorageDead(_3); StorageLive(_5); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-abort.diff index 6d5e34f23e8..30402df47c2 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-abort.diff @@ -28,7 +28,7 @@ _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); - _1 = move _2 as *const [i32] (Pointer(Unsize)); + _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); StorageDead(_3); StorageLive(_5); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff index 2c0e4844ecc..16d62daed29 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff @@ -28,7 +28,7 @@ _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); - _1 = move _2 as *const [i32] (Pointer(Unsize)); + _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); StorageDead(_3); StorageLive(_5); diff --git a/tests/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff b/tests/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff index 533a92f78a5..e7aa015d078 100644 --- a/tests/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff @@ -13,7 +13,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); - _3 = main as fn() (Pointer(ReifyFnPointer)); + _3 = main as fn() (PointerCoercion(ReifyFnPointer)); _2 = move _3 as usize (PointerExposeAddress); StorageDead(_3); _1 = move _2 as *const fn() (PointerFromExposedAddress); diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff index 2f64a185106..3c2b8e111cb 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff @@ -21,7 +21,7 @@ _9 = const _; _4 = _9; _3 = _4; - _2 = move _3 as &[u32] (Pointer(Unsize)); + _2 = move _3 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff index c0f290a9ab4..303096030b4 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff @@ -21,7 +21,7 @@ _9 = const _; _4 = _9; _3 = _4; - _2 = move _3 as &[u32] (Pointer(Unsize)); + _2 = move _3 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff index 2f64a185106..3c2b8e111cb 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff @@ -21,7 +21,7 @@ _9 = const _; _4 = _9; _3 = _4; - _2 = move _3 as &[u32] (Pointer(Unsize)); + _2 = move _3 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff index c0f290a9ab4..303096030b4 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff @@ -21,7 +21,7 @@ _9 = const _; _4 = _9; _3 = _4; - _2 = move _3 as &[u32] (Pointer(Unsize)); + _2 = move _3 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff index a16d79d0e64..a802d0256d4 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff @@ -47,7 +47,7 @@ StorageLive(_6); StorageLive(_7); _7 = &_2; - _6 = move _7 as &[i32] (Pointer(Unsize)); + _6 = move _7 as &[i32] (PointerCoercion(Unsize)); StorageDead(_7); _5 = core::slice::<impl [i32]>::len(move _6) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff index c2d892be35d..35f852098c3 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff @@ -47,7 +47,7 @@ StorageLive(_6); StorageLive(_7); _7 = &_2; - _6 = move _7 as &[i32] (Pointer(Unsize)); + _6 = move _7 as &[i32] (PointerCoercion(Unsize)); StorageDead(_7); _5 = core::slice::<impl [i32]>::len(move _6) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff index 1f5e2428095..57b0849e111 100644 --- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff @@ -31,7 +31,7 @@ _4 = &(*_2); - _0 = try_execute_query::<<Q as Query>::C>(move _4) -> [return: bb2, unwind unreachable]; + StorageLive(_5); -+ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); ++ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (PointerCoercion(Unsize)); + _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff index 941ba24605c..706c1d48195 100644 --- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff @@ -31,7 +31,7 @@ _4 = &(*_2); - _0 = try_execute_query::<<Q as Query>::C>(move _4) -> [return: bb2, unwind continue]; + StorageLive(_5); -+ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); ++ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (PointerCoercion(Unsize)); + _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> [return: bb2, unwind continue]; } diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff index 1e4c6fcca7a..9a6d3596fb9 100644 --- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff @@ -14,7 +14,7 @@ StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); + _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (PointerCoercion(Unsize)); StorageDead(_3); - _0 = mk_cycle::<<C as Cache>::V>(move _2) -> [return: bb1, unwind unreachable]; + _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff index 5e30da400d2..1a08df2b09b 100644 --- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff @@ -14,7 +14,7 @@ StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); + _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (PointerCoercion(Unsize)); StorageDead(_3); - _0 = mk_cycle::<<C as Cache>::V>(move _2) -> [return: bb1, unwind continue]; + _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> [return: bb1, unwind continue]; diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff index f3a6923415a..dfc00026ad0 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff @@ -164,7 +164,7 @@ + StorageDead(_17); + StorageLive(_19); + StorageLive(_20); -+ _19 = _16 as *const u8 (Pointer(MutToConstPointer)); ++ _19 = _16 as *const u8 (PointerCoercion(MutToConstPointer)); + _15 = NonNull::<u8> { pointer: _19 }; + StorageDead(_20); + StorageDead(_19); diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff index 0b643b3c7a9..f582adda88f 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff @@ -181,7 +181,7 @@ + StorageDead(_17); + StorageLive(_19); + StorageLive(_20); -+ _19 = _16 as *const u8 (Pointer(MutToConstPointer)); ++ _19 = _16 as *const u8 (PointerCoercion(MutToConstPointer)); + _15 = NonNull::<u8> { pointer: _19 }; + StorageDead(_20); + StorageDead(_19); diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir index 62c0805548b..503f153089c 100644 --- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir +++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir @@ -13,7 +13,7 @@ fn test2(_1: &dyn X) -> bool { StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = move _3 as &dyn X (Pointer(Unsize)); + _2 = move _3 as &dyn X (PointerCoercion(Unsize)); StorageDead(_3); _0 = <dyn X as X>::y(_2) -> [return: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir index 5d4979680a4..37bb53e79c6 100644 --- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir @@ -13,7 +13,7 @@ fn test2(_1: &dyn X) -> bool { StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = move _3 as &dyn X (Pointer(Unsize)); + _2 = move _3 as &dyn X (PointerCoercion(Unsize)); StorageDead(_3); _0 = <dyn X as X>::y(_2) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff index f2a925273db..1cc44ce06cf 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff @@ -32,7 +32,7 @@ StorageLive(_5); _5 = [_1, _1, _1]; _4 = &_5; - _2 = _4 as &[T] (Pointer(Unsize)); + _2 = _4 as &[T] (PointerCoercion(Unsize)); _9 = Len((*_2)); _10 = const 3_usize; - _11 = Eq(move _9, const 3_usize); diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff index 25df839c2db..b708f667438 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff @@ -32,7 +32,7 @@ StorageLive(_5); _5 = [_1, _1, _1]; _4 = &_5; - _2 = _4 as &[T] (Pointer(Unsize)); + _2 = _4 as &[T] (PointerCoercion(Unsize)); _9 = Len((*_2)); _10 = const 3_usize; - _11 = Eq(move _9, const 3_usize); diff --git a/tests/mir-opt/issue_99325.main.built.after.mir b/tests/mir-opt/issue_99325.main.built.after.mir index d8a88a0635c..0fe66d3fb70 100644 --- a/tests/mir-opt/issue_99325.main.built.after.mir +++ b/tests/mir-opt/issue_99325.main.built.after.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)]) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated([], DefId(0:8 ~ issue_99325[22bb]::main::{constant#1})) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), substs: [] } }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-abort.diff index de6c2366dbb..6174d5259d0 100644 --- a/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-abort.diff @@ -22,7 +22,7 @@ StorageLive(_6); StorageLive(_7); _7 = &(*_2); - _6 = move _7 as &[u8] (Pointer(Unsize)); + _6 = move _7 as &[u8] (PointerCoercion(Unsize)); StorageDead(_7); - _5 = Len((*_6)); + _5 = const N; diff --git a/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-unwind.diff index 1cba0f27afa..60c0772d8ec 100644 --- a/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-unwind.diff @@ -22,7 +22,7 @@ StorageLive(_6); StorageLive(_7); _7 = &(*_2); - _6 = move _7 as &[u8] (Pointer(Unsize)); + _6 = move _7 as &[u8] (PointerCoercion(Unsize)); StorageDead(_7); - _5 = Len((*_6)); + _5 = const N; diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-abort.diff index 76175afc2f8..e2de1845296 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-abort.diff @@ -25,7 +25,7 @@ StorageLive(_6); StorageLive(_7); _7 = &(*_2); - _6 = move _7 as &[u8] (Pointer(Unsize)); + _6 = move _7 as &[u8] (PointerCoercion(Unsize)); StorageDead(_7); - _5 = Len((*_6)); + _5 = const N; diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-unwind.diff index 6c450067cc4..eb81e0eea2c 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-unwind.diff @@ -25,7 +25,7 @@ StorageLive(_6); StorageLive(_7); _7 = &(*_2); - _6 = move _7 as &[u8] (Pointer(Unsize)); + _6 = move _7 as &[u8] (PointerCoercion(Unsize)); StorageDead(_7); - _5 = Len((*_6)); + _5 = const N; diff --git a/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.panic-abort.diff index a20d5288c40..1bdc62183c3 100644 --- a/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.panic-abort.diff @@ -11,7 +11,7 @@ StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = move _3 as &[u8] (Pointer(Unsize)); + _2 = move _3 as &[u8] (PointerCoercion(Unsize)); StorageDead(_3); - _0 = Len((*_2)); + _0 = const N; diff --git a/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.panic-unwind.diff index a20d5288c40..1bdc62183c3 100644 --- a/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.panic-unwind.diff @@ -11,7 +11,7 @@ StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = move _3 as &[u8] (Pointer(Unsize)); + _2 = move _3 as &[u8] (PointerCoercion(Unsize)); StorageDead(_3); - _0 = Len((*_2)); + _0 = const N; diff --git a/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.panic-abort.diff index c3842bf4edc..9862b2fad8e 100644 --- a/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.panic-abort.diff @@ -11,7 +11,7 @@ StorageLive(_2); StorageLive(_3); _3 = &_1; - _2 = move _3 as &[u8] (Pointer(Unsize)); + _2 = move _3 as &[u8] (PointerCoercion(Unsize)); StorageDead(_3); - _0 = Len((*_2)); + _0 = const N; diff --git a/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.panic-unwind.diff index c3842bf4edc..9862b2fad8e 100644 --- a/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.panic-unwind.diff @@ -11,7 +11,7 @@ StorageLive(_2); StorageLive(_3); _3 = &_1; - _2 = move _3 as &[u8] (Pointer(Unsize)); + _2 = move _3 as &[u8] (PointerCoercion(Unsize)); StorageDead(_3); - _0 = Len((*_2)); + _0 = const N; diff --git a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-abort.diff index c407482d17b..f9f73bf991d 100644 --- a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-abort.diff @@ -25,7 +25,7 @@ StorageLive(_4); _4 = &_1; _3 = &(*_4); - _2 = move _3 as &[u8] (Pointer(Unsize)); + _2 = move _3 as &[u8] (PointerCoercion(Unsize)); StorageDead(_3); StorageDead(_4); StorageLive(_5); diff --git a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-unwind.diff index c407482d17b..f9f73bf991d 100644 --- a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-unwind.diff @@ -25,7 +25,7 @@ StorageLive(_4); _4 = &_1; _3 = &(*_4); - _2 = move _3 as &[u8] (Pointer(Unsize)); + _2 = move _3 as &[u8] (PointerCoercion(Unsize)); StorageDead(_3); StorageDead(_4); StorageLive(_5); diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.panic-abort.diff index f50f7baa6e3..ecba06a2e4d 100644 --- a/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.panic-abort.diff @@ -22,7 +22,7 @@ StorageLive(_4); _4 = &mut _1; _3 = &mut (*_4); - _2 = move _3 as &mut [u8] (Pointer(Unsize)); + _2 = move _3 as &mut [u8] (PointerCoercion(Unsize)); StorageDead(_3); StorageDead(_4); StorageLive(_5); diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.panic-unwind.diff index f50f7baa6e3..ecba06a2e4d 100644 --- a/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.panic-unwind.diff @@ -22,7 +22,7 @@ StorageLive(_4); _4 = &mut _1; _3 = &mut (*_4); - _2 = move _3 as &mut [u8] (Pointer(Unsize)); + _2 = move _3 as &mut [u8] (PointerCoercion(Unsize)); StorageDead(_3); StorageDead(_4); StorageLive(_5); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index a337ca89992..e07e2bb7bfe 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -78,7 +78,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) -> StorageLive(_12); StorageLive(_11); StorageLive(_10); - _10 = _9 as *const () (Pointer(MutToConstPointer)); + _10 = _9 as *const () (PointerCoercion(MutToConstPointer)); _11 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 }; StorageDead(_10); _12 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 }; diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index a337ca89992..e07e2bb7bfe 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -78,7 +78,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) -> StorageLive(_12); StorageLive(_11); StorageLive(_10); - _10 = _9 as *const () (Pointer(MutToConstPointer)); + _10 = _9 as *const () (PointerCoercion(MutToConstPointer)); _11 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 }; StorageDead(_10); _12 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 }; diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 1e401c60bf3..d1ab16697a6 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -131,7 +131,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); - _10 = _9 as *const T (Pointer(MutToConstPointer)); + _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull::<T> { pointer: _10 }; StorageDead(_24); StorageDead(_10); diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 8294a5cb6dc..03751f7fdf7 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -131,7 +131,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); - _10 = _9 as *const T (Pointer(MutToConstPointer)); + _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull::<T> { pointer: _10 }; StorageDead(_24); StorageDead(_10); diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index c1c7861b9c9..db971e10f32 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -121,7 +121,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_22); - _10 = _9 as *const T (Pointer(MutToConstPointer)); + _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull::<T> { pointer: _10 }; StorageDead(_22); StorageDead(_10); diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index ff40e450968..74597799168 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -121,7 +121,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_22); - _10 = _9 as *const T (Pointer(MutToConstPointer)); + _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull::<T> { pointer: _10 }; StorageDead(_22); StorageDead(_10); diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 851d3311365..e546140e0c1 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -133,7 +133,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); - _10 = _9 as *const T (Pointer(MutToConstPointer)); + _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull::<T> { pointer: _10 }; StorageDead(_24); StorageDead(_10); diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index b40d9209d25..551cac46bdf 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -133,7 +133,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); - _10 = _9 as *const T (Pointer(MutToConstPointer)); + _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull::<T> { pointer: _10 }; StorageDead(_24); StorageDead(_10); diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir index 3c48e798ef7..70efdbf4b34 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir @@ -69,7 +69,7 @@ fn array_casts() -> () { StorageLive(_4); _4 = &mut _1; _3 = &raw mut (*_4); - _2 = move _3 as *mut usize (Pointer(ArrayToPointer)); + _2 = move _3 as *mut usize (PointerCoercion(ArrayToPointer)); StorageDead(_3); StorageDead(_4); StorageLive(_5); @@ -92,7 +92,7 @@ fn array_casts() -> () { StorageLive(_11); _11 = &_8; _10 = &raw const (*_11); - _9 = move _10 as *const usize (Pointer(ArrayToPointer)); + _9 = move _10 as *const usize (PointerCoercion(ArrayToPointer)); StorageDead(_10); StorageDead(_11); StorageLive(_12); diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 93f14af29b4..cfa9628d498 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -69,7 +69,7 @@ fn array_casts() -> () { StorageLive(_4); _4 = &mut _1; _3 = &raw mut (*_4); - _2 = move _3 as *mut usize (Pointer(ArrayToPointer)); + _2 = move _3 as *mut usize (PointerCoercion(ArrayToPointer)); StorageDead(_3); StorageDead(_4); StorageLive(_5); @@ -92,7 +92,7 @@ fn array_casts() -> () { StorageLive(_11); _11 = &_8; _10 = &raw const (*_11); - _9 = move _10 as *const usize (Pointer(ArrayToPointer)); + _9 = move _10 as *const usize (PointerCoercion(ArrayToPointer)); StorageDead(_10); StorageDead(_11); StorageLive(_12); diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir index 606a8ec44ec..fb37bec109a 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir @@ -105,7 +105,7 @@ fn main() -> () { StorageLive(_14); _14 = [closure@main::{closure#0}]; Retag(_14); - _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (Pointer(ClosureFnPointer(Normal))); + _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_14); StorageLive(_15); StorageLive(_16); diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 45034946328..508f964099a 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -105,7 +105,7 @@ fn main() -> () { StorageLive(_14); _14 = [closure@main::{closure#0}]; Retag(_14); - _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (Pointer(ClosureFnPointer(Normal))); + _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_14); StorageLive(_15); StorageLive(_16); diff --git a/tests/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff index 7546b3878d6..7cc5e335cb0 100644 --- a/tests/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff @@ -21,7 +21,7 @@ - StorageLive(_4); - _4 = &_1; - _3 = &(*_4); -- _2 = move _3 as &[u8] (Pointer(Unsize)); +- _2 = move _3 as &[u8] (PointerCoercion(Unsize)); - StorageDead(_3); - StorageDead(_4); - StorageDead(_2); diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff index 84247c0e8d5..bb14b909a95 100644 --- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff @@ -62,7 +62,7 @@ } bb1: { - _3 = move _4 as std::boxed::Box<dyn std::fmt::Display> (Pointer(Unsize)); + _3 = move _4 as std::boxed::Box<dyn std::fmt::Display> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Result::<Box<dyn std::fmt::Display>, <T as Err>::Err>::Ok(move _3); StorageDead(_3); @@ -95,7 +95,7 @@ _26 = const _; _14 = &(*_26); _13 = &(*_14); - _12 = move _13 as &[&str] (Pointer(Unsize)); + _12 = move _13 as &[&str] (PointerCoercion(Unsize)); StorageDead(_13); StorageLive(_16); StorageLive(_17); @@ -126,7 +126,7 @@ StorageDead(_20); _18 = &_19; _17 = &(*_18); - _16 = move _17 as &[core::fmt::rt::Argument<'_>] (Pointer(Unsize)); + _16 = move _17 as &[core::fmt::rt::Argument<'_>] (PointerCoercion(Unsize)); StorageDead(_17); _11 = Arguments::<'_>::new_v1(move _12, move _16) -> [return: bb5, unwind unreachable]; } diff --git a/tests/run-coverage/uses_crate.coverage b/tests/run-coverage/uses_crate.coverage index a3b78e21405..ccdcf350334 100644 --- a/tests/run-coverage/uses_crate.coverage +++ b/tests/run-coverage/uses_crate.coverage @@ -148,8 +148,8 @@ $DIR/auxiliary/used_crate.rs: 100| |// `unused_generic_function<T>()`, below. $DIR/uses_crate.rs: - 1| |// FIXME #110395 - 2| |// ignore-linux + 1| |// This test was failing on Linux for a while due to #110393 somehow making + 2| |// the unused functions not instrumented, but it seems to be fine now. 3| | 4| |// Validates coverage now works with optimizations 5| |// compile-flags: -C opt-level=3 diff --git a/tests/run-coverage/uses_crate.rs b/tests/run-coverage/uses_crate.rs index ab466970f8e..ab203ad781d 100644 --- a/tests/run-coverage/uses_crate.rs +++ b/tests/run-coverage/uses_crate.rs @@ -1,5 +1,5 @@ -// FIXME #110395 -// ignore-linux +// This test was failing on Linux for a while due to #110393 somehow making +// the unused functions not instrumented, but it seems to be fine now. // Validates coverage now works with optimizations // compile-flags: -C opt-level=3 diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/run-coverage/uses_inline_crate.coverage index f878d8107c5..64308c796d6 100644 --- a/tests/run-coverage/uses_inline_crate.coverage +++ b/tests/run-coverage/uses_inline_crate.coverage @@ -139,8 +139,8 @@ $DIR/auxiliary/used_inline_crate.rs: 90| 2|} $DIR/uses_inline_crate.rs: - 1| |// FIXME #110395 - 2| |// ignore-linux + 1| |// This test was failing on Linux for a while due to #110393 somehow making + 2| |// the unused functions not instrumented, but it seems to be fine now. 3| | 4| |// Validates coverage now works with optimizations 5| |// compile-flags: -C opt-level=3 diff --git a/tests/run-coverage/uses_inline_crate.rs b/tests/run-coverage/uses_inline_crate.rs index 4bd66d2f89c..d7b4c3c057f 100644 --- a/tests/run-coverage/uses_inline_crate.rs +++ b/tests/run-coverage/uses_inline_crate.rs @@ -1,5 +1,5 @@ -// FIXME #110395 -// ignore-linux +// This test was failing on Linux for a while due to #110393 somehow making +// the unused functions not instrumented, but it seems to be fine now. // Validates coverage now works with optimizations // compile-flags: -C opt-level=3 diff --git a/tests/run-make/wasm-exceptions-nostd/Makefile b/tests/run-make/wasm-exceptions-nostd/Makefile new file mode 100644 index 00000000000..34755ec14b7 --- /dev/null +++ b/tests/run-make/wasm-exceptions-nostd/Makefile @@ -0,0 +1,12 @@ +include ../tools.mk + +# only-wasm32-bare + +# Add a few command line args to make exceptions work +RUSTC := $(RUSTC) -C llvm-args=-wasm-enable-eh +RUSTC := $(RUSTC) -C target-feature=+exception-handling +RUSTC := $(RUSTC) -C panic=unwind + +all: + $(RUSTC) src/lib.rs --target wasm32-unknown-unknown + $(NODE) verify.mjs $(TMPDIR)/lib.wasm diff --git a/tests/run-make/wasm-exceptions-nostd/src/arena_alloc.rs b/tests/run-make/wasm-exceptions-nostd/src/arena_alloc.rs new file mode 100644 index 00000000000..572d253309c --- /dev/null +++ b/tests/run-make/wasm-exceptions-nostd/src/arena_alloc.rs @@ -0,0 +1,67 @@ +use core::alloc::{GlobalAlloc, Layout}; +use core::cell::UnsafeCell; + +#[global_allocator] +static ALLOCATOR: ArenaAllocator = ArenaAllocator::new(); + +/// Very simple allocator which never deallocates memory +/// +/// Based on the example from +/// https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html +pub struct ArenaAllocator { + arena: UnsafeCell<Arena>, +} + +impl ArenaAllocator { + pub const fn new() -> Self { + Self { + arena: UnsafeCell::new(Arena::new()), + } + } +} + +/// Safe because we are singlethreaded +unsafe impl Sync for ArenaAllocator {} + +unsafe impl GlobalAlloc for ArenaAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let arena = &mut *self.arena.get(); + arena.alloc(layout) + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +} + +const ARENA_SIZE: usize = 64 * 1024; // more than enough + +#[repr(C, align(4096))] +struct Arena { + buf: [u8; ARENA_SIZE], // aligned at 4096 + allocated: usize, +} + +impl Arena { + pub const fn new() -> Self { + Self { + buf: [0x55; ARENA_SIZE], + allocated: 0, + } + } + + pub unsafe fn alloc(&mut self, layout: Layout) -> *mut u8 { + if layout.align() > 4096 || layout.size() > ARENA_SIZE { + return core::ptr::null_mut(); + } + + let align_minus_one = layout.align() - 1; + let start = (self.allocated + align_minus_one) & !align_minus_one; // round up + let new_cursor = start + layout.size(); + + if new_cursor >= ARENA_SIZE { + return core::ptr::null_mut(); + } + + self.allocated = new_cursor; + self.buf.as_mut_ptr().add(start) + } +} diff --git a/tests/run-make/wasm-exceptions-nostd/src/lib.rs b/tests/run-make/wasm-exceptions-nostd/src/lib.rs new file mode 100644 index 00000000000..7049d2fd9e0 --- /dev/null +++ b/tests/run-make/wasm-exceptions-nostd/src/lib.rs @@ -0,0 +1,60 @@ +#![no_std] +#![crate_type = "cdylib"] + +// Allow a few unstable features because we create a panic +// runtime for native wasm exceptions from scratch + +#![feature(core_intrinsics)] +#![feature(lang_items)] +#![feature(link_llvm_intrinsics)] +#![feature(panic_info_message)] + +extern crate alloc; + +/// This module allows us to use `Box`, `String`, ... even in no-std +mod arena_alloc; + +/// This module allows logging text, even in no-std +mod logging; + +/// This module allows exceptions, even in no-std +#[cfg(target_arch = "wasm32")] +mod panicking; + +use alloc::boxed::Box; +use alloc::string::String; + +struct LogOnDrop; + +impl Drop for LogOnDrop { + fn drop(&mut self) { + logging::log_str("Dropped"); + } +} + +#[allow(unreachable_code)] +#[allow(unconditional_panic)] +#[no_mangle] +pub extern "C" fn start() -> usize { + let data = 0x1234usize as *mut u8; // Something to recognize + + unsafe { + core::intrinsics::r#try(|data: *mut u8| { + let _log_on_drop = LogOnDrop; + + logging::log_str(&alloc::format!("`r#try` called with ptr {:?}", data)); + let x = [12]; + let _ = x[4]; // should panic + + logging::log_str("This line should not be visible! :("); + }, data, |data, exception| { + let exception = *Box::from_raw(exception as *mut String); + logging::log_str("Caught something!"); + logging::log_str(&alloc::format!(" data : {:?}", data)); + logging::log_str(&alloc::format!(" exception: {:?}", exception)); + }); + } + + logging::log_str("This program terminates correctly."); + 0 +} diff --git a/tests/run-make/wasm-exceptions-nostd/src/logging.rs b/tests/run-make/wasm-exceptions-nostd/src/logging.rs new file mode 100644 index 00000000000..569d03ec82f --- /dev/null +++ b/tests/run-make/wasm-exceptions-nostd/src/logging.rs @@ -0,0 +1,9 @@ +extern "C" { + fn __log_utf8(ptr: *const u8, size: usize); +} + +pub fn log_str(text: &str) { + unsafe { + __log_utf8(text.as_ptr(), text.len()); + } +} diff --git a/tests/run-make/wasm-exceptions-nostd/src/panicking.rs b/tests/run-make/wasm-exceptions-nostd/src/panicking.rs new file mode 100644 index 00000000000..4a8923fd43d --- /dev/null +++ b/tests/run-make/wasm-exceptions-nostd/src/panicking.rs @@ -0,0 +1,29 @@ +#[lang = "eh_personality"] +fn eh_personality() {} + +mod internal { + extern "C" { + #[link_name = "llvm.wasm.throw"] + pub fn wasm_throw(tag: i32, ptr: *mut u8) -> !; + } +} + +unsafe fn wasm_throw(ptr: *mut u8) -> ! { + internal::wasm_throw(0, ptr); +} + +#[panic_handler] +fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { + use alloc::boxed::Box; + use alloc::string::ToString; + + let msg = info + .message() + .map(|msg| msg.to_string()) + .unwrap_or("(no message)".to_string()); + let exception = Box::new(msg.to_string()); + unsafe { + let exception_raw = Box::into_raw(exception); + wasm_throw(exception_raw as *mut u8); + } +} diff --git a/tests/run-make/wasm-exceptions-nostd/verify.mjs b/tests/run-make/wasm-exceptions-nostd/verify.mjs new file mode 100644 index 00000000000..e6c44d89d33 --- /dev/null +++ b/tests/run-make/wasm-exceptions-nostd/verify.mjs @@ -0,0 +1,75 @@ +import fs from 'fs'; + +const dec = new TextDecoder("utf-8"); + +if (process.argv.length != 3) { + console.log("Usage: node verify.mjs <wasm-file>"); + process.exit(0); +} + +const wasmfile = process.argv[2]; +if (!fs.existsSync(wasmfile)) { + console.log("Error: File not found:", wasmfile); + process.exit(1); +} + +const wasmBuffer = fs.readFileSync(wasmfile); + +async function main() { + + let memory = new ArrayBuffer(0) // will be changed after instantiate + + const captured_output = []; + + const imports = { + env: { + __log_utf8: (ptr, size) => { + const str = dec.decode(new DataView(memory, ptr, size)); + captured_output.push(str); + console.log(str); + } + } + }; + + const wasmModule = await WebAssembly.instantiate(wasmBuffer, imports); + memory = wasmModule.instance.exports.memory.buffer; + + const start = wasmModule.instance.exports.start; + const return_code = start(); + + console.log("Return-Code:", return_code); + + if (return_code !== 0) { + console.error("Expected return code 0"); + process.exit(return_code); + } + + const expected_output = [ + '`r#try` called with ptr 0x1234', + 'Dropped', + 'Caught something!', + ' data : 0x1234', + ' exception: "index out of bounds: the len is 1 but the index is 4"', + 'This program terminates correctly.', + ]; + + assert_equal(captured_output, expected_output); +} + +function assert_equal(captured_output, expected_output) { + if (captured_output.length != expected_output.length) { + console.error("Unexpected number of output lines. Got", captured_output.length, "but expected", expected_output.length); + process.exit(1); // exit with error + } + + for (let idx = 0; idx < expected_output.length; ++idx) { + if (captured_output[idx] !== expected_output[idx]) { + console.error("Unexpected output"); + console.error("[got] ", captured_output[idx]); + console.error("[expected]", expected_output[idx]); + process.exit(2); // exit with error + } + } +} + +await main(); \ No newline at end of file diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml index 520b2c59b0f..2cb88817884 100644 --- a/tests/rustdoc-gui/sidebar-source-code.goml +++ b/tests/rustdoc-gui/sidebar-source-code.goml @@ -25,24 +25,24 @@ call-function: ( "check-colors", { "theme": "ayu", - "color": "rgb(197, 197, 197)", - "background_color": "rgb(20, 25, 31)", + "color": "#c5c5c5", + "background_color": "#14191f", } ) call-function: ( "check-colors", { "theme": "dark", - "color": "rgb(221, 221, 221)", - "background_color": "rgb(80, 80, 80)", + "color": "#ddd", + "background_color": "#505050", } ) call-function: ( "check-colors", { "theme": "light", - "color": "rgb(0, 0, 0)", - "background_color": "rgb(245, 245, 245)", + "color": "black", + "background_color": "#F5F5F5", } ) diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 9ef208a14b2..f55d7d599f1 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -7,6 +7,7 @@ // edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_driver; extern crate rustc_hir; @@ -21,6 +22,7 @@ use rustc_interface::{interface, Queries}; use rustc_middle::ty::TyCtxt; use rustc_session::EarlyErrorHandler; use rustc_smir::{rustc_internal, stable_mir}; +use std::assert_matches::assert_matches; use std::io::Write; const CRATE_NAME: &str = "input"; @@ -65,6 +67,36 @@ fn test_stable_mir(tcx: TyCtxt<'_>) { other => panic!("{other:?}"), } + let types = get_item(tcx, &items, (DefKind::Fn, "types")).unwrap(); + let body = types.body(); + assert_eq!(body.locals.len(), 6); + assert_matches!( + body.locals[0].kind(), + stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool) + ); + assert_matches!( + body.locals[1].kind(), + stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool) + ); + assert_matches!( + body.locals[2].kind(), + stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Char) + ); + assert_matches!( + body.locals[3].kind(), + stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Int(stable_mir::ty::IntTy::I32)) + ); + assert_matches!( + body.locals[4].kind(), + stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Uint(stable_mir::ty::UintTy::U64)) + ); + assert_matches!( + body.locals[5].kind(), + stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Float( + stable_mir::ty::FloatTy::F64 + )) + ); + let drop = get_item(tcx, &items, (DefKind::Fn, "drop")).unwrap(); let body = drop.body(); assert_eq!(body.blocks.len(), 2); @@ -156,6 +188,10 @@ fn generate_input(path: &str) -> std::io::Result<()> { x_64.wrapping_add(y_64) }} + pub fn types(b: bool, _: char, _: i32, _: u64, _: f64) -> bool {{ + b + }} + pub fn drop(_: String) {{}} pub fn assert(x: i32) -> i32 {{ diff --git a/tests/ui/async-await/in-trait/async-associated-types2.rs b/tests/ui/async-await/in-trait/async-associated-types2.rs deleted file mode 100644 index b889f616a03..00000000000 --- a/tests/ui/async-await/in-trait/async-associated-types2.rs +++ /dev/null @@ -1,30 +0,0 @@ -// check-pass -// edition: 2021 -// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -// revisions: current next - -#![feature(async_fn_in_trait)] -#![feature(impl_trait_in_assoc_type)] -#![allow(incomplete_features)] - -use std::future::Future; - -trait MyTrait { - type Fut<'a>: Future<Output = i32> - where - Self: 'a; - - fn foo<'a>(&'a self) -> Self::Fut<'a>; -} - -impl MyTrait for i32 { - type Fut<'a> = impl Future<Output = i32> + 'a - where - Self: 'a; - - fn foo<'a>(&'a self) -> Self::Fut<'a> { - async { *self } - } -} - -fn main() {} diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.current.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.current.stderr new file mode 100644 index 00000000000..e6ac9bc2277 --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-feature-flag.current.stderr @@ -0,0 +1,30 @@ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/missing-feature-flag.rs:14:1 + | +LL | async fn foo(_: T) -> &'static str; + | ----------------------------------- `foo` from trait +... +LL | impl<T> MyTrait<T> for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/missing-feature-flag.rs:18:5 + | +LL | impl<T> MyTrait<T> for MyStruct {} + | ------------------------------- parent `impl` is here +... +LL | async fn foo(_: i32) -> &'static str {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0308]: mismatched types + --> $DIR/missing-feature-flag.rs:18:42 + | +LL | async fn foo(_: i32) -> &'static str {} + | ^^ expected `&str`, found `()` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0046, E0308, E0520. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.next.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.next.stderr new file mode 100644 index 00000000000..e6ac9bc2277 --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-feature-flag.next.stderr @@ -0,0 +1,30 @@ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/missing-feature-flag.rs:14:1 + | +LL | async fn foo(_: T) -> &'static str; + | ----------------------------------- `foo` from trait +... +LL | impl<T> MyTrait<T> for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/missing-feature-flag.rs:18:5 + | +LL | impl<T> MyTrait<T> for MyStruct {} + | ------------------------------- parent `impl` is here +... +LL | async fn foo(_: i32) -> &'static str {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0308]: mismatched types + --> $DIR/missing-feature-flag.rs:18:42 + | +LL | async fn foo(_: i32) -> &'static str {} + | ^^ expected `&str`, found `()` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0046, E0308, E0520. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.rs b/tests/ui/async-await/in-trait/missing-feature-flag.rs new file mode 100644 index 00000000000..6481f4a7059 --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-feature-flag.rs @@ -0,0 +1,23 @@ +// edition:2018 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next + +#![feature(async_fn_in_trait)] +#![feature(min_specialization)] + +struct MyStruct; + +trait MyTrait<T> { + async fn foo(_: T) -> &'static str; +} + +impl<T> MyTrait<T> for MyStruct {} +//~^ ERROR: not all trait items implemented, missing: `foo` [E0046] + +impl MyTrait<i32> for MyStruct { + async fn foo(_: i32) -> &'static str {} + //~^ ERROR: `foo` specializes an item from a parent `impl`, but that item is not marked `default` [E0520] + //~| ERROR: mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/return-not-existing-pair.current.stderr b/tests/ui/async-await/in-trait/return-not-existing-pair.current.stderr new file mode 100644 index 00000000000..56973a1d11a --- /dev/null +++ b/tests/ui/async-await/in-trait/return-not-existing-pair.current.stderr @@ -0,0 +1,39 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/return-not-existing-pair.rs:12:20 + | +LL | impl<'a, 'b, T, U> MyTrait<T> for U { + | ^^^^^^^^^^ expected lifetime parameters + | +help: indicate the anonymous lifetimes + | +LL | impl<'a, 'b, T, U> MyTrait<'_, '_, T> for U { + | +++++++ + +error[E0412]: cannot find type `ConnImpl` in this scope + --> $DIR/return-not-existing-pair.rs:8:48 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T); + | ^^^^^^^^ not found in this scope + +error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl + --> $DIR/return-not-existing-pair.rs:14:5 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T); + | ------------------------------------------------------------ `&self` used in trait +... +LL | async fn foo(_: T) -> (&'a U, &'b T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&self` in impl + +error[E0308]: mismatched types + --> $DIR/return-not-existing-pair.rs:14:42 + | +LL | async fn foo(_: T) -> (&'a U, &'b T) {} + | ^^ expected `(&U, &T)`, found `()` + | + = note: expected tuple `(&'a U, &'b T)` + found unit type `()` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0186, E0308, E0412, E0726. +For more information about an error, try `rustc --explain E0186`. diff --git a/tests/ui/async-await/in-trait/return-not-existing-pair.next.stderr b/tests/ui/async-await/in-trait/return-not-existing-pair.next.stderr new file mode 100644 index 00000000000..56973a1d11a --- /dev/null +++ b/tests/ui/async-await/in-trait/return-not-existing-pair.next.stderr @@ -0,0 +1,39 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/return-not-existing-pair.rs:12:20 + | +LL | impl<'a, 'b, T, U> MyTrait<T> for U { + | ^^^^^^^^^^ expected lifetime parameters + | +help: indicate the anonymous lifetimes + | +LL | impl<'a, 'b, T, U> MyTrait<'_, '_, T> for U { + | +++++++ + +error[E0412]: cannot find type `ConnImpl` in this scope + --> $DIR/return-not-existing-pair.rs:8:48 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T); + | ^^^^^^^^ not found in this scope + +error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl + --> $DIR/return-not-existing-pair.rs:14:5 + | +LL | async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T); + | ------------------------------------------------------------ `&self` used in trait +... +LL | async fn foo(_: T) -> (&'a U, &'b T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&self` in impl + +error[E0308]: mismatched types + --> $DIR/return-not-existing-pair.rs:14:42 + | +LL | async fn foo(_: T) -> (&'a U, &'b T) {} + | ^^ expected `(&U, &T)`, found `()` + | + = note: expected tuple `(&'a U, &'b T)` + found unit type `()` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0186, E0308, E0412, E0726. +For more information about an error, try `rustc --explain E0186`. diff --git a/tests/ui/async-await/in-trait/return-not-existing-pair.rs b/tests/ui/async-await/in-trait/return-not-existing-pair.rs new file mode 100644 index 00000000000..d1b3832d12b --- /dev/null +++ b/tests/ui/async-await/in-trait/return-not-existing-pair.rs @@ -0,0 +1,19 @@ +// edition:2021 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next + +#![feature(async_fn_in_trait)] + +trait MyTrait<'a, 'b, T> { + async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T); + //~^ ERROR: cannot find type `ConnImpl` in this scope [E0412] +} + +impl<'a, 'b, T, U> MyTrait<T> for U { + //~^ ERROR: implicit elided lifetime not allowed here [E0726] + async fn foo(_: T) -> (&'a U, &'b T) {} + //~^ ERROR: method `foo` has a `&self` declaration in the trait, but not in the impl [E0186] + //~| ERROR: mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.current.stderr b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.current.stderr new file mode 100644 index 00000000000..2564d68d591 --- /dev/null +++ b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.current.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/return-not-existing-type-wrapping-rpitit.rs:10:25 + | +LL | fn bar() -> Wrapper<Missing<impl Sized>>; + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.next.stderr b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.next.stderr new file mode 100644 index 00000000000..2564d68d591 --- /dev/null +++ b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.next.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/return-not-existing-type-wrapping-rpitit.rs:10:25 + | +LL | fn bar() -> Wrapper<Missing<impl Sized>>; + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs new file mode 100644 index 00000000000..37c02827e8d --- /dev/null +++ b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs @@ -0,0 +1,20 @@ +// edition:2021 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next + +#![feature(return_position_impl_trait_in_trait)] + +struct Wrapper<T>(T); + +trait Foo { + fn bar() -> Wrapper<Missing<impl Sized>>; + //~^ ERROR: cannot find type `Missing` in this scope [E0412] +} + +impl Foo for () { + fn bar() -> Wrapper<i32> { + Wrapper(0) + } +} + +fn main() {} diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs new file mode 100644 index 00000000000..1b16a492a7a --- /dev/null +++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs @@ -0,0 +1,13 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +// Shouldn't ICE when we have a (bad) RTN in an impl header + +trait Super1<'a> { + fn bar<'b>() -> bool; +} + +impl Super1<'_, bar(): Send> for () {} +//~^ ERROR associated type bindings are not allowed here + +fn main() {} diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr new file mode 100644 index 00000000000..52d8168c9d8 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr @@ -0,0 +1,18 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/rtn-in-impl-signature.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0229]: associated type bindings are not allowed here + --> $DIR/rtn-in-impl-signature.rs:10:17 + | +LL | impl Super1<'_, bar(): Send> for () {} + | ^^^^^^^^^^^ associated type not allowed here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/binop/binop-mul-i32-f32.stderr b/tests/ui/binop/binop-mul-i32-f32.stderr index c986bc3fd1e..115e7000619 100644 --- a/tests/ui/binop/binop-mul-i32-f32.stderr +++ b/tests/ui/binop/binop-mul-i32-f32.stderr @@ -6,10 +6,10 @@ LL | x * y | = help: the trait `Mul<f32>` is not implemented for `i32` = help: the following other types implement trait `Mul<Rhs>`: + <i32 as Mul> + <i32 as Mul<&i32>> <&'a i32 as Mul<i32>> <&i32 as Mul<&i32>> - <i32 as Mul<&i32>> - <i32 as Mul> error: aborting due to previous error diff --git a/tests/ui/binop/shift-various-bad-types.stderr b/tests/ui/binop/shift-various-bad-types.stderr index 38db66f86b4..b43672ef3b5 100644 --- a/tests/ui/binop/shift-various-bad-types.stderr +++ b/tests/ui/binop/shift-various-bad-types.stderr @@ -6,14 +6,14 @@ LL | 22 >> p.char; | = help: the trait `Shr<char>` is not implemented for `{integer}` = help: the following other types implement trait `Shr<Rhs>`: - <&'a i128 as Shr<i128>> - <&'a i128 as Shr<i16>> - <&'a i128 as Shr<i32>> - <&'a i128 as Shr<i64>> - <&'a i128 as Shr<i8>> - <&'a i128 as Shr<isize>> - <&'a i128 as Shr<u128>> - <&'a i128 as Shr<u16>> + <isize as Shr> + <isize as Shr<i8>> + <isize as Shr<i16>> + <isize as Shr<i32>> + <isize as Shr<i64>> + <isize as Shr<i128>> + <isize as Shr<usize>> + <isize as Shr<u8>> and 568 others error[E0277]: no implementation for `{integer} >> &str` @@ -24,14 +24,14 @@ LL | 22 >> p.str; | = help: the trait `Shr<&str>` is not implemented for `{integer}` = help: the following other types implement trait `Shr<Rhs>`: - <&'a i128 as Shr<i128>> - <&'a i128 as Shr<i16>> - <&'a i128 as Shr<i32>> - <&'a i128 as Shr<i64>> - <&'a i128 as Shr<i8>> - <&'a i128 as Shr<isize>> - <&'a i128 as Shr<u128>> - <&'a i128 as Shr<u16>> + <isize as Shr> + <isize as Shr<i8>> + <isize as Shr<i16>> + <isize as Shr<i32>> + <isize as Shr<i64>> + <isize as Shr<i128>> + <isize as Shr<usize>> + <isize as Shr<u8>> and 568 others error[E0277]: no implementation for `{integer} >> &Panolpy` @@ -42,14 +42,14 @@ LL | 22 >> p; | = help: the trait `Shr<&Panolpy>` is not implemented for `{integer}` = help: the following other types implement trait `Shr<Rhs>`: - <&'a i128 as Shr<i128>> - <&'a i128 as Shr<i16>> - <&'a i128 as Shr<i32>> - <&'a i128 as Shr<i64>> - <&'a i128 as Shr<i8>> - <&'a i128 as Shr<isize>> - <&'a i128 as Shr<u128>> - <&'a i128 as Shr<u16>> + <isize as Shr> + <isize as Shr<i8>> + <isize as Shr<i16>> + <isize as Shr<i32>> + <isize as Shr<i64>> + <isize as Shr<i128>> + <isize as Shr<usize>> + <isize as Shr<u8>> and 568 others error[E0308]: mismatched types diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs index d20e79b9db3..0898ca9cda4 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg a(b=c) +// compile-flags: --error-format=human --cfg a(b=c) // error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs index 48d656a4a28..70e42560066 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg a{b} +// compile-flags: --error-format=human --cfg a{b} // error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs index e7dfa17b4b6..2adc27eb932 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg a(b) +// compile-flags: --error-format=human --cfg a(b) // error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs index 9fa726f93e3..be3ded7dd8b 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg a{ +// compile-flags: --error-format=human --cfg a{ // error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs index 1d7fa788534..4a2f16f1133 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg ) +// compile-flags: --error-format=human --cfg ) // error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs index 628b335c873..a61989a3e9f 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs @@ -1,4 +1,4 @@ // Test for missing quotes around value, issue #66450. -// compile-flags: --cfg key=value +// compile-flags: --error-format=human --cfg key=value // error-pattern: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-empty-codemap.rs b/tests/ui/conditional-compilation/cfg-empty-codemap.rs index 9e34cacf74d..c7aded7338a 100644 --- a/tests/ui/conditional-compilation/cfg-empty-codemap.rs +++ b/tests/ui/conditional-compilation/cfg-empty-codemap.rs @@ -1,6 +1,6 @@ // Tests that empty source_maps don't ICE (#23301) -// compile-flags: --cfg "" +// compile-flags: --error-format=human --cfg "" // error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr index e8ebddade5c..4259ce2b626 100644 --- a/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/default-param-wf-concrete.rs:1:28 + --> $DIR/default-param-wf-concrete.rs:4:28 | LL | struct Foo<const N: u8 = { 255 + 1 }>; | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr new file mode 100644 index 00000000000..4259ce2b626 --- /dev/null +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/default-param-wf-concrete.rs:4:28 + | +LL | struct Foo<const N: u8 = { 255 + 1 }>; + | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.rs b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs index 41a52c7eb0d..09a00dd8e70 100644 --- a/tests/ui/const-generics/defaults/default-param-wf-concrete.rs +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -1,3 +1,6 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next + struct Foo<const N: u8 = { 255 + 1 }>; //~^ ERROR evaluation of constant value failed fn main() {} diff --git a/tests/ui/const-generics/exhaustive-value.stderr b/tests/ui/const-generics/exhaustive-value.stderr index 76a83ba67ce..4a26e09772d 100644 --- a/tests/ui/const-generics/exhaustive-value.stderr +++ b/tests/ui/const-generics/exhaustive-value.stderr @@ -6,13 +6,13 @@ LL | <() as Foo<N>>::test() | = help: the following other types implement trait `Foo<N>`: <() as Foo<0>> - <() as Foo<100>> - <() as Foo<101>> - <() as Foo<102>> - <() as Foo<103>> - <() as Foo<104>> - <() as Foo<105>> - <() as Foo<106>> + <() as Foo<1>> + <() as Foo<2>> + <() as Foo<3>> + <() as Foo<4>> + <() as Foo<5>> + <() as Foo<6>> + <() as Foo<7>> and 248 others error: aborting due to previous error diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr index 13ea4a295af..0096d4ee23d 100644 --- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -6,11 +6,11 @@ LL | let y = Mask::<_, _>::splat(false); | = note: cannot satisfy `_: MaskElement` = help: the following types implement trait `MaskElement`: + isize + i8 i16 i32 i64 - i8 - isize note: required by a bound in `Mask::<T, LANES>::splat` --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL help: consider giving `y` an explicit type, where the type for type parameter `T` is specified diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr index 032b0c41047..a2e5b805368 100644 --- a/tests/ui/const-generics/issues/issue-67185-2.stderr +++ b/tests/ui/const-generics/issues/issue-67185-2.stderr @@ -5,8 +5,8 @@ LL | <u8 as Baz>::Quaks: Bar, | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following other types implement trait `Bar`: - [[u16; 3]; 3] [u16; 4] + [[u16; 3]; 3] = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -17,8 +17,8 @@ LL | [<u8 as Baz>::Quaks; 2]: Bar, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following other types implement trait `Bar`: - [[u16; 3]; 3] [u16; 4] + [[u16; 3]; 3] = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -29,8 +29,8 @@ LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following other types implement trait `Bar`: - [[u16; 3]; 3] [u16; 4] + [[u16; 3]; 3] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:15:25 | @@ -47,8 +47,8 @@ LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following other types implement trait `Bar`: - [[u16; 3]; 3] [u16; 4] + [[u16; 3]; 3] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:14:30 | @@ -65,8 +65,8 @@ LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following other types implement trait `Bar`: - [[u16; 3]; 3] [u16; 4] + [[u16; 3]; 3] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:14:30 | @@ -83,8 +83,8 @@ LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following other types implement trait `Bar`: - [[u16; 3]; 3] [u16; 4] + [[u16; 3]; 3] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:15:25 | diff --git a/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr b/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr index 05f33c33946..06e398edca9 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -12,10 +12,10 @@ LL | = [0; (i8::MAX + 1u8) as usize]; | = help: the trait `Add<u8>` is not implemented for `i8` = help: the following other types implement trait `Add<Rhs>`: + <i8 as Add> + <i8 as Add<&i8>> <&'a i8 as Add<i8>> <&i8 as Add<&i8>> - <i8 as Add<&i8>> - <i8 as Add> error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr index d019f5920b5..07ef2ac090f 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -12,10 +12,10 @@ LL | : [u32; (i8::MAX as i8 + 1u8) as usize] | = help: the trait `Add<u8>` is not implemented for `i8` = help: the following other types implement trait `Add<Rhs>`: + <i8 as Add> + <i8 as Add<&i8>> <&'a i8 as Add<i8>> <&i8 as Add<&i8>> - <i8 as Add<&i8>> - <i8 as Add> error[E0604]: only `u8` can be cast as `char`, not `i8` --> $DIR/const-eval-overflow-4b.rs:22:13 diff --git a/tests/ui/consts/const-len-underflow-separate-spans.stderr b/tests/ui/consts/const-len-underflow-separate-spans.next.stderr index 269553631cc..d9208d0706a 100644 --- a/tests/ui/consts/const-len-underflow-separate-spans.stderr +++ b/tests/ui/consts/const-len-underflow-separate-spans.next.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const-len-underflow-separate-spans.rs:7:20 + --> $DIR/const-len-underflow-separate-spans.rs:10:20 | LL | const LEN: usize = ONE - TWO; | ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow note: erroneous constant used - --> $DIR/const-len-underflow-separate-spans.rs:11:17 + --> $DIR/const-len-underflow-separate-spans.rs:14:17 | LL | let a: [i8; LEN] = unimplemented!(); | ^^^ diff --git a/tests/ui/consts/const-len-underflow-separate-spans.old.stderr b/tests/ui/consts/const-len-underflow-separate-spans.old.stderr new file mode 100644 index 00000000000..d9208d0706a --- /dev/null +++ b/tests/ui/consts/const-len-underflow-separate-spans.old.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-len-underflow-separate-spans.rs:10:20 + | +LL | const LEN: usize = ONE - TWO; + | ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow + +note: erroneous constant used + --> $DIR/const-len-underflow-separate-spans.rs:14:17 + | +LL | let a: [i8; LEN] = unimplemented!(); + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-len-underflow-separate-spans.rs b/tests/ui/consts/const-len-underflow-separate-spans.rs index 4544c8876ae..55704b64154 100644 --- a/tests/ui/consts/const-len-underflow-separate-spans.rs +++ b/tests/ui/consts/const-len-underflow-separate-spans.rs @@ -2,6 +2,9 @@ // spot (where the underflow occurred), while also providing the // overall context for what caused the evaluation. +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next + const ONE: usize = 1; const TWO: usize = 2; const LEN: usize = ONE - TWO; diff --git a/tests/ui/consts/const_in_pattern/issue-73431.rs b/tests/ui/consts/const_in_pattern/issue-73431.rs index fa18a3af1b0..835f502b407 100644 --- a/tests/ui/consts/const_in_pattern/issue-73431.rs +++ b/tests/ui/consts/const_in_pattern/issue-73431.rs @@ -1,4 +1,5 @@ // run-pass +// unset-rustc-env:RUSTC_LOG_COLOR // Regression test for https://github.com/rust-lang/rust/issues/73431. diff --git a/tests/ui/consts/missing-larger-array-impl.rs b/tests/ui/consts/missing-larger-array-impl.rs new file mode 100644 index 00000000000..e6c879c8ebd --- /dev/null +++ b/tests/ui/consts/missing-larger-array-impl.rs @@ -0,0 +1,9 @@ +struct X; + +// Make sure that we show the impl trait refs in the help message with +// their evaluated constants, rather than `core::::array::{impl#30}::{constant#0}` + +fn main() { + <[X; 35] as Default>::default(); + //~^ ERROR the trait bound `[X; 35]: Default` is not satisfied +} diff --git a/tests/ui/consts/missing-larger-array-impl.stderr b/tests/ui/consts/missing-larger-array-impl.stderr new file mode 100644 index 00000000000..b8f6cb5ef97 --- /dev/null +++ b/tests/ui/consts/missing-larger-array-impl.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `[X; 35]: Default` is not satisfied + --> $DIR/missing-larger-array-impl.rs:7:5 + | +LL | <[X; 35] as Default>::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[X; 35]` + | + = help: the following other types implement trait `Default`: + [T; 0] + [T; 1] + [T; 2] + [T; 3] + [T; 4] + [T; 5] + [T; 6] + [T; 7] + and 27 others + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.stderr index 5af82a3e34b..843d6d9e04b 100644 --- a/tests/ui/consts/too_generic_eval_ice.stderr +++ b/tests/ui/consts/too_generic_eval_ice.stderr @@ -22,14 +22,14 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]` = help: the following other types implement trait `PartialEq<Rhs>`: - <&[B] as PartialEq<[A; N]>> - <&[T] as PartialEq<Vec<U, A>>> - <&mut [B] as PartialEq<[A; N]>> - <&mut [T] as PartialEq<Vec<U, A>>> - <[A; N] as PartialEq<&[B]>> - <[A; N] as PartialEq<&mut [B]>> <[A; N] as PartialEq<[B; N]>> <[A; N] as PartialEq<[B]>> + <[A; N] as PartialEq<&[B]>> + <[A; N] as PartialEq<&mut [B]>> + <[T] as PartialEq<Vec<U, A>>> + <[A] as PartialEq<[B]>> + <[B] as PartialEq<[A; N]>> + <&[T] as PartialEq<Vec<U, A>>> and 3 others error: aborting due to 3 previous errors diff --git a/tests/ui/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr index b18e1e5098b..01cce2a397a 100644 --- a/tests/ui/deriving/issue-103157.stderr +++ b/tests/ui/deriving/issue-103157.stderr @@ -8,14 +8,14 @@ LL | Float(Option<f64>), | ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64` | = help: the following other types implement trait `Eq`: - i128 + isize + i8 i16 i32 i64 - i8 - isize - u128 - u16 + i128 + usize + u8 and 4 others = note: required for `Option<f64>` to implement `Eq` note: required by a bound in `AssertParamIsEq` diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.rs b/tests/ui/diagnostic-flags/colored-session-opt-error.rs new file mode 100644 index 00000000000..b9f47285c14 --- /dev/null +++ b/tests/ui/diagnostic-flags/colored-session-opt-error.rs @@ -0,0 +1,4 @@ +// check-pass +// ignore-windows +// compile-flags: -Cremark=foo --error-format=human --color always +fn main() {} diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.stderr b/tests/ui/diagnostic-flags/colored-session-opt-error.stderr new file mode 100644 index 00000000000..ef79d5b0f2f --- /dev/null +++ b/tests/ui/diagnostic-flags/colored-session-opt-error.stderr @@ -0,0 +1,2 @@ +[0m[1m[33mwarning[0m[0m[1m: -C remark requires "-C debuginfo=n" to show source locations[0m + diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index 5e0e4a0115a..2d50c09645d 100644 --- a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -7,12 +7,12 @@ LL | f1.foo(1usize); | required by a bound introduced by this call | = help: the following other types implement trait `Foo<A>`: + <Bar as Foo<i8>> <Bar as Foo<i16>> <Bar as Foo<i32>> - <Bar as Foo<i8>> + <Bar as Foo<u8>> <Bar as Foo<u16>> <Bar as Foo<u32>> - <Bar as Foo<u8>> error: aborting due to previous error diff --git a/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index 7229b9ac986..ae15e054f62 100644 --- a/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -8,10 +8,10 @@ LL | Foo::<i32>::bar(&1i8); | = help: the following other types implement trait `Foo<B>`: <i8 as Foo<bool>> + <i8 as Foo<u8>> <i8 as Foo<u16>> <i8 as Foo<u32>> <i8 as Foo<u64>> - <i8 as Foo<u8>> error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 @@ -38,10 +38,10 @@ LL | Foo::<i32>::bar(&true); = help: the following other types implement trait `Foo<B>`: <bool as Foo<bool>> <bool as Foo<i8>> + <bool as Foo<u8>> <bool as Foo<u16>> <bool as Foo<u32>> <bool as Foo<u64>> - <bool as Foo<u8>> error: aborting due to 3 previous errors diff --git a/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr index 26986684f0c..44bdbb93ff5 100644 --- a/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr +++ b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr @@ -23,14 +23,14 @@ LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹ | = help: the trait `Sub<{integer}>` is not implemented for `{float}` = help: the following other types implement trait `Sub<Rhs>`: - <&'a f32 as Sub<f32>> - <&'a f64 as Sub<f64>> - <&'a i128 as Sub<i128>> - <&'a i16 as Sub<i16>> - <&'a i32 as Sub<i32>> - <&'a i64 as Sub<i64>> - <&'a i8 as Sub<i8>> - <&'a isize as Sub<isize>> + <isize as Sub> + <isize as Sub<&isize>> + <i8 as Sub> + <i8 as Sub<&i8>> + <i16 as Sub> + <i16 as Sub<&i16>> + <i32 as Sub> + <i32 as Sub<&i32>> and 48 others error: aborting due to 3 previous errors diff --git a/tests/ui/duplicate/dupe-symbols-7.rs b/tests/ui/duplicate/dupe-symbols-7.rs index 633ca4c3189..4983874729c 100644 --- a/tests/ui/duplicate/dupe-symbols-7.rs +++ b/tests/ui/duplicate/dupe-symbols-7.rs @@ -3,9 +3,6 @@ // // error-pattern: entry symbol `main` declared multiple times -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" #![allow(warnings)] #[no_mangle] diff --git a/tests/ui/duplicate/dupe-symbols-7.stderr b/tests/ui/duplicate/dupe-symbols-7.stderr index 1455f0e75ab..cd5147c0e15 100644 --- a/tests/ui/duplicate/dupe-symbols-7.stderr +++ b/tests/ui/duplicate/dupe-symbols-7.stderr @@ -1,5 +1,5 @@ error: entry symbol `main` declared multiple times - --> $DIR/dupe-symbols-7.rs:12:1 + --> $DIR/dupe-symbols-7.rs:9:1 | LL | fn main(){} | ^^^^^^^^^ diff --git a/tests/ui/dyn-star/box.rs b/tests/ui/dyn-star/box.rs index d1f1819d9f3..87c8356a174 100644 --- a/tests/ui/dyn-star/box.rs +++ b/tests/ui/dyn-star/box.rs @@ -1,5 +1,7 @@ // run-pass -// compile-flags: -C opt-level=0 +// revisions: current next +//[current] compile-flags: -C opt-level=0 +//[next] compile-flags: -Ztrait-solver=next -C opt-level=0 #![feature(dyn_star)] #![allow(incomplete_features)] diff --git a/tests/ui/dyn-star/param-env-region-infer.current.stderr b/tests/ui/dyn-star/param-env-region-infer.current.stderr index c606a50c8a9..902053ecfef 100644 --- a/tests/ui/dyn-star/param-env-region-infer.current.stderr +++ b/tests/ui/dyn-star/param-env-region-infer.current.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/param-env-region-infer.rs:16:10 + --> $DIR/param-env-region-infer.rs:18:10 | LL | t as _ | ^ cannot infer type diff --git a/tests/ui/dyn-star/param-env-region-infer.next.stderr b/tests/ui/dyn-star/param-env-region-infer.next.stderr new file mode 100644 index 00000000000..dd724a65908 --- /dev/null +++ b/tests/ui/dyn-star/param-env-region-infer.next.stderr @@ -0,0 +1,29 @@ +error[E0391]: cycle detected when computing type of `make_dyn_star::{opaque#0}` + --> $DIR/param-env-region-infer.rs:16:60 + | +LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `make_dyn_star`... + --> $DIR/param-env-region-infer.rs:16:1 + | +LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `make_dyn_star::{opaque#0}`... + = note: ...which requires normalizing `make_dyn_star::{opaque#0}`... + = note: ...which again requires computing type of `make_dyn_star::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/param-env-region-infer.rs:10:1 + | +LL | / #![feature(dyn_star, pointer_like_trait)] +LL | | #![allow(incomplete_features)] +LL | | +LL | | use std::fmt::Debug; +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/dyn-star/param-env-region-infer.rs b/tests/ui/dyn-star/param-env-region-infer.rs index 9c337e4a89b..537473abc3a 100644 --- a/tests/ui/dyn-star/param-env-region-infer.rs +++ b/tests/ui/dyn-star/param-env-region-infer.rs @@ -1,6 +1,7 @@ // revisions: current next -//[next] compile-flags: -Ztrait-solver=next -//[next] check-pass +// Need `-Zdeduplicate-diagnostics=yes` because the number of cycle errors +// emitted is for some horrible reason platform-specific. +//[next] compile-flags: -Ztrait-solver=next -Zdeduplicate-diagnostics=yes // incremental // checks that we don't ICE if there are region inference variables in the environment @@ -13,6 +14,7 @@ use std::fmt::Debug; use std::marker::PointerLike; fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a { + //[next]~^ ERROR cycle detected when computing t as _ //[current]~^ ERROR type annotations needed } diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs index 0d019b1f502..3f49020bbea 100644 --- a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs +++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -11,7 +11,7 @@ fn define() -> Bar { type Foo2 = impl Debug; -fn define2() { +fn define2(_: Foo2) { let x = || -> Foo2 { 42 }; } @@ -20,13 +20,13 @@ type Foo3 = impl Debug; fn define3(x: Foo3) { let y: i32 = x; } -fn define3_1() { +fn define3_1(_: Foo3) { define3(42) } type Foo4 = impl Debug; -fn define4() { +fn define4(_: Foo4) { let y: Foo4 = 42; } diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr index b0dddd3b1e8..4c0ac52865d 100644 --- a/tests/ui/fmt/ifmt-unimpl.stderr +++ b/tests/ui/fmt/ifmt-unimpl.stderr @@ -7,14 +7,14 @@ LL | format!("{:X}", "3"); | required by a bound introduced by this call | = help: the following other types implement trait `UpperHex`: - &T - &mut T - NonZeroI128 - NonZeroI16 - NonZeroI32 - NonZeroI64 - NonZeroI8 - NonZeroIsize + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 and 20 others = note: required for `&str` to implement `UpperHex` note: required by a bound in `core::fmt::rt::Argument::<'a>::new_upper_hex` diff --git a/tests/ui/generator/layout-error.rs b/tests/ui/generator/layout-error.rs index 7c3d187409a..44cfc1d70dd 100644 --- a/tests/ui/generator/layout-error.rs +++ b/tests/ui/generator/layout-error.rs @@ -24,5 +24,6 @@ fn main() { type F = impl Future; // Check that statics are inhabited computes they layout. static POOL: Task<F> = Task::new(); + //~^ ERROR: cannot check whether the hidden type of `layout_error[b009]::main::F::{opaque#0}` satisfies auto traits Task::spawn(&POOL, || cb()); } diff --git a/tests/ui/generator/layout-error.stderr b/tests/ui/generator/layout-error.stderr index b1a258f4f2c..ea3b25551c4 100644 --- a/tests/ui/generator/layout-error.stderr +++ b/tests/ui/generator/layout-error.stderr @@ -4,6 +4,24 @@ error[E0425]: cannot find value `Foo` in this scope LL | let a = Foo; | ^^^ not found in this scope -error: aborting due to previous error +error: cannot check whether the hidden type of `layout_error[b009]::main::F::{opaque#0}` satisfies auto traits + --> $DIR/layout-error.rs:26:18 + | +LL | static POOL: Task<F> = Task::new(); + | ^^^^^^^ + | +note: opaque type is declared here + --> $DIR/layout-error.rs:24:14 + | +LL | type F = impl Future; + | ^^^^^^^^^^^ +note: required because it appears within the type `Task<F>` + --> $DIR/layout-error.rs:9:12 + | +LL | pub struct Task<F: Future>(F); + | ^^^^ + = note: shared static variables must have a type that implements `Sync` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.rs b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.rs new file mode 100644 index 00000000000..05d205266b4 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.rs @@ -0,0 +1,29 @@ +// This test checks that we correctly reject the following unsound code. + +trait Lengthen<T> { + fn lengthen(self) -> T; +} + +impl<'a> Lengthen<&'a str> for &'a str { + fn lengthen(self) -> &'a str { self } +} + +trait Gat { + type Gat<'a>: for<'b> Lengthen<Self::Gat<'b>>; + + fn lengthen(s: Self::Gat<'_>) -> Self::Gat<'static> { + s.lengthen() + } +} + +impl Gat for () { + type Gat<'a> = &'a str; //~ ERROR: implementation of `Lengthen` is not general enough +} + +fn main() { + let s = "hello, garbage".to_string(); + let borrow: &'static str = <() as Gat>::lengthen(&s); + drop(s); + + println!("{borrow}"); +} diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr new file mode 100644 index 00000000000..7ea7a7b2de7 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -0,0 +1,11 @@ +error: implementation of `Lengthen` is not general enough + --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20 + | +LL | type Gat<'a> = &'a str; + | ^^^^^^^ implementation of `Lengthen` is not general enough + | + = note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... + = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-90014-tait.rs b/tests/ui/generic-associated-types/issue-90014-tait.rs new file mode 100644 index 00000000000..bc3a4e12965 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90014-tait.rs @@ -0,0 +1,23 @@ +//! This test is reporting the wrong error. We need +//! more inherent associated type tests that use opaque types +//! in general. Some variant of this test should compile successfully. +// known-bug: unknown +// edition:2018 + +#![feature(impl_trait_in_assoc_type, inherent_associated_types)] +#![allow(incomplete_features)] + +use std::future::Future; + +struct Foo<'a>(&'a mut ()); + +impl Foo<'_> { + type Fut<'a> = impl Future<Output = ()>; + //^ ERROR: the type `&mut ()` does not fulfill the required lifetime + + fn make_fut<'a>(&'a self) -> Self::Fut<'a> { + async { () } + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-90014-tait.stderr b/tests/ui/generic-associated-types/issue-90014-tait.stderr new file mode 100644 index 00000000000..8330a387ecd --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90014-tait.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/issue-90014-tait.rs:19:9 + | +LL | type Fut<'a> = impl Future<Output = ()>; + | ------------------------ the expected future +... +LL | fn make_fut<'a>(&'a self) -> Self::Fut<'a> { + | ------------- expected `Foo<'_>::Fut<'a>` because of return type +LL | async { () } + | ^^^^^^^^^^^^ expected future, found `async` block + | + = note: expected opaque type `Foo<'_>::Fut<'a>` + found `async` block `[async block@$DIR/issue-90014-tait.rs:19:9: 19:21]` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/issue-90014-tait.rs:18:8 + | +LL | fn make_fut<'a>(&'a self) -> Self::Fut<'a> { + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.rs b/tests/ui/generic-associated-types/issue-90014-tait2.rs new file mode 100644 index 00000000000..dacbc93dec8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90014-tait2.rs @@ -0,0 +1,46 @@ +//! This test checks that opaque type collection doesn't try to normalize the projection +//! without respecting its binders (which would ICE). +//! Unfortunately we don't even reach opaque type collection, as we ICE in typeck before that. +// known-bug: #109281 +// failure-status: 101 +// error-pattern:internal compiler error +// normalize-stderr-test "internal compiler error.*" -> "" +// normalize-stderr-test "DefId\([^)]*\)" -> "..." +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" +// normalize-stderr-test "thread.*panicked.*\n" -> "" +// normalize-stderr-test "stack backtrace:\n" -> "" +// normalize-stderr-test "\s\d{1,}: .*\n" -> "" +// normalize-stderr-test "\s at .*\n" -> "" +// normalize-stderr-test ".*note: Some details.*\n" -> "" +// normalize-stderr-test "\n\n[ ]*\n" -> "" +// normalize-stderr-test "compiler/.*: projection" -> "projection" +// edition:2018 + +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +struct Foo<'a>(&'a mut ()); + +type Fut<'a> = impl Future<Output = ()>; + +trait Trait<'x> { + type Thing; +} + +impl<'x, T: 'x> Trait<'x> for (T,) { + type Thing = T; +} + +impl Foo<'_> { + fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> { + Box::new((async { () },)) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr new file mode 100644 index 00000000000..3187be3334c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr @@ -0,0 +1,12 @@ +error: + --> $DIR/issue-90014-tait2.rs:41:27 + | +LL | fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^query stack during panic: +#0 [typeck] type-checking `<impl at $DIR/issue-90014-tait2.rs:40:1: 40:13>::make_fut` +#1 [type_of] computing type of `Fut::{opaque#0}` +#2 [check_mod_item_types] checking item types in top-level module +#3 [analysis] running analysis passes on this crate +end of query stack +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/auto-trait-leak.rs b/tests/ui/impl-trait/auto-trait-leak.rs index c2fbbf94fd6..d71c0987935 100644 --- a/tests/ui/impl-trait/auto-trait-leak.rs +++ b/tests/ui/impl-trait/auto-trait-leak.rs @@ -3,21 +3,23 @@ use std::rc::Rc; fn send<T: Send>(_: T) {} -fn main() { -} +fn main() {} // Cycles should work as the deferred obligations are // independently resolved and only require the concrete // return type, which can't depend on the obligation. fn cycle1() -> impl Clone { //~^ ERROR cycle detected + //~| ERROR cycle detected send(cycle2().clone()); + //~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits Rc::new(Cell::new(5)) } fn cycle2() -> impl Clone { send(cycle1().clone()); + //~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits Rc::new(String::from("foo")) } diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr index c0c4cd5013e..92a9763bc9b 100644 --- a/tests/ui/impl-trait/auto-trait-leak.stderr +++ b/tests/ui/impl-trait/auto-trait-leak.stderr @@ -1,5 +1,5 @@ error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}` - --> $DIR/auto-trait-leak.rs:12:16 + --> $DIR/auto-trait-leak.rs:11:16 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^ @@ -11,12 +11,12 @@ LL | send(cycle2().clone()); | ^^^^ = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`... note: ...which requires computing type of `cycle2::{opaque#0}`... - --> $DIR/auto-trait-leak.rs:19:16 + --> $DIR/auto-trait-leak.rs:20:16 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which requires type-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:20:5 + --> $DIR/auto-trait-leak.rs:21:5 | LL | send(cycle1().clone()); | ^^^^ @@ -34,6 +34,89 @@ LL | | Rc::new(String::from("foo")) LL | | } | |_^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}` + --> $DIR/auto-trait-leak.rs:11:16 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ + | +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:14:5 + | +LL | send(cycle2().clone()); + | ^^^^ + = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`... +note: ...which requires computing type of `cycle2::{opaque#0}`... + --> $DIR/auto-trait-leak.rs:20:16 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:20:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/auto-trait-leak.rs:1:1 + | +LL | / use std::cell::Cell; +LL | | use std::rc::Rc; +LL | | +LL | | fn send<T: Send>(_: T) {} +... | +LL | | Rc::new(String::from("foo")) +LL | | } + | |_^ + +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/auto-trait-leak.rs:21:10 + | +LL | send(cycle1().clone()); + | ---- ^^^^^^^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/auto-trait-leak.rs:11:16 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/auto-trait-leak.rs:20:4 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^ +note: required by a bound in `send` + --> $DIR/auto-trait-leak.rs:4:12 + | +LL | fn send<T: Send>(_: T) {} + | ^^^^ required by this bound in `send` + +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/auto-trait-leak.rs:14:10 + | +LL | send(cycle2().clone()); + | ---- ^^^^^^^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/auto-trait-leak.rs:20:16 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/auto-trait-leak.rs:11:4 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^ +note: required by a bound in `send` + --> $DIR/auto-trait-leak.rs:4:12 + | +LL | fn send<T: Send>(_: T) {} + | ^^^^ required by this bound in `send` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs index d2c34792035..7a51aac44e2 100644 --- a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs +++ b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs @@ -8,8 +8,10 @@ impl<T: Fn(i32)> SuperExpectation for T {} type Foo = impl SuperExpectation; -fn main() { +fn bop(_: Foo) { let _: Foo = |x| { let _ = x.to_string(); }; } + +fn main() {} diff --git a/tests/ui/impl-trait/equality.stderr b/tests/ui/impl-trait/equality.stderr index 69f4cbbbf42..9b8bff215e0 100644 --- a/tests/ui/impl-trait/equality.stderr +++ b/tests/ui/impl-trait/equality.stderr @@ -30,10 +30,10 @@ LL | n + sum_to(n - 1) | = help: the trait `Add<impl Foo>` is not implemented for `u32` = help: the following other types implement trait `Add<Rhs>`: + <u32 as Add> + <u32 as Add<&u32>> <&'a u32 as Add<u32>> <&u32 as Add<&u32>> - <u32 as Add<&u32>> - <u32 as Add> error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/impl-trait/in-assoc-type.rs b/tests/ui/impl-trait/in-assoc-type.rs index 36c54bdd6de..38ad2fa6f02 100644 --- a/tests/ui/impl-trait/in-assoc-type.rs +++ b/tests/ui/impl-trait/in-assoc-type.rs @@ -1,3 +1,6 @@ +//! This test checks that we don't allow registering hidden types for +//! opaque types from other impls. + #![feature(impl_trait_in_assoc_type)] trait Foo<T> { diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr index ab3f3a14410..af60da07cac 100644 --- a/tests/ui/impl-trait/in-assoc-type.stderr +++ b/tests/ui/impl-trait/in-assoc-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/in-assoc-type.rs:17:22 + --> $DIR/in-assoc-type.rs:20:22 | LL | type Bar = impl std::fmt::Debug; | -------------------- the expected opaque type @@ -12,7 +12,7 @@ LL | fn foo(&self) -> <Self as Foo<()>>::Bar {} = note: expected opaque type `<() as Foo<()>>::Bar` found unit type `()` note: this item must have the opaque type in its signature in order to be able to register hidden types - --> $DIR/in-assoc-type.rs:17:8 + --> $DIR/in-assoc-type.rs:20:8 | LL | fn foo(&self) -> <Self as Foo<()>>::Bar {} | ^^^ diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.current.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.current.stderr new file mode 100644 index 00000000000..ff30103b771 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.current.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:13:34 + | +LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> { + | ^^^^^^^^^^^^ the trait `Foo<char>` is not implemented for `impl Foo<u8>` + | + = help: the trait `Foo<char>` is implemented for `Bar` +note: required by a bound in `Foo::foo::{opaque#0}` + --> $DIR/return-dont-satisfy-bounds.rs:7:30 + | +LL | fn foo<F2>(self) -> impl Foo<T>; + | ^^^^^^ required by this bound in `Foo::foo::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.next.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.next.stderr new file mode 100644 index 00000000000..7c7f7feaa55 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.next.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:13:34 + | +LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> { + | ^^^^^^^^^^^^ the trait `Foo<char>` is not implemented for `impl Foo<u8>` + | + = help: the trait `Foo<char>` is implemented for `Bar` +note: required by a bound in `Foo::{opaque#0}` + --> $DIR/return-dont-satisfy-bounds.rs:7:30 + | +LL | fn foo<F2>(self) -> impl Foo<T>; + | ^^^^^^ required by this bound in `Foo::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs new file mode 100644 index 00000000000..65528f212e2 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -0,0 +1,19 @@ +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next + +#![feature(return_position_impl_trait_in_trait)] + +trait Foo<T> { + fn foo<F2>(self) -> impl Foo<T>; +} + +struct Bar; + +impl Foo<char> for Bar { + fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> { + //~^ ERROR: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied [E0277] + self + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-103181-2.rs b/tests/ui/impl-trait/issue-103181-2.rs index b43ac45075e..34deb98beef 100644 --- a/tests/ui/impl-trait/issue-103181-2.rs +++ b/tests/ui/impl-trait/issue-103181-2.rs @@ -24,6 +24,8 @@ where B: Send, // <- a second bound { normalize(broken_fut(), ()); + //~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits + //~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits } fn main() {} diff --git a/tests/ui/impl-trait/issue-103181-2.stderr b/tests/ui/impl-trait/issue-103181-2.stderr index 5eb2dd9184b..cb5253ea6cd 100644 --- a/tests/ui/impl-trait/issue-103181-2.stderr +++ b/tests/ui/impl-trait/issue-103181-2.stderr @@ -4,6 +4,61 @@ error[E0425]: cannot find value `ident_error` in this scope LL | ident_error; | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/issue-103181-2.rs:26:15 + | +LL | normalize(broken_fut(), ()); + | --------- ^^^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/issue-103181-2.rs:11:23 + | +LL | async fn broken_fut() { + | ^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/issue-103181-2.rs:20:10 + | +LL | async fn iceice<A, B>() + | ^^^^^^ +note: required for `impl Future<Output = ()>` to implement `SendFuture` + --> $DIR/issue-103181-2.rs:7:17 + | +LL | impl<Fut: Send> SendFuture for Fut { + | ---- ^^^^^^^^^^ ^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `normalize` + --> $DIR/issue-103181-2.rs:18:19 + | +LL | fn normalize<Fut: SendFuture>(_: Fut, _: Fut::Output) {} + | ^^^^^^^^^^ required by this bound in `normalize` + +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/issue-103181-2.rs:26:5 + | +LL | normalize(broken_fut(), ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: opaque type is declared here + --> $DIR/issue-103181-2.rs:11:23 + | +LL | async fn broken_fut() { + | ^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/issue-103181-2.rs:20:10 + | +LL | async fn iceice<A, B>() + | ^^^^^^ +note: required for `impl Future<Output = ()>` to implement `SendFuture` + --> $DIR/issue-103181-2.rs:7:17 + | +LL | impl<Fut: Send> SendFuture for Fut { + | ---- ^^^^^^^^^^ ^^^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/impl-trait/issues/issue-70877.rs b/tests/ui/impl-trait/issues/issue-70877.rs index 8169cfafac7..df772298674 100644 --- a/tests/ui/impl-trait/issues/issue-70877.rs +++ b/tests/ui/impl-trait/issues/issue-70877.rs @@ -25,12 +25,12 @@ fn ham() -> Foo { Bar(1) } -fn oof() -> impl std::fmt::Debug { +fn oof(_: Foo) -> impl std::fmt::Debug { let mut bar = ham(); let func = bar.next().unwrap(); return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type } fn main() { - let _ = oof(); + let _ = oof(ham()); } diff --git a/tests/ui/impl-trait/issues/issue-70877.stderr b/tests/ui/impl-trait/issues/issue-70877.stderr index 8813bff3c35..ee140e6f6c4 100644 --- a/tests/ui/impl-trait/issues/issue-70877.stderr +++ b/tests/ui/impl-trait/issues/issue-70877.stderr @@ -5,10 +5,10 @@ LL | return func(&"oof"); | ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope | note: opaque type whose hidden type is being assigned - --> $DIR/issue-70877.rs:28:13 + --> $DIR/issue-70877.rs:28:19 | -LL | fn oof() -> impl std::fmt::Debug { - | ^^^^^^^^^^^^^^^^^^^^ +LL | fn oof(_: Foo) -> impl std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ note: opaque type being used as hidden type --> $DIR/issue-70877.rs:4:15 | diff --git a/tests/ui/impl-trait/issues/issue-74282.rs b/tests/ui/impl-trait/issues/issue-74282.rs index 654de0cd025..51bd5f67ed5 100644 --- a/tests/ui/impl-trait/issues/issue-74282.rs +++ b/tests/ui/impl-trait/issues/issue-74282.rs @@ -3,9 +3,12 @@ type Closure = impl Fn() -> u64; struct Anonymous(Closure); -fn main() { +fn bop(_: Closure) { let y = || -> Closure { || 3 }; - Anonymous(|| { //~ ERROR mismatched types - 3 //~^ ERROR mismatched types + Anonymous(|| { + //~^ ERROR mismatched types + 3 //~^^ ERROR mismatched types }) } + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr index 724f3c5d674..d43e9fee0b3 100644 --- a/tests/ui/impl-trait/issues/issue-74282.stderr +++ b/tests/ui/impl-trait/issues/issue-74282.stderr @@ -8,6 +8,7 @@ LL | Anonymous(|| { | _____---------_^ | | | | | arguments to this struct are incorrect +LL | | LL | | 3 LL | | }) | |_____^ expected opaque type, found closure @@ -25,15 +26,20 @@ LL | struct Anonymous(Closure); error[E0308]: mismatched types --> $DIR/issue-74282.rs:8:5 | -LL | fn main() { - | - expected `()` because of default return type -LL | let y = || -> Closure { || 3 }; LL | / Anonymous(|| { +LL | | LL | | 3 LL | | }) - | | ^- help: consider using a semicolon here: `;` - | |______| - | expected `()`, found `Anonymous` + | |______^ expected `()`, found `Anonymous` + | +help: consider using a semicolon here + | +LL | }); + | + +help: try adding a return type + | +LL | fn bop(_: Closure) -> Anonymous { + | ++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-78722-2.rs b/tests/ui/impl-trait/issues/issue-78722-2.rs new file mode 100644 index 00000000000..cf5361e1e60 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-78722-2.rs @@ -0,0 +1,22 @@ +//! test that we cannot register hidden types for opaque types +//! declared outside an anonymous constant. +// edition:2018 + +#![feature(type_alias_impl_trait)] + +type F = impl core::future::Future<Output = u8>; + +struct Bug { + V1: [(); { + fn concrete_use() -> F { + //~^ ERROR future that resolves to `u8`, but it resolves to `()` + async {} + } + let f: F = async { 1 }; + //~^ ERROR item constrains opaque type that is not in its signature + //~| ERROR `async` blocks are not allowed in constants + 1 + }], +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr new file mode 100644 index 00000000000..6db603e7751 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr @@ -0,0 +1,32 @@ +error[E0658]: `async` blocks are not allowed in constants + --> $DIR/issue-78722-2.rs:15:20 + | +LL | let f: F = async { 1 }; + | ^^^^^^^^^^^ + | + = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information + = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable + +error[E0271]: expected `[async block@$DIR/issue-78722-2.rs:13:13: 13:21]` to be a future that resolves to `u8`, but it resolves to `()` + --> $DIR/issue-78722-2.rs:11:30 + | +LL | fn concrete_use() -> F { + | ^ expected `()`, found `u8` + +error: item constrains opaque type that is not in its signature + --> $DIR/issue-78722-2.rs:15:20 + | +LL | let f: F = async { 1 }; + | ^^^^^^^^^^^ + | + = note: this item must mention the opaque type in its signature in order to be able to register hidden types +note: this item must mention the opaque type in its signature in order to be able to register hidden types + --> $DIR/issue-78722-2.rs:15:20 + | +LL | let f: F = async { 1 }; + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0658. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/issues/issue-78722.rs b/tests/ui/impl-trait/issues/issue-78722.rs index 7b5ab5f2298..75ccc8d8e8a 100644 --- a/tests/ui/impl-trait/issues/issue-78722.rs +++ b/tests/ui/impl-trait/issues/issue-78722.rs @@ -2,10 +2,9 @@ #![feature(type_alias_impl_trait)] -type F = impl core::future::Future<Output = u8>; - struct Bug { V1: [(); { + type F = impl core::future::Future<Output = u8>; fn concrete_use() -> F { //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()` async {} diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.stderr index 05a2c135cf7..36340a0bab4 100644 --- a/tests/ui/impl-trait/issues/issue-78722.stderr +++ b/tests/ui/impl-trait/issues/issue-78722.stderr @@ -1,5 +1,5 @@ error[E0658]: `async` blocks are not allowed in constants - --> $DIR/issue-78722.rs:13:20 + --> $DIR/issue-78722.rs:12:20 | LL | let f: F = async { 1 }; | ^^^^^^^^^^^ @@ -7,8 +7,8 @@ LL | let f: F = async { 1 }; = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable -error[E0271]: expected `[async block@$DIR/issue-78722.rs:11:13: 11:21]` to be a future that resolves to `u8`, but it resolves to `()` - --> $DIR/issue-78722.rs:9:30 +error[E0271]: expected `[async block@$DIR/issue-78722.rs:10:13: 10:21]` to be a future that resolves to `u8`, but it resolves to `()` + --> $DIR/issue-78722.rs:8:30 | LL | fn concrete_use() -> F { | ^ expected `()`, found `u8` diff --git a/tests/ui/impl-trait/reveal-during-codegen.rs b/tests/ui/impl-trait/reveal-during-codegen.rs new file mode 100644 index 00000000000..11463772eb3 --- /dev/null +++ b/tests/ui/impl-trait/reveal-during-codegen.rs @@ -0,0 +1,11 @@ +// build-pass +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next + +fn test() -> Option<impl Sized> { + Some("") +} + +fn main() { + test(); +} diff --git a/tests/ui/issues/issue-11771.stderr b/tests/ui/issues/issue-11771.stderr index 161fce4b031..b37140f60f9 100644 --- a/tests/ui/issues/issue-11771.stderr +++ b/tests/ui/issues/issue-11771.stderr @@ -6,14 +6,14 @@ LL | 1 + | = help: the trait `Add<()>` is not implemented for `{integer}` = help: the following other types implement trait `Add<Rhs>`: - <&'a f32 as Add<f32>> - <&'a f64 as Add<f64>> - <&'a i128 as Add<i128>> - <&'a i16 as Add<i16>> - <&'a i32 as Add<i32>> - <&'a i64 as Add<i64>> - <&'a i8 as Add<i8>> - <&'a isize as Add<isize>> + <isize as Add> + <isize as Add<&isize>> + <i8 as Add> + <i8 as Add<&i8>> + <i16 as Add> + <i16 as Add<&i16>> + <i32 as Add> + <i32 as Add<&i32>> and 48 others error[E0277]: cannot add `()` to `{integer}` @@ -24,14 +24,14 @@ LL | 1 + | = help: the trait `Add<()>` is not implemented for `{integer}` = help: the following other types implement trait `Add<Rhs>`: - <&'a f32 as Add<f32>> - <&'a f64 as Add<f64>> - <&'a i128 as Add<i128>> - <&'a i16 as Add<i16>> - <&'a i32 as Add<i32>> - <&'a i64 as Add<i64>> - <&'a i8 as Add<i8>> - <&'a isize as Add<isize>> + <isize as Add> + <isize as Add<&isize>> + <i8 as Add> + <i8 as Add<&i8>> + <i16 as Add> + <i16 as Add<&i16>> + <i32 as Add> + <i32 as Add<&i32>> and 48 others error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-24352.stderr b/tests/ui/issues/issue-24352.stderr index 1f51b6e2905..f1c3891b870 100644 --- a/tests/ui/issues/issue-24352.stderr +++ b/tests/ui/issues/issue-24352.stderr @@ -6,10 +6,10 @@ LL | 1.0f64 - 1 | = help: the trait `Sub<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Sub<Rhs>`: + <f64 as Sub> + <f64 as Sub<&f64>> <&'a f64 as Sub<f64>> <&f64 as Sub<&f64>> - <f64 as Sub<&f64>> - <f64 as Sub> help: consider using a floating-point literal by writing it with `.0` | LL | 1.0f64 - 1.0 diff --git a/tests/ui/issues/issue-32709.stderr b/tests/ui/issues/issue-32709.stderr index a4ba5da4d87..94e8f9295fd 100644 --- a/tests/ui/issues/issue-32709.stderr +++ b/tests/ui/issues/issue-32709.stderr @@ -8,6 +8,7 @@ LL | Err(5)?; | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following other types implement trait `From<T>`: + <(T,) as From<[T; 1]>> <(T, T) as From<[T; 2]>> <(T, T, T) as From<[T; 3]>> <(T, T, T, T) as From<[T; 4]>> @@ -15,7 +16,6 @@ LL | Err(5)?; <(T, T, T, T, T, T) as From<[T; 6]>> <(T, T, T, T, T, T, T) as From<[T; 7]>> <(T, T, T, T, T, T, T, T) as From<[T; 8]>> - <(T, T, T, T, T, T, T, T, T) as From<[T; 9]>> and 4 others = note: required for `Result<i32, ()>` to implement `FromResidual<Result<Infallible, {integer}>>` diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr index 3d527eb6b4e..9eafd7ab4f0 100644 --- a/tests/ui/issues/issue-50582.stderr +++ b/tests/ui/issues/issue-50582.stderr @@ -15,14 +15,14 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); | = help: the trait `Add<()>` is not implemented for `{integer}` = help: the following other types implement trait `Add<Rhs>`: - <&'a f32 as Add<f32>> - <&'a f64 as Add<f64>> - <&'a i128 as Add<i128>> - <&'a i16 as Add<i16>> - <&'a i32 as Add<i32>> - <&'a i64 as Add<i64>> - <&'a i8 as Add<i8>> - <&'a isize as Add<isize>> + <isize as Add> + <isize as Add<&isize>> + <i8 as Add> + <i8 as Add<&i8>> + <i16 as Add> + <i16 as Add<&i16>> + <i32 as Add> + <i32 as Add<&i32>> and 48 others error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-67552.rs b/tests/ui/issues/issue-67552.rs index ec1997ccd5d..7336b873dd6 100644 --- a/tests/ui/issues/issue-67552.rs +++ b/tests/ui/issues/issue-67552.rs @@ -1,6 +1,7 @@ // build-fail // compile-flags: -Copt-level=0 // normalize-stderr-test: ".nll/" -> "/" +// ignore-compare-mode-next-solver (hangs) fn main() { rec(Empty); diff --git a/tests/ui/issues/issue-67552.stderr b/tests/ui/issues/issue-67552.stderr index 4746f918bf8..f93ed67dab2 100644 --- a/tests/ui/issues/issue-67552.stderr +++ b/tests/ui/issues/issue-67552.stderr @@ -1,11 +1,11 @@ error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut ...>` - --> $DIR/issue-67552.rs:29:9 + --> $DIR/issue-67552.rs:30:9 | LL | rec(identity(&mut it)) | ^^^^^^^^^^^^^^^^^^^^^^ | note: `rec` defined here - --> $DIR/issue-67552.rs:22:1 + --> $DIR/issue-67552.rs:23:1 | LL | / fn rec<T>(mut it: T) LL | | where diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr index 3cb5e44c711..7f1b9c38e67 100644 --- a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr +++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr @@ -6,8 +6,8 @@ LL | let x = Some(()).iter().map(|()| 1).sum::<f32>(); | = help: the trait `Sum<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Sum<A>`: - <f32 as Sum<&'a f32>> <f32 as Sum> + <f32 as Sum<&'a f32>> note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain-with-int-infer.rs:2:29 | diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr index f3dceca7e41..a2688107d10 100644 --- a/tests/ui/iterators/invalid-iterator-chain.stderr +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -24,8 +24,8 @@ LL | println!("{}", scores.sum::<i32>()); | = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum<A>`: - <i32 as Sum<&'a i32>> <i32 as Sum> + <i32 as Sum<&'a i32>> note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:12:10 | @@ -49,8 +49,8 @@ LL | .sum::<i32>(), | = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum<A>`: - <i32 as Sum<&'a i32>> <i32 as Sum> + <i32 as Sum<&'a i32>> note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:25:14 | @@ -81,8 +81,8 @@ LL | .sum::<i32>(), | = help: the trait `Sum<f64>` is not implemented for `i32` = help: the following other types implement trait `Sum<A>`: - <i32 as Sum<&'a i32>> <i32 as Sum> + <i32 as Sum<&'a i32>> note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:33:14 | @@ -109,8 +109,8 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); | = help: the trait `Sum<()>` is not implemented for `i32` = help: the following other types implement trait `Sum<A>`: - <i32 as Sum<&'a i32>> <i32 as Sum> + <i32 as Sum<&'a i32>> note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:38:38 | @@ -130,8 +130,8 @@ LL | println!("{}", vec![(), ()].iter().sum::<i32>()); | = help: the trait `Sum<&()>` is not implemented for `i32` = help: the following other types implement trait `Sum<A>`: - <i32 as Sum<&'a i32>> <i32 as Sum> + <i32 as Sum<&'a i32>> note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:39:33 | diff --git a/tests/ui/limits/huge-array-simple-32.rs b/tests/ui/limits/huge-array-simple-32.rs index 2290e3d5e76..f25b8887402 100644 --- a/tests/ui/limits/huge-array-simple-32.rs +++ b/tests/ui/limits/huge-array-simple-32.rs @@ -1,9 +1,6 @@ // ignore-64bit // build-fail -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" #![allow(arithmetic_overflow)] fn main() { diff --git a/tests/ui/limits/huge-array-simple-32.stderr b/tests/ui/limits/huge-array-simple-32.stderr index 31e120df626..d1e4e6295a9 100644 --- a/tests/ui/limits/huge-array-simple-32.stderr +++ b/tests/ui/limits/huge-array-simple-32.stderr @@ -1,5 +1,5 @@ error: values of the type `[u8; 2147516416]` are too big for the current architecture - --> $DIR/huge-array-simple-32.rs:10:9 + --> $DIR/huge-array-simple-32.rs:7:9 | LL | let _fat: [u8; (1<<31)+(1<<15)] = | ^^^^ diff --git a/tests/ui/limits/huge-array-simple-64.rs b/tests/ui/limits/huge-array-simple-64.rs index 02c961fc5fa..c5778c428ae 100644 --- a/tests/ui/limits/huge-array-simple-64.rs +++ b/tests/ui/limits/huge-array-simple-64.rs @@ -1,9 +1,6 @@ // build-fail // ignore-32bit -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" #![allow(arithmetic_overflow)] fn main() { diff --git a/tests/ui/limits/huge-array-simple-64.stderr b/tests/ui/limits/huge-array-simple-64.stderr index c5d3fe85d0d..5791b6439c9 100644 --- a/tests/ui/limits/huge-array-simple-64.stderr +++ b/tests/ui/limits/huge-array-simple-64.stderr @@ -1,5 +1,5 @@ error: values of the type `[u8; 2305843011361177600]` are too big for the current architecture - --> $DIR/huge-array-simple-64.rs:10:9 + --> $DIR/huge-array-simple-64.rs:7:9 | LL | let _fat: [u8; (1<<61)+(1<<31)] = | ^^^^ diff --git a/tests/ui/limits/huge-array.rs b/tests/ui/limits/huge-array.rs index 3070801f865..811cf25dd76 100644 --- a/tests/ui/limits/huge-array.rs +++ b/tests/ui/limits/huge-array.rs @@ -1,8 +1,4 @@ -// FIXME https://github.com/rust-lang/rust/issues/59774 - // build-fail -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" fn generic<T: Copy>(t: T) { let s: [T; 1518600000] = [t; 1518600000]; diff --git a/tests/ui/limits/huge-array.stderr b/tests/ui/limits/huge-array.stderr index 817458b73e4..24adb33b088 100644 --- a/tests/ui/limits/huge-array.stderr +++ b/tests/ui/limits/huge-array.stderr @@ -1,5 +1,5 @@ error: values of the type `[[u8; 1518599999]; 1518600000]` are too big for the current architecture - --> $DIR/huge-array.rs:8:9 + --> $DIR/huge-array.rs:4:9 | LL | let s: [T; 1518600000] = [t; 1518600000]; | ^ diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs index 39ea6e11b1f..dd4bae60d3e 100644 --- a/tests/ui/limits/huge-enum.rs +++ b/tests/ui/limits/huge-enum.rs @@ -2,10 +2,6 @@ // normalize-stderr-test "std::option::Option<\[u32; \d+\]>" -> "TYPE" // normalize-stderr-test "\[u32; \d+\]" -> "TYPE" -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" - #[cfg(target_pointer_width = "32")] type BIG = Option<[u32; (1<<29)-1]>; diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.stderr index a1456e1a8ab..5e2bda9be50 100644 --- a/tests/ui/limits/huge-enum.stderr +++ b/tests/ui/limits/huge-enum.stderr @@ -1,5 +1,5 @@ error: values of the type `Option<TYPE>` are too big for the current architecture - --> $DIR/huge-enum.rs:16:9 + --> $DIR/huge-enum.rs:12:9 | LL | let big: BIG = None; | ^^^ diff --git a/tests/ui/limits/huge-struct.rs b/tests/ui/limits/huge-struct.rs index 02f38d860b4..904e2774b19 100644 --- a/tests/ui/limits/huge-struct.rs +++ b/tests/ui/limits/huge-struct.rs @@ -3,10 +3,6 @@ // normalize-stderr-test "S1M" -> "SXX" // error-pattern: too big for the current -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" - struct S32<T> { v0: T, v1: T, diff --git a/tests/ui/limits/huge-struct.stderr b/tests/ui/limits/huge-struct.stderr index f0ee88e5955..ce14bc5b888 100644 --- a/tests/ui/limits/huge-struct.stderr +++ b/tests/ui/limits/huge-struct.stderr @@ -1,5 +1,5 @@ error: values of the type `SXX<SXX<SXX<u32>>>` are too big for the current architecture - --> $DIR/huge-struct.rs:50:9 + --> $DIR/huge-struct.rs:46:9 | LL | let fat: Option<SXX<SXX<SXX<u32>>>> = None; | ^^^ diff --git a/tests/ui/limits/issue-15919-32.rs b/tests/ui/limits/issue-15919-32.rs index 3c93f14ccc7..3254cb2c5bb 100644 --- a/tests/ui/limits/issue-15919-32.rs +++ b/tests/ui/limits/issue-15919-32.rs @@ -1,10 +1,6 @@ // ignore-64bit // build-fail -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" - fn main() { let x = [0usize; 0xffff_ffff]; //~ ERROR too big } diff --git a/tests/ui/limits/issue-15919-32.stderr b/tests/ui/limits/issue-15919-32.stderr index 0d79fc0c770..f9e48a52cb9 100644 --- a/tests/ui/limits/issue-15919-32.stderr +++ b/tests/ui/limits/issue-15919-32.stderr @@ -1,5 +1,5 @@ error: values of the type `[usize; usize::MAX]` are too big for the current architecture - --> $DIR/issue-15919-32.rs:9:9 + --> $DIR/issue-15919-32.rs:5:9 | LL | let x = [0usize; 0xffff_ffff]; | ^ diff --git a/tests/ui/limits/issue-15919-64.rs b/tests/ui/limits/issue-15919-64.rs index 3ecbd34eaaa..272e8800d68 100644 --- a/tests/ui/limits/issue-15919-64.rs +++ b/tests/ui/limits/issue-15919-64.rs @@ -1,10 +1,6 @@ // build-fail // ignore-32bit -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" - fn main() { let x = [0usize; 0xffff_ffff_ffff_ffff]; //~ ERROR too big } diff --git a/tests/ui/limits/issue-15919-64.stderr b/tests/ui/limits/issue-15919-64.stderr index 3399d644ede..167272890aa 100644 --- a/tests/ui/limits/issue-15919-64.stderr +++ b/tests/ui/limits/issue-15919-64.stderr @@ -1,5 +1,5 @@ error: values of the type `[usize; usize::MAX]` are too big for the current architecture - --> $DIR/issue-15919-64.rs:9:9 + --> $DIR/issue-15919-64.rs:5:9 | LL | let x = [0usize; 0xffff_ffff_ffff_ffff]; | ^ diff --git a/tests/ui/limits/issue-17913.rs b/tests/ui/limits/issue-17913.rs index 56cf5d831bd..6b37d6f0551 100644 --- a/tests/ui/limits/issue-17913.rs +++ b/tests/ui/limits/issue-17913.rs @@ -2,10 +2,6 @@ // normalize-stderr-test "\[&usize; \d+\]" -> "[&usize; usize::MAX]" // error-pattern: too big for the current architecture -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" - #[cfg(target_pointer_width = "64")] fn main() { let n = 0_usize; diff --git a/tests/ui/limits/issue-56762.rs b/tests/ui/limits/issue-56762.rs index fb0a270f18b..ed7ee4da85d 100644 --- a/tests/ui/limits/issue-56762.rs +++ b/tests/ui/limits/issue-56762.rs @@ -1,8 +1,5 @@ // only-x86_64 -// FIXME https://github.com/rust-lang/rust/issues/59774 -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" const HUGE_SIZE: usize = !0usize / 8; diff --git a/tests/ui/limits/issue-56762.stderr b/tests/ui/limits/issue-56762.stderr index e6b9c676278..29f2a8859ee 100644 --- a/tests/ui/limits/issue-56762.stderr +++ b/tests/ui/limits/issue-56762.stderr @@ -1,11 +1,11 @@ error[E0080]: values of the type `[u8; 2305843009213693951]` are too big for the current architecture - --> $DIR/issue-56762.rs:19:1 + --> $DIR/issue-56762.rs:16:1 | LL | static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: values of the type `[u8; 2305843009213693951]` are too big for the current architecture - --> $DIR/issue-56762.rs:21:1 + --> $DIR/issue-56762.rs:18:1 | LL | static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/linkage-attr/linkage3.rs b/tests/ui/linkage-attr/linkage3.rs index 112eb1d3bd9..cac10af6338 100644 --- a/tests/ui/linkage-attr/linkage3.rs +++ b/tests/ui/linkage-attr/linkage3.rs @@ -1,8 +1,4 @@ -// FIXME https://github.com/rust-lang/rust/issues/59774 - // check-fail -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" #![feature(linkage)] diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr index f2579c6e850..dbb5880ab92 100644 --- a/tests/ui/linkage-attr/linkage3.stderr +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -1,5 +1,5 @@ error: invalid linkage specified - --> $DIR/linkage3.rs:11:5 + --> $DIR/linkage3.rs:7:5 | LL | static foo: *const i32; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/issue-99387.rs b/tests/ui/lint/issue-99387.rs index 616eb935e93..ba5031167e3 100644 --- a/tests/ui/lint/issue-99387.rs +++ b/tests/ui/lint/issue-99387.rs @@ -1,4 +1,5 @@ -// check-pass +//! Test that we don't follow through projections to find +//! opaque types. #![feature(type_alias_impl_trait)] #![allow(private_in_public)] @@ -18,6 +19,7 @@ impl<'a> Tr for &'a () { } pub fn ohno<'a>() -> <&'a () as Tr>::Item { + //~^ ERROR item constrains opaque type that is not in its signature None.into_iter() } diff --git a/tests/ui/lint/issue-99387.stderr b/tests/ui/lint/issue-99387.stderr new file mode 100644 index 00000000000..3a46ce7e195 --- /dev/null +++ b/tests/ui/lint/issue-99387.stderr @@ -0,0 +1,15 @@ +error: item constrains opaque type that is not in its signature + --> $DIR/issue-99387.rs:21:22 + | +LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item { + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this item must mention the opaque type in its signature in order to be able to register hidden types +note: this item must mention the opaque type in its signature in order to be able to register hidden types + --> $DIR/issue-99387.rs:21:8 + | +LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item { + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/mismatched_types/binops.stderr b/tests/ui/mismatched_types/binops.stderr index 3585587ed4c..b18ab7f7608 100644 --- a/tests/ui/mismatched_types/binops.stderr +++ b/tests/ui/mismatched_types/binops.stderr @@ -6,14 +6,14 @@ LL | 1 + Some(1); | = help: the trait `Add<Option<{integer}>>` is not implemented for `{integer}` = help: the following other types implement trait `Add<Rhs>`: - <&'a f32 as Add<f32>> - <&'a f64 as Add<f64>> - <&'a i128 as Add<i128>> - <&'a i16 as Add<i16>> - <&'a i32 as Add<i32>> - <&'a i64 as Add<i64>> - <&'a i8 as Add<i8>> - <&'a isize as Add<isize>> + <isize as Add> + <isize as Add<&isize>> + <i8 as Add> + <i8 as Add<&i8>> + <i16 as Add> + <i16 as Add<&i16>> + <i32 as Add> + <i32 as Add<&i32>> and 48 others error[E0277]: cannot subtract `Option<{integer}>` from `usize` @@ -24,10 +24,10 @@ LL | 2 as usize - Some(1); | = help: the trait `Sub<Option<{integer}>>` is not implemented for `usize` = help: the following other types implement trait `Sub<Rhs>`: + <usize as Sub> + <usize as Sub<&usize>> <&'a usize as Sub<usize>> <&usize as Sub<&usize>> - <usize as Sub<&usize>> - <usize as Sub> error[E0277]: cannot multiply `{integer}` by `()` --> $DIR/binops.rs:4:7 @@ -37,14 +37,14 @@ LL | 3 * (); | = help: the trait `Mul<()>` is not implemented for `{integer}` = help: the following other types implement trait `Mul<Rhs>`: - <&'a f32 as Mul<f32>> - <&'a f64 as Mul<f64>> - <&'a i128 as Mul<i128>> - <&'a i16 as Mul<i16>> - <&'a i32 as Mul<i32>> - <&'a i64 as Mul<i64>> - <&'a i8 as Mul<i8>> - <&'a isize as Mul<isize>> + <isize as Mul> + <isize as Mul<&isize>> + <i8 as Mul> + <i8 as Mul<&i8>> + <i16 as Mul> + <i16 as Mul<&i16>> + <i32 as Mul> + <i32 as Mul<&i32>> and 49 others error[E0277]: cannot divide `{integer}` by `&str` @@ -55,14 +55,14 @@ LL | 4 / ""; | = help: the trait `Div<&str>` is not implemented for `{integer}` = help: the following other types implement trait `Div<Rhs>`: - <&'a f32 as Div<f32>> - <&'a f64 as Div<f64>> - <&'a i128 as Div<i128>> - <&'a i16 as Div<i16>> - <&'a i32 as Div<i32>> - <&'a i64 as Div<i64>> - <&'a i8 as Div<i8>> - <&'a isize as Div<isize>> + <isize as Div> + <isize as Div<&isize>> + <i8 as Div> + <i8 as Div<&i8>> + <i16 as Div> + <i16 as Div<&i16>> + <i32 as Div> + <i32 as Div<&i32>> and 54 others error[E0277]: can't compare `{integer}` with `String` @@ -73,14 +73,14 @@ LL | 5 < String::new(); | = help: the trait `PartialOrd<String>` is not implemented for `{integer}` = help: the following other types implement trait `PartialOrd<Rhs>`: - f32 - f64 - i128 + isize + i8 i16 i32 i64 - i8 - isize + i128 + usize + u8 and 6 others error[E0277]: can't compare `{integer}` with `Result<{integer}, _>` @@ -91,14 +91,14 @@ LL | 6 == Ok(1); | = help: the trait `PartialEq<Result<{integer}, _>>` is not implemented for `{integer}` = help: the following other types implement trait `PartialEq<Rhs>`: - f32 - f64 - i128 + isize + i8 i16 i32 i64 - i8 - isize + i128 + usize + u8 and 6 others error: aborting due to 6 previous errors diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr index 3215c4669d5..df29fe22713 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr +++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr @@ -7,8 +7,8 @@ LL | unconstrained_arg(return); | required by a bound introduced by this call | = help: the following other types implement trait `Test`: - () i32 + () = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `unconstrained_arg` diff --git a/tests/ui/never_type/issue-13352.stderr b/tests/ui/never_type/issue-13352.stderr index 2d22da0b420..406785bfea0 100644 --- a/tests/ui/never_type/issue-13352.stderr +++ b/tests/ui/never_type/issue-13352.stderr @@ -6,10 +6,10 @@ LL | 2_usize + (loop {}); | = help: the trait `Add<()>` is not implemented for `usize` = help: the following other types implement trait `Add<Rhs>`: + <usize as Add> + <usize as Add<&usize>> <&'a usize as Add<usize>> <&usize as Add<&usize>> - <usize as Add<&usize>> - <usize as Add> error: aborting due to previous error diff --git a/tests/ui/nll/user-annotations/normalization-2.stderr b/tests/ui/nll/user-annotations/normalization-2.stderr index 5299282ea15..6b0dcb414ae 100644 --- a/tests/ui/nll/user-annotations/normalization-2.stderr +++ b/tests/ui/nll/user-annotations/normalization-2.stderr @@ -147,7 +147,7 @@ LL | fn test_variants<'a, 'b, 'c>() { | -- lifetime `'b` defined here ... LL | <Ty<'b>>::Tuple(); - | ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + | ^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` error: lifetime may not live long enough --> $DIR/normalization-2.rs:93:5 diff --git a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr index 8f0eef237cf..e1825eb5b54 100644 --- a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr +++ b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -6,10 +6,10 @@ LL | x + 100.0 | = help: the trait `Add<{float}>` is not implemented for `u8` = help: the following other types implement trait `Add<Rhs>`: + <u8 as Add> + <u8 as Add<&u8>> <&'a u8 as Add<u8>> <&u8 as Add<&u8>> - <u8 as Add<&u8>> - <u8 as Add> error[E0277]: cannot add `&str` to `f64` --> $DIR/not-suggest-float-literal.rs:6:7 @@ -19,10 +19,10 @@ LL | x + "foo" | = help: the trait `Add<&str>` is not implemented for `f64` = help: the following other types implement trait `Add<Rhs>`: + <f64 as Add> + <f64 as Add<&f64>> <&'a f64 as Add<f64>> <&f64 as Add<&f64>> - <f64 as Add<&f64>> - <f64 as Add> error[E0277]: cannot add `{integer}` to `f64` --> $DIR/not-suggest-float-literal.rs:11:7 @@ -32,10 +32,10 @@ LL | x + y | = help: the trait `Add<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Add<Rhs>`: + <f64 as Add> + <f64 as Add<&f64>> <&'a f64 as Add<f64>> <&f64 as Add<&f64>> - <f64 as Add<&f64>> - <f64 as Add> error[E0277]: cannot subtract `{float}` from `u8` --> $DIR/not-suggest-float-literal.rs:15:7 @@ -45,10 +45,10 @@ LL | x - 100.0 | = help: the trait `Sub<{float}>` is not implemented for `u8` = help: the following other types implement trait `Sub<Rhs>`: + <u8 as Sub> + <u8 as Sub<&u8>> <&'a u8 as Sub<u8>> <&u8 as Sub<&u8>> - <u8 as Sub<&u8>> - <u8 as Sub> error[E0277]: cannot subtract `&str` from `f64` --> $DIR/not-suggest-float-literal.rs:19:7 @@ -58,10 +58,10 @@ LL | x - "foo" | = help: the trait `Sub<&str>` is not implemented for `f64` = help: the following other types implement trait `Sub<Rhs>`: + <f64 as Sub> + <f64 as Sub<&f64>> <&'a f64 as Sub<f64>> <&f64 as Sub<&f64>> - <f64 as Sub<&f64>> - <f64 as Sub> error[E0277]: cannot subtract `{integer}` from `f64` --> $DIR/not-suggest-float-literal.rs:24:7 @@ -71,10 +71,10 @@ LL | x - y | = help: the trait `Sub<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Sub<Rhs>`: + <f64 as Sub> + <f64 as Sub<&f64>> <&'a f64 as Sub<f64>> <&f64 as Sub<&f64>> - <f64 as Sub<&f64>> - <f64 as Sub> error[E0277]: cannot multiply `u8` by `{float}` --> $DIR/not-suggest-float-literal.rs:28:7 @@ -84,10 +84,10 @@ LL | x * 100.0 | = help: the trait `Mul<{float}>` is not implemented for `u8` = help: the following other types implement trait `Mul<Rhs>`: + <u8 as Mul> + <u8 as Mul<&u8>> <&'a u8 as Mul<u8>> <&u8 as Mul<&u8>> - <u8 as Mul<&u8>> - <u8 as Mul> error[E0277]: cannot multiply `f64` by `&str` --> $DIR/not-suggest-float-literal.rs:32:7 @@ -97,10 +97,10 @@ LL | x * "foo" | = help: the trait `Mul<&str>` is not implemented for `f64` = help: the following other types implement trait `Mul<Rhs>`: + <f64 as Mul> + <f64 as Mul<&f64>> <&'a f64 as Mul<f64>> <&f64 as Mul<&f64>> - <f64 as Mul<&f64>> - <f64 as Mul> error[E0277]: cannot multiply `f64` by `{integer}` --> $DIR/not-suggest-float-literal.rs:37:7 @@ -110,10 +110,10 @@ LL | x * y | = help: the trait `Mul<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Mul<Rhs>`: + <f64 as Mul> + <f64 as Mul<&f64>> <&'a f64 as Mul<f64>> <&f64 as Mul<&f64>> - <f64 as Mul<&f64>> - <f64 as Mul> error[E0277]: cannot divide `u8` by `{float}` --> $DIR/not-suggest-float-literal.rs:41:7 @@ -123,11 +123,11 @@ LL | x / 100.0 | = help: the trait `Div<{float}>` is not implemented for `u8` = help: the following other types implement trait `Div<Rhs>`: + <u8 as Div> + <u8 as Div<NonZeroU8>> + <u8 as Div<&u8>> <&'a u8 as Div<u8>> <&u8 as Div<&u8>> - <u8 as Div<&u8>> - <u8 as Div<NonZeroU8>> - <u8 as Div> error[E0277]: cannot divide `f64` by `&str` --> $DIR/not-suggest-float-literal.rs:45:7 @@ -137,10 +137,10 @@ LL | x / "foo" | = help: the trait `Div<&str>` is not implemented for `f64` = help: the following other types implement trait `Div<Rhs>`: + <f64 as Div> + <f64 as Div<&f64>> <&'a f64 as Div<f64>> <&f64 as Div<&f64>> - <f64 as Div<&f64>> - <f64 as Div> error[E0277]: cannot divide `f64` by `{integer}` --> $DIR/not-suggest-float-literal.rs:50:7 @@ -150,10 +150,10 @@ LL | x / y | = help: the trait `Div<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Div<Rhs>`: + <f64 as Div> + <f64 as Div<&f64>> <&'a f64 as Div<f64>> <&f64 as Div<&f64>> - <f64 as Div<&f64>> - <f64 as Div> error: aborting due to 12 previous errors diff --git a/tests/ui/numbers-arithmetic/suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/suggest-float-literal.stderr index 03779d35637..929a9e3b595 100644 --- a/tests/ui/numbers-arithmetic/suggest-float-literal.stderr +++ b/tests/ui/numbers-arithmetic/suggest-float-literal.stderr @@ -6,10 +6,10 @@ LL | x + 100 | = help: the trait `Add<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Add<Rhs>`: + <f32 as Add> + <f32 as Add<&f32>> <&'a f32 as Add<f32>> <&f32 as Add<&f32>> - <f32 as Add<&f32>> - <f32 as Add> help: consider using a floating-point literal by writing it with `.0` | LL | x + 100.0 @@ -23,10 +23,10 @@ LL | x + 100 | = help: the trait `Add<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Add<Rhs>`: + <f64 as Add> + <f64 as Add<&f64>> <&'a f64 as Add<f64>> <&f64 as Add<&f64>> - <f64 as Add<&f64>> - <f64 as Add> help: consider using a floating-point literal by writing it with `.0` | LL | x + 100.0 @@ -40,10 +40,10 @@ LL | x - 100 | = help: the trait `Sub<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Sub<Rhs>`: + <f32 as Sub> + <f32 as Sub<&f32>> <&'a f32 as Sub<f32>> <&f32 as Sub<&f32>> - <f32 as Sub<&f32>> - <f32 as Sub> help: consider using a floating-point literal by writing it with `.0` | LL | x - 100.0 @@ -57,10 +57,10 @@ LL | x - 100 | = help: the trait `Sub<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Sub<Rhs>`: + <f64 as Sub> + <f64 as Sub<&f64>> <&'a f64 as Sub<f64>> <&f64 as Sub<&f64>> - <f64 as Sub<&f64>> - <f64 as Sub> help: consider using a floating-point literal by writing it with `.0` | LL | x - 100.0 @@ -74,10 +74,10 @@ LL | x * 100 | = help: the trait `Mul<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Mul<Rhs>`: + <f32 as Mul> + <f32 as Mul<&f32>> <&'a f32 as Mul<f32>> <&f32 as Mul<&f32>> - <f32 as Mul<&f32>> - <f32 as Mul> help: consider using a floating-point literal by writing it with `.0` | LL | x * 100.0 @@ -91,10 +91,10 @@ LL | x * 100 | = help: the trait `Mul<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Mul<Rhs>`: + <f64 as Mul> + <f64 as Mul<&f64>> <&'a f64 as Mul<f64>> <&f64 as Mul<&f64>> - <f64 as Mul<&f64>> - <f64 as Mul> help: consider using a floating-point literal by writing it with `.0` | LL | x * 100.0 @@ -108,10 +108,10 @@ LL | x / 100 | = help: the trait `Div<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Div<Rhs>`: + <f32 as Div> + <f32 as Div<&f32>> <&'a f32 as Div<f32>> <&f32 as Div<&f32>> - <f32 as Div<&f32>> - <f32 as Div> help: consider using a floating-point literal by writing it with `.0` | LL | x / 100.0 @@ -125,10 +125,10 @@ LL | x / 100 | = help: the trait `Div<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Div<Rhs>`: + <f64 as Div> + <f64 as Div<&f64>> <&'a f64 as Div<f64>> <&f64 as Div<&f64>> - <f64 as Div<&f64>> - <f64 as Div> help: consider using a floating-point literal by writing it with `.0` | LL | x / 100.0 diff --git a/tests/ui/object-safety/assoc_type_bounds_sized.rs b/tests/ui/object-safety/assoc_type_bounds_sized.rs index 61ad3cf9dc6..6d10ceeb1b4 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized.rs +++ b/tests/ui/object-safety/assoc_type_bounds_sized.rs @@ -1,9 +1,24 @@ +//! This test checks that associated types only need to be +//! mentioned in trait objects, if they don't require `Self: Sized`. + +// check-pass + trait Foo { type Bar where Self: Sized; } -fn foo(_: &dyn Foo) {} //~ ERROR: the value of the associated type `Bar` (from trait `Foo`) must be specified +fn foo(_: &dyn Foo) {} + +trait Other: Sized {} + +trait Boo { + type Assoc + where + Self: Other; +} + +fn boo(_: &dyn Boo) {} fn main() {} diff --git a/tests/ui/object-safety/assoc_type_bounds_sized.stderr b/tests/ui/object-safety/assoc_type_bounds_sized.stderr deleted file mode 100644 index 49d624f9b1d..00000000000 --- a/tests/ui/object-safety/assoc_type_bounds_sized.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0191]: the value of the associated type `Bar` (from trait `Foo`) must be specified - --> $DIR/assoc_type_bounds_sized.rs:7:16 - | -LL | type Bar - | -------- `Bar` defined here -... -LL | fn foo(_: &dyn Foo) {} - | ^^^ help: specify the associated type: `Foo<Bar = Type>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_others.rs b/tests/ui/object-safety/assoc_type_bounds_sized_others.rs new file mode 100644 index 00000000000..647b72a759f --- /dev/null +++ b/tests/ui/object-safety/assoc_type_bounds_sized_others.rs @@ -0,0 +1,25 @@ +//! This test checks that even if some associated types have +//! `where Self: Sized` bounds, those without still need to be +//! mentioned in trait objects. + +trait Foo { + type Bar + where + Self: Sized; + type Bop; +} + +fn foo(_: &dyn Foo) {} +//~^ ERROR the value of the associated type `Bop` (from trait `Foo`) must be specified + +trait Bar { + type Bop; + type Bar + where + Self: Sized; +} + +fn bar(_: &dyn Bar) {} +//~^ ERROR the value of the associated type `Bop` (from trait `Bar`) must be specified + +fn main() {} diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_others.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_others.stderr new file mode 100644 index 00000000000..e4c44334b34 --- /dev/null +++ b/tests/ui/object-safety/assoc_type_bounds_sized_others.stderr @@ -0,0 +1,21 @@ +error[E0191]: the value of the associated type `Bop` (from trait `Foo`) must be specified + --> $DIR/assoc_type_bounds_sized_others.rs:12:16 + | +LL | type Bop; + | -------- `Bop` defined here +... +LL | fn foo(_: &dyn Foo) {} + | ^^^ help: specify the associated type: `Foo<Bop = Type>` + +error[E0191]: the value of the associated type `Bop` (from trait `Bar`) must be specified + --> $DIR/assoc_type_bounds_sized_others.rs:22:16 + | +LL | type Bop; + | -------- `Bop` defined here +... +LL | fn bar(_: &dyn Bar) {} + | ^^^ help: specify the associated type: `Bar<Bop = Type>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs new file mode 100644 index 00000000000..800624e3124 --- /dev/null +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs @@ -0,0 +1,17 @@ +// check-pass + +trait Foo { + type Bar + where + Self: Sized; +} + +fn foo(_: &dyn Foo<Bar = ()>) {} +//~^ WARN: unnecessary associated type bound for not object safe associated type +//~| WARN: unnecessary associated type bound for not object safe associated type +//~| WARN: unnecessary associated type bound for not object safe associated type + +#[allow(unused_associated_type_bounds)] +fn bar(_: &dyn Foo<Bar = ()>) {} + +fn main() {} diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr new file mode 100644 index 00000000000..d0a4179fe3e --- /dev/null +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr @@ -0,0 +1,27 @@ +warning: unnecessary associated type bound for not object safe associated type + --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 + | +LL | fn foo(_: &dyn Foo<Bar = ()>) {} + | ^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. + = note: `#[warn(unused_associated_type_bounds)]` on by default + +warning: unnecessary associated type bound for not object safe associated type + --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 + | +LL | fn foo(_: &dyn Foo<Bar = ()>) {} + | ^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. + +warning: unnecessary associated type bound for not object safe associated type + --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 + | +LL | fn foo(_: &dyn Foo<Bar = ()>) {} + | ^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. + +warning: 3 warnings emitted + diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.rs b/tests/ui/object-safety/assoc_type_bounds_sized_used.rs new file mode 100644 index 00000000000..cf5345b1c1d --- /dev/null +++ b/tests/ui/object-safety/assoc_type_bounds_sized_used.rs @@ -0,0 +1,20 @@ +//! This test checks that even if some associated types have +//! `where Self: Sized` bounds, those without still need to be +//! mentioned in trait objects. + +trait Bop { + type Bar: Default + where + Self: Sized; +} + +fn bop<T: Bop + ?Sized>() { + let _ = <T as Bop>::Bar::default(); + //~^ ERROR: trait bounds were not satisfied + //~| ERROR: the size for values of type `T` cannot be known at compilation time +} + +fn main() { + bop::<dyn Bop>(); + //~^ ERROR: the size for values of type `dyn Bop` cannot be known at compilation time +} diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr new file mode 100644 index 00000000000..f8488d842e2 --- /dev/null +++ b/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr @@ -0,0 +1,53 @@ +error[E0599]: the function or associated item `default` exists for associated type `<T as Bop>::Bar`, but its trait bounds were not satisfied + --> $DIR/assoc_type_bounds_sized_used.rs:12:30 + | +LL | let _ = <T as Bop>::Bar::default(); + | ^^^^^^^ function or associated item cannot be called on `<T as Bop>::Bar` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `T: Sized` + which is required by `<T as Bop>::Bar: Default` +help: consider restricting the type parameter to satisfy the trait bound + | +LL | fn bop<T: Bop + ?Sized>() where T: Sized { + | ++++++++++++++ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/assoc_type_bounds_sized_used.rs:12:13 + | +LL | fn bop<T: Bop + ?Sized>() { + | - this type parameter needs to be `Sized` +LL | let _ = <T as Bop>::Bar::default(); + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Bop::Bar` + --> $DIR/assoc_type_bounds_sized_used.rs:8:15 + | +LL | type Bar: Default + | --- required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bop::Bar` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn bop<T: Bop + ?Sized>() { +LL + fn bop<T: Bop>() { + | + +error[E0277]: the size for values of type `dyn Bop` cannot be known at compilation time + --> $DIR/assoc_type_bounds_sized_used.rs:18:11 + | +LL | bop::<dyn Bop>(); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Bop` +note: required by a bound in `bop` + --> $DIR/assoc_type_bounds_sized_used.rs:11:11 + | +LL | fn bop<T: Bop + ?Sized>() { + | ^^^ required by this bound in `bop` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/multiple-impls.stderr b/tests/ui/on-unimplemented/multiple-impls.stderr index d628b159a66..3d0e36db752 100644 --- a/tests/ui/on-unimplemented/multiple-impls.stderr +++ b/tests/ui/on-unimplemented/multiple-impls.stderr @@ -8,8 +8,8 @@ LL | Index::index(&[] as &[i32], 2u32); | = help: the trait `Index<u32>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied --> $DIR/multiple-impls.rs:33:5 @@ -19,8 +19,8 @@ LL | Index::index(&[] as &[i32], 2u32); | = help: the trait `Index<u32>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied --> $DIR/multiple-impls.rs:37:33 @@ -32,8 +32,8 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied --> $DIR/multiple-impls.rs:37:5 @@ -43,8 +43,8 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied --> $DIR/multiple-impls.rs:41:33 @@ -56,8 +56,8 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied --> $DIR/multiple-impls.rs:41:5 @@ -67,8 +67,8 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied --> $DIR/multiple-impls.rs:33:5 @@ -78,8 +78,8 @@ LL | Index::index(&[] as &[i32], 2u32); | = help: the trait `Index<u32>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied --> $DIR/multiple-impls.rs:37:5 @@ -89,8 +89,8 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied --> $DIR/multiple-impls.rs:41:5 @@ -100,8 +100,8 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]` = help: the following other types implement trait `Index<Idx>`: - <[i32] as Index<Bar<usize>>> <[i32] as Index<Foo<usize>>> + <[i32] as Index<Bar<usize>>> error: aborting due to 9 previous errors diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr index a7ec3bda85e..b9bca211f43 100644 --- a/tests/ui/on-unimplemented/slice-index.stderr +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -16,8 +16,8 @@ LL | x[..1i32]; | = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>` = help: the following other types implement trait `SliceIndex<T>`: - <RangeTo<usize> as SliceIndex<[T]>> <RangeTo<usize> as SliceIndex<str>> + <RangeTo<usize> as SliceIndex<[T]>> = note: required for `[i32]` to implement `Index<RangeTo<i32>>` error: aborting due to 2 previous errors diff --git a/tests/ui/on-unimplemented/sum.stderr b/tests/ui/on-unimplemented/sum.stderr index 2a316dba778..a2357e49b07 100644 --- a/tests/ui/on-unimplemented/sum.stderr +++ b/tests/ui/on-unimplemented/sum.stderr @@ -6,8 +6,8 @@ LL | vec![(), ()].iter().sum::<i32>(); | = help: the trait `Sum<&()>` is not implemented for `i32` = help: the following other types implement trait `Sum<A>`: - <i32 as Sum<&'a i32>> <i32 as Sum> + <i32 as Sum<&'a i32>> note: the method call chain might not have had the expected associated types --> $DIR/sum.rs:4:18 | @@ -26,8 +26,8 @@ LL | vec![(), ()].iter().product::<i32>(); | = help: the trait `Product<&()>` is not implemented for `i32` = help: the following other types implement trait `Product<A>`: - <i32 as Product<&'a i32>> <i32 as Product> + <i32 as Product<&'a i32>> note: the method call chain might not have had the expected associated types --> $DIR/sum.rs:7:18 | diff --git a/tests/ui/parser/issue-113342.rs b/tests/ui/parser/issue-113342.rs new file mode 100644 index 00000000000..18b502736f7 --- /dev/null +++ b/tests/ui/parser/issue-113342.rs @@ -0,0 +1,9 @@ +#[link(name = "my_c_library")] +extern "C" { + fn my_c_function(x: i32) -> bool; +} + +#[no_mangle] +extern "C" pub fn id(x: i32) -> i32 { x } //~ ERROR expected `fn`, found keyword `pub` + +fn main() {} diff --git a/tests/ui/parser/issue-113342.stderr b/tests/ui/parser/issue-113342.stderr new file mode 100644 index 00000000000..a0c5e665ff8 --- /dev/null +++ b/tests/ui/parser/issue-113342.stderr @@ -0,0 +1,11 @@ +error: expected `fn`, found keyword `pub` + --> $DIR/issue-113342.rs:7:12 + | +LL | extern "C" pub fn id(x: i32) -> i32 { x } + | -----------^^^ + | | | + | | expected `fn` + | help: visibility `pub` must come before `extern "C"`: `pub extern "C"` + +error: aborting due to previous error + diff --git a/tests/ui/pattern/issue-110508.rs b/tests/ui/pattern/issue-110508.rs new file mode 100644 index 00000000000..1024ff05578 --- /dev/null +++ b/tests/ui/pattern/issue-110508.rs @@ -0,0 +1,38 @@ +// run-pass + +#[derive(PartialEq, Eq)] +pub enum Foo { + FooA(()), + FooB(Vec<()>), +} + +impl Foo { + const A1: Foo = Foo::FooA(()); + const A2: Foo = Self::FooA(()); + const A3: Self = Foo::FooA(()); + const A4: Self = Self::FooA(()); +} + +fn main() { + let foo = Foo::FooA(()); + + match foo { + Foo::A1 => {}, + _ => {}, + } + + match foo { + Foo::A2 => {}, + _ => {}, + } + + match foo { + Foo::A3 => {}, + _ => {}, + } + + match foo { + Foo::A4 => {}, + _ => {}, + } +} diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 3956390368f..277d9b2682d 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -12,13 +12,13 @@ LL | for i in false..true {} | = help: the following other types implement trait `Step`: char - i128 + isize + i8 i16 i32 i64 - i8 - isize - u128 + i128 + usize and 5 others = note: required for `std::ops::Range<bool>` to implement `Iterator` = note: required for `std::ops::Range<bool>` to implement `IntoIterator` diff --git a/tests/ui/recursion/issue-95134.rs b/tests/ui/recursion/issue-95134.rs index 2f1cffa2fa9..7ee31d85c2b 100644 --- a/tests/ui/recursion/issue-95134.rs +++ b/tests/ui/recursion/issue-95134.rs @@ -3,6 +3,7 @@ // compile-flags: -Copt-level=0 // dont-check-failure-status // dont-check-compiler-stderr +// ignore-compare-mode-next-solver (hangs) pub fn encode_num<Writer: ExampleWriter>(n: u32, mut writer: Writer) -> Result<(), Writer::Error> { if n > 15 { diff --git a/tests/ui/resolve/issue-2356.stderr b/tests/ui/resolve/issue-2356.stderr index 313b3e30dd9..30f5f059526 100644 --- a/tests/ui/resolve/issue-2356.stderr +++ b/tests/ui/resolve/issue-2356.stderr @@ -1,18 +1,3 @@ -error[E0425]: cannot find function `default` in this scope - --> $DIR/issue-2356.rs:31:5 - | -LL | default(); - | ^^^^^^^ - | -help: you might have meant to call the associated function - | -LL | Self::default(); - | ~~~~~~~~~~~~~ -help: consider importing this function - | -LL + use std::default::default; - | - error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:39:5 | @@ -64,6 +49,12 @@ error[E0425]: cannot find function `clone` in this scope LL | clone(); | ^^^^^ help: you might have meant to call the method: `self.clone` +error[E0425]: cannot find function `default` in this scope + --> $DIR/issue-2356.rs:31:5 + | +LL | default(); + | ^^^^^^^ help: you might have meant to call the associated function: `Self::default` + error[E0425]: cannot find function `shave` in this scope --> $DIR/issue-2356.rs:41:5 | diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs new file mode 100644 index 00000000000..49457354cc9 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs @@ -0,0 +1,29 @@ +// check-pass + +// gate-test-effects +// ^ effects doesn't have a gate so we will trick tidy into thinking this is a gate test + +#![feature(const_trait_impl, effects, rustc_attrs)] + +// ensure we are passing in the correct host effect in always const contexts. + +pub const fn hmm</* T, */ #[rustc_host] const host: bool = true>() -> usize { + if host { + 1 + } else { + 0 + } +} + +const _: () = { + let x = hmm(); + assert!(0 == x); +}; + +/* FIXME(effects) +pub const fn uwu(x: [u8; hmm::<()>()]) { + let [] = x; +} +*/ + +fn main() {} diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs index e4b07ab8108..3fc5fd481ea 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs @@ -1,4 +1,6 @@ -// run-pass +// FIXME(c_str_literals): This should be `run-pass` +// known-bug: #113333 +// edition: 2021 #![feature(c_str_literals)] diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr new file mode 100644 index 00000000000..571c319d8c5 --- /dev/null +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr @@ -0,0 +1,25 @@ +error: prefix `c` is unknown + --> $DIR/basic.rs:8:27 + | +LL | assert_eq!(b"test\0", c"test".to_bytes_with_nul()); + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | assert_eq!(b"test\0", c "test".to_bytes_with_nul()); + | + + +error: no rules expected the token `"test"` + --> $DIR/basic.rs:8:28 + | +LL | assert_eq!(b"test\0", c"test".to_bytes_with_nul()); + | -^^^^^ + | | + | no rules expected this token in macro call + | help: missing comma here + | + = note: while trying to match sequence start + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/edition-2015-2018-lexing.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-2015-2018-lexing.rs new file mode 100644 index 00000000000..2a4cd600426 --- /dev/null +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-2015-2018-lexing.rs @@ -0,0 +1,24 @@ +// Regression test for issue #113235. + +// check-pass +// revisions: edition2015 edition2018 +//[edition2015] edition: 2015 +//[edition2018] edition: 2018 + +// Make sure that in pre-2021 editions we continue to parse the snippet +// `c"hello"` as an identifier followed by a (normal) string literal and +// allow the code below to compile. +// Prefixes including `c` as used by C string literals are only reserved +// in edition 2021 and onward. +// +// Consider checking out rust-2021/reserved-prefixes-migration.rs as well. + +macro_rules! parse { + (c $e:expr) => { + $e + }; +} + +fn main() { + let _: &'static str = parse!(c"hello"); +} diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs index b27da26ed23..ddd6d9a25da 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs @@ -1,4 +1,6 @@ // gate-test-c_str_literals +// known-bug: #113333 +// edition: 2021 macro_rules! m { ($t:tt) => {} @@ -6,8 +8,8 @@ macro_rules! m { fn main() { c"foo"; - //~^ ERROR: `c".."` literals are experimental + // FIXME(c_str_literals): This should be ``c".."` literals are experimental` m!(c"test"); - //~^ ERROR: `c".."` literals are experimental + // FIXME(c_str_literals): This should be ``c".."` literals are experimental` } diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr index bc0c537aada..8de36ca4a6e 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr @@ -1,21 +1,32 @@ -error[E0658]: `c".."` literals are experimental - --> $DIR/gate.rs:8:5 +error: prefix `c` is unknown + --> $DIR/gate.rs:10:5 | LL | c"foo"; - | ^^^^^^ + | ^ unknown prefix | - = note: see issue #105723 <https://github.com/rust-lang/rust/issues/105723> for more information - = help: add `#![feature(c_str_literals)]` to the crate attributes to enable + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | c "foo"; + | + -error[E0658]: `c".."` literals are experimental - --> $DIR/gate.rs:11:8 +error: prefix `c` is unknown + --> $DIR/gate.rs:13:8 | LL | m!(c"test"); - | ^^^^^^^ + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here | - = note: see issue #105723 <https://github.com/rust-lang/rust/issues/105723> for more information - = help: add `#![feature(c_str_literals)]` to the crate attributes to enable +LL | m!(c "test"); + | + + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"foo"` + --> $DIR/gate.rs:10:6 + | +LL | c"foo"; + | ^^^^^ expected one of 8 possible tokens -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs index 7bc6097f124..96945f125da 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs Binary files differdiff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr index ff9006f6f97..2226c7aa6a9 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr Binary files differdiff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs index 82e8e2090d7..066505c23df 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs @@ -1,4 +1,6 @@ -// run-pass +// FIXME(c_str_literals): This should be `run-pass` +// known-bug: #113333 +// edition: 2021 #![feature(c_str_literals)] diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr new file mode 100644 index 00000000000..47361fb61d2 --- /dev/null +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr @@ -0,0 +1,38 @@ +error: prefix `c` is unknown + --> $DIR/non-ascii.rs:9:9 + | +LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | c "\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | + + +error: out of range hex escape + --> $DIR/non-ascii.rs:9:11 + | +LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | ^^^^ must be a character in the range [\x00-\x7f] + +error: out of range hex escape + --> $DIR/non-ascii.rs:9:15 + | +LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | ^^^^ must be a character in the range [\x00-\x7f] + +error: no rules expected the token `"\xEF\x80🦀\u{1F980}"` + --> $DIR/non-ascii.rs:9:10 + | +LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | -^^^^^^^^^^^^^^^^^^^^ + | | + | no rules expected this token in macro call + | help: missing comma here + | +note: while trying to match `,` + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + +error: aborting due to 4 previous errors + diff --git a/tests/ui/span/multiline-span-simple.stderr b/tests/ui/span/multiline-span-simple.stderr index b44df962a9b..b6052a209bf 100644 --- a/tests/ui/span/multiline-span-simple.stderr +++ b/tests/ui/span/multiline-span-simple.stderr @@ -6,10 +6,10 @@ LL | foo(1 as u32 + | = help: the trait `Add<()>` is not implemented for `u32` = help: the following other types implement trait `Add<Rhs>`: + <u32 as Add> + <u32 as Add<&u32>> <&'a u32 as Add<u32>> <&u32 as Add<&u32>> - <u32 as Add<&u32>> - <u32 as Add> error: aborting due to previous error diff --git a/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr index e74c2c4214f..6465eeb8bc6 100644 --- a/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr +++ b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -16,8 +16,8 @@ LL | fn bar() -> impl Bar { | ^^^^^^^^ the trait `Bar` is not implemented for `()` | = help: the following other types implement trait `Bar`: - Qux i32 + Qux error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr index a56a2a188cb..7e24150e7f4 100644 --- a/tests/ui/suggestions/into-str.stderr +++ b/tests/ui/suggestions/into-str.stderr @@ -8,12 +8,12 @@ LL | foo(String::new()); | = note: to coerce a `String` into a `&str`, use `&*` as a prefix = help: the following other types implement trait `From<T>`: - <String as From<&String>> - <String as From<&mut str>> - <String as From<&str>> + <String as From<char>> <String as From<Box<str>>> <String as From<Cow<'a, str>>> - <String as From<char>> + <String as From<&str>> + <String as From<&mut str>> + <String as From<&String>> = note: required for `String` to implement `Into<&str>` note: required by a bound in `foo` --> $DIR/into-str.rs:1:31 diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index ea57992b483..004f1c1622b 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -5,14 +5,14 @@ LL | let _: &[i8] = data.into(); | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` | = help: the following other types implement trait `From<T>`: - <&'input [u8] as From<gimli::read::endian_slice::EndianSlice<'input, Endian>>> - <[T; 10] as From<(T, T, T, T, T, T, T, T, T, T)>> - <[T; 11] as From<(T, T, T, T, T, T, T, T, T, T, T)>> - <[T; 12] as From<(T, T, T, T, T, T, T, T, T, T, T, T)>> + <[bool; LANES] as From<Mask<T, LANES>>> + <[T; N] as From<Simd<T, N>>> <[T; 1] as From<(T,)>> <[T; 2] as From<(T, T)>> <[T; 3] as From<(T, T, T)>> <[T; 4] as From<(T, T, T, T)>> + <[T; 5] as From<(T, T, T, T, T)>> + <[T; 6] as From<(T, T, T, T, T, T)>> and 7 others = note: required for `&[u8]` to implement `Into<&[i8]>` diff --git a/tests/ui/thir-print/thir-flat-const-variant.rs b/tests/ui/thir-print/thir-flat-const-variant.rs new file mode 100644 index 00000000000..2cd87a5cbb2 --- /dev/null +++ b/tests/ui/thir-print/thir-flat-const-variant.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z unpretty=thir-flat +// check-pass + +// Previously, the constants with `Self::Bar(())` would be `Call`s instead of +// `Adt`s in THIR. + +pub enum Foo { + Bar(()), +} + +impl Foo { + const BAR1: Foo = Foo::Bar(()); + const BAR2: Foo = Self::Bar(()); + const BAR3: Self = Foo::Bar(()); + const BAR4: Self = Self::Bar(()); +} + +fn main() {} diff --git a/tests/ui/thir-print/thir-flat-const-variant.stdout b/tests/ui/thir-print/thir-flat-const-variant.stdout new file mode 100644 index 00000000000..1b76f07c318 --- /dev/null +++ b/tests/ui/thir-print/thir-flat-const-variant.stdout @@ -0,0 +1,399 @@ +DefId(0:8 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR1): +Thir { + body_type: Const( + Foo, + ), + arms: [], + blocks: [], + exprs: [ + Expr { + kind: Tuple { + fields: [], + }, + ty: (), + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:12:32: 12:34 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(7), + lint_level: Explicit( + HirId(DefId(0:8 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR1).7), + ), + value: e0, + }, + ty: (), + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:12:32: 12:34 (#0), + }, + Expr { + kind: Adt( + AdtExpr { + adt_def: Foo, + variant_index: 0, + substs: [], + user_ty: None, + fields: [ + FieldExpr { + name: 0, + expr: e1, + }, + ], + base: None, + }, + ), + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(3), + lint_level: Explicit( + HirId(DefId(0:8 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR1).3), + ), + value: e2, + }, + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0), + }, + Expr { + kind: Scope { + region_scope: Destruction(3), + lint_level: Inherited, + value: e3, + }, + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0), + }, + ], + stmts: [], + params: [], +} + +DefId(0:9 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR2): +Thir { + body_type: Const( + Foo, + ), + arms: [], + blocks: [], + exprs: [ + Expr { + kind: Tuple { + fields: [], + }, + ty: (), + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:13:33: 13:35 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(8), + lint_level: Explicit( + HirId(DefId(0:9 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR2).8), + ), + value: e0, + }, + ty: (), + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:13:33: 13:35 (#0), + }, + Expr { + kind: Adt( + AdtExpr { + adt_def: Foo, + variant_index: 0, + substs: [], + user_ty: None, + fields: [ + FieldExpr { + name: 0, + expr: e1, + }, + ], + base: None, + }, + ), + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(3), + lint_level: Explicit( + HirId(DefId(0:9 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR2).3), + ), + value: e2, + }, + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0), + }, + Expr { + kind: Scope { + region_scope: Destruction(3), + lint_level: Inherited, + value: e3, + }, + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0), + }, + ], + stmts: [], + params: [], +} + +DefId(0:10 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR3): +Thir { + body_type: Const( + Foo, + ), + arms: [], + blocks: [], + exprs: [ + Expr { + kind: Tuple { + fields: [], + }, + ty: (), + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:14:33: 14:35 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(7), + lint_level: Explicit( + HirId(DefId(0:10 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR3).7), + ), + value: e0, + }, + ty: (), + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:14:33: 14:35 (#0), + }, + Expr { + kind: Adt( + AdtExpr { + adt_def: Foo, + variant_index: 0, + substs: [], + user_ty: None, + fields: [ + FieldExpr { + name: 0, + expr: e1, + }, + ], + base: None, + }, + ), + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(3), + lint_level: Explicit( + HirId(DefId(0:10 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR3).3), + ), + value: e2, + }, + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0), + }, + Expr { + kind: Scope { + region_scope: Destruction(3), + lint_level: Inherited, + value: e3, + }, + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0), + }, + ], + stmts: [], + params: [], +} + +DefId(0:11 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR4): +Thir { + body_type: Const( + Foo, + ), + arms: [], + blocks: [], + exprs: [ + Expr { + kind: Tuple { + fields: [], + }, + ty: (), + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:15:34: 15:36 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(8), + lint_level: Explicit( + HirId(DefId(0:11 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR4).8), + ), + value: e0, + }, + ty: (), + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:15:34: 15:36 (#0), + }, + Expr { + kind: Adt( + AdtExpr { + adt_def: Foo, + variant_index: 0, + substs: [], + user_ty: None, + fields: [ + FieldExpr { + name: 0, + expr: e1, + }, + ], + base: None, + }, + ), + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(3), + lint_level: Explicit( + HirId(DefId(0:11 ~ thir_flat_const_variant[1f54]::{impl#0}::BAR4).3), + ), + value: e2, + }, + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0), + }, + Expr { + kind: Scope { + region_scope: Destruction(3), + lint_level: Inherited, + value: e3, + }, + ty: Foo, + temp_lifetime: Some( + Node(3), + ), + span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0), + }, + ], + stmts: [], + params: [], +} + +DefId(0:12 ~ thir_flat_const_variant[1f54]::main): +Thir { + body_type: Fn( + fn(), + ), + arms: [], + blocks: [ + Block { + targeted_by_break: false, + region_scope: Node(1), + opt_destruction_scope: None, + span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), + stmts: [], + expr: None, + safety_mode: Safe, + }, + ], + exprs: [ + Expr { + kind: Block { + block: b0, + }, + ty: (), + temp_lifetime: Some( + Node(2), + ), + span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), + }, + Expr { + kind: Scope { + region_scope: Node(2), + lint_level: Explicit( + HirId(DefId(0:12 ~ thir_flat_const_variant[1f54]::main).2), + ), + value: e0, + }, + ty: (), + temp_lifetime: Some( + Node(2), + ), + span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), + }, + Expr { + kind: Scope { + region_scope: Destruction(2), + lint_level: Inherited, + value: e1, + }, + ty: (), + temp_lifetime: Some( + Node(2), + ), + span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), + }, + ], + stmts: [], + params: [], +} + diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr index ce9ab2d811a..b1c683e4729 100644 --- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -6,13 +6,13 @@ LL | s.strip_suffix(b'\n').unwrap_or(s) | = help: the trait `FnMut<(char,)>` is not implemented for `u8` = help: the following other types implement trait `Pattern<'a>`: + char + [char; N] &'b String &'b [char; N] &'b [char] - &'b str &'c &'b str - [char; N] - char + &'b str = note: required for `u8` to implement `Pattern<'_>` error: aborting due to previous error diff --git a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs index 08c08e83076..309bee8aa8c 100644 --- a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs +++ b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs @@ -1,5 +1,5 @@ // compile-flags: -Ztrait-solver=next -// known-bug: #112825 +// check-pass // Makes sure we don't prepopulate the MIR typeck of `define` // with `Foo<T, U> = T`, but instead, `Foo<B, A> = B`, so that @@ -12,7 +12,7 @@ type Foo<T: Send, U> = impl NeedsSend<T>; trait NeedsSend<T> {} impl<T: Send> NeedsSend<T> for T {} -fn define<A, B: Send>(a: A, b: B) { +fn define<A, B: Send>(a: A, b: B, _: Foo<B, A>) { let y: Option<Foo<B, A>> = Some(b); } diff --git a/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr b/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr deleted file mode 100644 index 769eea7dfd6..00000000000 --- a/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr +++ /dev/null @@ -1,99 +0,0 @@ -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/dont-remap-tait-substs.rs:10:24 - | -LL | type Foo<T: Send, U> = impl NeedsSend<T>; - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `define`... - --> $DIR/dont-remap-tait-substs.rs:15:1 - | -LL | fn define<A, B: Send>(a: A, b: B) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/dont-remap-tait-substs.rs:8:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | type Foo<T: Send, U> = impl NeedsSend<T>; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/dont-remap-tait-substs.rs:10:24 - | -LL | type Foo<T: Send, U> = impl NeedsSend<T>; - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `define`... - --> $DIR/dont-remap-tait-substs.rs:15:1 - | -LL | fn define<A, B: Send>(a: A, b: B) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/dont-remap-tait-substs.rs:8:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | type Foo<T: Send, U> = impl NeedsSend<T>; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/dont-remap-tait-substs.rs:10:24 - | -LL | type Foo<T: Send, U> = impl NeedsSend<T>; - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `define`... - --> $DIR/dont-remap-tait-substs.rs:15:1 - | -LL | fn define<A, B: Send>(a: A, b: B) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/dont-remap-tait-substs.rs:8:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | type Foo<T: Send, U> = impl NeedsSend<T>; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/dont-remap-tait-substs.rs:10:24 - | -LL | type Foo<T: Send, U> = impl NeedsSend<T>; - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `define`... - --> $DIR/dont-remap-tait-substs.rs:15:1 - | -LL | fn define<A, B: Send>(a: A, b: B) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/dont-remap-tait-substs.rs:8:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | type Foo<T: Send, U> = impl NeedsSend<T>; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr new file mode 100644 index 00000000000..ec1c3231abc --- /dev/null +++ b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr @@ -0,0 +1,16 @@ +error[E0283]: type annotations needed: cannot satisfy `Foo: Send` + --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:5 + | +LL | needs_send::<Foo>(); + | ^^^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `Foo: Send` +note: required by a bound in `needs_send` + --> $DIR/dont-type_of-tait-in-defining-scope.rs:13:18 + | +LL | fn needs_send<T: Send>() {} + | ^^^^ required by this bound in `needs_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs new file mode 100644 index 00000000000..08f14d7494d --- /dev/null +++ b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs @@ -0,0 +1,24 @@ +// revisions: is_send not_send +// compile-flags: -Ztrait-solver=next +//[is_send] check-pass + +#![feature(type_alias_impl_trait)] + +#[cfg(is_send)] +type Foo = impl Send; + +#[cfg(not_send)] +type Foo = impl Sized; + +fn needs_send<T: Send>() {} + +fn test(_: Foo) { + needs_send::<Foo>(); + //[not_send]~^ ERROR type annotations needed: cannot satisfy `Foo: Send` +} + +fn defines(_: Foo) { + let _: Foo = (); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs b/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs new file mode 100644 index 00000000000..7d15b8c6392 --- /dev/null +++ b/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs @@ -0,0 +1,13 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +use std::any::Any; + +fn needs_usize(_: &usize) {} + +fn main() { + let x: &dyn Any = &1usize; + if let Some(x) = x.downcast_ref::<usize>() { + needs_usize(x); + } +} diff --git a/tests/ui/traits/new-solver/slice-match-byte-lit.rs b/tests/ui/traits/new-solver/slice-match-byte-lit.rs index 5f9c0df6450..4f848062595 100644 --- a/tests/ui/traits/new-solver/slice-match-byte-lit.rs +++ b/tests/ui/traits/new-solver/slice-match-byte-lit.rs @@ -1,5 +1,5 @@ // compile-flags: -Ztrait-solver=next -// known-bug: rust-lang/trait-system-refactor-initiative#38 +// check-pass fn test(s: &[u8]) { match &s[0..3] { diff --git a/tests/ui/traits/new-solver/slice-match-byte-lit.stderr b/tests/ui/traits/new-solver/slice-match-byte-lit.stderr deleted file mode 100644 index cd48a6d1843..00000000000 --- a/tests/ui/traits/new-solver/slice-match-byte-lit.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0271]: type mismatch resolving `[u8; 3] <: <[u8] as Index<Range<usize>>>::Output` - --> $DIR/slice-match-byte-lit.rs:6:9 - | -LL | match &s[0..3] { - | -------- this expression has type `&<[u8] as Index<std::ops::Range<usize>>>::Output` -LL | b"uwu" => {} - | ^^^^^^ types differ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/new-solver/tait-eq-proj-2.rs b/tests/ui/traits/new-solver/tait-eq-proj-2.rs index 99a3d02bd1a..77ea8bc246e 100644 --- a/tests/ui/traits/new-solver/tait-eq-proj-2.rs +++ b/tests/ui/traits/new-solver/tait-eq-proj-2.rs @@ -8,9 +8,11 @@ type Tait = impl Iterator<Item = impl Sized>; -fn mk<T>() -> T { todo!() } +fn mk<T>() -> T { + todo!() +} -fn a() { +fn a(_: Tait) { let x: Tait = mk(); let mut array = mk(); let mut z = IntoIterator::into_iter(array); diff --git a/tests/ui/traits/new-solver/tait-eq-proj.rs b/tests/ui/traits/new-solver/tait-eq-proj.rs index 01141b2819a..01ef2ec953a 100644 --- a/tests/ui/traits/new-solver/tait-eq-proj.rs +++ b/tests/ui/traits/new-solver/tait-eq-proj.rs @@ -28,7 +28,7 @@ goals together. Essentially: */ -fn a() { +fn a(_: Tait) { let _: Tait = IntoIterator::into_iter([0i32; 32]); } diff --git a/tests/ui/traits/new-solver/tait-eq-tait.rs b/tests/ui/traits/new-solver/tait-eq-tait.rs index 532c4c39bd4..70d9dc0eaa8 100644 --- a/tests/ui/traits/new-solver/tait-eq-tait.rs +++ b/tests/ui/traits/new-solver/tait-eq-tait.rs @@ -6,12 +6,13 @@ #![feature(type_alias_impl_trait)] -type Tait = impl Sized; -type Tait2 = impl Sized; - -fn mk<T>() -> T { todo!() } +fn mk<T>() -> T { + todo!() +} fn main() { + type Tait = impl Sized; + type Tait2 = impl Sized; let x: Tait = 1u32; let y: Tait2 = x; } diff --git a/tests/ui/traits/new-solver/winnow-specializing-impls.rs b/tests/ui/traits/new-solver/winnow-specializing-impls.rs new file mode 100644 index 00000000000..06f64de7403 --- /dev/null +++ b/tests/ui/traits/new-solver/winnow-specializing-impls.rs @@ -0,0 +1,22 @@ +// build-pass +// compile-flags: -Ztrait-solver=next + +// Tests that the specializing impl `<() as Foo>` holds during codegen. + +#![feature(min_specialization)] + +trait Foo { + fn bar(); +} + +impl<T> Foo for T { + default fn bar() {} +} + +impl Foo for () { + fn bar() {} +} + +fn main() { + <() as Foo>::bar(); +} diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index a49630adb95..7eb392faa66 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -8,8 +8,8 @@ LL | Ok(Err(123_i32)?) | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following other types implement trait `From<T>`: - <u8 as From<NonZeroU8>> <u8 as From<bool>> + <u8 as From<NonZeroU8>> = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>` error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` @@ -22,8 +22,8 @@ LL | Some(3)?; | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>` = help: the following other types implement trait `FromResidual<R>`: - <Result<T, F> as FromResidual<Result<Infallible, E>>> <Result<T, F> as FromResidual<Yeet<E>>> + <Result<T, F> as FromResidual<Result<Infallible, E>>> error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result` --> $DIR/bad-interconversion.rs:17:31 @@ -35,8 +35,8 @@ LL | Ok(ControlFlow::Break(123)?) | = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>` = help: the following other types implement trait `FromResidual<R>`: - <Result<T, F> as FromResidual<Result<Infallible, E>>> <Result<T, F> as FromResidual<Yeet<E>>> + <Result<T, F> as FromResidual<Result<Infallible, E>>> error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/bad-interconversion.rs:22:22 diff --git a/tests/ui/try-trait/option-to-result.stderr b/tests/ui/try-trait/option-to-result.stderr index fabc1ff2c76..1c4d718f1ee 100644 --- a/tests/ui/try-trait/option-to-result.stderr +++ b/tests/ui/try-trait/option-to-result.stderr @@ -9,8 +9,8 @@ LL | a?; | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>` = help: the following other types implement trait `FromResidual<R>`: - <Result<T, F> as FromResidual<Result<Infallible, E>>> <Result<T, F> as FromResidual<Yeet<E>>> + <Result<T, F> as FromResidual<Result<Infallible, E>>> error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/option-to-result.rs:11:6 diff --git a/tests/ui/try-trait/try-on-option.stderr b/tests/ui/try-trait/try-on-option.stderr index fad6a1fe823..eeb0439df29 100644 --- a/tests/ui/try-trait/try-on-option.stderr +++ b/tests/ui/try-trait/try-on-option.stderr @@ -9,8 +9,8 @@ LL | x?; | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>` = help: the following other types implement trait `FromResidual<R>`: - <Result<T, F> as FromResidual<Result<Infallible, E>>> <Result<T, F> as FromResidual<Yeet<E>>> + <Result<T, F> as FromResidual<Result<Infallible, E>>> error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option.rs:11:6 diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs index 5fb7a9473d3..fd3f9c61420 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -4,8 +4,9 @@ // FIXME This should compile, but it currently doesn't mod m { - type Foo = impl std::fmt::Debug; + pub type Foo = impl std::fmt::Debug; //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] pub fn foo() -> Foo { 22_u32 @@ -13,6 +14,7 @@ mod m { pub fn bar() { is_send(foo()); + //~^ ERROR: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0} } fn is_send<T: Send>(_: T) {} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index 1e9a45aac79..dd56c59bf5f 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -1,11 +1,11 @@ error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` - --> $DIR/auto-trait-leakage3.rs:7:16 + --> $DIR/auto-trait-leakage3.rs:7:20 | -LL | type Foo = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... - --> $DIR/auto-trait-leakage3.rs:15:9 + --> $DIR/auto-trait-leakage3.rs:16:9 | LL | is_send(foo()); | ^^^^^^^ @@ -17,6 +17,48 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/auto-trait-leakage3.rs:7:20 + | +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/auto-trait-leakage3.rs:15:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/auto-trait-leakage3.rs:6:1 + | +LL | mod m { + | ^^^^^ + +error: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0}` satisfies auto traits + --> $DIR/auto-trait-leakage3.rs:16:17 + | +LL | is_send(foo()); + | ------- ^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/auto-trait-leakage3.rs:7:20 + | +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/auto-trait-leakage3.rs:15:12 + | +LL | pub fn bar() { + | ^^^ +note: required by a bound in `is_send` + --> $DIR/auto-trait-leakage3.rs:20:19 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.rs b/tests/ui/type-alias-impl-trait/bound_reduction2.rs index 0bcc9e002ca..4e9f65d88a1 100644 --- a/tests/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.rs @@ -13,6 +13,7 @@ trait Trait<U> {} impl<W> Trait<W> for () {} fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { + //~^ ERROR non-defining opaque type use () //~^ ERROR expected generic type parameter, found `<T as TraitWithAssoc>::Assoc` } diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr index 3c259bd9e97..14f9dbbdb4e 100644 --- a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -1,5 +1,17 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/bound_reduction2.rs:15:46 + | +LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { + | ^^^^^^^^^^^^^ argument `<T as TraitWithAssoc>::Assoc` is not a generic parameter + | +note: for this opaque type + --> $DIR/bound_reduction2.rs:9:15 + | +LL | type Foo<V> = impl Trait<V>; + | ^^^^^^^^^^^^^ + error[E0792]: expected generic type parameter, found `<T as TraitWithAssoc>::Assoc` - --> $DIR/bound_reduction2.rs:16:5 + --> $DIR/bound_reduction2.rs:17:5 | LL | type Foo<V> = impl Trait<V>; | - this generic parameter must be used with a generic type parameter @@ -7,6 +19,6 @@ LL | type Foo<V> = impl Trait<V>; LL | () | ^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/closure_args.rs b/tests/ui/type-alias-impl-trait/closure_args.rs index c5e7af81d3d..243f9cd6d4f 100644 --- a/tests/ui/type-alias-impl-trait/closure_args.rs +++ b/tests/ui/type-alias-impl-trait/closure_args.rs @@ -11,6 +11,13 @@ fn run<F: FnOnce(Input) -> ()>(f: F, i: Input) { f(i); } -fn main() { - run(|x: u32| {println!("{x}");}, 0); +fn bop(_: Input) { + run( + |x: u32| { + println!("{x}"); + }, + 0, + ); } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/closure_args2.rs b/tests/ui/type-alias-impl-trait/closure_args2.rs index 82386c280a8..1dd5c3e40cd 100644 --- a/tests/ui/type-alias-impl-trait/closure_args2.rs +++ b/tests/ui/type-alias-impl-trait/closure_args2.rs @@ -1,10 +1,12 @@ -// run-pass +// check-pass #![feature(type_alias_impl_trait)] trait Foo { // This was reachable in https://github.com/rust-lang/rust/issues/100800 - fn foo(&self) { unreachable!() } + fn foo(&self) { + unreachable!() + } } impl<T> Foo for T {} @@ -14,10 +16,17 @@ impl B { } type Input = impl Foo; -fn run1<F: FnOnce(Input)>(f: F, i: Input) {f(i)} -fn run2<F: FnOnce(B)>(f: F, i: B) {f(i)} +fn run1<F: FnOnce(Input)>(f: F, i: Input) { + f(i) +} +fn run2<F: FnOnce(B)>(f: F, i: B) { + f(i) +} -fn main() { - run1(|x: B| {x.foo()}, B); - run2(|x: B| {x.foo()}, B); +fn bop() -> Input { + run1(|x: B| x.foo(), B); + run2(|x: B| x.foo(), B); + panic!() } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr index fbfa0ccf1e8..d60f1ffbccc 100644 --- a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr +++ b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr @@ -19,6 +19,11 @@ LL | "" | = note: expected opaque type `Boo` found reference `&'static str` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/declared_but_not_defined_in_scope.rs:10:4 + | +LL | fn bomp() -> boo::Boo { + | ^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs index e5bfbfdae91..b2842df150a 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs @@ -2,7 +2,7 @@ type Tait<'a> = impl Sized + 'a; -fn foo<'a, 'b>() { +fn foo<'a, 'b>() -> Tait<'a> { if false { if { return } { let y: Tait<'b> = 1i32; @@ -10,6 +10,7 @@ fn foo<'a, 'b>() { } } let x: Tait<'a> = (); + x } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr index f2eb7bc4dc7..b138f9d5c45 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr @@ -5,10 +5,10 @@ LL | let y: Tait<'b> = 1i32; | ^^^^ expected `()`, got `i32` | note: previous use here - --> $DIR/different_defining_uses_never_type-2.rs:12:23 + --> $DIR/different_defining_uses_never_type-2.rs:7:14 | -LL | let x: Tait<'a> = (); - | ^^ +LL | if { return } { + | ^^^^^^ error: aborting due to previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs index 2b30a9cd57c..a4ac27378e1 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs @@ -2,7 +2,7 @@ type Tait<T> = impl Sized; -fn foo<T, U>() { +fn foo<T, U>() -> Tait<T> { if false { if { return } { let y: Tait<U> = 1i32; @@ -10,6 +10,7 @@ fn foo<T, U>() { } } let x: Tait<T> = (); + x } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs index 9d938a61600..14ced341854 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -9,6 +9,7 @@ impl<'a, T: ?Sized> Captures<'a> for T {} type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; fn one<'a>(t: &'a ()) -> Two<'a, 'a> { + //~^ ERROR non-defining opaque type use t //~^ ERROR non-defining opaque type use } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr index 72e1ef4b492..4da69a705c0 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr @@ -1,5 +1,17 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_lifetime_param.rs:12:5 + --> $DIR/generic_duplicate_lifetime_param.rs:11:26 + | +LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> { + | ^^^^^^^^^^^ generic argument `'a` used twice + | +note: for this opaque type + --> $DIR/generic_duplicate_lifetime_param.rs:9:20 + | +LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_lifetime_param.rs:13:5 | LL | t | ^ @@ -10,5 +22,5 @@ note: lifetime used multiple times LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; | ^^ ^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs index 80462f8ac04..1e391b55a4f 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -1,5 +1,12 @@ #![feature(type_alias_impl_trait)] +//! This test checks various cases where we are using the same +//! generic parameter twice in the parameter list of a TAIT. +//! Within defining scopes that is not legal, because the hidden type +//! is not fully defined then. This could cause us to have a TAIT +//! that doesn't have a hidden type for all possible combinations of generic +//! parameters passed to it. + use std::fmt::Debug; fn main() {} @@ -7,7 +14,6 @@ fn main() {} // test that unused generic parameters are ok type TwoTys<T, U> = impl Debug; - pub trait Captures<'a> {} impl<'a, T: ?Sized> Captures<'a> for T {} @@ -16,18 +22,20 @@ type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>; type TwoConsts<const X: usize, const Y: usize> = impl Debug; - fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> { + //~^ ERROR non-defining opaque type use in defining scope t //~^ ERROR non-defining opaque type use in defining scope } fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { + //~^ ERROR non-defining opaque type use in defining scope t //~^ ERROR non-defining opaque type use in defining scope } fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> { + //~^ ERROR non-defining opaque type use in defining scope t //~^ ERROR non-defining opaque type use in defining scope } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index 98e4bfea10d..d8330771d30 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -1,38 +1,74 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:21:5 + --> $DIR/generic_duplicate_param_use.rs:25:30 + | +LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> { + | ^^^^^^^^^^^^ generic argument `T` used twice + | +note: for this opaque type + --> $DIR/generic_duplicate_param_use.rs:15:21 + | +LL | type TwoTys<T, U> = impl Debug; + | ^^^^^^^^^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:27:5 | LL | t | ^ | note: type used multiple times - --> $DIR/generic_duplicate_param_use.rs:8:13 + --> $DIR/generic_duplicate_param_use.rs:15:13 | LL | type TwoTys<T, U> = impl Debug; | ^ ^ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:26:5 + --> $DIR/generic_duplicate_param_use.rs:31:36 + | +LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { + | ^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice + | +note: for this opaque type + --> $DIR/generic_duplicate_param_use.rs:21:29 + | +LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:33:5 | LL | t | ^ | note: lifetime used multiple times - --> $DIR/generic_duplicate_param_use.rs:15:19 + --> $DIR/generic_duplicate_param_use.rs:21:19 | LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>; | ^^ ^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:31:5 + --> $DIR/generic_duplicate_param_use.rs:37:50 + | +LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> { + | ^^^^^^^^^^^^^^^ generic argument `N` used twice + | +note: for this opaque type + --> $DIR/generic_duplicate_param_use.rs:23:50 + | +LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug; + | ^^^^^^^^^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:39:5 | LL | t | ^ | note: constant used multiple times - --> $DIR/generic_duplicate_param_use.rs:17:16 + --> $DIR/generic_duplicate_param_use.rs:23:16 | LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug; | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs index e7b8567b9a2..68f4c6923ae 100644 --- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -13,16 +13,19 @@ type OneConst<const X: usize> = impl Debug; // Not defining uses, because they doesn't define *all* possible generics. fn concrete_ty() -> OneTy<u32> { + //~^ ERROR: non-defining opaque type use in defining scope 5u32 - //~^ ERROR expected generic type parameter, found `u32` + //~^ ERROR: expected generic type parameter, found `u32` } fn concrete_lifetime() -> OneLifetime<'static> { + //~^ ERROR: non-defining opaque type use in defining scope 6u32 - //~^ ERROR expected generic lifetime parameter, found `'static` + //~^ ERROR: expected generic lifetime parameter, found `'static` } fn concrete_const() -> OneConst<{ 123 }> { + //~^ ERROR: non-defining opaque type use in defining scope 7u32 - //~^ ERROR expected generic constant parameter, found `123` + //~^ ERROR: expected generic constant parameter, found `123` } diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 966fe823f02..e3b7b1a76b0 100644 --- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -1,5 +1,17 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:15:21 + | +LL | fn concrete_ty() -> OneTy<u32> { + | ^^^^^^^^^^ argument `u32` is not a generic parameter + | +note: for this opaque type + --> $DIR/generic_nondefining_use.rs:7:17 + | +LL | type OneTy<T> = impl Debug; + | ^^^^^^^^^^ + error[E0792]: expected generic type parameter, found `u32` - --> $DIR/generic_nondefining_use.rs:16:5 + --> $DIR/generic_nondefining_use.rs:17:5 | LL | type OneTy<T> = impl Debug; | - this generic parameter must be used with a generic type parameter @@ -7,8 +19,20 @@ LL | type OneTy<T> = impl Debug; LL | 5u32 | ^^^^ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:21:27 + | +LL | fn concrete_lifetime() -> OneLifetime<'static> { + | ^^^^^^^^^^^^^^^^^^^^ argument `'static` is not a generic parameter + | +note: for this opaque type + --> $DIR/generic_nondefining_use.rs:9:24 + | +LL | type OneLifetime<'a> = impl Debug; + | ^^^^^^^^^^ + error[E0792]: expected generic lifetime parameter, found `'static` - --> $DIR/generic_nondefining_use.rs:21:5 + --> $DIR/generic_nondefining_use.rs:23:5 | LL | type OneLifetime<'a> = impl Debug; | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type @@ -16,8 +40,20 @@ LL | type OneLifetime<'a> = impl Debug; LL | 6u32 | ^^^^ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:27:24 + | +LL | fn concrete_const() -> OneConst<{ 123 }> { + | ^^^^^^^^^^^^^^^^^ argument `123` is not a generic parameter + | +note: for this opaque type + --> $DIR/generic_nondefining_use.rs:11:33 + | +LL | type OneConst<const X: usize> = impl Debug; + | ^^^^^^^^^^ + error[E0792]: expected generic constant parameter, found `123` - --> $DIR/generic_nondefining_use.rs:26:5 + --> $DIR/generic_nondefining_use.rs:29:5 | LL | type OneConst<const X: usize> = impl Debug; | -------------- this generic parameter must be used with a generic constant parameter @@ -25,6 +61,6 @@ LL | type OneConst<const X: usize> = impl Debug; LL | 7u32 | ^^^^ -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index cdd8f6f1976..c60f5c11cd1 100644 --- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -5,12 +5,12 @@ fn main() { let x = wrong_generic(&y); let z: i32 = x; //~^ ERROR expected generic type parameter, found `&i32` -} -type WrongGeneric<T> = impl 'static; -//~^ ERROR: at least one trait must be specified + type WrongGeneric<T> = impl 'static; + //~^ ERROR: at least one trait must be specified -fn wrong_generic<T>(t: T) -> WrongGeneric<T> { - t - //~^ ERROR the parameter type `T` may not live long enough + fn wrong_generic<T>(t: T) -> WrongGeneric<T> { + t + //~^ ERROR the parameter type `T` may not live long enough + } } diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index fa79e51e9f7..8c3a25dbfe7 100644 --- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -1,8 +1,8 @@ error: at least one trait must be specified - --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 + --> $DIR/generic_type_does_not_live_long_enough.rs:9:28 | -LL | type WrongGeneric<T> = impl 'static; - | ^^^^^^^^^^^^ +LL | type WrongGeneric<T> = impl 'static; + | ^^^^^^^^^^^^ error[E0792]: expected generic type parameter, found `&i32` --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 @@ -10,19 +10,19 @@ error[E0792]: expected generic type parameter, found `&i32` LL | let z: i32 = x; | ^ ... -LL | type WrongGeneric<T> = impl 'static; - | - this generic parameter must be used with a generic type parameter +LL | type WrongGeneric<T> = impl 'static; + | - this generic parameter must be used with a generic type parameter error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 + --> $DIR/generic_type_does_not_live_long_enough.rs:13:9 | -LL | t - | ^ ...so that the type `T` will meet its required lifetime bounds +LL | t + | ^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | -LL | fn wrong_generic<T: 'static>(t: T) -> WrongGeneric<T> { - | +++++++++ +LL | fn wrong_generic<T: 'static>(t: T) -> WrongGeneric<T> { + | +++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params.rs new file mode 100644 index 00000000000..db1a3a1c7a9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params.rs @@ -0,0 +1,28 @@ +//! This test checks that walking into binders +//! during opaque type collection does not ICE or raise errors. + +// edition: 2021 + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait B { + type C; +} + +struct A; + +impl<'a> B for &'a A { + type C = (); +} + +struct Terminator; + +type Successors<'a> = impl std::fmt::Debug + 'a; + +impl Terminator { + fn successors(&self, _: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs new file mode 100644 index 00000000000..f011e5b2148 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs @@ -0,0 +1,35 @@ +//! This test checks the behaviour of walking into binders +//! and normalizing something behind them actually works. + +// edition: 2021 + +#![feature(type_alias_impl_trait)] + +trait B { + type C; +} + +struct A; + +impl<'a> B for &'a A { + type C = Tait; +} + +type Tait = impl std::fmt::Debug; + +struct Terminator; + +type Successors<'a> = impl std::fmt::Debug + 'a; + +impl Terminator { + fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { + f = g; + //~^ ERROR item constrains opaque type that is not in its signature + } +} + +fn g(_: &()) -> String { + String::new() +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr new file mode 100644 index 00000000000..39f584dd49c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr @@ -0,0 +1,15 @@ +error: item constrains opaque type that is not in its signature + --> $DIR/higher_kinded_params2.rs:26:13 + | +LL | f = g; + | ^ + | + = note: this item must mention the opaque type in its signature in order to be able to register hidden types +note: this item must mention the opaque type in its signature in order to be able to register hidden types + --> $DIR/higher_kinded_params2.rs:25:8 + | +LL | fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs index 839a611cb71..6edfccaf7d1 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs @@ -24,7 +24,8 @@ type Successors<'a> = impl std::fmt::Debug + 'a; impl Terminator { fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { f = g; - //~^ ERROR: mismatched types + //~^ ERROR mismatched types + //~| ERROR item constrains opaque type that is not in its signature } } diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr index aaba9ad5ca7..14372d8f3e6 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr @@ -1,3 +1,16 @@ +error: item constrains opaque type that is not in its signature + --> $DIR/higher_kinded_params3.rs:26:13 + | +LL | f = g; + | ^ + | + = note: this item must mention the opaque type in its signature in order to be able to register hidden types +note: this item must mention the opaque type in its signature in order to be able to register hidden types + --> $DIR/higher_kinded_params3.rs:25:8 + | +LL | fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { + | ^^^^^^^^^^ + error[E0308]: mismatched types --> $DIR/higher_kinded_params3.rs:26:9 | @@ -10,6 +23,6 @@ LL | f = g; = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>` found fn pointer `for<'a> fn(&'a ()) -> &'a ()` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs index 79caddf7913..20175a4feca 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.rs +++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs @@ -2,8 +2,9 @@ #![allow(dead_code)] mod m { - type Foo = impl std::fmt::Debug; + pub type Foo = impl std::fmt::Debug; //~^ ERROR cycle detected + //~| ERROR cycle detected // Cycle: error today, but it'd be nice if it eventually worked @@ -13,10 +14,11 @@ mod m { pub fn bar() { is_send(foo()); // Today: error + //~^ ERROR: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits } - fn baz() { - let f: Foo = 22_u32; + fn baz() -> Foo { + () } fn is_send<T: Send>(_: T) {} diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr index b9d646b927a..4d5f367476b 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -1,11 +1,11 @@ error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` - --> $DIR/inference-cycle.rs:5:16 + --> $DIR/inference-cycle.rs:5:20 | -LL | type Foo = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... - --> $DIR/inference-cycle.rs:15:9 + --> $DIR/inference-cycle.rs:16:9 | LL | is_send(foo()); // Today: error | ^^^^^^^ @@ -17,6 +17,48 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/inference-cycle.rs:5:20 + | +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/inference-cycle.rs:15:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/inference-cycle.rs:4:1 + | +LL | mod m { + | ^^^^^ + +error: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits + --> $DIR/inference-cycle.rs:16:17 + | +LL | is_send(foo()); // Today: error + | ------- ^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/inference-cycle.rs:5:20 + | +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/inference-cycle.rs:15:12 + | +LL | pub fn bar() { + | ^^^ +note: required by a bound in `is_send` + --> $DIR/inference-cycle.rs:24:19 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/issue-109054.rs b/tests/ui/type-alias-impl-trait/issue-109054.rs new file mode 100644 index 00000000000..1fbec47b14b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-109054.rs @@ -0,0 +1,22 @@ +// edition:2021 + +#![feature(type_alias_impl_trait)] + +struct CallMe; + +type ReturnType<'a> = impl std::future::Future<Output = u32> + 'a; +type FnType = impl Fn(&u32) -> ReturnType; + +impl std::ops::Deref for CallMe { + type Target = FnType; + + fn deref(&self) -> &Self::Target { + fn inner(val: &u32) -> ReturnType { + async move { *val * 2 } + } + + &inner //~ ERROR: expected generic lifetime parameter, found `'_` + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-109054.stderr b/tests/ui/type-alias-impl-trait/issue-109054.stderr new file mode 100644 index 00000000000..a611b9fe448 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-109054.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/issue-109054.rs:18:9 + | +LL | type ReturnType<'a> = impl std::future::Future<Output = u32> + 'a; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | &inner + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs index a3f126d56cf..a213dbba4ea 100644 --- a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs +++ b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs @@ -1,19 +1,22 @@ #![feature(generators, generator_trait, rustc_attrs)] #![feature(type_alias_impl_trait)] -use std::ops::Generator; +// check-pass -type GenOnce<Y, R> = impl Generator<Yield = Y, Return = R>; +mod gen { + use std::ops::Generator; -const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> { - move || { - yield yielding; + pub type GenOnce<Y, R> = impl Generator<Yield = Y, Return = R>; - return returning; + pub const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> { + move || { + yield yielding; + + return returning; + } } } -const FOO: GenOnce<usize, usize> = const_generator(10, 100); +const FOO: gen::GenOnce<usize, usize> = gen::const_generator(10, 100); -#[rustc_error] -fn main() {} //~ ERROR +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr deleted file mode 100644 index eb1c9603a60..00000000000 --- a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/issue-53678-generator-and-const-fn.rs:19:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/type-alias-impl-trait/issue-57961.rs b/tests/ui/type-alias-impl-trait/issue-57961.rs index 4aa5966ff25..61af7a0f625 100644 --- a/tests/ui/type-alias-impl-trait/issue-57961.rs +++ b/tests/ui/type-alias-impl-trait/issue-57961.rs @@ -11,8 +11,8 @@ impl Foo for () { //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32` } -fn incoherent() { - let f: X = 22_i32; +fn incoherent() -> X { + 22_i32 } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60564.rs b/tests/ui/type-alias-impl-trait/issue-60564.rs index c2f4c370807..48bd70bcca9 100644 --- a/tests/ui/type-alias-impl-trait/issue-60564.rs +++ b/tests/ui/type-alias-impl-trait/issue-60564.rs @@ -17,6 +17,7 @@ where { type BitsIter = IterBitsIter<T, E, u8>; fn iter_bits(self, n: u8) -> Self::BitsIter { + //~^ ERROR non-defining opaque type use (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) //~^ ERROR expected generic type parameter, found `u8` } diff --git a/tests/ui/type-alias-impl-trait/issue-60564.stderr b/tests/ui/type-alias-impl-trait/issue-60564.stderr index f8fdb004d09..d42495e934d 100644 --- a/tests/ui/type-alias-impl-trait/issue-60564.stderr +++ b/tests/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,5 +1,17 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/issue-60564.rs:19:34 + | +LL | fn iter_bits(self, n: u8) -> Self::BitsIter { + | ^^^^^^^^^^^^^^ argument `u8` is not a generic parameter + | +note: for this opaque type + --> $DIR/issue-60564.rs:8:30 + | +LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0792]: expected generic type parameter, found `u8` - --> $DIR/issue-60564.rs:20:9 + --> $DIR/issue-60564.rs:21:9 | LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>; | - this generic parameter must be used with a generic type parameter @@ -7,6 +19,6 @@ LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>; LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs index 7414611a748..ddea7aeb6cd 100644 --- a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs +++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs @@ -8,6 +8,9 @@ pub type Closure = impl FnOnce(); -fn main() { +fn bop() -> Closure { || -> Closure { || () }; + panic!() } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs index b91cbce3727..7b3e9e12405 100644 --- a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs +++ b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -11,7 +11,9 @@ type T = impl Sized; fn take(_: fn() -> T) {} -fn main() { +fn bop(_: T) { take(|| {}); take(|| {}); } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs index 5e0a82a7286..9dcdb578568 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs @@ -7,7 +7,8 @@ trait Trait<T> {} type Alias<'a, U> = impl Trait<U>; fn f<'a>() -> Alias<'a, ()> {} -//~^ ERROR expected generic type parameter, found `()` +//~^ ERROR non-defining opaque type use +//~| ERROR expected generic type parameter, found `()` fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr index 271743a4010..085bffe907b 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -1,3 +1,15 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/issue-68368-non-defining-use-2.rs:9:15 + | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^^^^^^^^^^^^ argument `()` is not a generic parameter + | +note: for this opaque type + --> $DIR/issue-68368-non-defining-use-2.rs:7:21 + | +LL | type Alias<'a, U> = impl Trait<U>; + | ^^^^^^^^^^^^^ + error[E0792]: expected generic type parameter, found `()` --> $DIR/issue-68368-non-defining-use-2.rs:9:29 | @@ -7,6 +19,6 @@ LL | LL | fn f<'a>() -> Alias<'a, ()> {} | ^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs index 3b32260c96f..dfe2ee8204c 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -8,6 +8,7 @@ type Alias<'a, U> = impl Trait<U>; fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR expected generic type parameter, found `()` +//~| ERROR non-defining opaque type use fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index 4d9a8d6eef9..ea704ffff97 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -1,3 +1,15 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/issue-68368-non-defining-use.rs:9:15 + | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^^^^^^^^^^^^ argument `()` is not a generic parameter + | +note: for this opaque type + --> $DIR/issue-68368-non-defining-use.rs:7:21 + | +LL | type Alias<'a, U> = impl Trait<U>; + | ^^^^^^^^^^^^^ + error[E0792]: expected generic type parameter, found `()` --> $DIR/issue-68368-non-defining-use.rs:9:29 | @@ -7,6 +19,6 @@ LL | LL | fn f<'a>() -> Alias<'a, ()> {} | ^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs index 7657fe2fb1a..a0f8e48e268 100644 --- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs @@ -1,4 +1,6 @@ -// Regression test for #69136 +//! Regression test for #69136 +//! This test checks that the unknown lifetime `'a` doesn't cause +//! ICEs after emitting the error. #![feature(type_alias_impl_trait)] @@ -17,7 +19,6 @@ impl<T> WithAssoc<T> for () { type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; //~^ ERROR use of undeclared lifetime name `'a` -fn my_fun() -> Return<()> {} -//~^ ERROR expected generic type parameter, found `()` +fn my_fun<T>() -> Return<T> {} fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr index d1250786d93..b7af3f06d0d 100644 --- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr @@ -1,5 +1,5 @@ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65 + --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:19:65 | LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; | ^^ undeclared lifetime @@ -14,16 +14,6 @@ help: consider introducing lifetime `'a` here LL | type Return<'a, A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; | +++ -error[E0792]: expected generic type parameter, found `()` - --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27 - | -LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; - | - this generic parameter must be used with a generic type parameter -... -LL | fn my_fun() -> Return<()> {} - | ^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0261, E0792. -For more information about an error, try `rustc --explain E0261`. +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/type-alias-impl-trait/issue-70121.rs b/tests/ui/type-alias-impl-trait/issue-70121.rs index dff0d89d465..bfd8d8872e3 100644 --- a/tests/ui/type-alias-impl-trait/issue-70121.rs +++ b/tests/ui/type-alias-impl-trait/issue-70121.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(type_alias_impl_trait)] pub type Successors<'a> = impl Iterator<Item = &'a ()>; @@ -17,6 +15,7 @@ impl<'a> Tr for &'a () { } pub fn kazusa<'a>() -> <&'a () as Tr>::Item { + //~^ ERROR item constrains opaque type that is not in its signature None.into_iter() } diff --git a/tests/ui/type-alias-impl-trait/issue-70121.stderr b/tests/ui/type-alias-impl-trait/issue-70121.stderr new file mode 100644 index 00000000000..30c3ddd8659 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-70121.stderr @@ -0,0 +1,15 @@ +error: item constrains opaque type that is not in its signature + --> $DIR/issue-70121.rs:17:24 + | +LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item { + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this item must mention the opaque type in its signature in order to be able to register hidden types +note: this item must mention the opaque type in its signature in order to be able to register hidden types + --> $DIR/issue-70121.rs:17:8 + | +LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs index 8d818d4a387..e7b04a48975 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.rs +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -2,7 +2,7 @@ #![feature(type_alias_impl_trait)] -type Pointer<T> = impl std::ops::Deref<Target=T>; +type Pointer<T> = impl std::ops::Deref<Target = T>; fn test() -> Pointer<_> { //~^ ERROR: the placeholder `_` is not allowed within types diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr index f4d96038d91..dccf84362f0 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -8,8 +8,8 @@ LL | () | -- return type was inferred to be `()` here | = help: the following other types implement trait `Foo<A>`: - <() as Foo<()>> <() as Foo<u32>> + <() as Foo<()>> error: aborting due to previous error diff --git a/tests/ui/type-alias-impl-trait/nested_in_closure.rs b/tests/ui/type-alias-impl-trait/nested_in_closure.rs new file mode 100644 index 00000000000..362f3d53e88 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_in_closure.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] +// check-pass + +fn main() { + let x = || { + type Tait = impl Sized; + let y: Tait = (); + }; + + let y = || { + type Tait = impl std::fmt::Debug; + let y: Tait = (); + y + }; + let mut z = y(); + z = (); +} diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs index 60b6e1aac62..07607516cc4 100644 --- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs +++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs @@ -10,11 +10,11 @@ mod my_mod { 5i32 } - pub fn get_foot() -> Foot { + pub fn get_foot(_: Foo) -> Foot { get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type } } fn main() { - let _: my_mod::Foot = my_mod::get_foot(); + let _: my_mod::Foot = my_mod::get_foot(my_mod::get_foo()); } diff --git a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr index ae03a5b3e37..863282a0ff9 100644 --- a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr +++ b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr @@ -11,6 +11,11 @@ LL | let _: &str = bomp(); | = note: expected reference `&str` found opaque type `Boo` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/no_revealing_outside_defining_module.rs:14:4 + | +LL | fn bomp2() { + | ^^^^^ error[E0308]: mismatched types --> $DIR/no_revealing_outside_defining_module.rs:19:5 @@ -25,6 +30,11 @@ LL | "" | = note: expected opaque type `Boo` found reference `&'static str` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/no_revealing_outside_defining_module.rs:18:4 + | +LL | fn bomp() -> boo::Boo { + | ^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs index 7ecb5535301..7943bb240f1 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.rs +++ b/tests/ui/type-alias-impl-trait/reveal_local.rs @@ -4,22 +4,28 @@ use std::fmt::Debug; type Foo = impl Debug; //~^ ERROR cycle detected +//~| ERROR cycle detected +//~| ERROR cycle detected -fn is_send<T: Send>() { } +fn is_send<T: Send>() {} fn not_good() { // Error: this function does not constrain `Foo` to any particular // hidden type, so it cannot rely on `Send` being true. is_send::<Foo>(); + //~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits } -fn not_gooder() { +fn not_gooder() -> Foo { // Constrain `Foo = u32` let x: Foo = 22_u32; // while we could know this from the hidden type, it would // need extra roundabout logic to support it. is_send::<Foo>(); + //~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits + + x } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr index 27fded33329..0c5ef4a6fb4 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.stderr +++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr @@ -5,7 +5,7 @@ LL | type Foo = impl Debug; | ^^^^^^^^^^ | note: ...which requires type-checking `not_good`... - --> $DIR/reveal_local.rs:13:5 + --> $DIR/reveal_local.rs:15:5 | LL | is_send::<Foo>(); | ^^^^^^^^^^^^^^ @@ -23,6 +23,98 @@ LL | | LL | | fn main() {} | |____________^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_good`... + --> $DIR/reveal_local.rs:12:1 + | +LL | fn not_good() { + | ^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits + --> $DIR/reveal_local.rs:15:15 + | +LL | is_send::<Foo>(); + | ^^^ + | +note: opaque type is declared here + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/reveal_local.rs:12:4 + | +LL | fn not_good() { + | ^^^^^^^^ +note: required by a bound in `is_send` + --> $DIR/reveal_local.rs:10:15 + | +LL | fn is_send<T: Send>() {} + | ^^^^ required by this bound in `is_send` + +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_gooder`... + --> $DIR/reveal_local.rs:19:1 + | +LL | fn not_gooder() -> Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits + --> $DIR/reveal_local.rs:25:15 + | +LL | is_send::<Foo>(); + | ^^^ + | +note: opaque type is declared here + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/reveal_local.rs:19:4 + | +LL | fn not_gooder() -> Foo { + | ^^^^^^^^^^ +note: required by a bound in `is_send` + --> $DIR/reveal_local.rs:10:15 + | +LL | fn is_send<T: Send>() {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.rs b/tests/ui/type-alias-impl-trait/type_of_a_let.rs index 4e9d1788b94..36161171555 100644 --- a/tests/ui/type-alias-impl-trait/type_of_a_let.rs +++ b/tests/ui/type-alias-impl-trait/type_of_a_let.rs @@ -5,16 +5,16 @@ use std::fmt::Debug; type Foo = impl Debug; -fn foo1() -> u32 { +fn foo1() -> (u32, Foo) { let x: Foo = 22_u32; - x + (x, todo!()) } -fn foo2() -> u32 { +fn foo2() -> (u32, Foo) { let x: Foo = 22_u32; let y: Foo = x; same_type((x, y)); //~ ERROR use of moved value - y //~ ERROR use of moved value + (y, todo!()) //~ ERROR use of moved value } fn same_type<T>(x: (T, T)) {} diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr index 1dabe4586c5..7d7cad874fa 100644 --- a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr +++ b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr @@ -9,14 +9,14 @@ LL | same_type((x, y)); | ^ value used here after move error[E0382]: use of moved value: `y` - --> $DIR/type_of_a_let.rs:17:5 + --> $DIR/type_of_a_let.rs:17:6 | LL | let y: Foo = x; | - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait LL | same_type((x, y)); | - value moved here -LL | y - | ^ value used here after move +LL | (y, todo!()) + | ^ value used here after move error: aborting due to 2 previous errors diff --git a/tests/ui/type-inference/issue-113283-alllocator-trait-eq.rs b/tests/ui/type-inference/issue-113283-alllocator-trait-eq.rs new file mode 100644 index 00000000000..5d0e456d9dd --- /dev/null +++ b/tests/ui/type-inference/issue-113283-alllocator-trait-eq.rs @@ -0,0 +1,18 @@ +// run-pass +// Verify that PartialEq implementations do not break type inference when +// accepting types with different allocators + +use std::rc::Rc; +use std::sync::Arc; + + +fn main() { + let boxed: Vec<Box<i32>> = vec![]; + assert_eq!(boxed, vec![]); + + let rc: Vec<Rc<i32>> = vec![]; + assert_eq!(rc, vec![]); + + let arc: Vec<Arc<i32>> = vec![]; + assert_eq!(arc, vec![]); +} diff --git a/tests/ui/type/type-check-defaults.stderr b/tests/ui/type/type-check-defaults.stderr index 9ba63ffe9c9..10d600cbfcc 100644 --- a/tests/ui/type/type-check-defaults.stderr +++ b/tests/ui/type/type-check-defaults.stderr @@ -66,10 +66,10 @@ LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} | = help: the trait `Add<u8>` is not implemented for `i32` = help: the following other types implement trait `Add<Rhs>`: + <i32 as Add> + <i32 as Add<&i32>> <&'a i32 as Add<i32>> <&i32 as Add<&i32>> - <i32 as Add<&i32>> - <i32 as Add> error: aborting due to 7 previous errors diff --git a/tests/ui/typeck/issue-81293.stderr b/tests/ui/typeck/issue-81293.stderr index 6976be71135..292c63070ae 100644 --- a/tests/ui/typeck/issue-81293.stderr +++ b/tests/ui/typeck/issue-81293.stderr @@ -21,10 +21,10 @@ LL | a = c + b * 5; | = help: the trait `Add<u16>` is not implemented for `usize` = help: the following other types implement trait `Add<Rhs>`: + <usize as Add> + <usize as Add<&usize>> <&'a usize as Add<usize>> <&usize as Add<&usize>> - <usize as Add<&usize>> - <usize as Add> error: aborting due to 3 previous errors diff --git a/tests/ui/typeck/issue-90101.stderr b/tests/ui/typeck/issue-90101.stderr index d2729d85354..484089f9e87 100644 --- a/tests/ui/typeck/issue-90101.stderr +++ b/tests/ui/typeck/issue-90101.stderr @@ -7,11 +7,11 @@ LL | func(Path::new("hello").to_path_buf().to_string_lossy(), "world") | required by a bound introduced by this call | = help: the following other types implement trait `From<T>`: - <PathBuf as From<&T>> <PathBuf as From<Box<Path>>> <PathBuf as From<Cow<'a, Path>>> <PathBuf as From<OsString>> <PathBuf as From<String>> + <PathBuf as From<&T>> = note: required for `Cow<'_, str>` to implement `Into<PathBuf>` note: required by a bound in `func` --> $DIR/issue-90101.rs:3:20 diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 96ac4321689..85adf775139 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -8,10 +8,10 @@ LL | <i32 as Add<u32>>::add(1, 2); | = help: the trait `Add<u32>` is not implemented for `i32` = help: the following other types implement trait `Add<Rhs>`: + <i32 as Add> + <i32 as Add<&i32>> <&'a i32 as Add<i32>> <&i32 as Add<&i32>> - <i32 as Add<&i32>> - <i32 as Add> error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 @@ -65,10 +65,10 @@ LL | <i32 as Add<u32>>::add(1, 2); | = help: the trait `Add<u32>` is not implemented for `i32` = help: the following other types implement trait `Add<Rhs>`: + <i32 as Add> + <i32 as Add<&i32>> <&'a i32 as Add<i32>> <&i32 as Add<&i32>> - <i32 as Add<&i32>> - <i32 as Add> error: aborting due to 4 previous errors diff --git a/triagebot.toml b/triagebot.toml index 4bab8facc85..e6c593204ca 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -20,6 +20,7 @@ allow-unauthenticated = [ "regression-*", "perf-*", "AsyncAwait-OnDeck", + "needs-triage", ] [glacier] @@ -254,6 +255,9 @@ trigger_files = [ [autolabel."S-waiting-on-review"] new_pr = true +[autolabel."needs-triage"] +new_issue = true + [autolabel."WG-trait-system-refactor"] trigger_files = [ "compiler/rustc_trait_selection/src/solve", |
